@wootsup/mcp 0.1.0-rc.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/index.d.ts +19 -0
- package/dist/index.js +71 -5
- package/dist/index.js.map +1 -1
- package/dist/modules/apimapper/cache.d.ts +2 -2
- package/dist/modules/apimapper/cache.js +107 -25
- package/dist/modules/apimapper/cache.js.map +1 -1
- package/dist/modules/apimapper/client.d.ts +40 -0
- package/dist/modules/apimapper/client.js +82 -12
- package/dist/modules/apimapper/client.js.map +1 -1
- package/dist/modules/apimapper/connections-format.d.ts +51 -0
- package/dist/modules/apimapper/connections-format.js +261 -0
- package/dist/modules/apimapper/connections-format.js.map +1 -0
- package/dist/modules/apimapper/connections-trim.d.ts +82 -0
- package/dist/modules/apimapper/connections-trim.js +224 -0
- package/dist/modules/apimapper/connections-trim.js.map +1 -0
- package/dist/modules/apimapper/connections.d.ts +14 -2
- package/dist/modules/apimapper/connections.js +447 -143
- package/dist/modules/apimapper/connections.js.map +1 -1
- package/dist/modules/apimapper/credentials-format.d.ts +21 -0
- package/dist/modules/apimapper/credentials-format.js +145 -0
- package/dist/modules/apimapper/credentials-format.js.map +1 -0
- package/dist/modules/apimapper/credentials.d.ts +12 -2
- package/dist/modules/apimapper/credentials.js +253 -72
- package/dist/modules/apimapper/credentials.js.map +1 -1
- package/dist/modules/apimapper/diagnose.d.ts +54 -2
- package/dist/modules/apimapper/diagnose.js +193 -11
- package/dist/modules/apimapper/diagnose.js.map +1 -1
- package/dist/modules/apimapper/elicitation.d.ts +54 -0
- package/dist/modules/apimapper/elicitation.js +90 -0
- package/dist/modules/apimapper/elicitation.js.map +1 -0
- package/dist/modules/apimapper/flows-format.d.ts +50 -0
- package/dist/modules/apimapper/flows-format.js +318 -0
- package/dist/modules/apimapper/flows-format.js.map +1 -0
- package/dist/modules/apimapper/flows.d.ts +13 -2
- package/dist/modules/apimapper/flows.js +325 -118
- package/dist/modules/apimapper/flows.js.map +1 -1
- package/dist/modules/apimapper/gateway/advanced-tool.d.ts +9 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js +214 -0
- package/dist/modules/apimapper/gateway/advanced-tool.js.map +1 -0
- package/dist/modules/apimapper/gateway/capturing-server.d.ts +81 -0
- package/dist/modules/apimapper/gateway/capturing-server.js +87 -0
- package/dist/modules/apimapper/gateway/capturing-server.js.map +1 -0
- package/dist/modules/apimapper/gateway/essentials.d.ts +4 -0
- package/dist/modules/apimapper/gateway/essentials.js +28 -0
- package/dist/modules/apimapper/gateway/essentials.js.map +1 -0
- package/dist/modules/apimapper/gateway/test-support.d.ts +17 -0
- package/dist/modules/apimapper/gateway/test-support.js +43 -0
- package/dist/modules/apimapper/gateway/test-support.js.map +1 -0
- package/dist/modules/apimapper/get-skill.d.ts +3 -3
- package/dist/modules/apimapper/get-skill.js +4 -2
- package/dist/modules/apimapper/get-skill.js.map +1 -1
- package/dist/modules/apimapper/graph-builder.js +1 -1
- package/dist/modules/apimapper/graph-builder.js.map +1 -1
- package/dist/modules/apimapper/graph.d.ts +2 -2
- package/dist/modules/apimapper/graph.js +165 -34
- package/dist/modules/apimapper/graph.js.map +1 -1
- package/dist/modules/apimapper/index.d.ts +17 -1
- package/dist/modules/apimapper/index.js +66 -17
- package/dist/modules/apimapper/index.js.map +1 -1
- package/dist/modules/apimapper/inspect.d.ts +3 -2
- package/dist/modules/apimapper/inspect.js +97 -13
- package/dist/modules/apimapper/inspect.js.map +1 -1
- package/dist/modules/apimapper/library.d.ts +2 -2
- package/dist/modules/apimapper/library.js +303 -60
- package/dist/modules/apimapper/library.js.map +1 -1
- package/dist/modules/apimapper/license-format.d.ts +22 -0
- package/dist/modules/apimapper/license-format.js +149 -0
- package/dist/modules/apimapper/license-format.js.map +1 -0
- package/dist/modules/apimapper/license.d.ts +16 -2
- package/dist/modules/apimapper/license.js +85 -37
- package/dist/modules/apimapper/license.js.map +1 -1
- package/dist/modules/apimapper/local-sources.d.ts +2 -2
- package/dist/modules/apimapper/local-sources.js +58 -30
- package/dist/modules/apimapper/local-sources.js.map +1 -1
- package/dist/modules/apimapper/misc.d.ts +30 -2
- package/dist/modules/apimapper/misc.js +129 -50
- package/dist/modules/apimapper/misc.js.map +1 -1
- package/dist/modules/apimapper/node-schema.d.ts +52 -0
- package/dist/modules/apimapper/node-schema.js +70 -2
- package/dist/modules/apimapper/node-schema.js.map +1 -1
- package/dist/modules/apimapper/normalizers.d.ts +1 -0
- package/dist/modules/apimapper/normalizers.js +51 -0
- package/dist/modules/apimapper/normalizers.js.map +1 -1
- package/dist/modules/apimapper/onboarding.d.ts +48 -2
- package/dist/modules/apimapper/onboarding.js +324 -17
- package/dist/modules/apimapper/onboarding.js.map +1 -1
- package/dist/modules/apimapper/read-cache.d.ts +31 -2
- package/dist/modules/apimapper/read-cache.js +20 -6
- package/dist/modules/apimapper/read-cache.js.map +1 -1
- package/dist/modules/apimapper/render/_shared.d.ts +24 -0
- package/dist/modules/apimapper/render/_shared.js +84 -0
- package/dist/modules/apimapper/render/_shared.js.map +1 -0
- package/dist/modules/apimapper/render/dag.d.ts +18 -0
- package/dist/modules/apimapper/render/dag.js +70 -0
- package/dist/modules/apimapper/render/dag.js.map +1 -0
- package/dist/modules/apimapper/render/index.d.ts +2 -0
- package/dist/modules/apimapper/render/index.js +112 -0
- package/dist/modules/apimapper/render/index.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js +70 -0
- package/dist/modules/apimapper/render/renderers/chart-bar.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/chart-line.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js +71 -0
- package/dist/modules/apimapper/render/renderers/chart-line.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/diff.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/diff.js +154 -0
- package/dist/modules/apimapper/render/renderers/diff.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.d.ts +1 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js +180 -0
- package/dist/modules/apimapper/render/renderers/flow-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/json-tree.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js +87 -0
- package/dist/modules/apimapper/render/renderers/json-tree.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js +83 -0
- package/dist/modules/apimapper/render/renderers/schema-diagram.js.map +1 -0
- package/dist/modules/apimapper/render/renderers/table.d.ts +2 -0
- package/dist/modules/apimapper/render/renderers/table.js +75 -0
- package/dist/modules/apimapper/render/renderers/table.js.map +1 -0
- package/dist/modules/apimapper/render/schemas.d.ts +23 -0
- package/dist/modules/apimapper/render/schemas.js +56 -0
- package/dist/modules/apimapper/render/schemas.js.map +1 -0
- package/dist/modules/apimapper/render/secret-masking.d.ts +5 -0
- package/dist/modules/apimapper/render/secret-masking.js +51 -0
- package/dist/modules/apimapper/render/secret-masking.js.map +1 -0
- package/dist/modules/apimapper/render/sidecar.d.ts +21 -0
- package/dist/modules/apimapper/render/sidecar.js +66 -0
- package/dist/modules/apimapper/render/sidecar.js.map +1 -0
- package/dist/modules/apimapper/render/token-cap.d.ts +21 -0
- package/dist/modules/apimapper/render/token-cap.js +57 -0
- package/dist/modules/apimapper/render/token-cap.js.map +1 -0
- package/dist/modules/apimapper/schema.d.ts +2 -2
- package/dist/modules/apimapper/schema.js +100 -32
- package/dist/modules/apimapper/schema.js.map +1 -1
- package/dist/modules/apimapper/settings-format.d.ts +23 -0
- package/dist/modules/apimapper/settings-format.js +135 -0
- package/dist/modules/apimapper/settings-format.js.map +1 -0
- package/dist/modules/apimapper/settings.d.ts +2 -2
- package/dist/modules/apimapper/settings.js +101 -40
- package/dist/modules/apimapper/settings.js.map +1 -1
- package/dist/modules/apimapper/skill-resources.d.ts +2 -2
- package/dist/modules/apimapper/skill-resources.js.map +1 -1
- package/dist/modules/apimapper/token-baseline.harness.d.ts +91 -0
- package/dist/modules/apimapper/token-baseline.harness.js +291 -0
- package/dist/modules/apimapper/token-baseline.harness.js.map +1 -0
- package/dist/modules/apimapper/toolslist-size.d.ts +55 -0
- package/dist/modules/apimapper/toolslist-size.js +190 -0
- package/dist/modules/apimapper/toolslist-size.js.map +1 -0
- package/dist/modules/apimapper/types.d.ts +23 -8
- package/dist/modules/apimapper/types.js +26 -1
- package/dist/modules/apimapper/types.js.map +1 -1
- package/dist/modules/apimapper/use-profile.d.ts +21 -0
- package/dist/modules/apimapper/use-profile.js +56 -2
- package/dist/modules/apimapper/use-profile.js.map +1 -1
- package/dist/modules/apimapper/workflows.d.ts +2 -2
- package/dist/modules/apimapper/workflows.js +143 -16
- package/dist/modules/apimapper/workflows.js.map +1 -1
- package/dist/platform/index.js +44 -5
- package/dist/platform/index.js.map +1 -1
- package/dist/setup-cli.d.ts +53 -0
- package/dist/setup-cli.js +126 -4
- package/dist/setup-cli.js.map +1 -1
- package/docs/architecture.md +1 -1
- package/docs/tools.md +1 -1
- package/manifest.json +12 -3
- package/package.json +9 -4
- package/skills/apimapper/SKILL.md +1 -1
- package/skills/apimapper/reference/render.md +132 -0
- package/skills/apimapper/reference/troubleshooting.md +1 -1
- package/skills/apimapper/reference/yootheme.md +1 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// token-baseline.harness.ts — W3.0.C
|
|
2
|
+
//
|
|
3
|
+
// Deterministic, offline token-output measurement for the canonical API
|
|
4
|
+
// Mapper tool-call sequence. The SAME harness is re-run after Welle 3 ships;
|
|
5
|
+
// the before/after delta is what proves the ≥40% token-reduction goal, so
|
|
6
|
+
// consistency between runs matters more than the absolute number.
|
|
7
|
+
//
|
|
8
|
+
// How it works:
|
|
9
|
+
// 1. The caller passes the registered apimapper tools map (the live
|
|
10
|
+
// `registerTool` config + handler for every tool) and a `fetchResponder`
|
|
11
|
+
// that maps an upstream URL to a canned real-shape REST response.
|
|
12
|
+
// 2. `runTokenBaseline` installs the responder as `globalThis.fetch`,
|
|
13
|
+
// replays the 8-call canonical sequence against the real tool handlers
|
|
14
|
+
// with canned real-shape inputs, sums the UTF-8 byte length of every
|
|
15
|
+
// result's `content[].text` block, and restores `globalThis.fetch`.
|
|
16
|
+
// 3. It returns `{ sequence: [{ tool, bytes }], totalBytes }`.
|
|
17
|
+
//
|
|
18
|
+
// No network, no child process — the tool handlers run in-process and the
|
|
19
|
+
// REST layer is the supplied responder. Given the same tools map and the
|
|
20
|
+
// same responder, the result is byte-for-byte identical (determinism is
|
|
21
|
+
// pinned by token-baseline.test.ts).
|
|
22
|
+
/**
|
|
23
|
+
* The canonical 8-call walkthrough (the Maria mixed-feed flow): a fresh user
|
|
24
|
+
* discovers the install, activates a library template, inspects a connection,
|
|
25
|
+
* builds and validates a flow, then compiles it. Inputs are real-shape and
|
|
26
|
+
* fixed so the measurement is reproducible.
|
|
27
|
+
*/
|
|
28
|
+
export const CANONICAL_SEQUENCE = [
|
|
29
|
+
{ tool: "apimapper_onboarding", args: {} },
|
|
30
|
+
{ tool: "apimapper_library_list", args: { limit: 25 } },
|
|
31
|
+
{
|
|
32
|
+
tool: "apimapper_library_activate",
|
|
33
|
+
args: { id: "pexels", extra_fields: { api_key: "demo-key" } },
|
|
34
|
+
},
|
|
35
|
+
{ tool: "apimapper_connection_list", args: {} },
|
|
36
|
+
{ tool: "apimapper_connection_data", args: { id: "con_pexels", limit: 10 } },
|
|
37
|
+
{
|
|
38
|
+
tool: "apimapper_flow_create",
|
|
39
|
+
args: {
|
|
40
|
+
name: "Maria Mixed Feed",
|
|
41
|
+
nodes: [
|
|
42
|
+
{
|
|
43
|
+
id: "src1",
|
|
44
|
+
type: "source",
|
|
45
|
+
position: { x: 0, y: 0 },
|
|
46
|
+
data: { connectionId: "con_pexels" },
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "out1",
|
|
50
|
+
type: "output-yootheme",
|
|
51
|
+
position: { x: 300, y: 0 },
|
|
52
|
+
data: { name: "Mixed Feed" },
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
edges: [{ id: "e1", source: "src1", target: "out1" }],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
tool: "apimapper_graph_validate",
|
|
60
|
+
args: {
|
|
61
|
+
nodes: [
|
|
62
|
+
{
|
|
63
|
+
id: "src1",
|
|
64
|
+
type: "source",
|
|
65
|
+
position: { x: 0, y: 0 },
|
|
66
|
+
data: { connectionId: "con_pexels" },
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "out1",
|
|
70
|
+
type: "output-yootheme",
|
|
71
|
+
position: { x: 300, y: 0 },
|
|
72
|
+
data: { name: "Mixed Feed" },
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
edges: [{ id: "e1", source: "src1", target: "out1" }],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ tool: "apimapper_flow_compile", args: { id: "flow_maria01" } },
|
|
79
|
+
];
|
|
80
|
+
/** The tool names the canonical sequence exercises, in call order. */
|
|
81
|
+
export const CANONICAL_TOOLS = CANONICAL_SEQUENCE.map((s) => s.tool);
|
|
82
|
+
// ── Canonical real-shape REST fixtures ──────────────────────────────────
|
|
83
|
+
//
|
|
84
|
+
// One fixture per upstream endpoint the canonical sequence touches. Shapes
|
|
85
|
+
// mirror the actual PHP wire responses (the same shapes the per-module test
|
|
86
|
+
// files assert against). Keeping them here — alongside the sequence — means
|
|
87
|
+
// the determinism test and the scripts/token-baseline.mjs runner measure the
|
|
88
|
+
// exact same byte budget; the responder is a single source of truth.
|
|
89
|
+
// `provider` mirrors the real library.test.ts fixtures — the library_list
|
|
90
|
+
// handler reads it for the client-side provider filter, so shipping it keeps
|
|
91
|
+
// the measured shape faithful to the live PHP wire response.
|
|
92
|
+
const LIBRARY_ITEMS = [
|
|
93
|
+
{
|
|
94
|
+
id: "pexels",
|
|
95
|
+
name: "Pexels",
|
|
96
|
+
provider: "pexels",
|
|
97
|
+
category: "media",
|
|
98
|
+
description: "Free stock photos and videos via the Pexels REST API.",
|
|
99
|
+
auth_type: "apikey",
|
|
100
|
+
popular: true,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "google-sheets",
|
|
104
|
+
name: "Google Sheets",
|
|
105
|
+
provider: "google",
|
|
106
|
+
category: "productivity",
|
|
107
|
+
description: "Read rows from a Google Sheets spreadsheet.",
|
|
108
|
+
auth_type: "oauth2_authcode",
|
|
109
|
+
popular: true,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "instagram",
|
|
113
|
+
name: "Instagram Graph",
|
|
114
|
+
provider: "instagram",
|
|
115
|
+
category: "social",
|
|
116
|
+
description: "Fetch media from an Instagram Business account.",
|
|
117
|
+
auth_type: "oauth2_authcode",
|
|
118
|
+
popular: false,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
const CONNECTIONS = [
|
|
122
|
+
{
|
|
123
|
+
id: "con_pexels",
|
|
124
|
+
name: "Pexels — Curated",
|
|
125
|
+
source_type: "pexels",
|
|
126
|
+
status: "active",
|
|
127
|
+
credential_id: "cred_pexels1",
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
const PEXELS_ROWS = Array.from({ length: 10 }, (_, i) => ({
|
|
131
|
+
id: 1000 + i,
|
|
132
|
+
title: `Curated photo ${i + 1}`,
|
|
133
|
+
photographer: `Photographer ${i + 1}`,
|
|
134
|
+
image: { url: `https://images.pexels.com/photos/${1000 + i}/photo.jpg` },
|
|
135
|
+
width: 1920,
|
|
136
|
+
height: 1280,
|
|
137
|
+
}));
|
|
138
|
+
const FLOW_OBJECT = {
|
|
139
|
+
id: "flow_maria01",
|
|
140
|
+
name: "Maria Mixed Feed",
|
|
141
|
+
node_count: 2,
|
|
142
|
+
is_compiled: false,
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Canonical fetch responder — routes an upstream URL to its real-shape
|
|
146
|
+
* fixture. Anything unmatched returns an empty-success envelope, which is the
|
|
147
|
+
* benign default for the optional sub-calls inside `apimapper_onboarding`.
|
|
148
|
+
*/
|
|
149
|
+
export function canonicalFetchResponder(url) {
|
|
150
|
+
if (url.includes("/library/popular")) {
|
|
151
|
+
return { body: { connections: LIBRARY_ITEMS.filter((i) => i.popular) } };
|
|
152
|
+
}
|
|
153
|
+
if (url.includes("/library/featured")) {
|
|
154
|
+
return { body: { connections: LIBRARY_ITEMS.slice(0, 2) } };
|
|
155
|
+
}
|
|
156
|
+
if (url.includes("/library/categories")) {
|
|
157
|
+
return {
|
|
158
|
+
body: {
|
|
159
|
+
categories: [
|
|
160
|
+
{ id: "media", name: "Media", count: 4 },
|
|
161
|
+
{ id: "social", name: "Social", count: 3 },
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (url.includes("/library/pexels/activate")) {
|
|
167
|
+
return {
|
|
168
|
+
body: {
|
|
169
|
+
success: true,
|
|
170
|
+
connection: { id: "con_pexels", name: "Pexels", source_type: "pexels" },
|
|
171
|
+
reused: false,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (url.includes("/library")) {
|
|
176
|
+
return { body: { connections: LIBRARY_ITEMS, total: LIBRARY_ITEMS.length } };
|
|
177
|
+
}
|
|
178
|
+
if (url.includes("/connections/con_pexels/data")) {
|
|
179
|
+
// Real backend returns the connection as an OBJECT, not a bare id —
|
|
180
|
+
// mirrors the {data, connection:{…}} envelope the connections.test.ts
|
|
181
|
+
// fixtures assert against, so the byte measurement stays realistic.
|
|
182
|
+
return {
|
|
183
|
+
body: {
|
|
184
|
+
data: PEXELS_ROWS,
|
|
185
|
+
connection: {
|
|
186
|
+
id: "con_pexels",
|
|
187
|
+
name: "Pexels — Curated",
|
|
188
|
+
source_type: "pexels",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (url.includes("/connections")) {
|
|
194
|
+
return { body: { connections: CONNECTIONS } };
|
|
195
|
+
}
|
|
196
|
+
if (url.includes("/flows/flow_maria01/compile")) {
|
|
197
|
+
return { body: { compiled: {}, flowId: "flow_maria01" } };
|
|
198
|
+
}
|
|
199
|
+
if (url.includes("/flows")) {
|
|
200
|
+
return { body: { success: true, flow: FLOW_OBJECT } };
|
|
201
|
+
}
|
|
202
|
+
if (url.includes("/graph/validate")) {
|
|
203
|
+
return {
|
|
204
|
+
body: { valid: true, warnings: [], nodeCount: 2, edgeCount: 1 },
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (url.includes("/health")) {
|
|
208
|
+
return {
|
|
209
|
+
body: { plugin_version: "2.0.7", api_version: "v1", status: "ok" },
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (url.includes("/license")) {
|
|
213
|
+
return { body: { tier: "pro", status: "active" } };
|
|
214
|
+
}
|
|
215
|
+
// Benign default for any onboarding sub-call without a dedicated fixture.
|
|
216
|
+
return { body: {} };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Matches the toolkit's embedded structured-meta marker — a trailing
|
|
220
|
+
* `\n\n<!-- structured-meta:<base64> -->` block appended by the
|
|
221
|
+
* `tableResult` / `detailResult` / … builders so `_meta.ui` survives
|
|
222
|
+
* `@ai-sdk/mcp`'s conversion (see @getimo/mcp-toolkit `embedStructuredMeta`).
|
|
223
|
+
* The `[A-Za-z0-9+/=]*` body is base64; `g` strips every occurrence.
|
|
224
|
+
*/
|
|
225
|
+
const STRUCTURED_META_MARKER = /\n\n<!-- structured-meta:[A-Za-z0-9+/=]*? -->/g;
|
|
226
|
+
/**
|
|
227
|
+
* Strip every embedded structured-meta marker from a text block. What remains
|
|
228
|
+
* is the human/LLM-readable text a marker-aware host (the WootsUp Chat UI)
|
|
229
|
+
* presents after extracting the marker into a Rich Card.
|
|
230
|
+
*/
|
|
231
|
+
export function stripStructuredMeta(text) {
|
|
232
|
+
return text.replace(STRUCTURED_META_MARKER, "");
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Sum the UTF-8 byte length of every text block in a tool result — both the
|
|
236
|
+
* raw bytes (`bytes`) and the marker-stripped, LLM-visible bytes
|
|
237
|
+
* (`visibleBytes`). The raw figure is the token-baseline metric; the visible
|
|
238
|
+
* figure is what a marker-stripping host actually feeds the model.
|
|
239
|
+
*/
|
|
240
|
+
function resultBytes(result) {
|
|
241
|
+
const blocks = Array.isArray(result.content) ? result.content : [];
|
|
242
|
+
let bytes = 0;
|
|
243
|
+
let visibleBytes = 0;
|
|
244
|
+
for (const block of blocks) {
|
|
245
|
+
if (typeof block.text === "string") {
|
|
246
|
+
bytes += Buffer.byteLength(block.text, "utf8");
|
|
247
|
+
visibleBytes += Buffer.byteLength(stripStructuredMeta(block.text), "utf8");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return { bytes, visibleBytes };
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Replay the canonical sequence and measure total token output.
|
|
254
|
+
*
|
|
255
|
+
* @param tools the registered apimapper tools map (name → tool)
|
|
256
|
+
* @param fetchResponder maps each upstream URL to a canned REST response
|
|
257
|
+
* @returns per-tool byte tally + `totalBytes` across the whole sequence
|
|
258
|
+
*/
|
|
259
|
+
export async function runTokenBaseline(tools, fetchResponder) {
|
|
260
|
+
const originalFetch = globalThis.fetch;
|
|
261
|
+
globalThis.fetch = (async (input, init) => {
|
|
262
|
+
const url = String(input);
|
|
263
|
+
const canned = fetchResponder(url, init);
|
|
264
|
+
const body = typeof canned.body === "string"
|
|
265
|
+
? canned.body
|
|
266
|
+
: JSON.stringify(canned.body);
|
|
267
|
+
return new Response(body, {
|
|
268
|
+
status: canned.status ?? 200,
|
|
269
|
+
headers: { "Content-Type": "application/json" },
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
try {
|
|
273
|
+
const sequence = [];
|
|
274
|
+
for (const step of CANONICAL_SEQUENCE) {
|
|
275
|
+
const tool = tools[step.tool];
|
|
276
|
+
if (!tool) {
|
|
277
|
+
throw new Error(`token-baseline: tool "${step.tool}" is not registered`);
|
|
278
|
+
}
|
|
279
|
+
const result = await tool.handler(step.args);
|
|
280
|
+
const { bytes, visibleBytes } = resultBytes(result);
|
|
281
|
+
sequence.push({ tool: step.tool, bytes, visibleBytes });
|
|
282
|
+
}
|
|
283
|
+
const totalBytes = sequence.reduce((sum, e) => sum + e.bytes, 0);
|
|
284
|
+
const totalVisibleBytes = sequence.reduce((sum, e) => sum + e.visibleBytes, 0);
|
|
285
|
+
return { sequence, totalBytes, totalVisibleBytes };
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
globalThis.fetch = originalFetch;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=token-baseline.harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-baseline.harness.js","sourceRoot":"","sources":["../../../src/modules/apimapper/token-baseline.harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CollectedTool } from "./gateway/test-support.js";
|
|
2
|
+
/**
|
|
3
|
+
* The minimal `tools/list`-relevant slice of a registered tool: the fields the
|
|
4
|
+
* MCP client receives and the LLM reads as part of the static catalog.
|
|
5
|
+
*/
|
|
6
|
+
export interface ToolCatalogEntry {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
inputSchema?: unknown;
|
|
10
|
+
annotations?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
/** One side of the measurement: its tool count and total serialized bytes. */
|
|
13
|
+
export interface ToolsListMeasurement {
|
|
14
|
+
/** Number of tools in this `tools/list` surface. */
|
|
15
|
+
toolCount: number;
|
|
16
|
+
/** Sum of `Buffer.byteLength(JSON.stringify(entry))` across all tools. */
|
|
17
|
+
totalBytes: number;
|
|
18
|
+
/** Per-tool byte tally, sorted by name, for the breakdown table. */
|
|
19
|
+
perTool: Array<{
|
|
20
|
+
name: string;
|
|
21
|
+
bytes: number;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
/** The full Task-B result: the post-W3 and pre-W3-equivalent surfaces. */
|
|
25
|
+
export interface ToolsListComparison {
|
|
26
|
+
/** Post-W3 `tools/list` — the 17 surface tools the server exposes today. */
|
|
27
|
+
postW3: ToolsListMeasurement;
|
|
28
|
+
/** Pre-W3-equivalent `tools/list` — all 76 tools exposed flat (no gateway). */
|
|
29
|
+
preW3Flat: ToolsListMeasurement;
|
|
30
|
+
/** Absolute byte reduction (preW3Flat.totalBytes − postW3.totalBytes). */
|
|
31
|
+
bytesSaved: number;
|
|
32
|
+
/** Reduction as a fraction of the pre-W3-equivalent total (0..1). */
|
|
33
|
+
fractionSaved: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Projects one tool to its `tools/list` JSON-Schema-bearing catalog entry.
|
|
37
|
+
* The `inputSchema` is JSON-Schema-projected the same way the SDK and the
|
|
38
|
+
* gateway's discovery mode do, so the byte count reflects the real wire shape.
|
|
39
|
+
*/
|
|
40
|
+
export declare function toCatalogEntry(name: string, tool: Pick<CollectedTool, "description" | "inputSchema" | "annotations">): ToolCatalogEntry;
|
|
41
|
+
/**
|
|
42
|
+
* Builds the full 77-tool catalog from the current build and measures the
|
|
43
|
+
* post-W3 vs pre-W3-equivalent `tools/list` payload sizes.
|
|
44
|
+
*
|
|
45
|
+
* Surface composition (verified against `gateway/essentials.ts` + `src/index.ts`):
|
|
46
|
+
* - module tools : 13 essentials + `apimapper_advanced` = 14 (on the real
|
|
47
|
+
* McpServer) + 60 advanced (gateway registry) = 74
|
|
48
|
+
* - top-level tools: rest_modules_status + use_profile + list_profiles = 3
|
|
49
|
+
* total = 77
|
|
50
|
+
*
|
|
51
|
+
* POST-W3 `tools/list` = the 14 module-real tools + the 3 top-level tools = 17.
|
|
52
|
+
* PRE-W3 flat `tools/list` = the 16 non-gateway surface tools + the 60 advanced
|
|
53
|
+
* tools = 76 (the `apimapper_advanced` gateway did not exist pre-W3).
|
|
54
|
+
*/
|
|
55
|
+
export declare function measureToolsList(): Promise<ToolsListComparison>;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// toolslist-size.ts — W3 Stage-5 token-Δ measurement (Task B)
|
|
2
|
+
//
|
|
3
|
+
// Measures the `tools/list` catalog overhead — the static tool descriptions +
|
|
4
|
+
// JSON schemas an MCP client receives once per session, before any tool is
|
|
5
|
+
// called. This is the DOMINANT token cost center of an API Mapper session.
|
|
6
|
+
//
|
|
7
|
+
// Two figures, both derived from the CURRENT build:
|
|
8
|
+
//
|
|
9
|
+
// - POST-W3 `tools/list` — the 17 surface tools the server now exposes
|
|
10
|
+
// (13 module essentials + `apimapper_advanced`
|
|
11
|
+
// + the 3 src/index.ts top-level tools).
|
|
12
|
+
// - PRE-W3-equivalent `tools/list` — what `tools/list` WOULD be if all 77
|
|
13
|
+
// tools were exposed flat (the pre-Gateway
|
|
14
|
+
// state): the 17 surface tools minus the
|
|
15
|
+
// gateway tool, plus the 60 advanced-registry
|
|
16
|
+
// tool configs — 76 flat tools. (Pre-W3 the
|
|
17
|
+
// `apimapper_advanced` gateway did not exist.)
|
|
18
|
+
//
|
|
19
|
+
// Per-tool serialization mirrors what the MCP SDK puts on the wire for one
|
|
20
|
+
// `tools/list` entry: `{ name, description, inputSchema, annotations }`, where
|
|
21
|
+
// `inputSchema` is the JSON Schema projected from the tool's Zod raw-shape
|
|
22
|
+
// (the same `z.toJSONSchema` projection `gateway/advanced-tool.ts` uses for
|
|
23
|
+
// discovery mode). `title` and `_meta` are omitted: they are small, present on
|
|
24
|
+
// both sides, and cancel out in the delta — keeping the measurement focused on
|
|
25
|
+
// the description + schema payload that actually scales with the tool count.
|
|
26
|
+
//
|
|
27
|
+
// Determinism: given the same build, every figure is byte-for-byte identical.
|
|
28
|
+
// Pinned by toolslist-size.test.ts.
|
|
29
|
+
import * as os from "node:os";
|
|
30
|
+
import * as path from "node:path";
|
|
31
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
32
|
+
import { loadModules } from "@getimo/mcp-toolkit";
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
import { apimapperRestModule } from "./index.js";
|
|
35
|
+
import { collectModuleTools } from "./gateway/test-support.js";
|
|
36
|
+
import { registerListProfilesTool, registerUseProfileTool, } from "./use-profile.js";
|
|
37
|
+
import { ProfileStore } from "../../auth/profiles.js";
|
|
38
|
+
/**
|
|
39
|
+
* Reads a tool config's `inputSchema` as a Zod raw-shape. Mirrors `shapeOf`
|
|
40
|
+
* in `gateway/advanced-tool.ts` — a registered `inputSchema` is the raw shape
|
|
41
|
+
* object; a zero-arg tool has none.
|
|
42
|
+
*/
|
|
43
|
+
function shapeOf(inputSchema) {
|
|
44
|
+
if (inputSchema && typeof inputSchema === "object") {
|
|
45
|
+
return inputSchema;
|
|
46
|
+
}
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Projects one tool to its `tools/list` JSON-Schema-bearing catalog entry.
|
|
51
|
+
* The `inputSchema` is JSON-Schema-projected the same way the SDK and the
|
|
52
|
+
* gateway's discovery mode do, so the byte count reflects the real wire shape.
|
|
53
|
+
*/
|
|
54
|
+
export function toCatalogEntry(name, tool) {
|
|
55
|
+
let inputSchema;
|
|
56
|
+
try {
|
|
57
|
+
inputSchema = z.toJSONSchema(z.object(shapeOf(tool.inputSchema)));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// A schema that cannot be JSON-projected still yields a usable entry; the
|
|
61
|
+
// description carries the rest. Matches the gateway discovery-mode guard.
|
|
62
|
+
inputSchema = { type: "object" };
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
name,
|
|
66
|
+
description: tool.description,
|
|
67
|
+
inputSchema,
|
|
68
|
+
annotations: tool.annotations,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Serializes a list of catalog entries and tallies the UTF-8 byte length of
|
|
73
|
+
* each entry's `JSON.stringify`. The total is the `tools/list` payload size
|
|
74
|
+
* for that surface.
|
|
75
|
+
*/
|
|
76
|
+
function measure(entries) {
|
|
77
|
+
const perTool = entries
|
|
78
|
+
.map((entry) => ({
|
|
79
|
+
name: entry.name,
|
|
80
|
+
bytes: Buffer.byteLength(JSON.stringify(entry), "utf8"),
|
|
81
|
+
}))
|
|
82
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
83
|
+
const totalBytes = perTool.reduce((sum, t) => sum + t.bytes, 0);
|
|
84
|
+
return { toolCount: perTool.length, totalBytes, perTool };
|
|
85
|
+
}
|
|
86
|
+
/** A no-op keychain: registration stores the dep but never invokes it here. */
|
|
87
|
+
const STUB_KEYCHAIN = {
|
|
88
|
+
set: async () => undefined,
|
|
89
|
+
get: async () => null,
|
|
90
|
+
delete: async () => undefined,
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Captures the 3 top-level tools registered in `src/index.ts` —
|
|
94
|
+
* `apimapper_rest_modules_status`, `apimapper_use_profile`,
|
|
95
|
+
* `apimapper_list_profiles` — by replaying their registration against a
|
|
96
|
+
* recording registrar. `src/index.ts` registers these directly on the
|
|
97
|
+
* McpServer (not via the module / CapturingServer), so they must be added to
|
|
98
|
+
* the catalog explicitly for an accurate `tools/list` count.
|
|
99
|
+
*
|
|
100
|
+
* The use-profile registrations only *store* their `{ store, keychain }` deps;
|
|
101
|
+
* they are never invoked at registration time, so a real `ProfileStore` over a
|
|
102
|
+
* throwaway dir + a stub keychain is sufficient to capture the configs.
|
|
103
|
+
*/
|
|
104
|
+
function captureTopLevelTools() {
|
|
105
|
+
const captured = new Map();
|
|
106
|
+
const recorder = {
|
|
107
|
+
registerTool(name, config) {
|
|
108
|
+
const cfg = config;
|
|
109
|
+
captured.set(name, {
|
|
110
|
+
handler: () => ({ content: [] }),
|
|
111
|
+
description: cfg.description,
|
|
112
|
+
inputSchema: cfg.inputSchema,
|
|
113
|
+
annotations: cfg.annotations,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
// apimapper_rest_modules_status — registered inline in src/index.ts. Its
|
|
118
|
+
// config is replicated here verbatim (zero-arg readOnly status tool). The
|
|
119
|
+
// toolslist-size.test.ts cross-checks the captured name set, so drift
|
|
120
|
+
// between this replica and src/index.ts surfaces as a failing pin.
|
|
121
|
+
recorder.registerTool("apimapper_rest_modules_status", {
|
|
122
|
+
title: "Adapter Modules Status",
|
|
123
|
+
description: "Module-loading status for this MCP adapter (which sub-modules registered cleanly). " +
|
|
124
|
+
"For runtime connectivity + auth checks against the API Mapper REST surface, use apimapper_health.",
|
|
125
|
+
inputSchema: {},
|
|
126
|
+
annotations: { readOnlyHint: true, openWorldHint: false, title: "MCP Modules Status" },
|
|
127
|
+
});
|
|
128
|
+
// apimapper_use_profile + apimapper_list_profiles — registered via the
|
|
129
|
+
// use-profile module functions. Replaying the real registration functions
|
|
130
|
+
// captures their exact live config (description + Zod inputSchema).
|
|
131
|
+
// F-1.1 (Pass-1 consolidation): platform-portable temp path. The store is a
|
|
132
|
+
// throwaway used purely for tool-list shape capture during the measurement.
|
|
133
|
+
const store = new ProfileStore(path.join(os.tmpdir(), "__w3_toolslist_measure__"));
|
|
134
|
+
registerUseProfileTool(recorder, { store, keychain: STUB_KEYCHAIN });
|
|
135
|
+
registerListProfilesTool(recorder, { store, keychain: STUB_KEYCHAIN });
|
|
136
|
+
return captured;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Builds the full 77-tool catalog from the current build and measures the
|
|
140
|
+
* post-W3 vs pre-W3-equivalent `tools/list` payload sizes.
|
|
141
|
+
*
|
|
142
|
+
* Surface composition (verified against `gateway/essentials.ts` + `src/index.ts`):
|
|
143
|
+
* - module tools : 13 essentials + `apimapper_advanced` = 14 (on the real
|
|
144
|
+
* McpServer) + 60 advanced (gateway registry) = 74
|
|
145
|
+
* - top-level tools: rest_modules_status + use_profile + list_profiles = 3
|
|
146
|
+
* total = 77
|
|
147
|
+
*
|
|
148
|
+
* POST-W3 `tools/list` = the 14 module-real tools + the 3 top-level tools = 17.
|
|
149
|
+
* PRE-W3 flat `tools/list` = the 16 non-gateway surface tools + the 60 advanced
|
|
150
|
+
* tools = 76 (the `apimapper_advanced` gateway did not exist pre-W3).
|
|
151
|
+
*/
|
|
152
|
+
export async function measureToolsList() {
|
|
153
|
+
const server = new McpServer({
|
|
154
|
+
name: "toolslist-size-measure",
|
|
155
|
+
version: "0.0.0",
|
|
156
|
+
});
|
|
157
|
+
await loadModules(server, [apimapperRestModule]);
|
|
158
|
+
// collectModuleTools unifies the real-server essentials (incl. the gateway
|
|
159
|
+
// tool) with the captured advanced-registry tools.
|
|
160
|
+
const moduleTools = collectModuleTools(server, apimapperRestModule);
|
|
161
|
+
const topLevelTools = captureTopLevelTools();
|
|
162
|
+
const advancedRegistry = apimapperRestModule.getAdvancedRegistry();
|
|
163
|
+
const advancedNames = new Set(advancedRegistry ? advancedRegistry.keys() : []);
|
|
164
|
+
// POST-W3 surface: every tool in `tools/list` today — module-real tools that
|
|
165
|
+
// are NOT in the advanced registry (i.e. essentials + the gateway) plus the
|
|
166
|
+
// 3 top-level tools.
|
|
167
|
+
const postEntries = [];
|
|
168
|
+
for (const [name, tool] of Object.entries(moduleTools)) {
|
|
169
|
+
if (advancedNames.has(name))
|
|
170
|
+
continue; // advanced — gated behind the gateway
|
|
171
|
+
postEntries.push(toCatalogEntry(name, tool));
|
|
172
|
+
}
|
|
173
|
+
for (const [name, tool] of topLevelTools) {
|
|
174
|
+
postEntries.push(toCatalogEntry(name, tool));
|
|
175
|
+
}
|
|
176
|
+
// PRE-W3-equivalent flat surface: the post-W3 surface MINUS the gateway tool
|
|
177
|
+
// (it did not exist pre-W3) PLUS every advanced tool exposed flat.
|
|
178
|
+
const preEntries = postEntries.filter((e) => e.name !== "apimapper_advanced");
|
|
179
|
+
for (const [name, tool] of Object.entries(moduleTools)) {
|
|
180
|
+
if (!advancedNames.has(name))
|
|
181
|
+
continue; // only the advanced tools
|
|
182
|
+
preEntries.push(toCatalogEntry(name, tool));
|
|
183
|
+
}
|
|
184
|
+
const postW3 = measure(postEntries);
|
|
185
|
+
const preW3Flat = measure(preEntries);
|
|
186
|
+
const bytesSaved = preW3Flat.totalBytes - postW3.totalBytes;
|
|
187
|
+
const fractionSaved = preW3Flat.totalBytes > 0 ? bytesSaved / preW3Flat.totalBytes : 0;
|
|
188
|
+
return { postW3, preW3Flat, bytesSaved, fractionSaved };
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=toolslist-size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolslist-size.js","sourceRoot":"","sources":["../../../src/modules/apimapper/toolslist-size.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,14 +53,8 @@ export interface FlowNode {
|
|
|
53
53
|
data?: Record<string, unknown>;
|
|
54
54
|
[k: string]: unknown;
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
source: string;
|
|
59
|
-
target: string;
|
|
60
|
-
sourceHandle?: string;
|
|
61
|
-
targetHandle?: string;
|
|
62
|
-
[k: string]: unknown;
|
|
63
|
-
}
|
|
56
|
+
import type { FlowEdge } from "./node-schema.js";
|
|
57
|
+
export type { FlowEdge };
|
|
64
58
|
export interface Flow {
|
|
65
59
|
id: string;
|
|
66
60
|
name: string;
|
|
@@ -109,3 +103,24 @@ export interface LicenseStatus {
|
|
|
109
103
|
activation_count?: number;
|
|
110
104
|
max_activations?: number;
|
|
111
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Bridge a typed-domain array to the toolkit's structurally-typed table-row
|
|
108
|
+
* shape.
|
|
109
|
+
*
|
|
110
|
+
* The mcp-core `tableResult()` (and other table builders) accept
|
|
111
|
+
* `Record<string, unknown>[]` for ASCII-table serialization. Our domain
|
|
112
|
+
* interfaces (`Connection`, `Credential`, `Flow`, `LibraryItem`, …) are
|
|
113
|
+
* nominal types without an index signature, so they are not structurally
|
|
114
|
+
* assignable to `Record<string, unknown>` even though every concrete row
|
|
115
|
+
* happens to satisfy it at runtime.
|
|
116
|
+
*
|
|
117
|
+
* Rather than scatter `items as unknown as Record<string, unknown>[]`
|
|
118
|
+
* across call-sites — each one looking like a code smell — this is the
|
|
119
|
+
* single documented interop point. Call-sites stay cast-free and the
|
|
120
|
+
* narrowing decision lives in ONE place that reviewers can audit.
|
|
121
|
+
*
|
|
122
|
+
* This is NOT a license to widen domain types — fields used downstream
|
|
123
|
+
* (column `key`s in the table config) are still type-checked against the
|
|
124
|
+
* domain interface separately.
|
|
125
|
+
*/
|
|
126
|
+
export declare function toRows<T extends object>(items: readonly T[]): Record<string, unknown>[];
|
|
@@ -10,5 +10,30 @@
|
|
|
10
10
|
// - LocalSource wire fmt = camelCase (contentType) with "platform/type" id ("wordpress/posts")
|
|
11
11
|
//
|
|
12
12
|
// These types reflect the actual REST contract verified against the PHP controllers.
|
|
13
|
-
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Domain → toolkit interop bridge (F-1.2 — Pass-1 consolidation)
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Bridge a typed-domain array to the toolkit's structurally-typed table-row
|
|
18
|
+
* shape.
|
|
19
|
+
*
|
|
20
|
+
* The mcp-core `tableResult()` (and other table builders) accept
|
|
21
|
+
* `Record<string, unknown>[]` for ASCII-table serialization. Our domain
|
|
22
|
+
* interfaces (`Connection`, `Credential`, `Flow`, `LibraryItem`, …) are
|
|
23
|
+
* nominal types without an index signature, so they are not structurally
|
|
24
|
+
* assignable to `Record<string, unknown>` even though every concrete row
|
|
25
|
+
* happens to satisfy it at runtime.
|
|
26
|
+
*
|
|
27
|
+
* Rather than scatter `items as unknown as Record<string, unknown>[]`
|
|
28
|
+
* across call-sites — each one looking like a code smell — this is the
|
|
29
|
+
* single documented interop point. Call-sites stay cast-free and the
|
|
30
|
+
* narrowing decision lives in ONE place that reviewers can audit.
|
|
31
|
+
*
|
|
32
|
+
* This is NOT a license to widen domain types — fields used downstream
|
|
33
|
+
* (column `key`s in the table config) are still type-checked against the
|
|
34
|
+
* domain interface separately.
|
|
35
|
+
*/
|
|
36
|
+
export function toRows(items) {
|
|
37
|
+
return items;
|
|
38
|
+
}
|
|
14
39
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/apimapper/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,EAAE;AACF,yEAAyE;AACzE,iGAAiG;AACjG,oFAAoF;AACpF,wEAAwE;AACxE,iFAAiF;AACjF,sEAAsE;AACtE,6EAA6E;AAC7E,mGAAmG;AACnG,EAAE;AACF,qFAAqF"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/apimapper/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,EAAE;AACF,yEAAyE;AACzE,iGAAiG;AACjG,oFAAoF;AACpF,wEAAwE;AACxE,iFAAiF;AACjF,sEAAsE;AACtE,6EAA6E;AAC7E,mGAAmG;AACnG,EAAE;AACF,qFAAqF;AA8HrF,gFAAgF;AAChF,iEAAiE;AACjE,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,MAAM,CAAmB,KAAmB;IAC1D,OAAO,KAAwD,CAAC;AAClE,CAAC"}
|