@bleedingdev/modern-js-code-tools 3.9.0-ultramodern.3 → 3.9.0-ultramodern.5

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.
@@ -4,7 +4,8 @@ import node_path from "node:path";
4
4
  import { parse } from "@babel/parser";
5
5
  import traverse, { Hub, NodePath } from "@babel/traverse";
6
6
  import * as __rspack_external__babel_types_6e8337dd from "@babel/types";
7
- const edge = '@modern-js/plugin-bff/effect-edge';
7
+ const edge = '@modern-js/bff-effect/effect-edge';
8
+ const nodeRuntime = '@modern-js/bff-effect/effect';
8
9
  const sharedRuntime = /^@[^/]+\/shared-contracts\/server\/effect-bff-runtime$/u;
9
10
  const failure = 'Generated API entries must export defineEffectBff(...) or the server-only shared Effect BFF assembly helper with an explicitly composed handler Layer and an unshadowed executable root; entries must implement handlers through HttpApiBuilder.group.';
10
11
  const invalidSources = new WeakSet();
@@ -120,23 +121,38 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
120
121
  const imported = (node)=>{
121
122
  const value = binding(node);
122
123
  const decl = value?.path.node;
123
- if (!decl || !__rspack_external__babel_types_6e8337dd.isImportSpecifier(decl) || 'type' === decl.importKind) return;
124
+ if (!decl || !__rspack_external__babel_types_6e8337dd.isImportSpecifier(decl) && !__rspack_external__babel_types_6e8337dd.isImportNamespaceSpecifier(decl) || __rspack_external__babel_types_6e8337dd.isImportSpecifier(decl) && 'type' === decl.importKind) return;
124
125
  const statement = value.path.parent;
125
126
  if (!__rspack_external__babel_types_6e8337dd.isImportDeclaration(statement) || 'type' === statement.importKind) return;
126
127
  return {
127
- name: __rspack_external__babel_types_6e8337dd.isIdentifier(decl.imported) ? decl.imported.name : decl.imported.value,
128
+ namespace: __rspack_external__babel_types_6e8337dd.isImportNamespaceSpecifier(decl),
129
+ name: __rspack_external__babel_types_6e8337dd.isImportNamespaceSpecifier(decl) ? '*' : __rspack_external__babel_types_6e8337dd.isIdentifier(decl.imported) ? decl.imported.name : decl.imported.value,
128
130
  specifier: statement.source.value
129
131
  };
130
132
  };
