Skip to content

Commit 41e3971

Browse files
authored
Merge pull request #203 from Marketrix-ai/contract-subcontracts-split
Scope widget SDK to widgetContract; drop unused schema from bundle (~36 KB)
2 parents d22187d + 8844808 commit 41e3971

21 files changed

Lines changed: 1316 additions & 6012 deletions
Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
name: Contract Drift
2-
# Fails the PR if widget's oRPC contract mirrors (src/sdk/routes.ts,
3-
# src/sdk/schema.ts) have drifted STRUCTURALLY from the source of truth in
4-
# Marketrix-ai/api (routes.ts, schema.ts). "Structural" = presence of routes,
5-
# exported schema identifiers, and discriminated-union event tags — comments,
6-
# import paths, and whitespace are ignored.
7-
#
8-
# Widget is a strict SUBSET of the api contract: it intentionally omits the
9-
# dashboard-only `simulationIssue*` routes and `SimulationIssue*` schemas. The
10-
# drift script is run with --allow-subset, which tolerates those (and only
11-
# those) being absent. Anything else missing — or anything EXTRA in the widget
12-
# mirror — is still drift. See scripts/check-contract-drift.mjs for the known
13-
# field-level gap.
2+
# Fails the PR if widget's scoped SDK mirror (src/sdk/contract.ts + contracts/*)
3+
# has drifted from the source of truth in Marketrix-ai/api (sdk/widget.ts +
4+
# contracts/*). Uses the same sync-consumers.mjs generator in --check mode so
5+
# the gate and the write path are provably equivalent.
146
#
157
# TOKEN REQUIREMENT
168
# -----------------
17-
# This workflow reads two files from the PRIVATE Marketrix-ai/api repo, so it
18-
# needs a token with read access. Create a repo or org secret:
9+
# This workflow sparse-checkouts the relevant paths from the PRIVATE
10+
# Marketrix-ai/api repo, so it needs a token with read access. Create a
11+
# repo or org secret:
1912
#
2013
# CONTRACTS_READ_TOKEN = fine-grained PAT with "Contents: read" on
2114
# Marketrix-ai/api (read-only, no write scopes).
@@ -25,9 +18,7 @@ name: Contract Drift
2518
on:
2619
pull_request:
2720
paths:
28-
- src/sdk/routes.ts
29-
- src/sdk/schema.ts
30-
- scripts/check-contract-drift.mjs
21+
- src/sdk/**
3122
- .github/workflows/contract-drift.yml
3223
workflow_dispatch:
3324
schedule:
@@ -57,34 +48,26 @@ jobs:
5748
exit 1
5849
fi
5950
60-
- name: Fetch api contract source (routes.ts, schema.ts) from Marketrix-ai/api@dev
51+
- name: Sparse-checkout api contracts + sync generator from Marketrix-ai/api@dev
6152
env:
6253
GH_TOKEN: ${{ secrets.CONTRACTS_READ_TOKEN }}
6354
run: |
6455
set -euo pipefail
6556
mkdir -p .api-src
66-
for f in routes.ts schema.ts; do
67-
echo "Fetching api/${f}@dev ..."
68-
gh api "repos/Marketrix-ai/api/contents/${f}?ref=dev" \
69-
-H 'Accept: application/vnd.github.raw' > ".api-src/${f}"
70-
if [ ! -s ".api-src/${f}" ]; then
71-
echo "::error::Fetched empty .api-src/${f} — check the token has Contents:read on Marketrix-ai/api and that the file exists on dev."
72-
exit 1
73-
fi
74-
done
75-
76-
- name: Check routes drift (subset mode)
77-
run: |
78-
node scripts/check-contract-drift.mjs \
79-
--api .api-src/routes.ts \
80-
--mirror src/sdk/routes.ts \
81-
--kind routes \
82-
--allow-subset
57+
git -C .api-src init
58+
git -C .api-src remote add origin "https://x-access-token:${GH_TOKEN}@github.com/Marketrix-ai/api.git"
59+
git -C .api-src config core.sparseCheckout true
60+
printf 'contracts/\nscripts/sync-consumers.mjs\nsdk/\n' > .api-src/.git/info/sparse-checkout
61+
git -C .api-src fetch --depth=1 origin dev
62+
git -C .api-src checkout FETCH_HEAD
63+
if [ ! -f ".api-src/scripts/sync-consumers.mjs" ]; then
64+
echo "::error::sync-consumers.mjs not found in .api-src — check token and branch."
65+
exit 1
66+
fi
8367
84-
- name: Check schema drift (subset mode)
68+
- name: Check contract drift (sync-consumers --check)
8569
run: |
86-
node scripts/check-contract-drift.mjs \
87-
--api .api-src/schema.ts \
88-
--mirror src/sdk/schema.ts \
89-
--kind schema \
90-
--allow-subset
70+
node .api-src/scripts/sync-consumers.mjs widget \
71+
--check \
72+
--api-root .api-src \
73+
--dest src/sdk

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "@marketrix.ai/widget",
33
"version": "3.8.3",
44
"type": "module",
5+
"sideEffects": false,
56
"main": "./dist/widget.mjs",
67
"module": "./dist/widget.mjs",
78
"types": "./dist/src/index.d.ts",

scripts/check-contract-drift.mjs

Lines changed: 0 additions & 204 deletions
This file was deleted.

src/context/TaskContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
22

3-
import type { WidgetEvent } from '../sdk/schema';
3+
import type { WidgetEvent } from '../sdk';
44
import { StreamClient, type StreamStatus } from '../services/StreamClient';
55
import { toolExecutionService } from '../services/ToolService';
66
import type { ChatMessage, InstructionType, TaskProgress } from '../types';

src/context/__tests__/sseReducer.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
import { describe, expect, it } from 'vitest';
77

8-
import type { WidgetEvent } from '@/sdk/schema';
8+
import type { WidgetEvent } from '@/sdk';
99
import type { ChatMessage } from '@/types';
1010
import { hasThinkingMarker } from '@/utils/chat';
1111

src/context/sseReducer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Keeping this pure makes the previously-untestable ~180-line SSE handler unit
99
* testable and removes the nested setState-within-setState that hid bugs.
1010
*/
11-
import type { WidgetEvent } from '../sdk/schema';
11+
import type { WidgetEvent } from '../sdk';
1212
import type { ChatMessage, InstructionType } from '../types';
1313
import {
1414
addProgressLine,

src/sdk/contract.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { activityLogCreate } from './contracts/activityLog';
2+
import { agentGet } from './contracts/agent';
3+
import { applicationGet } from './contracts/application';
4+
import { chatCreate } from './contracts/chat';
5+
import { widgetGetDefaults, widgetMessage, widgetSearch, widgetStream } from './contracts/widget';
6+
7+
export const widgetContract = {
8+
activityLogCreate,
9+
agentGet,
10+
applicationGet,
11+
chatCreate,
12+
widgetGetDefaults,
13+
widgetSearch,
14+
widgetMessage,
15+
widgetStream,
16+
};

src/sdk/contracts/activityLog.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { oc } from '@orpc/contract';
2+
import { z } from 'zod';
3+
4+
import { paginatedListOf, PaginationSchema } from './common';
5+
import { ActionLogCreateSchema, ActionLogEntitySchema, ActionLogTypeSchema } from './entities';
6+
7+
// ---- procedures ----
8+
9+
export const activityLogCreate = oc
10+
.route({
11+
method: 'POST',
12+
tags: ['Activity Log'],
13+
path: '/log',
14+
summary: 'Create new activity log entry',
15+
description: 'Records user or system action for auditing and tracking purposes',
16+
})
17+
.input(ActionLogCreateSchema)
18+
.output(ActionLogEntitySchema);
19+
20+
export const activityLogSearch = oc
21+
.route({
22+
method: 'GET',
23+
tags: ['Activity Log'],
24+
path: '/log',
25+
summary: 'Search and filter activity logs',
26+
description: 'Returns list of activity logs matching search parameters (workspace, type)',
27+
})
28+
.input(
29+
z
30+
.object({
31+
workspace_id: z.coerce.number().optional(),
32+
type: ActionLogTypeSchema.optional(),
33+
application_id: z.coerce.number().optional(),
34+
})
35+
.extend(PaginationSchema.shape),
36+
)
37+
.output(paginatedListOf(ActionLogEntitySchema));
38+
39+
// ---- domain aggregate ----
40+
41+
export const activityLogRoutes = {
42+
activityLogCreate,
43+
activityLogSearch,
44+
};

0 commit comments

Comments
 (0)