@bleedingdev/modern-js-code-tools 3.9.0-ultramodern.1 → 3.9.0-ultramodern.10

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.
Files changed (29) hide show
  1. package/bin/modern-api-check-files.mjs +4 -0
  2. package/bin/modern-api-check.mjs +4 -0
  3. package/dist/cjs/cli/microvertical-api-check.cjs +71 -0
  4. package/dist/cjs/cli/oxlint.cjs +9 -5
  5. package/dist/cjs/microvertical-api-baseline.cjs +677 -0
  6. package/dist/cjs/microvertical-api-boundary.cjs +507 -0
  7. package/dist/cjs/microvertical-api-owner.cjs +217 -0
  8. package/dist/cjs/oxlint-plugin/rules/strict-effect-api-boundaries.cjs +7 -5
  9. package/dist/cjs/strict-effect-runtime.cjs +411 -0
  10. package/dist/esm/cli/microvertical-api-check.js +33 -0
  11. package/dist/esm/cli/oxlint.js +10 -6
  12. package/dist/esm/microvertical-api-baseline.js +621 -0
  13. package/dist/esm/microvertical-api-boundary.js +449 -0
  14. package/dist/esm/microvertical-api-owner.js +162 -0
  15. package/dist/esm/oxlint-plugin/rules/strict-effect-api-boundaries.js +7 -5
  16. package/dist/esm/strict-effect-runtime.js +358 -0
  17. package/dist/esm-node/cli/microvertical-api-check.js +34 -0
  18. package/dist/esm-node/cli/oxlint.js +10 -6
  19. package/dist/esm-node/microvertical-api-baseline.js +622 -0
  20. package/dist/esm-node/microvertical-api-boundary.js +450 -0
  21. package/dist/esm-node/microvertical-api-owner.js +163 -0
  22. package/dist/esm-node/oxlint-plugin/rules/strict-effect-api-boundaries.js +7 -5
  23. package/dist/esm-node/strict-effect-runtime.js +359 -0
  24. package/dist/types/cli/microvertical-api-check.d.ts +1 -0
  25. package/dist/types/microvertical-api-baseline.d.ts +28 -0
  26. package/dist/types/microvertical-api-boundary.d.ts +32 -0
  27. package/dist/types/microvertical-api-owner.d.ts +6 -0
  28. package/dist/types/strict-effect-runtime.d.ts +10 -0
  29. package/package.json +25 -4