131
- const native = (node, name, sources = [
132
- edge
133
- ])=>{
133
+ const namespaceSources = {
134
+ HttpApi: [
135
+ edge,
136
+ 'effect/unstable/httpapi'
137
+ ],
138
+ HttpApiBuilder: [
139
+ edge,
140
+ 'effect/unstable/httpapi'
141
+ ],
142
+ HttpRouter: [
143
+ edge,
144
+ 'effect/unstable/http'
145
+ ]
146
+ };
147
+ const native = (node, name, sources)=>{
134
148
  const value = imported(node);
135
- return value?.name === name && sources.includes(value.specifier);
149
+ if (!value) return false;
150
+ const importedNameMatches = value.namespace ? value.specifier === `effect/${name}` : value.name === name && value.specifier !== `effect/${name}`;
151
+ return importedNameMatches && (sources ?? namespaceSources[name] ?? [
152
+ edge
153
+ ]).includes(value.specifier);
136
154
  };
137
- const method = (node, namespace, member, sources = [
138
- edge
139
- ])=>{
155
+ const method = (node, namespace, member, sources)=>{
140
156
  node = unwrap(node);
141
157
  return __rspack_external__babel_types_6e8337dd.isMemberExpression(node) && !node.computed && __rspack_external__babel_types_6e8337dd.isIdentifier(node.property, {
142
158
  name: member
@@ -214,8 +230,15 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
214
230
  };
215
231
  const layerSources = [
216
232
  edge,
217
- 'effect'
233
+ 'effect',
234
+ 'effect/Layer'
218
235
  ];
236
+ const returned = (body)=>{
237
+ if (!__rspack_external__babel_types_6e8337dd.isBlockStatement(body)) return body;
238
+ const statements = body.body;
239
+ const last = statements.at(-1);
240
+ return statements.slice(0, -1).every((statement)=>__rspack_external__babel_types_6e8337dd.isVariableDeclaration(statement)) && __rspack_external__babel_types_6e8337dd.isReturnStatement(last) ? last.argument : void 0;
241
+ };
219
242
  const pipe = (node, check)=>__rspack_external__babel_types_6e8337dd.isMemberExpression(node.callee) && !node.callee.computed && __rspack_external__babel_types_6e8337dd.isIdentifier(node.callee.property, {
220
243
  name: 'pipe'
221
244
  }) && check(node.callee.object) && node.arguments.every((argument)=>method(argument, 'Layer', 'orDie', layerSources) || __rspack_external__babel_types_6e8337dd.isCallExpression(argument) && method(argument.callee, 'Layer', 'provide', layerSources) && argument.arguments.length > 0);
@@ -224,7 +247,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
224
247
  if (!__rspack_external__babel_types_6e8337dd.isArrowFunctionExpression(node) && !__rspack_external__babel_types_6e8337dd.isFunctionExpression(node)) return false;
225
248
  const parameter = node.params[0];
226
249
  if (!__rspack_external__babel_types_6e8337dd.isIdentifier(parameter)) return false;
227
- const body = __rspack_external__babel_types_6e8337dd.isBlockStatement(node.body) ? 1 === node.body.body.length && __rspack_external__babel_types_6e8337dd.isReturnStatement(node.body.body[0]) ? node.body.body[0].argument : void 0 : node.body;
250
+ const body = returned(node.body);
228
251
  const chain = (value, count = 0)=>{
229
252
  value = unwrap(value);
230
253
  if (__rspack_external__babel_types_6e8337dd.isIdentifier(value)) return count > 0 && declaration(value) === parameter;
@@ -280,7 +303,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
280
303
  const groupInit = groupValue && initialized(groupValue);
281
304
  if (!groupInit || !__rspack_external__babel_types_6e8337dd.isCallExpression(groupInit) || !method(groupInit.callee, 'RpcGroup', 'make', [
282
305
  'effect/unstable/rpc',
283
- '@modern-js/plugin-bff/effect-client'
306
+ '@modern-js/bff-effect/effect-client'
284
307
  ])) return false;
285
308
  const layerInit = initialized(layer) ?? unwrap(layer);
286
309
  if (!__rspack_external__babel_types_6e8337dd.isCallExpression(layerInit) || !__rspack_external__babel_types_6e8337dd.isMemberExpression(layerInit.callee) || layerInit.callee.computed || !__rspack_external__babel_types_6e8337dd.isIdentifier(layerInit.callee.property, {
@@ -300,7 +323,10 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
300
323
  if (init) return runtime(init);
301
324
  if (!__rspack_external__babel_types_6e8337dd.isCallExpression(node)) return false;
302
325
  const value = imported(node.callee);
303
- if (value?.name === 'defineEffectBff' && value.specifier === edge || value?.name === 'assembleEffectBffRuntime' && sharedRuntime.test(value.specifier)) {
326
+ if (value?.name === 'defineEffectBff' && [
327
+ edge,
328
+ nodeRuntime
329
+ ].includes(value.specifier) || value?.name === 'assembleEffectBffRuntime' && sharedRuntime.test(value.specifier)) {
304
330
  if (1 !== node.arguments.length) return false;
305
331
  const values = properties(node.arguments[0]);
306
332
  if (!values) return false;
@@ -316,11 +342,9 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
316
342
  }
317
343
  const decl = declaration(node.callee);
318
344
  const factory = decl && __rspack_external__babel_types_6e8337dd.isFunctionDeclaration(decl) ? decl : initialized(node.callee);
319
- if (!factory || !__rspack_external__babel_types_6e8337dd.isFunctionDeclaration(factory) && !__rspack_external__babel_types_6e8337dd.isArrowFunctionExpression(factory) && !__rspack_external__babel_types_6e8337dd.isFunctionExpression(factory) || factory.params.length || node.arguments.length || !factory.body) return false;
320
- if (!__rspack_external__babel_types_6e8337dd.isBlockStatement(factory.body)) return runtime(factory.body);
321
- const statements = factory.body.body;
322
- const last = statements.at(-1);
323
- return statements.slice(0, -1).every((statement)=>__rspack_external__babel_types_6e8337dd.isVariableDeclaration(statement)) && !!last && __rspack_external__babel_types_6e8337dd.isReturnStatement(last) && !!last.argument && runtime(last.argument);
345
+ if (!factory || !__rspack_external__babel_types_6e8337dd.isFunctionDeclaration(factory) && !__rspack_external__babel_types_6e8337dd.isArrowFunctionExpression(factory) && !__rspack_external__babel_types_6e8337dd.isFunctionExpression(factory) || !factory.body) return false;
346
+ const result = returned(factory.body);
347
+ return !!result && runtime(result);
324
348
  });
325
349
  const root = entry.file.program.body.find((statement)=>__rspack_external__babel_types_6e8337dd.isExportDefaultDeclaration(statement));
326
350
  return root && runtime(root.declaration) ? void 0 : failure;
@@ -0,0 +1 @@
1
+ export declare function runMicroVerticalApiCheckCli(args?: string[], filesOnly?: boolean): number;
@@ -0,0 +1,23 @@
1
+ export interface MicroVerticalApiBaselineExpectation {
2
+ /** Optional override for operation IDs outside reachable endpoint naming conventions. */
3
+ readonly operationPaths?: Readonly<Record<string, string>>;
4
+ readonly additionalPaths: Readonly<Record<string, string>>;
5
+ readonly apiPrefix: string;
6
+ readonly basePath: string;
7
+ readonly effectClientPackage: string;
8
+ readonly ownerId: string;
9
+ readonly readinessPath: string;
10
+ readonly baselinePackage: '@modern-js/bff-effect/microvertical-api';
11
+ readonly baselinePackageDirectory: string;
12
+ }
13
+ export interface MicroVerticalTopologyEntry {
14
+ readonly api?: {
15
+ readonly readiness?: {
16
+ readonly endpoint?: string;
17
+ };
18
+ };
19
+ readonly id: string;
20
+ readonly path?: string;
21
+ }
22
+ export declare const configuredMicroVerticalApiStem: (verticalPath: string, verticals: readonly MicroVerticalTopologyEntry[]) => string | undefined;
23
+ export declare const microVerticalApiBaselineViolation: (stem: string, filePath: string, expectation: MicroVerticalApiBaselineExpectation) => string | undefined;
@@ -0,0 +1,32 @@
1
+ export type { MicroVerticalApiBaselineExpectation, MicroVerticalTopologyEntry, } from './microvertical-api-baseline.js';
2
+ export { configuredMicroVerticalApiStem, microVerticalApiBaselineViolation, } from './microvertical-api-baseline.js';
3
+ export interface MicroVerticalConfiguredApp {
4
+ readonly path: string;
5
+ readonly id?: string;
6
+ readonly kind?: string;
7
+ readonly package?: string;
8
+ readonly surfaceProfile?: string;
9
+ readonly deliveryUnitKind?: string;
10
+ readonly api?: {
11
+ readonly stem?: string;
12
+ readonly prefix?: string;
13
+ readonly protocol?: 'rest' | 'rpc';
14
+ readonly operationPaths?: Readonly<Record<string, string>>;
15
+ readonly additionalPaths?: Readonly<Record<string, string>>;
16
+ };
17
+ }
18
+ export interface MicroVerticalApiCheckOptions {
19
+ readonly workspaceRoot: string;
20
+ readonly configuredApps?: readonly MicroVerticalConfiguredApp[];
21
+ /** Explicit expected installed owner, useful for isolated/non-hoisted installations. */
22
+ readonly baselinePackageDirectory?: string;
23
+ }
24
+ export interface MicroVerticalApiCheckResult {
25
+ readonly diagnostics: readonly string[];
26
+ readonly toolErrors: readonly string[];
27
+ readonly topologyFilesAnalyzed: number;
28
+ }
29
+ /** Full standalone check: source runtime topology is analyzed once per entry. */
30
+ export declare const checkMicroVerticalApiBoundaries: (options: MicroVerticalApiCheckOptions) => MicroVerticalApiCheckResult;
31
+ /** Consumer files/export/owner checks; caller must separately run runtime topology analysis. */
32
+ export declare const checkMicroVerticalApiConsumerFiles: (options: MicroVerticalApiCheckOptions) => MicroVerticalApiCheckResult;
@@ -0,0 +1,6 @@
1
+ import type { MicroVerticalApiBaselineExpectation } from './microvertical-api-baseline.js';
2
+ export declare const baselinePackage = "@modern-js/bff-effect/microvertical-api";
3
+ /** Locate the installed package from this consumer's resolver, never this tool's installation. */
4
+ export declare function resolveBaselinePackageDirectory(fromFile: string): string;
5
+ /** Follow only public bindings and local barrels. Never examine schema implementation expressions. */
6
+ export declare function baselinePublicIdentityIsExact(fromFile: string, expectation: MicroVerticalApiBaselineExpectation): boolean;
package/package.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "engines": {
24
24
  "node": ">=20"
25
25
  },
26
- "version": "3.9.0-ultramodern.3",
26
+ "version": "3.9.0-ultramodern.5",
27
27
  "types": "./dist/types/index.d.ts",
28
28
  "main": "./dist/esm-node/index.js",
29
29
  "typesVersions": {
@@ -33,6 +33,9 @@
33
33
  ],
34
34
  "oxlint-plugin": [
35
35
  "./dist/types/oxlint-plugin.d.ts"
36
+ ],
37
+ "microvertical-api-boundary": [
38
+ "./dist/types/microvertical-api-boundary.d.ts"
36
39
  ]
37
40
  }
38
41
  },
@@ -57,10 +60,16 @@
57
60
  "require": "./dist/cjs/oxlint-plugin.cjs"
58
61
  },
59
62
  "default": "./dist/esm-node/oxlint-plugin.js"
63
+ },
64
+ "./microvertical-api-boundary": {
65
+ "types": "./dist/types/microvertical-api-boundary.d.ts",
66
+ "import": "./dist/esm-node/microvertical-api-boundary.js",
67
+ "require": "./dist/cjs/microvertical-api-boundary.cjs"
60
68
  }
61
69
  },
62
70
  "files": [
63
- "dist"
71
+ "dist",
72
+ "bin"
64
73
  ],
65
74
  "dependencies": {
66
75
  "@babel/parser": "^8.0.4",
@@ -79,6 +88,10 @@
79
88
  "access": "public"
80
89
  },
81
90
  "modern:source": "./src/index.ts",
91
+ "bin": {
92
+ "modern-api-check": "bin/modern-api-check.mjs",
93
+ "modern-api-check-files": "bin/modern-api-check-files.mjs"
94
+ },
82
95
  "scripts": {
83
96
  "build": "rm -rf dist && rslib build -c rslib.config.mts",
84
97
  "dev": "rslib build -c rslib.config.mts -w",