@bleedingdev/modern-js-code-tools 3.9.0-ultramodern.9 → 3.9.3-ultramodern.2

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 (38) hide show
  1. package/bin/modern-api-check-files.mjs +4 -1
  2. package/bin/modern-api-check.mjs +1 -1
  3. package/bin/modern-i18n-check.mjs +4 -0
  4. package/dist/cjs/cli/microvertical-api-check.cjs +36 -7
  5. package/dist/cjs/cli/workspace-source-check.cjs +90 -17
  6. package/dist/cjs/microvertical-api-baseline.cjs +81 -244
  7. package/dist/cjs/microvertical-api-boundary.cjs +352 -64
  8. package/dist/cjs/microvertical-api-owner.cjs +5 -2
  9. package/dist/cjs/module-graph.cjs +1862 -0
  10. package/dist/cjs/oxlint-plugin/rules/strict-effect-api-boundaries.cjs +1 -1
  11. package/dist/cjs/source-analysis.cjs +108 -0
  12. package/dist/cjs/strict-effect-runtime.cjs +75 -57
  13. package/dist/esm/cli/microvertical-api-check.js +26 -7
  14. package/dist/esm/cli/workspace-source-check.js +86 -13
  15. package/dist/esm/microvertical-api-baseline.js +66 -214
  16. package/dist/esm/microvertical-api-boundary.js +350 -65
  17. package/dist/esm/microvertical-api-owner.js +5 -2
  18. package/dist/esm/module-graph.js +1804 -0
  19. package/dist/esm/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
  20. package/dist/esm/source-analysis.js +48 -0
  21. package/dist/esm/strict-effect-runtime.js +75 -56
  22. package/dist/esm-node/cli/microvertical-api-check.js +26 -7
  23. package/dist/esm-node/cli/workspace-source-check.js +86 -13
  24. package/dist/esm-node/microvertical-api-baseline.js +66 -214
  25. package/dist/esm-node/microvertical-api-boundary.js +350 -65
  26. package/dist/esm-node/microvertical-api-owner.js +5 -2
  27. package/dist/esm-node/module-graph.js +1805 -0
  28. package/dist/esm-node/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
  29. package/dist/esm-node/source-analysis.js +49 -0
  30. package/dist/esm-node/strict-effect-runtime.js +75 -56
  31. package/dist/types/cli/microvertical-api-check.d.ts +1 -1
  32. package/dist/types/cli/workspace-source-check.d.ts +1 -1
  33. package/dist/types/microvertical-api-baseline.d.ts +0 -5
  34. package/dist/types/microvertical-api-boundary.d.ts +17 -2
  35. package/dist/types/microvertical-api-owner.d.ts +1 -1
  36. package/dist/types/module-graph.d.ts +100 -0
  37. package/dist/types/source-analysis.d.ts +13 -0
  38. package/package.json +17 -13
@@ -1,14 +1,5 @@
1
1
  "use strict";
