@bleedingdev/modern-js-code-tools 3.9.0-ultramodern.4 → 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.
- package/bin/modern-api-check-files.mjs +4 -0
- package/bin/modern-api-check.mjs +4 -0
- package/dist/cjs/cli/microvertical-api-check.cjs +71 -0
- package/dist/cjs/microvertical-api-baseline.cjs +526 -0
- package/dist/cjs/microvertical-api-boundary.cjs +470 -0
- package/dist/cjs/microvertical-api-owner.cjs +217 -0
- package/dist/cjs/oxlint-plugin/rules/strict-effect-api-boundaries.cjs +1 -1
- package/dist/cjs/strict-effect-runtime.cjs +33 -13
- package/dist/esm/cli/microvertical-api-check.js +33 -0
- package/dist/esm/microvertical-api-baseline.js +474 -0
- package/dist/esm/microvertical-api-boundary.js +412 -0
- package/dist/esm/microvertical-api-owner.js +162 -0
- package/dist/esm/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
- package/dist/esm/strict-effect-runtime.js +33 -13
- package/dist/esm-node/cli/microvertical-api-check.js +34 -0
- package/dist/esm-node/microvertical-api-baseline.js +475 -0
- package/dist/esm-node/microvertical-api-boundary.js +413 -0
- package/dist/esm-node/microvertical-api-owner.js +163 -0
- package/dist/esm-node/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
- package/dist/esm-node/strict-effect-runtime.js +33 -13
- package/dist/types/cli/microvertical-api-check.d.ts +1 -0
- package/dist/types/microvertical-api-baseline.d.ts +23 -0
- package/dist/types/microvertical-api-boundary.d.ts +32 -0
- package/dist/types/microvertical-api-owner.d.ts +6 -0
- package/package.json +15 -2
|
@@ -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/
|
|
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
|
-
|
|
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
|
|
132
|
-
|
|
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
|
-
|
|
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,7 +230,8 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
214
230
|
};
|
|
215
231
|
const layerSources = [
|
|
216
232
|
edge,
|
|
217
|
-
'effect'
|
|
233
|
+
'effect',
|
|
234
|
+
'effect/Layer'
|
|
218
235
|
];
|
|
219
236
|
const returned = (body)=>{
|
|
220
237
|
if (!__rspack_external__babel_types_6e8337dd.isBlockStatement(body)) return body;
|
|
@@ -286,7 +303,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
286
303
|
const groupInit = groupValue && initialized(groupValue);
|
|
287
304
|
if (!groupInit || !__rspack_external__babel_types_6e8337dd.isCallExpression(groupInit) || !method(groupInit.callee, 'RpcGroup', 'make', [
|
|
288
305
|
'effect/unstable/rpc',
|
|
289
|
-
'@modern-js/
|
|
306
|
+
'@modern-js/bff-effect/effect-client'
|
|
290
307
|
])) return false;
|
|
291
308
|
const layerInit = initialized(layer) ?? unwrap(layer);
|
|
292
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, {
|
|
@@ -306,7 +323,10 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
306
323
|
if (init) return runtime(init);
|
|
307
324
|
if (!__rspack_external__babel_types_6e8337dd.isCallExpression(node)) return false;
|
|
308
325
|
const value = imported(node.callee);
|
|
309
|
-
if (value?.name === 'defineEffectBff' &&
|
|
326
|
+
if (value?.name === 'defineEffectBff' && [
|
|
327
|
+
edge,
|
|
328
|
+
nodeRuntime
|
|
329
|
+
].includes(value.specifier) || value?.name === 'assembleEffectBffRuntime' && sharedRuntime.test(value.specifier)) {
|
|
310
330
|
if (1 !== node.arguments.length) return false;
|
|
311
331
|
const values = properties(node.arguments[0]);
|
|
312
332
|
if (!values) return false;
|
|
@@ -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.
|
|
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",
|