@@ -0,0 +1,677 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, getters, values)=>{
14
+ var define = (defs, kind)=>{
15
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
16
+ enumerable: true,
17
+ [kind]: defs[key]
18
+ });
19
+ };
20
+ define(getters, "get");
21
+ define(values, "value");
22
+ };
23
+ })();
24
+ (()=>{
25
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
26
+ })();
27
+ (()=>{
28
+ __webpack_require__.r = (exports1)=>{
29
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
30
+ value: 'Module'
31
+ });
32
+ Object.defineProperty(exports1, '__esModule', {
33
+ value: true
34
+ });
35
+ };
36
+ })();
37
+ var __webpack_exports__ = {};
38
+ __webpack_require__.r(__webpack_exports__);
39
+ __webpack_require__.d(__webpack_exports__, {
40
+ configuredMicroVerticalApiStem: ()=>configuredMicroVerticalApiStem,
41
+ consumerParserPlugins: ()=>consumerParserPlugins,
42
+ microVerticalApiBaselineViolation: ()=>microVerticalApiBaselineViolation
43
+ });
44
+ const external_node_fs_namespaceObject = require("node:fs");
45
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
46
+ const external_node_path_namespaceObject = require("node:path");
47
+ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
48
+ const parser_namespaceObject = require("@babel/parser");
49
+ const traverse_namespaceObject = require("@babel/traverse");
50
+ var traverse_default = /*#__PURE__*/ __webpack_require__.n(traverse_namespaceObject);
51
+ const types_namespaceObject = require("@babel/types");
52
+ const external_microvertical_api_owner_cjs_namespaceObject = require("./microvertical-api-owner.cjs");
53
+ const consumerParserPlugins = (filePath)=>filePath.endsWith('.tsx') || filePath.endsWith('.jsx') ? [
54
+ "typescript",
55
+ 'jsx'
56
+ ] : [
57
+ "typescript"
58
+ ];
59
+ class ConsumerSyntaxError extends Error {
60
+ }
61
+ class ConsumerValidationHub extends traverse_namespaceObject.Hub {
62
+ buildError(_node, message) {
63
+ return new ConsumerSyntaxError(message);
64
+ }
65
+ }
66
+ function parseConsumer(filePath) {
67
+ if (external_node_fs_default().statSync(filePath).size > 1000000) throw new Error(`${filePath}: consumer source exceeds 1 MB analysis budget`);
68
+ let file;
69
+ try {
70
+ file = (0, parser_namespaceObject.parse)(external_node_fs_default().readFileSync(filePath, 'utf8'), {
71
+ sourceType: 'module',
72
+ sourceFilename: filePath,
73
+ plugins: consumerParserPlugins(filePath)
74
+ });
75
+ } catch (error) {
76
+ if ('object' == typeof error && null !== error && 'code' in error && 'BABEL_PARSER_SYNTAX_ERROR' === error.code) throw new ConsumerSyntaxError(error instanceof Error ? error.message : String(error));
77
+ throw error;
78
+ }
79
+ const program = traverse_namespaceObject.NodePath.get({
80
+ hub: new ConsumerValidationHub(),
81
+ parentPath: void 0,
82
+ parent: file,
83
+ container: file,
84
+ key: 'program'
85
+ });
86
+ program.setContext();
87
+ traverse_default()(file, {
88
+ AssignmentExpression (p) {
89
+ throw new ConsumerSyntaxError(`contract bindings must be immutable at ${p.node.start}`);
90
+ },
91
+ UpdateExpression (p) {
92
+ throw new ConsumerSyntaxError(`contract bindings must be immutable at ${p.node.start}`);
93
+ },
94
+ TSModuleDeclaration () {
95
+ throw new ConsumerSyntaxError('contract bindings must not be merged with namespaces');
96
+ }
97
+ }, program.scope, void 0, program);
98
+ return file;
99
+ }
100
+ const camelCaseStem = (stem)=>stem.replaceAll(/-([a-z0-9])/gu, (_match, letter)=>letter.toUpperCase());
101
+ const pascalCaseStem = (stem)=>{
102
+ const camelStem = camelCaseStem(stem);
103
+ return `${camelStem.slice(0, 1).toUpperCase()}${camelStem.slice(1)}`;
104
+ };
105
+ const identifierName = (node)=>void 0 !== node && types_namespaceObject.isIdentifier(node) ? node.name : void 0;
106
+ const propertyName = (node)=>{
107
+ if (void 0 !== node && (types_namespaceObject.isIdentifier(node) || types_namespaceObject.isStringLiteral(node) || types_namespaceObject.isNumericLiteral(node))) return types_namespaceObject.isIdentifier(node) ? node.name : String(node.value);
108
+ };
109
+ const accessPath = (node)=>{
110
+ if (types_namespaceObject.isIdentifier(node)) return [
111
+ node.name
112
+ ];
113
+ if (types_namespaceObject.isMemberExpression(node) && !node.computed && types_namespaceObject.isIdentifier(node.property)) {
114
+ const parent = accessPath(node.object);
115
+ return void 0 === parent ? void 0 : [
116
+ ...parent,
117
+ node.property.name
118
+ ];
119
+ }
120
+ };
121
+ const isAccessPath = (node, expected)=>accessPath(node)?.join('.') === expected.join('.');
122
+ const unwrapExpression = (expression)=>{
123
+ let current = expression;
124
+ while(types_namespaceObject.isTSAsExpression(current) || types_namespaceObject.isParenthesizedExpression(current) || types_namespaceObject.isTSSatisfiesExpression(current))current = current.expression;
125
+ return current;
126
+ };
127
+ const stringLiteral = (expression)=>{
128
+ if (null == expression) return;
129
+ const unwrapped = unwrapExpression(expression);
130
+ return types_namespaceObject.isStringLiteral(unwrapped) ? unwrapped.value : void 0;
131
+ };
132
+ const numericLiteral = (expression)=>{
133
+ if (null == expression) return;
134
+ const unwrapped = unwrapExpression(expression);
135
+ return types_namespaceObject.isNumericLiteral(unwrapped) ? Number(unwrapped.value) : void 0;
136
+ };
137
+ const callExpression = (expression, callee)=>{
138
+ if (null == expression) return;
139
+ const unwrapped = unwrapExpression(expression);
140
+ return types_namespaceObject.isCallExpression(unwrapped) && isAccessPath(unwrapped.callee, callee) ? unwrapped : void 0;
141
+ };
142
+ const localConst = (sourceFile, name)=>{
143
+ for (const item of sourceFile.program.body){
144
+ const statement = types_namespaceObject.isExportNamedDeclaration(item) ? item.declaration : item;
145
+ if (!types_namespaceObject.isVariableDeclaration(statement) || 'const' !== statement.kind) continue;
146
+ const matches = statement.declarations.filter((declaration)=>types_namespaceObject.isIdentifier(declaration.id, {
147
+ name
148
+ }));
149
+ if (1 === matches.length) return matches[0];
150
+ }
151
+ };
152
+ const exportedConst = (sourceFile, name)=>{
153
+ for (const statement of sourceFile.program.body)if (types_namespaceObject.isExportNamedDeclaration(statement) && 'type' !== statement.exportKind) {
154
+ if (types_namespaceObject.isVariableDeclaration(statement.declaration) && 'const' === statement.declaration.kind) {
155
+ const declaration = statement.declaration.declarations.find((value)=>types_namespaceObject.isIdentifier(value.id, {
156
+ name
157
+ }));
158
+ if (declaration) return declaration;
159
+ }
160
+ if (!statement.source && statement.specifiers.some((value)=>types_namespaceObject.isExportSpecifier(value) && 'type' !== value.exportKind && types_namespaceObject.isIdentifier(value.local, {
161
+ name
162
+ }) && types_namespaceObject.isIdentifier(value.exported, {
163
+ name
164
+ }))) return localConst(sourceFile, name);
165
+ }
166
+ };
167
+ const resolveRelativeModulePath = (fromPath, specifier)=>{
168
+ if (!/^\.\.?\//u.test(specifier)) return;
169
+ const resolved = external_node_path_default().resolve(external_node_path_default().dirname(fromPath), specifier);
170
+ const stem = resolved.replace(/\.(?:[cm]?[jt]sx?)$/u, '');
171
+ for (const candidate of [
172
+ `${stem}.ts`,
173
+ `${stem}.tsx`,
174
+ external_node_path_default().join(stem, 'index.ts'),
175
+ external_node_path_default().join(stem, 'index.tsx')
176
+ ])if (external_node_fs_default().existsSync(candidate) && external_node_fs_default().statSync(candidate).isFile()) return candidate;
177
+ };
178
+ const createModuleReader = (root)=>{
179
+ const modules = new Map([
180
+ [
181
+ root.path,
182
+ root
183
+ ]
184
+ ]);
185
+ return (filePath)=>{
186
+ if (modules.has(filePath)) return modules.get(filePath);
187
+ if (modules.size >= 256) return;
188
+ let module;
189
+ try {
190
+ module = {
191
+ file: parseConsumer(filePath),
192
+ path: filePath
193
+ };
194
+ } catch {
195
+ module = void 0;
196
+ }
197
+ modules.set(filePath, module);
198
+ return module;
199
+ };
200
+ };
201
+ const importedBinding = (module, name)=>{
202
+ for (const statement of module.file.program.body)if (types_namespaceObject.isImportDeclaration(statement) && 'type' !== statement.importKind) {
203
+ for (const specifier of statement.specifiers)if (types_namespaceObject.isIdentifier(specifier.local, {
204
+ name
205
+ })) {
206
+ if (types_namespaceObject.isImportSpecifier(specifier) && 'type' !== specifier.importKind) return {
207
+ imported: propertyName(specifier.imported) ?? name,
208
+ specifier: statement.source.value
209
+ };
210
+ if (types_namespaceObject.isImportDefaultSpecifier(specifier)) return {
211
+ imported: 'default',
212
+ specifier: statement.source.value
213
+ };
214
+ }
215
+ }
216
+ };
217
+ const reexportedBinding = (module, name)=>{
218
+ for (const statement of module.file.program.body){
219
+ if (!types_namespaceObject.isExportNamedDeclaration(statement) || 'type' === statement.exportKind) continue;
220
+ const specifier = statement.specifiers.find((value)=>types_namespaceObject.isExportSpecifier(value) && 'type' !== value.exportKind && propertyName(value.exported) === name);
221
+ if (void 0 !== specifier && types_namespaceObject.isExportSpecifier(specifier)) return {
222
+ local: specifier.local.name,
223
+ ...statement.source ? {
224
+ specifier: statement.source.value
225
+ } : {}
226
+ };
227
+ }
228
+ };
229
+ const defaultExport = (module)=>{
230
+ for (const statement of module.file.program.body){
231
+ if (!types_namespaceObject.isExportDefaultDeclaration(statement)) continue;
232
+ const declaration = statement.declaration;
233
+ if (types_namespaceObject.isIdentifier(declaration)) return declaration.name;
234
+ return types_namespaceObject.isExpression(declaration) ? declaration : void 0;
235
+ }
236
+ };
237
+ const resolveBinding = (module, name, scope, readModule, seen)=>{
238
+ const key = `${scope}:${module.path}#${name}`;
239
+ if (seen.has(key) || seen.size >= 512) return;
240
+ seen.add(key);
241
+ const declaration = 'export' === scope ? exportedConst(module.file, name) : localConst(module.file, name);
242
+ if (declaration?.init) return {
243
+ expression: declaration.init,
244
+ module
245
+ };
246
+ const throughModule = (specifier, imported)=>{
247
+ const resolvedPath = resolveRelativeModulePath(module.path, specifier);
248
+ const target = void 0 === resolvedPath ? void 0 : readModule(resolvedPath);
249
+ return void 0 === target ? void 0 : resolveBinding(target, imported, 'export', readModule, seen);
250
+ };
251
+ if ('local' === scope) {
252
+ const imported = importedBinding(module, name);
253
+ return void 0 === imported ? void 0 : throughModule(imported.specifier, imported.imported);
254
+ }
255
+ if ('default' === name) {
256
+ const exported = defaultExport(module);
257
+ if ('string' == typeof exported) return resolveBinding(module, exported, 'local', readModule, seen);
258
+ return void 0 === exported ? void 0 : {
259
+ expression: exported,
260
+ module
261
+ };
262
+ }
263
+ const reexported = reexportedBinding(module, name);
264
+ if (void 0 !== reexported) return void 0 === reexported.specifier ? resolveBinding(module, reexported.local, 'local', readModule, seen) : throughModule(reexported.specifier, reexported.local);
265
+ for (const statement of module.file.program.body){
266
+ if (!types_namespaceObject.isExportAllDeclaration(statement) || 'type' === statement.exportKind) continue;
267
+ const resolved = throughModule(statement.source.value, name);
268
+ if (void 0 !== resolved) return resolved;
269
+ }
270
+ };
271
+ const objectLiteral = (expression)=>{
272
+ if (null == expression) return;
273
+ const unwrapped = unwrapExpression(expression);
274
+ return types_namespaceObject.isObjectExpression(unwrapped) ? unwrapped : void 0;
275
+ };
276
+ const propertyAssignments = (properties)=>{
277
+ const assignments = new Map();
278
+ for (const property of properties){
279
+ if (!types_namespaceObject.isObjectProperty(property) || property.computed || property.shorthand) return;
280
+ const name = propertyName(property.key);
281
+ if (void 0 === name || assignments.has(name)) return;
282
+ assignments.set(name, property);
283
+ }
284
+ return assignments;
285
+ };
286
+ const exactCall = (expression, callee, argumentCount)=>{
287
+ const call = callExpression(expression, callee);
288
+ return call?.arguments.length === argumentCount ? call : void 0;
289
+ };
290
+ const sharedSchemaObject = (declaration, sharedSchemaName, protectedFields)=>{
291
+ if (declaration?.init == null) return;
292
+ const initializer = unwrapExpression(declaration.init);
293
+ if (types_namespaceObject.isIdentifier(initializer) && initializer.name === sharedSchemaName) return {
294
+ assignments: new Map(),
295
+ identity: true
296
+ };
297
+ const struct = exactCall(initializer, [
298
+ 'Schema',
299
+ 'Struct'
300
+ ], 1);
301
+ const schemaObject = objectLiteral(struct?.arguments[0]);
302
+ if (void 0 === schemaObject) return;
303
+ const spreads = schemaObject.properties.filter(types_namespaceObject.isSpreadElement);
304
+ const assignments = propertyAssignments(schemaObject.properties.filter((property)=>!types_namespaceObject.isSpreadElement(property)));
305
+ if (1 !== spreads.length || !spreads.every((spread)=>isAccessPath(spread.argument, [
306
+ sharedSchemaName,
307
+ 'fields'
308
+ ])) || void 0 === assignments || protectedFields.some((field)=>assignments.has(field))) return;
309
+ return {
310
+ assignments,
311
+ identity: false
312
+ };
313
+ };
314
+ const directCallChain = (expression)=>{
315
+ if (null == expression) return;
316
+ let current = unwrapExpression(expression);
317
+ const methods = [];
318
+ while(types_namespaceObject.isCallExpression(current) && types_namespaceObject.isMemberExpression(current.callee) && !current.callee.computed && types_namespaceObject.isIdentifier(current.callee.property) && !types_namespaceObject.isIdentifier(current.callee.object)){
319
+ methods.unshift({
320
+ arguments: current.arguments,
321
+ name: current.callee.property.name
322
+ });
323
+ current = unwrapExpression(current.callee.object);
324
+ }
325
+ if (!types_namespaceObject.isCallExpression(current)) return;
326
+ return {
327
+ base: current,
328
+ methods
329
+ };
330
+ };
331
+ const brandedStringSchemaIsExact = (declaration, brand)=>{
332
+ const initializer = declaration?.init;
333
+ if (null == initializer) return false;
334
+ const pipeCall = unwrapExpression(initializer);
335
+ if (!types_namespaceObject.isCallExpression(pipeCall) || !types_namespaceObject.isMemberExpression(pipeCall.callee) || pipeCall.callee.computed || !types_namespaceObject.isIdentifier(pipeCall.callee.property, {
336
+ name: 'pipe'
337
+ }) || !isAccessPath(pipeCall.callee.object, [
338
+ 'Schema',
339
+ 'String'
340
+ ]) || 1 !== pipeCall.arguments.length) return false;
341
+ const brandCall = exactCall(pipeCall.arguments[0], [
342
+ 'Schema',
343
+ 'brand'
344
+ ], 1);
345
+ return stringLiteral(brandCall?.arguments[0]) === brand;
346
+ };
347
+ const importedRuntimeNames = (statement, expectedPackage)=>{
348
+ if (!types_namespaceObject.isImportDeclaration(statement) || statement.source.value !== expectedPackage || 'type' === statement.importKind) return [];
349
+ return statement.specifiers.flatMap((value)=>types_namespaceObject.isImportSpecifier(value) && 'type' !== value.importKind && types_namespaceObject.isIdentifier(value.imported) && value.imported.name === value.local.name ? [
350
+ value.local.name
351
+ ] : []);
352
+ };
353
+ const importsExactBindings = (sourceFile, expectedPackage, expectedBindings)=>{
354
+ const names = new Set(sourceFile.program.body.flatMap((statement)=>importedRuntimeNames(statement, expectedPackage)));
355
+ return expectedBindings.every((name)=>names.has(name));
356
+ };
357
+ const baselineBindings = [
358
+ 'MicroVerticalBuildMarkerSchema',
359
+ 'MicroVerticalReadinessSchema',
360
+ 'createMicroVerticalOperationContext'
361
+ ];
362
+ const importsSharedBaselinePrimitives = (sourceFile, expectedPackage)=>importsExactBindings(sourceFile, expectedPackage, baselineBindings);
363
+ const singleAddedArgument = (expression, factory, names)=>{
364
+ const chain = directCallChain(expression);
365
+ if (void 0 === chain || !isAccessPath(chain.base.callee, factory)) return;
366
+ const [method] = chain.methods;
367
+ if (1 !== chain.base.arguments.length || !names.includes(stringLiteral(chain.base.arguments[0]) ?? '') || 1 !== chain.methods.length || method?.name !== 'add' || 1 !== method.arguments.length) return;
368
+ return method.arguments[0];
369
+ };
370
+ const foundationIsExact = (declaration, stem, readinessSchemaName)=>{
371
+ const group = singleAddedArgument(declaration?.init, [
372
+ 'HttpApi',
373
+ 'make'
374
+ ], [
375
+ `${pascalCaseStem(stem)}FoundationApi`,
376
+ `${pascalCaseStem(stem)}ApiFoundation`
377
+ ]);
378
+ const endpointExpression = singleAddedArgument(group, [
379
+ 'HttpApiGroup',
380
+ 'make'
381
+ ], [
382
+ 'foundation'
383
+ ]);
384
+ const endpoint = exactCall(endpointExpression, [
385
+ 'HttpApiEndpoint',
386
+ 'get'
387
+ ], 3);
388
+ const endpointOptions = objectLiteral(endpoint?.arguments[2]);
389
+ const endpointProperties = void 0 === endpointOptions ? void 0 : propertyAssignments(endpointOptions.properties);
390
+ return void 0 !== endpoint && 'readiness' === stringLiteral(endpoint.arguments[0]) && stringLiteral(endpoint.arguments[1]) === `/${stem}/readiness` && endpointProperties?.size === 1 && identifierName(endpointProperties.get('success')?.value) === readinessSchemaName;
391
+ };
392
+ const rootComposesFoundation = (sourceFile, declaration, stem, foundationName)=>{
393
+ const chain = directCallChain(declaration?.init);
394
+ const first = chain?.methods[0];
395
+ return void 0 !== chain && isAccessPath(chain.base.callee, [
396
+ 'HttpApi',
397
+ 'make'
398
+ ]) && 1 === chain.base.arguments.length && stringLiteral(chain.base.arguments[0]) === `${pascalCaseStem(stem)}Api` && chain.methods.length > 0 && chain.methods.every((method, index)=>1 === method.arguments.length && ('add' === method.name || 'addHttpApi' === method.name || index === chain.methods.length - 1 && 'pipe' === method.name && 'identity' === identifierName(method.arguments[0]) && importsExactBindings(sourceFile, 'effect', [
399
+ 'identity'
400
+ ]))) && first?.name === 'addHttpApi' && identifierName(first.arguments[0]) === foundationName;
401
+ };
402
+ const nonEndpointCombinators = {
403
+ api: {
404
+ annotate: 2,
405
+ annotateMerge: 1,
406
+ middleware: 1
407
+ },
408
+ group: {
409
+ annotate: 2,
410
+ annotateEndpoints: 2,
411
+ annotateEndpointsMerge: 1,
412
+ annotateMerge: 1,
413
+ middleware: 1
414
+ }
415
+ };
416
+ const reachableEndpoints = (rootModule, declaration)=>{
417
+ const readModule = createModuleReader(rootModule);
418
+ const active = new Set();
419
+ const endpoints = [];
420
+ const identities = new Set();
421
+ const verbs = {
422
+ get: 'GET',
423
+ post: 'POST',
424
+ put: 'PUT',
425
+ patch: 'PATCH',
426
+ del: 'DELETE',
427
+ delete: 'DELETE',
428
+ head: 'HEAD',
429
+ options: 'OPTIONS'
430
+ };
431
+ let visits = 0;
432
+ const visit = (expression, module, kind, group = '')=>{
433
+ if (!expression) return false;
434
+ const node = unwrapExpression(expression);
435
+ if (active.has(node) || active.size >= 128 || ++visits > 2048) return false;
436
+ active.add(node);
437
+ try {
438
+ if (types_namespaceObject.isIdentifier(node)) {
439
+ const resolved = resolveBinding(module, node.name, 'local', readModule, new Set());
440
+ return void 0 !== resolved && visit(resolved.expression, resolved.module, kind, group);
441
+ }
442
+ if ('endpoint' === kind) {
443
+ if (!types_namespaceObject.isCallExpression(node) || node.arguments.length < 2 || node.arguments.length > 3) return false;
444
+ const callee = accessPath(node.callee);
445
+ const method = callee?.length === 2 && 'HttpApiEndpoint' === callee[0] ? verbs[callee[1]] : void 0;
446
+ const name = stringLiteral(node.arguments[0]);
447
+ const routePath = stringLiteral(node.arguments[1]);
448
+ if (!method || !name || !routePath) return false;
449
+ const identity = `${group}:${name}`;
450
+ if (identities.has(identity)) return false;
451
+ identities.add(identity);
452
+ endpoints.push({
453
+ group,
454
+ name,
455
+ method,
456
+ routePath
457
+ });
458
+ return true;
459
+ }
460
+ const chain = directCallChain(node);
461
+ if (!chain || !isAccessPath(chain.base.callee, [
462
+ 'api' === kind ? 'HttpApi' : 'HttpApiGroup',
463
+ 'make'
464
+ ]) || 1 !== chain.base.arguments.length) return false;
465
+ const name = stringLiteral(chain.base.arguments[0]);
466
+ if (!name) return false;
467
+ const chainStart = endpoints.length;
468
+ const combinators = nonEndpointCombinators[kind];
469
+ return chain.methods.every((method)=>{
470
+ if ('prefix' === method.name) {
471
+ const prefix = stringLiteral(method.arguments[0]);
472
+ if (1 !== method.arguments.length || !prefix?.startsWith('/')) return false;
473
+ for(let index = chainStart; index < endpoints.length; index += 1){
474
+ const endpoint = endpoints[index];
475
+ endpoints[index] = {
476
+ ...endpoint,
477
+ routePath: `${prefix}${endpoint.routePath}`
478
+ };
479
+ }
480
+ return true;
481
+ }
482
+ const combinatorArity = combinators[method.name];
483
+ if (void 0 !== combinatorArity) return method.arguments.length === combinatorArity;
484
+ if (1 !== method.arguments.length) return false;
485
+ if ('pipe' === method.name) return 'identity' === identifierName(method.arguments[0]) && importsExactBindings(module.file, 'effect', [
486
+ 'identity'
487
+ ]);
488
+ if ('add' === method.name) return visit(method.arguments[0], module, 'api' === kind ? 'group' : 'endpoint', 'group' === kind ? name : '');
489
+ return 'api' === kind && 'addHttpApi' === method.name && visit(method.arguments[0], module, 'api');
490
+ });
491
+ } finally{
492
+ active.delete(node);
493
+ }
494
+ };
495
+ return visit(declaration?.init, rootModule, 'api') ? endpoints : void 0;
496
+ };
497
+ const operationContextFields = (property)=>{
498
+ const constructorCall = exactCall(property.value, [
499
+ 'createMicroVerticalOperationContext'
500
+ ], 1);
501
+ const input = objectLiteral(constructorCall?.arguments[0]);
502
+ return void 0 === input ? void 0 : propertyAssignments(input.properties);
503
+ };
504
+ const operationContextIdentity = (property)=>{
505
+ const fields = operationContextFields(property);
506
+ const method = stringLiteral(fields?.get('method')?.value);
507
+ const operationId = stringLiteral(fields?.get('operationId')?.value);
508
+ const routePath = stringLiteral(fields?.get('routePath')?.value);
509
+ if (fields?.size !== 3 || void 0 === method || void 0 === operationId || void 0 === routePath) return;
510
+ return {
511
+ method,
512
+ operationId,
513
+ routePath
514
+ };
515
+ };
516
+ const operationContextIsConstructed = (property, stem, propertyKey, operationPaths, endpoints)=>{
517
+ const identity = operationContextIdentity(property);
518
+ if (void 0 === identity) return false;
519
+ const { method, operationId, routePath } = identity;
520
+ if (!/^[A-Z]+$/u.test(method) || !/^\/(?!.*(?:^|\/)\.\.?\/)[^\s?#]*$/u.test(routePath)) return false;
521
+ const apiName = `${pascalCaseStem(stem)}Api`;
522
+ if ('readiness' === propertyKey && ('GET' !== method || routePath !== `/${stem}/readiness`)) return false;
523
+ return operationId === `${apiName}:${routePath}` || operationPaths[operationId] === routePath || endpoints.some((endpoint)=>endpoint.name === propertyKey && endpoint.method === method && endpoint.routePath === routePath && (operationId === `${apiName}:${endpoint.group}:${propertyKey}` || 'readiness' === propertyKey && operationId === `${apiName}:${camelCaseStem(stem)}:readiness`));
524
+ };
525
+ const operationMapIsConnected = (declaration, stem, operationPaths, endpoints)=>{
526
+ const map = objectLiteral(declaration?.init);
527
+ const properties = void 0 === map ? void 0 : propertyAssignments(map.properties);
528
+ return void 0 !== properties && properties.has('readiness') && [
529
+ ...properties
530
+ ].every(([key, property])=>operationContextIsConstructed(property, stem, key, operationPaths, endpoints));
531
+ };
532
+ const constAssertionObject = (declaration)=>{
533
+ const initializer = declaration?.init;
534
+ if (null == initializer || !types_namespaceObject.isTSAsExpression(initializer) || !types_namespaceObject.isTSTypeReference(initializer.typeAnnotation) || !types_namespaceObject.isIdentifier(initializer.typeAnnotation.typeName, {
535
+ name: 'const'
536
+ })) return;
537
+ return objectLiteral(initializer.expression);
538
+ };
539
+ const metadataIsExact = (declaration, expectation, endpoints)=>{
540
+ const object = constAssertionObject(declaration);
541
+ const fields = void 0 === object ? void 0 : propertyAssignments(object.properties);
542
+ const expectedFields = [
543
+ [
544
+ 'apiPrefix',
545
+ expectation.apiPrefix
546
+ ],
547
+ [
548
+ 'basePath',
549
+ expectation.basePath
550
+ ],
551
+ [
552
+ 'ownerId',
553
+ expectation.ownerId
554
+ ],
555
+ [
556
+ 'readinessPath',
557
+ expectation.readinessPath
558
+ ]
559
+ ];
560
+ if (!fields || !expectedFields.every(([field, value])=>stringLiteral(fields.get(field)?.value) === value)) return false;
561
+ const common = new Set(expectedFields.map(([field])=>field));
562
+ return [
563
+ ...fields
564
+ ].every(([field, property])=>{
565
+ if (common.has(field)) return true;
566
+ const value = stringLiteral(property.value);
567
+ if (void 0 === value) return false;
568
+ const explicit = expectation.additionalPaths[field];
569
+ if (void 0 !== explicit) return value === explicit;
570
+ if (!value.startsWith(`${expectation.apiPrefix}/`) || /[\s?#]/u.test(value) || value.split('/').some((segment)=>'.' === segment || '..' === segment)) return false;
571
+ return endpoints.some((endpoint)=>{
572
+ const route = `${expectation.apiPrefix}${endpoint.routePath}`;
573
+ return route === value || route.startsWith(`${value}/`);
574
+ });
575
+ });
576
+ };
577
+ const markerSchemaIsShared = (sourceFile, declaration)=>{
578
+ const schema = sharedSchemaObject(declaration, 'MicroVerticalBuildMarkerSchema', [
579
+ 'build',
580
+ 'buildMarker',
581
+ 'deployProfile',
582
+ 'packageName',
583
+ 'sourceRevision',
584
+ 'surface',
585
+ 'version'
586
+ ]);
587
+ if (void 0 === schema || schema.identity) return schema?.identity === true;
588
+ const brandedField = (property, brand)=>identifierName(property.value) === `${brand}Schema` && brandedStringSchemaIsExact(localConst(sourceFile, `${brand}Schema`), brand);
589
+ const validators = new Map([
590
+ [
591
+ 'appId',
592
+ (property)=>brandedField(property, 'AppId')
593
+ ],
594
+ [
595
+ 'unitId',
596
+ (property)=>brandedField(property, 'UnitId')
597
+ ],
598
+ [
599
+ 'kind',
600
+ (property)=>'microvertical-delivery-unit' === stringLiteral(exactCall(property.value, [
601
+ 'Schema',
602
+ 'Literal'
603
+ ], 1)?.arguments[0])
604
+ ],
605
+ [
606
+ 'schemaVersion',
607
+ (property)=>1 === numericLiteral(exactCall(property.value, [
608
+ 'Schema',
609
+ 'Literal'
610
+ ], 1)?.arguments[0])
611
+ ]
612
+ ]);
613
+ return [
614
+ ...schema.assignments
615
+ ].every(([field, property])=>validators.get(field)?.(property) === true);
616
+ };
617
+ const readinessSchemaIsShared = (declaration, markerSchemaName, ownerMarkerIsIdentity)=>{
618
+ const schema = sharedSchemaObject(declaration, 'MicroVerticalReadinessSchema', [
619
+ 'checks',
620
+ 'status',
621
+ 'versionSkew'
622
+ ]);
623
+ return void 0 !== schema && (schema.identity && ownerMarkerIsIdentity || 1 === schema.assignments.size && identifierName(schema.assignments.get('marker')?.value) === markerSchemaName);
624
+ };
625
+ const declarationIsIdentifier = (declaration, identifier)=>declaration?.init != null && identifierName(unwrapExpression(declaration.init)) === identifier;
626
+ const validateParsedContract = (module, stem, expectation)=>{
627
+ const sourceFile = module.file;
628
+ const exportStem = camelCaseStem(stem);
629
+ const foundationName = `${exportStem}FoundationApi`;
630
+ const markerSchemaName = `${exportStem}MarkerSchema`;
631
+ const readinessSchemaName = `${exportStem}ReadinessSchema`;
632
+ const markerDeclaration = exportedConst(sourceFile, markerSchemaName);
633
+ if (!importsExactBindings(sourceFile, expectation.effectClientPackage, [
634
+ 'HttpApi',
635
+ 'HttpApiEndpoint',
636
+ 'HttpApiGroup',
637
+ 'Schema'
638
+ ])) return 'MicroVertical root contract must import exact Effect API primitives from the framework client package';
639
+ if (!importsSharedBaselinePrimitives(sourceFile, expectation.baselinePackage)) return 'MicroVertical root contract must import exact baseline primitives from the framework baseline package';
640
+ if (!markerSchemaIsShared(sourceFile, markerDeclaration)) return 'MicroVertical root contract must consume the shared build marker schema without overriding shared fields';
641
+ if (!readinessSchemaIsShared(exportedConst(sourceFile, readinessSchemaName), markerSchemaName, declarationIsIdentifier(markerDeclaration, 'MicroVerticalBuildMarkerSchema'))) return 'MicroVertical readiness schema must consume the shared readiness schema without overriding shared fields';
642
+ if (!foundationIsExact(exportedConst(sourceFile, foundationName), stem, readinessSchemaName)) return 'MicroVertical readiness foundation API must directly compose its exact readiness endpoint and foundation identity';
643
+ if (!rootComposesFoundation(sourceFile, exportedConst(sourceFile, `${exportStem}Api`), stem, foundationName)) return 'MicroVertical root API must explicitly compose its readiness foundation API';
644
+ const endpoints = reachableEndpoints(module, exportedConst(sourceFile, `${exportStem}Api`));
645
+ if (!endpoints) return 'MicroVertical root API must compose bounded native endpoint declarations without ambiguous identities';
646
+ if (!operationMapIsConnected(exportedConst(sourceFile, `${exportStem}OperationContexts`), stem, expectation.operationPaths ?? {}, endpoints)) return 'MicroVertical operation map must construct every operation with the shared context constructor';
647
+ if (!metadataIsExact(exportedConst(sourceFile, `${exportStem}ApiContract`), expectation, endpoints)) return 'MicroVertical root contract must keep exact owner and API path metadata without forbidden fields';
648
+ };
649
+ const configuredMicroVerticalApiStem = (verticalPath, verticals)=>{
650
+ const topologyVertical = verticals.find((vertical)=>(vertical.path ?? `verticals/${vertical.id}`) === verticalPath);
651
+ const endpoint = topologyVertical?.api?.readiness?.endpoint;
652
+ return endpoint?.match(/^\/([a-z0-9]+(?:-[a-z0-9]+)*)\/readiness$/u)?.[1];
653
+ };
654
+ const microVerticalApiBaselineViolation = (stem, filePath, expectation)=>{
655
+ try {
656
+ const sourceFile = parseConsumer(filePath);
657
+ if (!(0, external_microvertical_api_owner_cjs_namespaceObject.baselinePublicIdentityIsExact)(filePath, expectation)) return 'MicroVertical baseline imports must resolve the exact framework owner public export and schema identity';
658
+ return validateParsedContract({
659
+ file: sourceFile,
660
+ path: filePath
661
+ }, stem, expectation);
662
+ } catch (error) {
663
+ if (error instanceof ConsumerSyntaxError) return `MicroVertical root contract must be valid TypeScript syntax (${error.message})`;
664
+ throw error;
665
+ }
666
+ };
667
+ exports.configuredMicroVerticalApiStem = __webpack_exports__.configuredMicroVerticalApiStem;
668
+ exports.consumerParserPlugins = __webpack_exports__.consumerParserPlugins;
669
+ exports.microVerticalApiBaselineViolation = __webpack_exports__.microVerticalApiBaselineViolation;
670
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
671
+ "configuredMicroVerticalApiStem",
672
+ "consumerParserPlugins",
673
+ "microVerticalApiBaselineViolation"
674
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
675
+ Object.defineProperty(exports, '__esModule', {
676
+ value: true
677
+ });