2
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
3
  (()=>{
13
4
  __webpack_require__.d = (exports1, getters, values)=>{
14
5
  var define = (defs, kind)=>{
@@ -38,74 +29,18 @@ var __webpack_exports__ = {};
38
29
  __webpack_require__.r(__webpack_exports__);
39
30
  __webpack_require__.d(__webpack_exports__, {
40
31
  configuredMicroVerticalApiStem: ()=>configuredMicroVerticalApiStem,
41
- consumerParserPlugins: ()=>consumerParserPlugins,
42
32
  microVerticalApiBaselineViolation: ()=>microVerticalApiBaselineViolation
43
33
  });
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
34
  const types_namespaceObject = require("@babel/types");
52
35
  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
- }
36
+ const external_module_graph_cjs_namespaceObject = require("./module-graph.cjs");
37
+ const external_source_analysis_cjs_namespaceObject = require("./source-analysis.cjs");
100
38
  const camelCaseStem = (stem)=>stem.replaceAll(/-([a-z0-9])/gu, (_match, letter)=>letter.toUpperCase());
101
39
  const pascalCaseStem = (stem)=>{
102
40
  const camelStem = camelCaseStem(stem);
103
41
  return `${camelStem.slice(0, 1).toUpperCase()}${camelStem.slice(1)}`;
104
42
  };
105
43
  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
44
  const accessPath = (node)=>{
110
45
  if (types_namespaceObject.isIdentifier(node)) return [
111
46
  node.name
@@ -119,165 +54,31 @@ const accessPath = (node)=>{
119
54
  }
120
55
  };
121
56
  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
57
  const stringLiteral = (expression)=>{
128
58
  if (null == expression) return;
129
- const unwrapped = unwrapExpression(expression);
59
+ const unwrapped = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
130
60
  return types_namespaceObject.isStringLiteral(unwrapped) ? unwrapped.value : void 0;
131
61
  };
132
62
  const numericLiteral = (expression)=>{
133
63
  if (null == expression) return;
134
- const unwrapped = unwrapExpression(expression);
64
+ const unwrapped = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
135
65
  return types_namespaceObject.isNumericLiteral(unwrapped) ? Number(unwrapped.value) : void 0;
136
66
  };
137
67
  const callExpression = (expression, callee)=>{
138
68
  if (null == expression) return;
139
- const unwrapped = unwrapExpression(expression);
69
+ const unwrapped = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
140
70
  return types_namespaceObject.isCallExpression(unwrapped) && isAccessPath(unwrapped.callee, callee) ? unwrapped : void 0;
141
71
  };
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
72
  const objectLiteral = (expression)=>{
272
73
  if (null == expression) return;
273
- const unwrapped = unwrapExpression(expression);
74
+ const unwrapped = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
274
75
  return types_namespaceObject.isObjectExpression(unwrapped) ? unwrapped : void 0;
275
76
  };
276
77
  const propertyAssignments = (properties)=>{
277
78
  const assignments = new Map();
278
79
  for (const property of properties){
279
80
  if (!types_namespaceObject.isObjectProperty(property) || property.computed || property.shorthand) return;
280
- const name = propertyName(property.key);
81
+ const name = (0, external_module_graph_cjs_namespaceObject.propertyName)(property.key);
281
82
  if (void 0 === name || assignments.has(name)) return;
282
83
  assignments.set(name, property);
283
84
  }
@@ -289,7 +90,7 @@ const exactCall = (expression, callee, argumentCount)=>{
289
90
  };
290
91
  const sharedSchemaObject = (declaration, sharedSchemaName, protectedFields)=>{
291
92
  if (declaration?.init == null) return;
292
- const initializer = unwrapExpression(declaration.init);
93
+ const initializer = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(declaration.init);
293
94
  if (types_namespaceObject.isIdentifier(initializer) && initializer.name === sharedSchemaName) return {
294
95
  assignments: new Map(),
295
96
  identity: true
@@ -313,14 +114,14 @@ const sharedSchemaObject = (declaration, sharedSchemaName, protectedFields)=>{
313
114
  };
314
115
  const directCallChain = (expression)=>{
315
116
  if (null == expression) return;
316
- let current = unwrapExpression(expression);
117
+ let current = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
317
118
  const methods = [];
318
119
  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
120
  methods.unshift({
320
121
  arguments: current.arguments,
321
122
  name: current.callee.property.name
322
123
  });
323
- current = unwrapExpression(current.callee.object);
124
+ current = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(current.callee.object);
324
125
  }
325
126
  if (!types_namespaceObject.isCallExpression(current)) return;
326
127
  return {
@@ -331,7 +132,7 @@ const directCallChain = (expression)=>{
331
132
  const brandedStringSchemaIsExact = (declaration, brand)=>{
332
133
  const initializer = declaration?.init;
333
134
  if (null == initializer) return false;
334
- const pipeCall = unwrapExpression(initializer);
135
+ const pipeCall = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(initializer);
335
136
  if (!types_namespaceObject.isCallExpression(pipeCall) || !types_namespaceObject.isMemberExpression(pipeCall.callee) || pipeCall.callee.computed || !types_namespaceObject.isIdentifier(pipeCall.callee.property, {
336
137
  name: 'pipe'
337
138
  }) || !isAccessPath(pipeCall.callee.object, [
@@ -367,14 +168,21 @@ const singleAddedArgument = (expression, factory, names)=>{
367
168
  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
169
  return method.arguments[0];
369
170
  };
370
- const foundationIsExact = (declaration, stem, readinessSchemaName)=>{
371
- const group = singleAddedArgument(declaration?.init, [
171
+ const rootGroupExpression = (graph, expression)=>{
172
+ if (void 0 === expression) return;
173
+ const node = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
174
+ if (!types_namespaceObject.isIdentifier(node)) return node;
175
+ const resolved = graph.resolve(graph.root, node.name, 'local');
176
+ return resolved?.kind === 'declaration' && resolved.module === graph.root ? (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(resolved.expression) : void 0;
177
+ };
178
+ const foundationGroup = (graph, declaration, stem, readinessSchemaName)=>{
179
+ const group = rootGroupExpression(graph, singleAddedArgument(declaration?.init, [
372
180
  'HttpApi',
373
181
  'make'
374
182
  ], [
375
183
  `${pascalCaseStem(stem)}FoundationApi`,
376
184
  `${pascalCaseStem(stem)}ApiFoundation`
377
- ]);
185
+ ]));
378
186
  const endpointExpression = singleAddedArgument(group, [
379
187
  'HttpApiGroup',
380
188
  'make'
@@ -387,17 +195,24 @@ const foundationIsExact = (declaration, stem, readinessSchemaName)=>{
387
195
  ], 3);
388
196
  const endpointOptions = objectLiteral(endpoint?.arguments[2]);
389
197
  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;
198
+ return void 0 !== endpoint && 'readiness' === stringLiteral(endpoint.arguments[0]) && stringLiteral(endpoint.arguments[1]) === `/${stem}/readiness` && endpointProperties?.size === 1 && identifierName(endpointProperties.get('success')?.value) === readinessSchemaName ? group : void 0;
391
199
  };
392
- const rootComposesFoundation = (sourceFile, declaration, stem, foundationName)=>{
200
+ const rootComposesFoundation = (graph, declaration, stem, foundationName, foundation)=>{
201
+ const sourceFile = graph.root.file;
393
202
  const chain = directCallChain(declaration?.init);
394
203
  const first = chain?.methods[0];
204
+ const firstArgument = first?.arguments[0];
395
205
  return void 0 !== chain && isAccessPath(chain.base.callee, [
396
206
  'HttpApi',
397
207
  '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', [
208
+ ]) && 1 === chain.base.arguments.length && stringLiteral(chain.base.arguments[0]) === `${pascalCaseStem(stem)}Api` && chain.methods.length > 0 && chain.methods.every((method, index)=>{
209
+ const combinatorArity = nonEndpointCombinators.api[method.name];
210
+ if (void 0 !== combinatorArity) return method.arguments.length === combinatorArity;
211
+ if ('add' === method.name) return method.arguments.length > 0;
212
+ return 1 === method.arguments.length && ('addHttpApi' === method.name || index === chain.methods.length - 1 && 'pipe' === method.name && 'identity' === identifierName(method.arguments[0]) && importsExactBindings(sourceFile, 'effect', [
399
213
  'identity'
400
- ]))) && first?.name === 'addHttpApi' && identifierName(first.arguments[0]) === foundationName;
214
+ ]));
215
+ }) && void 0 !== firstArgument && (first?.name === 'addHttpApi' && identifierName(firstArgument) === foundationName || first?.name === 'add' && types_namespaceObject.isIdentifier(firstArgument) && rootGroupExpression(graph, firstArgument) === foundation);
401
216
  };
402
217
  const nonEndpointCombinators = {
403
218
  api: {
@@ -413,8 +228,7 @@ const nonEndpointCombinators = {
413
228
  middleware: 1
414
229
  }
415
230
  };
416
- const reachableEndpoints = (rootModule, declaration)=>{
417
- const readModule = createModuleReader(rootModule);
231
+ const reachableEndpoints = (graph, declaration)=>{
418
232
  const active = new Set();
419
233
  const endpoints = [];
420
234
  const identities = new Set();
@@ -431,13 +245,13 @@ const reachableEndpoints = (rootModule, declaration)=>{
431
245
  let visits = 0;
432
246
  const visit = (expression, module, kind, group = '')=>{
433
247
  if (!expression) return false;
434
- const node = unwrapExpression(expression);
248
+ const node = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(expression);
435
249
  if (active.has(node) || active.size >= 128 || ++visits > 2048) return false;
436
250
  active.add(node);
437
251
  try {
438
252
  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);
253
+ const resolved = graph.resolve(module, node.name, 'local');
254
+ return resolved?.kind === 'declaration' && visit(resolved.expression, resolved.module, kind, group);
441
255
  }
442
256
  if ('endpoint' === kind) {
443
257
  if (!types_namespaceObject.isCallExpression(node) || node.arguments.length < 2 || node.arguments.length > 3) return false;
@@ -481,18 +295,36 @@ const reachableEndpoints = (rootModule, declaration)=>{
481
295
  }
482
296
  const combinatorArity = combinators[method.name];
483
297
  if (void 0 !== combinatorArity) return method.arguments.length === combinatorArity;
298
+ if ('add' === method.name) return method.arguments.length > 0 && method.arguments.every((argument)=>visitAdded(argument, module, 'api' === kind ? 'group' : 'endpoint', 'group' === kind ? name : ''));
484
299
  if (1 !== method.arguments.length) return false;
485
300
  if ('pipe' === method.name) return 'identity' === identifierName(method.arguments[0]) && importsExactBindings(module.file, 'effect', [
486
301
  'identity'
487
302
  ]);
488
- if ('add' === method.name) return visit(method.arguments[0], module, 'api' === kind ? 'group' : 'endpoint', 'group' === kind ? name : '');
489
303
  return 'api' === kind && 'addHttpApi' === method.name && visit(method.arguments[0], module, 'api');
490
304
  });
491
305
  } finally{
492
306
  active.delete(node);
493
307
  }
494
308
  };
495
- return visit(declaration?.init, rootModule, 'api') ? endpoints : void 0;
309
+ const visitAdded = (argument, module, kind, group)=>{
310
+ if (!types_namespaceObject.isSpreadElement(argument)) return visit(argument, module, kind, group);
311
+ let node = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(argument.argument);
312
+ let owner = module;
313
+ if (types_namespaceObject.isIdentifier(node)) {
314
+ const resolved = graph.resolve(module, node.name, 'local');
315
+ if (resolved?.kind !== 'declaration') return false;
316
+ node = (0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(resolved.expression);
317
+ owner = resolved.module;
318
+ }
319
+ if (!types_namespaceObject.isArrayExpression(node) || active.has(node) || ++visits > 2048) return false;
320
+ active.add(node);
321
+ try {
322
+ return node.elements.every((element)=>null !== element && visitAdded(element, owner, kind, group));
323
+ } finally{
324
+ active.delete(node);
325
+ }
326
+ };
327
+ return visit(declaration?.init, graph.root, 'api') ? endpoints : void 0;
496
328
  };
497
329
  const operationContextFields = (property)=>{
498
330
  const constructorCall = exactCall(property.value, [
@@ -585,7 +417,7 @@ const markerSchemaIsShared = (sourceFile, declaration)=>{
585
417
  'version'
586
418
  ]);
587
419
  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);
420
+ const brandedField = (property, brand)=>identifierName(property.value) === `${brand}Schema` && brandedStringSchemaIsExact((0, external_module_graph_cjs_namespaceObject.localConst)(sourceFile, `${brand}Schema`), brand);
589
421
  const validators = new Map([
590
422
  [
591
423
  'appId',
@@ -622,14 +454,14 @@ const readinessSchemaIsShared = (declaration, markerSchemaName, ownerMarkerIsIde
622
454
  ]);
623
455
  return void 0 !== schema && (schema.identity && ownerMarkerIsIdentity || 1 === schema.assignments.size && identifierName(schema.assignments.get('marker')?.value) === markerSchemaName);
624
456
  };
625
- const declarationIsIdentifier = (declaration, identifier)=>declaration?.init != null && identifierName(unwrapExpression(declaration.init)) === identifier;
626
- const validateParsedContract = (module, stem, expectation)=>{
627
- const sourceFile = module.file;
457
+ const declarationIsIdentifier = (declaration, identifier)=>declaration?.init != null && identifierName((0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(declaration.init)) === identifier;
458
+ const validateParsedContract = (graph, stem, expectation)=>{
459
+ const sourceFile = graph.root.file;
628
460
  const exportStem = camelCaseStem(stem);
629
461
  const foundationName = `${exportStem}FoundationApi`;
630
462
  const markerSchemaName = `${exportStem}MarkerSchema`;
631
463
  const readinessSchemaName = `${exportStem}ReadinessSchema`;
632
- const markerDeclaration = exportedConst(sourceFile, markerSchemaName);
464
+ const markerDeclaration = (0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, markerSchemaName);
633
465
  if (!importsExactBindings(sourceFile, expectation.effectClientPackage, [
634
466
  'HttpApi',
635
467
  'HttpApiEndpoint',
@@ -638,13 +470,14 @@ const validateParsedContract = (module, stem, expectation)=>{
638
470
  ])) return 'MicroVertical root contract must import exact Effect API primitives from the framework client package';
639
471
  if (!importsSharedBaselinePrimitives(sourceFile, expectation.baselinePackage)) return 'MicroVertical root contract must import exact baseline primitives from the framework baseline package';
640
472
  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`));
473
+ if (!readinessSchemaIsShared((0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, readinessSchemaName), markerSchemaName, declarationIsIdentifier(markerDeclaration, 'MicroVerticalBuildMarkerSchema'))) return 'MicroVertical readiness schema must consume the shared readiness schema without overriding shared fields';
474
+ const foundation = foundationGroup(graph, (0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, foundationName), stem, readinessSchemaName);
475
+ if (void 0 === foundation) return 'MicroVertical readiness foundation API must directly compose its exact readiness endpoint and foundation identity';
476
+ if (!rootComposesFoundation(graph, (0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, `${exportStem}Api`), stem, foundationName, foundation)) return 'MicroVertical root API must explicitly compose its readiness foundation API';
477
+ const endpoints = reachableEndpoints(graph, (0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, `${exportStem}Api`));
645
478
  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';
479
+ if (!operationMapIsConnected((0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, `${exportStem}OperationContexts`), stem, expectation.operationPaths ?? {}, endpoints)) return 'MicroVertical operation map must construct every operation with the shared context constructor';
480
+ if (!metadataIsExact((0, external_module_graph_cjs_namespaceObject.exportedConst)(sourceFile, `${exportStem}ApiContract`), expectation, endpoints)) return 'MicroVertical root contract must keep exact owner and API path metadata without forbidden fields';
648
481
  };
649
482
  const configuredMicroVerticalApiStem = (verticalPath, verticals)=>{
650
483
  const topologyVertical = verticals.find((vertical)=>(vertical.path ?? `verticals/${vertical.id}`) === verticalPath);
@@ -653,23 +486,27 @@ const configuredMicroVerticalApiStem = (verticalPath, verticals)=>{
653
486
  };
654
487
  const microVerticalApiBaselineViolation = (stem, filePath, expectation)=>{
655
488
  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);
489
+ const modules = (0, external_module_graph_cjs_namespaceObject.createModuleGraph)();
490
+ const graph = {
491
+ ...modules,
492
+ root: modules.module(filePath)
493
+ };
494
+ const [mutation] = graph.root.mutations;
495
+ if (mutation) return `MicroVertical root contract must be valid TypeScript syntax (contract bindings must be immutable at ${mutation.start})`;
496
+ let identityMismatch;
497
+ if (!(0, external_microvertical_api_owner_cjs_namespaceObject.baselinePublicIdentityIsExact)(filePath, expectation, (message)=>{
498
+ identityMismatch = message;
499
+ })) return `MicroVertical baseline imports must resolve the exact framework owner public export and schema identity${identityMismatch ? ` (${identityMismatch})` : ''}`;
500
+ return validateParsedContract(graph, stem, expectation);
662
501
  } catch (error) {
663
- if (error instanceof ConsumerSyntaxError) return `MicroVertical root contract must be valid TypeScript syntax (${error.message})`;
502
+ if (error instanceof external_source_analysis_cjs_namespaceObject.SourceSyntaxError) return `MicroVertical root contract must be valid TypeScript syntax (${error.message})`;
664
503
  throw error;
665
504
  }
666
505
  };
667
506
  exports.configuredMicroVerticalApiStem = __webpack_exports__.configuredMicroVerticalApiStem;
668
- exports.consumerParserPlugins = __webpack_exports__.consumerParserPlugins;
669
507
  exports.microVerticalApiBaselineViolation = __webpack_exports__.microVerticalApiBaselineViolation;
670
508
  for(var __rspack_i in __webpack_exports__)if (-1 === [
671
509
  "configuredMicroVerticalApiStem",
672
- "consumerParserPlugins",
673
510
  "microVerticalApiBaselineViolation"
674
511
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
675
512
  Object.defineProperty(exports, '__esModule', {