@glubean/scanner 0.1.36 → 0.2.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/dist/contract-extraction.d.ts +135 -123
- package/dist/contract-extraction.d.ts.map +1 -1
- package/dist/contract-extraction.js +204 -135
- package/dist/contract-extraction.js.map +1 -1
- package/dist/index.d.ts +18 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -12
- package/dist/index.js.map +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +70 -25
- package/dist/scanner.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
* Runtime contract extraction — dynamically imports .contract.ts modules
|
|
3
3
|
* and extracts metadata from exported contract objects.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Scanner is duck-typing-only (no @glubean/sdk dependency). We recognize
|
|
6
|
+
* shapes without importing types.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
8
|
+
* Output:
|
|
9
|
+
* - NormalizedContractMeta — JSON-safe contract projection (mirrors
|
|
10
|
+
* ExtractedContractProjection from sdk, plus `exportName`)
|
|
11
|
+
* - NormalizedFlowMeta — JSON-safe flow projection (mirrors
|
|
12
|
+
* ExtractedFlowProjection, plus `exportName`)
|
|
13
|
+
*
|
|
14
|
+
* Schema conversion: anywhere scanner sees a value with `.toJSONSchema()`
|
|
15
|
+
* it invokes that method. This handles Zod schemas embedded inside
|
|
16
|
+
* adapter-defined `schemas` opaque blobs without knowing the protocol.
|
|
11
17
|
*/
|
|
12
18
|
import { pathToFileURL } from "node:url";
|
|
13
19
|
import { resolve, basename } from "node:path";
|
|
@@ -16,32 +22,41 @@ import { readdirSync, statSync } from "node:fs";
|
|
|
16
22
|
// Duck typing
|
|
17
23
|
// =============================================================================
|
|
18
24
|
/**
|
|
19
|
-
* Check if a value looks like
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
export function isHttpContract(val) {
|
|
23
|
-
return (Array.isArray(val) &&
|
|
24
|
-
typeof val.id === "string" &&
|
|
25
|
-
typeof val.endpoint === "string");
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Check if a value looks like a ProtocolContract (duck-typing).
|
|
29
|
-
* ProtocolContract extends Array<Test> and has _projection with protocol + target.
|
|
25
|
+
* Check if a value looks like a ProtocolContract.
|
|
26
|
+
* ProtocolContract extends Array<Test> and has `_projection` with protocol + target.
|
|
27
|
+
* (HTTP contracts now go through the same shape since the rewrite.)
|
|
30
28
|
*/
|
|
31
29
|
export function isProtocolContract(val) {
|
|
32
30
|
return (Array.isArray(val) &&
|
|
33
31
|
typeof val._projection === "object" &&
|
|
34
32
|
val._projection !== null &&
|
|
35
33
|
typeof val._projection.protocol === "string" &&
|
|
36
|
-
typeof val._projection.target === "string"
|
|
34
|
+
typeof val._projection.target === "string" &&
|
|
35
|
+
val._projection.protocol !== "flow");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if a value looks like a FlowContract.
|
|
39
|
+
* FlowContract extends Array<Test> and has `_flow.protocol === "flow"`.
|
|
40
|
+
*
|
|
41
|
+
* May also carry `_extracted` — a pre-computed ExtractedFlowProjection
|
|
42
|
+
* populated by the SDK's flow builder via `normalizeFlow(_flow)`. When
|
|
43
|
+
* present it is the source of truth for scanner output (full field
|
|
44
|
+
* mappings, compute reads/writes). When absent we degrade to duck-typing
|
|
45
|
+
* `_flow` directly (no lens proxy tracing in scanner since it is
|
|
46
|
+
* dependency-free).
|
|
47
|
+
*/
|
|
48
|
+
export function isFlowContract(val) {
|
|
49
|
+
return (Array.isArray(val) &&
|
|
50
|
+
typeof val._flow === "object" &&
|
|
51
|
+
val._flow !== null &&
|
|
52
|
+
val._flow.protocol === "flow");
|
|
37
53
|
}
|
|
38
54
|
// =============================================================================
|
|
39
|
-
// Schema conversion
|
|
55
|
+
// Schema conversion — embedded .toJSONSchema() recursive walk
|
|
40
56
|
// =============================================================================
|
|
41
57
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Returns null if the schema is not a Zod type or conversion fails.
|
|
58
|
+
* Convert a live schema (Zod/Valibot/etc.) to a JSON Schema plain object.
|
|
59
|
+
* Falls back to passing through or null.
|
|
45
60
|
*/
|
|
46
61
|
export function schemaToJsonSchema(schema) {
|
|
47
62
|
if (!schema || typeof schema !== "object")
|
|
@@ -56,112 +71,55 @@ export function schemaToJsonSchema(schema) {
|
|
|
56
71
|
}
|
|
57
72
|
return null;
|
|
58
73
|
}
|
|
59
|
-
// =============================================================================
|
|
60
|
-
// Mapping functions
|
|
61
|
-
// =============================================================================
|
|
62
74
|
/**
|
|
63
|
-
*
|
|
75
|
+
* Recursively walk a value converting any embedded Zod/valibot schemas
|
|
76
|
+
* (detected by `.toJSONSchema()` method) to plain JSON Schema objects.
|
|
77
|
+
* Other values pass through as-is.
|
|
78
|
+
*
|
|
79
|
+
* Used by scanner to produce JSON-safe output even when adapter didn't run
|
|
80
|
+
* `.normalize()` (e.g. when we read `_projection` directly).
|
|
64
81
|
*/
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
for (const [k, v] of Object.entries(m)) {
|
|
79
|
-
result[k] = {
|
|
80
|
-
schema: schemaToJsonSchema(v.schema),
|
|
81
|
-
description: v.description,
|
|
82
|
-
required: v.required,
|
|
83
|
-
deprecated: v.deprecated,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return result;
|
|
87
|
-
};
|
|
88
|
-
// Normalize examples: prefer meta.examples, fall back to meta.example (single)
|
|
89
|
-
let examples;
|
|
90
|
-
if (meta.examples) {
|
|
91
|
-
examples = {};
|
|
92
|
-
for (const [name, ex] of Object.entries(meta.examples)) {
|
|
93
|
-
examples[name] = { value: ex.value, summary: ex.summary, description: ex.description };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else if (meta.example !== undefined) {
|
|
97
|
-
examples = { default: { value: meta.example } };
|
|
98
|
-
}
|
|
99
|
-
cases.push({
|
|
100
|
-
key,
|
|
101
|
-
description: meta.description,
|
|
102
|
-
lifecycle,
|
|
103
|
-
severity: meta.severity ?? "warning",
|
|
104
|
-
deferredReason: meta.deferred,
|
|
105
|
-
deprecatedReason: meta.deprecated,
|
|
106
|
-
requires: meta.requires,
|
|
107
|
-
defaultRun: meta.defaultRun,
|
|
108
|
-
schemaMount: "response.body",
|
|
109
|
-
protocolExpect: meta.expectStatus != null
|
|
110
|
-
? { status: meta.expectStatus }
|
|
111
|
-
: undefined,
|
|
112
|
-
responseSchema: schemaToJsonSchema(meta.responseSchema),
|
|
113
|
-
responseHeaders: schemaToJsonSchema(meta.responseHeaders),
|
|
114
|
-
responseContentType: meta.responseContentType,
|
|
115
|
-
examples,
|
|
116
|
-
paramSchemas: mapParamMeta(meta.paramSchemas),
|
|
117
|
-
querySchemas: mapParamMeta(meta.querySchemas),
|
|
118
|
-
extensions: meta.extensions,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
82
|
+
export function deepNormalizeSchemas(value, depth = 0) {
|
|
83
|
+
if (depth > 20)
|
|
84
|
+
return value;
|
|
85
|
+
if (value == null)
|
|
86
|
+
return value;
|
|
87
|
+
if (typeof value !== "object")
|
|
88
|
+
return value;
|
|
89
|
+
// Has toJSONSchema? Convert it.
|
|
90
|
+
if (typeof value.toJSONSchema === "function") {
|
|
91
|
+
const converted = schemaToJsonSchema(value);
|
|
92
|
+
if (converted != null)
|
|
93
|
+
return converted;
|
|
94
|
+
return null;
|
|
121
95
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
security: value.security,
|
|
131
|
-
schemaMount: "response.body",
|
|
132
|
-
requestSchema: schemaToJsonSchema(value.request),
|
|
133
|
-
requestContentType: value.requestContentType,
|
|
134
|
-
requestHeaders: schemaToJsonSchema(value.requestHeaders),
|
|
135
|
-
requestExample: value.requestExample,
|
|
136
|
-
requestExamples: value.requestExamples
|
|
137
|
-
? Object.fromEntries(Object.entries(value.requestExamples).map(([k, ex]) => [
|
|
138
|
-
k,
|
|
139
|
-
{ value: ex.value, summary: ex.summary, description: ex.description },
|
|
140
|
-
]))
|
|
141
|
-
: undefined,
|
|
142
|
-
deprecated: value.deprecated,
|
|
143
|
-
extensions: value.extensions,
|
|
144
|
-
cases,
|
|
145
|
-
};
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
return value.map((v) => deepNormalizeSchemas(v, depth + 1));
|
|
98
|
+
}
|
|
99
|
+
const out = {};
|
|
100
|
+
for (const [k, v] of Object.entries(value)) {
|
|
101
|
+
out[k] = deepNormalizeSchemas(v, depth + 1);
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
146
104
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// Mapping: projection → NormalizedContractMeta
|
|
107
|
+
// =============================================================================
|
|
150
108
|
function protocolContractToNormalized(value, exportName) {
|
|
151
109
|
const proj = value._projection;
|
|
152
110
|
return {
|
|
153
|
-
id: proj.id ?? exportName,
|
|
111
|
+
id: proj.id ?? exportName,
|
|
154
112
|
exportName,
|
|
155
113
|
protocol: proj.protocol,
|
|
156
114
|
target: proj.target,
|
|
157
115
|
description: proj.description,
|
|
158
116
|
feature: proj.feature,
|
|
159
117
|
instanceName: proj.instanceName,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
118
|
+
tags: proj.tags,
|
|
119
|
+
deprecated: proj.deprecated,
|
|
120
|
+
extensions: proj.extensions,
|
|
121
|
+
schemas: proj.schemas != null ? deepNormalizeSchemas(proj.schemas) : undefined,
|
|
122
|
+
meta: proj.meta,
|
|
165
123
|
cases: (proj.cases ?? []).map((c) => ({
|
|
166
124
|
key: c.key,
|
|
167
125
|
description: c.description,
|
|
@@ -171,29 +129,122 @@ function protocolContractToNormalized(value, exportName) {
|
|
|
171
129
|
deprecatedReason: c.deprecatedReason,
|
|
172
130
|
requires: c.requires,
|
|
173
131
|
defaultRun: c.defaultRun,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
132
|
+
tags: c.tags,
|
|
133
|
+
extensions: c.extensions,
|
|
134
|
+
schemas: c.schemas != null ? deepNormalizeSchemas(c.schemas) : undefined,
|
|
135
|
+
meta: c.meta,
|
|
178
136
|
})),
|
|
179
137
|
};
|
|
180
138
|
}
|
|
139
|
+
function flowContractToNormalized(value, exportName) {
|
|
140
|
+
// Prefer the pre-computed extracted projection. The SDK's flow builder
|
|
141
|
+
// populates `_extracted` via `normalizeFlow(_flow)` — this path carries
|
|
142
|
+
// full FieldMapping data for `.step()` lenses and reads/writes for
|
|
143
|
+
// `.compute()` nodes. Scanner just attaches `exportName`.
|
|
144
|
+
if (value._extracted) {
|
|
145
|
+
const ex = value._extracted;
|
|
146
|
+
return {
|
|
147
|
+
id: ex.id,
|
|
148
|
+
exportName,
|
|
149
|
+
protocol: "flow",
|
|
150
|
+
description: ex.description,
|
|
151
|
+
tags: ex.tags,
|
|
152
|
+
extensions: ex.extensions,
|
|
153
|
+
setupDynamic: ex.setupDynamic,
|
|
154
|
+
steps: (ex.steps ?? []).map((s) => {
|
|
155
|
+
if (s.kind === "compute") {
|
|
156
|
+
return {
|
|
157
|
+
kind: "compute",
|
|
158
|
+
name: s.name,
|
|
159
|
+
reads: s.reads ?? [],
|
|
160
|
+
writes: s.writes ?? [],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
kind: "contract-call",
|
|
165
|
+
name: s.name,
|
|
166
|
+
contractId: s.contractId ?? "",
|
|
167
|
+
caseKey: s.caseKey ?? "",
|
|
168
|
+
protocol: s.protocol ?? "",
|
|
169
|
+
target: s.target ?? "",
|
|
170
|
+
inputs: s.inputs,
|
|
171
|
+
outputs: s.outputs,
|
|
172
|
+
};
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// Fallback: duck-type `_flow` directly. Lens tracing is unavailable
|
|
177
|
+
// here (scanner is dep-free); callers downstream lose FieldMappings +
|
|
178
|
+
// compute reads/writes. In practice this only fires for flows
|
|
179
|
+
// constructed outside the canonical SDK path (e.g. test fixtures).
|
|
180
|
+
const f = value._flow;
|
|
181
|
+
return {
|
|
182
|
+
id: f.id,
|
|
183
|
+
exportName,
|
|
184
|
+
protocol: "flow",
|
|
185
|
+
description: f.description,
|
|
186
|
+
tags: f.tags,
|
|
187
|
+
extensions: f.extensions,
|
|
188
|
+
setupDynamic: f.setup ? true : undefined,
|
|
189
|
+
steps: (f.steps ?? []).map((s) => {
|
|
190
|
+
if (s.kind === "compute") {
|
|
191
|
+
return { kind: "compute", name: s.name, reads: [], writes: [] };
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
kind: "contract-call",
|
|
195
|
+
name: s.name,
|
|
196
|
+
contractId: s.contract?._projection?.id ?? s.ref?.contractId ?? "",
|
|
197
|
+
caseKey: s.caseKey ?? s.ref?.caseKey ?? "",
|
|
198
|
+
protocol: s.ref?.protocol ?? "",
|
|
199
|
+
target: s.ref?.target ?? "",
|
|
200
|
+
};
|
|
201
|
+
}),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// =============================================================================
|
|
205
|
+
// FlowBuilder auto-build
|
|
206
|
+
// =============================================================================
|
|
207
|
+
/**
|
|
208
|
+
* If `val` is an unbuilt FlowBuilder (from `contract.flow(id).step(...)`
|
|
209
|
+
* without a trailing `.build()`), call `.build()` to resolve it to a
|
|
210
|
+
* FlowContract. Scanner is dep-free, so we duck-type the builder shape.
|
|
211
|
+
*/
|
|
212
|
+
function autoBuildFlowBuilder(val) {
|
|
213
|
+
if (typeof val === "object" &&
|
|
214
|
+
val !== null &&
|
|
215
|
+
val.__glubean_type === "flow-builder" &&
|
|
216
|
+
typeof val.build === "function") {
|
|
217
|
+
try {
|
|
218
|
+
return val.build();
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return val;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return val;
|
|
225
|
+
}
|
|
181
226
|
// =============================================================================
|
|
182
227
|
// File-level extraction
|
|
183
228
|
// =============================================================================
|
|
184
229
|
/**
|
|
185
|
-
* Extract contracts from a single file by dynamic import.
|
|
186
|
-
*
|
|
230
|
+
* Extract contracts + flows from a single file by dynamic import.
|
|
231
|
+
* One file's import failure does not block others.
|
|
187
232
|
*/
|
|
188
233
|
export async function extractContractFromFile(filePath) {
|
|
189
234
|
const contracts = [];
|
|
235
|
+
const flows = [];
|
|
190
236
|
const errors = [];
|
|
191
237
|
const absolutePath = resolve(filePath);
|
|
192
238
|
try {
|
|
193
239
|
const mod = await import(pathToFileURL(absolutePath).href);
|
|
194
|
-
for (const [exportName,
|
|
195
|
-
|
|
196
|
-
|
|
240
|
+
for (const [exportName, rawValue] of Object.entries(mod)) {
|
|
241
|
+
// Auto-resolve unbuilt FlowBuilder exports. User code like
|
|
242
|
+
// `export const signup = contract.flow(...).step(...)` returns a
|
|
243
|
+
// FlowBuilder (not a FlowContract) because `.build()` is optional.
|
|
244
|
+
// Scanner must build it to reach the `_flow` projection.
|
|
245
|
+
const value = autoBuildFlowBuilder(rawValue);
|
|
246
|
+
if (isFlowContract(value)) {
|
|
247
|
+
flows.push(flowContractToNormalized(value, exportName));
|
|
197
248
|
}
|
|
198
249
|
else if (isProtocolContract(value)) {
|
|
199
250
|
contracts.push(protocolContractToNormalized(value, exportName));
|
|
@@ -204,15 +255,15 @@ export async function extractContractFromFile(filePath) {
|
|
|
204
255
|
const message = err instanceof Error ? err.message : String(err);
|
|
205
256
|
errors.push({ file: absolutePath, error: message });
|
|
206
257
|
}
|
|
207
|
-
return { contracts, errors };
|
|
258
|
+
return { contracts, flows: flows.length > 0 ? flows : undefined, errors };
|
|
208
259
|
}
|
|
209
260
|
// =============================================================================
|
|
210
261
|
// Project-level extraction
|
|
211
262
|
// =============================================================================
|
|
212
263
|
/**
|
|
213
|
-
* Find all .contract.{ts,js,mjs} files in a directory tree.
|
|
264
|
+
* Find all .contract.{ts,js,mjs} and .flow.{ts,js,mjs} files in a directory tree.
|
|
214
265
|
*/
|
|
215
|
-
function
|
|
266
|
+
function findContractAndFlowFiles(dir) {
|
|
216
267
|
const files = [];
|
|
217
268
|
const walk = (d) => {
|
|
218
269
|
for (const entry of readdirSync(d)) {
|
|
@@ -221,28 +272,46 @@ function findContractFiles(dir) {
|
|
|
221
272
|
continue;
|
|
222
273
|
if (statSync(full).isDirectory())
|
|
223
274
|
walk(full);
|
|
224
|
-
else
|
|
225
|
-
|
|
275
|
+
else {
|
|
276
|
+
const base = basename(entry);
|
|
277
|
+
if (base.includes(".contract.") || base.includes(".flow.")) {
|
|
278
|
+
files.push(full);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
226
281
|
}
|
|
227
282
|
};
|
|
228
283
|
walk(dir);
|
|
229
284
|
return files;
|
|
230
285
|
}
|
|
231
286
|
/**
|
|
232
|
-
* Extract contracts from all
|
|
233
|
-
* Each file is imported independently — one file's failure does not block others.
|
|
287
|
+
* Extract contracts + flows from all recognized files in a project.
|
|
234
288
|
*/
|
|
235
289
|
export async function extractContractsFromProject(dir) {
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
290
|
+
const files = findContractAndFlowFiles(dir);
|
|
291
|
+
if (files.length === 0)
|
|
238
292
|
return { contracts: [], errors: [] };
|
|
239
293
|
const allContracts = [];
|
|
294
|
+
const allFlows = [];
|
|
240
295
|
const allErrors = [];
|
|
241
|
-
for (const filePath of
|
|
242
|
-
const { contracts, errors } = await extractContractFromFile(filePath);
|
|
296
|
+
for (const filePath of files) {
|
|
297
|
+
const { contracts, flows, errors } = await extractContractFromFile(filePath);
|
|
243
298
|
allContracts.push(...contracts);
|
|
299
|
+
if (flows)
|
|
300
|
+
allFlows.push(...flows);
|
|
244
301
|
allErrors.push(...errors);
|
|
245
302
|
}
|
|
246
|
-
return {
|
|
303
|
+
return {
|
|
304
|
+
contracts: allContracts,
|
|
305
|
+
flows: allFlows.length > 0 ? allFlows : undefined,
|
|
306
|
+
errors: allErrors,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
// =============================================================================
|
|
310
|
+
// Backward-compat: isHttpContract — removed permanently in v0.2.
|
|
311
|
+
// =============================================================================
|
|
312
|
+
/** @deprecated Removed in v0.2 — HTTP now goes through isProtocolContract. */
|
|
313
|
+
export function isHttpContract(_val) {
|
|
314
|
+
throw new Error("isHttpContract() was removed in v0.2. HTTP contracts now use the unified " +
|
|
315
|
+
"isProtocolContract() shape (_projection.protocol === 'http').");
|
|
247
316
|
}
|
|
248
317
|
//# sourceMappingURL=contract-extraction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-extraction.js","sourceRoot":"","sources":["../src/contract-extraction.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"contract-extraction.js","sourceRoot":"","sources":["../src/contract-extraction.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,13 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Scanner for Glubean test files.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* - **Static analysis**: Uses regex patterns to extract metadata
|
|
8
|
-
* without importing files. Works everywhere.
|
|
9
|
-
* - **Runtime extraction**: Imports test files via tsx subprocess and reads
|
|
10
|
-
* metadata from the SDK's global registry (100% accurate).
|
|
6
|
+
* Two independent extraction paths:
|
|
11
7
|
*
|
|
12
|
-
*
|
|
8
|
+
* - **Static analysis (tests)** — regex-based, no `import()`. Discovers
|
|
9
|
+
* `test()` / `test.each()` / `test.pick()` call sites and returns case
|
|
10
|
+
* metadata from source alone. Always safe; never executes user code.
|
|
11
|
+
*
|
|
12
|
+
* - **Runtime extraction (contracts + flows)** — dynamic `import()` of
|
|
13
|
+
* `.contract.ts` and `.flow.ts` files. Recognizes `ProtocolContract`
|
|
14
|
+
* (via `_projection.protocol`) and `FlowContract` (via
|
|
15
|
+
* `_flow.protocol === "flow"`). Required because contracts/flows
|
|
16
|
+
* encode schemas and cases as runtime object shapes.
|
|
17
|
+
*
|
|
18
|
+
* @example Static analysis
|
|
13
19
|
* ```ts
|
|
14
20
|
* import { createScanner } from "@glubean/scanner";
|
|
15
21
|
*
|
|
@@ -18,12 +24,11 @@
|
|
|
18
24
|
* console.log(`Found ${result.testCount} tests`);
|
|
19
25
|
* ```
|
|
20
26
|
*
|
|
21
|
-
* @example
|
|
27
|
+
* @example Runtime contract extraction
|
|
22
28
|
* ```ts
|
|
23
|
-
* import {
|
|
29
|
+
* import { extractContractsFromProject } from "@glubean/scanner";
|
|
24
30
|
*
|
|
25
|
-
* const
|
|
26
|
-
* const exports = extractFromSource(content);
|
|
31
|
+
* const { contracts, flows, errors } = await extractContractsFromProject(".");
|
|
27
32
|
* ```
|
|
28
33
|
*/
|
|
29
34
|
export { isSpecVersionSupported, SPEC_VERSION, SUPPORTED_SPEC_VERSIONS } from "./spec.js";
|
|
@@ -32,8 +37,9 @@ export { Scanner } from "./scanner.js";
|
|
|
32
37
|
export type { FileSystem, Hasher, MetadataExtractor } from "./scanner.js";
|
|
33
38
|
export { createStaticExtractor, extractAliasesFromSource, extractContractCases, extractFromSource, isGlubeanFile } from "./extractor-static.js";
|
|
34
39
|
export type { ContractStaticMeta, ContractCaseStaticMeta } from "./extractor-static.js";
|
|
35
|
-
export { extractContractFromFile, extractContractsFromProject,
|
|
36
|
-
|
|
40
|
+
export { extractContractFromFile, extractContractsFromProject, isProtocolContract, isFlowContract, isHttpContract, // deprecated-throw, kept for diagnostic
|
|
41
|
+
schemaToJsonSchema, deepNormalizeSchemas, } from "./contract-extraction.js";
|
|
42
|
+
export type { NormalizedContractMeta, NormalizedCaseMeta, NormalizedExample, NormalizedParamMeta, NormalizedFlowMeta, NormalizedFlowStep, NormalizedFieldMapping, ExtractedContract, ExtractionResult, CaseLifecycle, CaseSeverity, CaseRequires, CaseDefaultRun, } from "./contract-extraction.js";
|
|
37
43
|
export { nodeFs, nodeHasher } from "./fs.js";
|
|
38
44
|
import { Scanner } from "./scanner.js";
|
|
39
45
|
import type { ScanOptions, ScanResult, ValidationResult } from "./types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAG1F,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGlH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChJ,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,kBAAkB,EAClB,cAAc,EACd,cAAc,EAAE,wCAAwC;AACxD,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAU5E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAE/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAE5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,WAAW,GAAE,MAAqB,GAAG,OAAO,CAGzE"}
|
package/dist/index.js
CHANGED
|
@@ -3,13 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Scanner for Glubean test files.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* - **Static analysis**: Uses regex patterns to extract metadata
|
|
8
|
-
* without importing files. Works everywhere.
|
|
9
|
-
* - **Runtime extraction**: Imports test files via tsx subprocess and reads
|
|
10
|
-
* metadata from the SDK's global registry (100% accurate).
|
|
6
|
+
* Two independent extraction paths:
|
|
11
7
|
*
|
|
12
|
-
*
|
|
8
|
+
* - **Static analysis (tests)** — regex-based, no `import()`. Discovers
|
|
9
|
+
* `test()` / `test.each()` / `test.pick()` call sites and returns case
|
|
10
|
+
* metadata from source alone. Always safe; never executes user code.
|
|
11
|
+
*
|
|
12
|
+
* - **Runtime extraction (contracts + flows)** — dynamic `import()` of
|
|
13
|
+
* `.contract.ts` and `.flow.ts` files. Recognizes `ProtocolContract`
|
|
14
|
+
* (via `_projection.protocol`) and `FlowContract` (via
|
|
15
|
+
* `_flow.protocol === "flow"`). Required because contracts/flows
|
|
16
|
+
* encode schemas and cases as runtime object shapes.
|
|
17
|
+
*
|
|
18
|
+
* @example Static analysis
|
|
13
19
|
* ```ts
|
|
14
20
|
* import { createScanner } from "@glubean/scanner";
|
|
15
21
|
*
|
|
@@ -18,12 +24,11 @@
|
|
|
18
24
|
* console.log(`Found ${result.testCount} tests`);
|
|
19
25
|
* ```
|
|
20
26
|
*
|
|
21
|
-
* @example
|
|
27
|
+
* @example Runtime contract extraction
|
|
22
28
|
* ```ts
|
|
23
|
-
* import {
|
|
29
|
+
* import { extractContractsFromProject } from "@glubean/scanner";
|
|
24
30
|
*
|
|
25
|
-
* const
|
|
26
|
-
* const exports = extractFromSource(content);
|
|
31
|
+
* const { contracts, flows, errors } = await extractContractsFromProject(".");
|
|
27
32
|
* ```
|
|
28
33
|
*/
|
|
29
34
|
// Re-export spec constants
|
|
@@ -32,8 +37,9 @@ export { isSpecVersionSupported, SPEC_VERSION, SUPPORTED_SPEC_VERSIONS } from ".
|
|
|
32
37
|
export { Scanner } from "./scanner.js";
|
|
33
38
|
// Re-export static analysis extractor
|
|
34
39
|
export { createStaticExtractor, extractAliasesFromSource, extractContractCases, extractFromSource, isGlubeanFile } from "./extractor-static.js";
|
|
35
|
-
// Re-export runtime contract extraction
|
|
36
|
-
export { extractContractFromFile, extractContractsFromProject,
|
|
40
|
+
// Re-export runtime contract + flow extraction
|
|
41
|
+
export { extractContractFromFile, extractContractsFromProject, isProtocolContract, isFlowContract, isHttpContract, // deprecated-throw, kept for diagnostic
|
|
42
|
+
schemaToJsonSchema, deepNormalizeSchemas, } from "./contract-extraction.js";
|
|
37
43
|
// Re-export file system implementations
|
|
38
44
|
export { nodeFs, nodeHasher } from "./fs.js";
|
|
39
45
|
// Imports for convenience functions
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAK1F,yCAAyC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,sCAAsC;AACtC,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGhJ,+CAA+C;AAC/C,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,kBAAkB,EAClB,cAAc,EACd,cAAc,EAAE,wCAAwC;AACxD,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAiBlC,wCAAwC;AACxC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE7C,oCAAoC;AACpC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,6CAA6C;AAC7C,MAAM,cAAc,GAAG,IAAI,OAAO,CAChC,MAAM,EACN,UAAU,EACV,YAAY,EACZ,qBAAqB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CACvD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,OAAqB;IACrD,OAAO,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,cAAsB,YAAY;IAC9D,MAAM,SAAS,GAAG,qBAAqB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACzE,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/scanner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAY,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElG,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,wBAAwB;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,uCAAuC;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7C,sDAAsD;IACtD,IAAI,CACF,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,GACpD,aAAa,CAAC,MAAM,CAAC,CAAC;IACzB,yBAAyB;IACzB,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/C,+BAA+B;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,8BAA8B;AAC9B,MAAM,WAAW,MAAM;IACrB,8DAA8D;IAC9D,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;AAqBlG;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAoB;gBAG7C,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,MAAqB,EAClC,SAAS,CAAC,EAAE,iBAAiB;IAiB/B;;;OAGG;YACW,cAAc;IAmB5B;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwEtD;;;;;;OAMG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;CAqMxE"}
|