@bleedingdev/modern-js-code-tools 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/microvertical-api-baseline.cjs +108 -78
- package/dist/cjs/microvertical-api-boundary.cjs +90 -36
- package/dist/cjs/oxlint-plugin/rules/strict-effect-api-boundaries.cjs +1 -1
- package/dist/cjs/source-analysis.cjs +104 -0
- package/dist/cjs/strict-effect-runtime.cjs +12 -47
- package/dist/esm/microvertical-api-baseline.js +99 -65
- package/dist/esm/microvertical-api-boundary.js +90 -36
- package/dist/esm/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
- package/dist/esm/source-analysis.js +44 -0
- package/dist/esm/strict-effect-runtime.js +12 -46
- package/dist/esm-node/microvertical-api-baseline.js +99 -65
- package/dist/esm-node/microvertical-api-boundary.js +90 -36
- package/dist/esm-node/oxlint-plugin/rules/strict-effect-api-boundaries.js +1 -1
- package/dist/esm-node/source-analysis.js +45 -0
- package/dist/esm-node/strict-effect-runtime.js +12 -46
- package/dist/types/microvertical-api-baseline.d.ts +0 -5
- package/dist/types/source-analysis.d.ts +10 -0
- package/package.json +8 -7
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
SourceSyntaxError: ()=>SourceSyntaxError,
|
|
41
|
+
consumerParserPlugins: ()=>consumerParserPlugins,
|
|
42
|
+
parseSource: ()=>parseSource,
|
|
43
|
+
traverseSource: ()=>traverseSource,
|
|
44
|
+
unwrapExpression: ()=>unwrapExpression
|
|
45
|
+
});
|
|
46
|
+
const parser_namespaceObject = require("@babel/parser");
|
|
47
|
+
const traverse_namespaceObject = require("@babel/traverse");
|
|
48
|
+
var traverse_default = /*#__PURE__*/ __webpack_require__.n(traverse_namespaceObject);
|
|
49
|
+
const types_namespaceObject = require("@babel/types");
|
|
50
|
+
const consumerParserPlugins = (filePath)=>/\.[jt]sx$/u.test(filePath) ? [
|
|
51
|
+
"typescript",
|
|
52
|
+
'jsx'
|
|
53
|
+
] : [
|
|
54
|
+
"typescript"
|
|
55
|
+
];
|
|
56
|
+
class SourceSyntaxError extends Error {
|
|
57
|
+
}
|
|
58
|
+
class SourceValidationHub extends traverse_namespaceObject.Hub {
|
|
59
|
+
buildError(_node, message) {
|
|
60
|
+
return new SourceSyntaxError(message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function parseSource(source, filename, syntaxMessage) {
|
|
64
|
+
try {
|
|
65
|
+
return (0, parser_namespaceObject.parse)(source, {
|
|
66
|
+
sourceType: 'module',
|
|
67
|
+
sourceFilename: filename,
|
|
68
|
+
plugins: consumerParserPlugins(filename)
|
|
69
|
+
});
|
|
70
|
+
} catch (cause) {
|
|
71
|
+
if ('object' == typeof cause && null !== cause && 'code' in cause && 'BABEL_PARSER_SYNTAX_ERROR' === cause.code && 'reasonCode' in cause && 'string' == typeof cause.reasonCode) throw new SourceSyntaxError(syntaxMessage ?? (cause instanceof Error ? cause.message : String(cause)));
|
|
72
|
+
throw cause;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function traverseSource(file, visitor) {
|
|
76
|
+
const program = traverse_namespaceObject.NodePath.get({
|
|
77
|
+
hub: new SourceValidationHub(),
|
|
78
|
+
parentPath: void 0,
|
|
79
|
+
parent: file,
|
|
80
|
+
container: file,
|
|
81
|
+
key: 'program'
|
|
82
|
+
});
|
|
83
|
+
program.setContext();
|
|
84
|
+
traverse_default()(file, visitor, program.scope, void 0, program);
|
|
85
|
+
}
|
|
86
|
+
function unwrapExpression(node, includeAssertions = false) {
|
|
87
|
+
while(types_namespaceObject.isTSAsExpression(node) || types_namespaceObject.isParenthesizedExpression(node) || types_namespaceObject.isTSSatisfiesExpression(node) || includeAssertions && (types_namespaceObject.isTSTypeAssertion(node) || types_namespaceObject.isTSNonNullExpression(node)))node = node.expression;
|
|
88
|
+
return node;
|
|
89
|
+
}
|
|
90
|
+
exports.SourceSyntaxError = __webpack_exports__.SourceSyntaxError;
|
|
91
|
+
exports.consumerParserPlugins = __webpack_exports__.consumerParserPlugins;
|
|
92
|
+
exports.parseSource = __webpack_exports__.parseSource;
|
|
93
|
+
exports.traverseSource = __webpack_exports__.traverseSource;
|
|
94
|
+
exports.unwrapExpression = __webpack_exports__.unwrapExpression;
|
|
95
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
96
|
+
"SourceSyntaxError",
|
|
97
|
+
"consumerParserPlugins",
|
|
98
|
+
"parseSource",
|
|
99
|
+
"traverseSource",
|
|
100
|
+
"unwrapExpression"
|
|
101
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
102
|
+
Object.defineProperty(exports, '__esModule', {
|
|
103
|
+
value: true
|
|
104
|
+
});
|
|
@@ -44,25 +44,13 @@ const external_node_fs_namespaceObject = require("node:fs");
|
|
|
44
44
|
var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
|
|
45
45
|
const external_node_path_namespaceObject = require("node:path");
|
|
46
46
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
47
|
-
const parser_namespaceObject = require("@babel/parser");
|
|
48
|
-
const traverse_namespaceObject = require("@babel/traverse");
|
|
49
|
-
var traverse_default = /*#__PURE__*/ __webpack_require__.n(traverse_namespaceObject);
|
|
50
47
|
const types_namespaceObject = require("@babel/types");
|
|
48
|
+
const external_source_analysis_cjs_namespaceObject = require("./source-analysis.cjs");
|
|
51
49
|
const edge = '@modern-js/bff-effect/effect-edge';
|
|
52
50
|
const nodeRuntime = '@modern-js/bff-effect/effect';
|
|
53
|
-
const
|
|
54
|
-
const failure = 'Generated API entries must export defineEffectBff(...) or the
|
|
55
|
-
const
|
|
56
|
-
function invalidSource(message) {
|
|
57
|
-
const error = new Error(message);
|
|
58
|
-
invalidSources.add(error);
|
|
59
|
-
return error;
|
|
60
|
-
}
|
|
61
|
-
class SourceValidationHub extends traverse_namespaceObject.Hub {
|
|
62
|
-
buildError(_node, message) {
|
|
63
|
-
return invalidSource(message);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
51
|
+
const assembly = '@modern-js/bff-effect/assembly';
|
|
52
|
+
const failure = 'Generated API entries must export defineEffectBff(...) or the native Effect BFF assembly helper with an explicitly composed handler Layer and an unshadowed executable root; entries must implement handlers through HttpApiBuilder.group.';
|
|
53
|
+
const MAX_API_SOURCE_MODULES = 256;
|
|
66
54
|
function createEffectApiImportResolver(filename) {
|
|
67
55
|
const directory = external_node_fs_default().realpathSync(external_node_path_default().dirname(filename));
|
|
68
56
|
const owner = external_node_fs_default().realpathSync(external_node_path_default().resolve(directory, '..'));
|
|
@@ -94,34 +82,14 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
94
82
|
const load = (input)=>{
|
|
95
83
|
const existing = modules.get(input.id);
|
|
96
84
|
if (existing) return existing;
|
|
97
|
-
if (modules.size >=
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
file = (0, parser_namespaceObject.parse)(input.source, {
|
|
101
|
-
sourceType: 'module',
|
|
102
|
-
sourceFilename: input.id,
|
|
103
|
-
plugins: [
|
|
104
|
-
"typescript"
|
|
105
|
-
]
|
|
106
|
-
});
|
|
107
|
-
} catch (cause) {
|
|
108
|
-
if ('object' == typeof cause && null !== cause && 'code' in cause && 'BABEL_PARSER_SYNTAX_ERROR' === cause.code && 'reasonCode' in cause && 'string' == typeof cause.reasonCode) throw invalidSource('Invalid API syntax');
|
|
109
|
-
throw cause;
|
|
110
|
-
}
|
|
85
|
+
if (modules.size >= MAX_API_SOURCE_MODULES || input.source.length > 1000000) throw new external_source_analysis_cjs_namespaceObject.SourceSyntaxError('API source budget exceeded');
|
|
86
|
+
const file = (0, external_source_analysis_cjs_namespaceObject.parseSource)(input.source, input.id, 'Invalid API syntax');
|
|
111
87
|
const module = {
|
|
112
88
|
...input,
|
|
113
89
|
file
|
|
114
90
|
};
|
|
115
91
|
modules.set(input.id, module);
|
|
116
|
-
|
|
117
|
-
hub: new SourceValidationHub(),
|
|
118
|
-
parentPath: void 0,
|
|
119
|
-
parent: file,
|
|
120
|
-
container: file,
|
|
121
|
-
key: 'program'
|
|
122
|
-
});
|
|
123
|
-
program.setContext();
|
|
124
|
-
traverse_default()(file, {
|
|
92
|
+
(0, external_source_analysis_cjs_namespaceObject.traverseSource)(file, {
|
|
125
93
|
enter (nodePath) {
|
|
126
94
|
paths.set(nodePath.node, nodePath);
|
|
127
95
|
owners.set(nodePath.node, module);
|
|
@@ -140,7 +108,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
140
108
|
if (binding) mutated.add(binding);
|
|
141
109
|
}
|
|
142
110
|
}
|
|
143
|
-
}
|
|
111
|
+
});
|
|
144
112
|
return module;
|
|
145
113
|
};
|
|
146
114
|
try {
|
|
@@ -149,10 +117,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
149
117
|
source,
|
|
150
118
|
resolveImport
|
|
151
119
|
});
|
|
152
|
-
const unwrap = (node)=>
|
|
153
|
-
while(types_namespaceObject.isParenthesizedExpression(node) || types_namespaceObject.isTSSatisfiesExpression(node) || types_namespaceObject.isTSAsExpression(node) || types_namespaceObject.isTSTypeAssertion(node) || types_namespaceObject.isTSNonNullExpression(node))node = node.expression;
|
|
154
|
-
return node;
|
|
155
|
-
};
|
|
120
|
+
const unwrap = (node)=>(0, external_source_analysis_cjs_namespaceObject.unwrapExpression)(node, true);
|
|
156
121
|
const binding = (node)=>{
|
|
157
122
|
node = unwrap(node);
|
|
158
123
|
if (!types_namespaceObject.isIdentifier(node)) return;
|
|
@@ -281,7 +246,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
281
246
|
if (!types_namespaceObject.isBlockStatement(body)) return body;
|
|
282
247
|
const statements = body.body;
|
|
283
248
|
const last = statements.at(-1);
|
|
284
|
-
return statements.slice(0, -1).every((statement)=>types_namespaceObject.isVariableDeclaration(statement)) && types_namespaceObject.isReturnStatement(last) ? last.argument : void 0;
|
|
249
|
+
return statements.slice(0, -1).every((statement)=>types_namespaceObject.isVariableDeclaration(statement) || types_namespaceObject.isTSTypeAliasDeclaration(statement) || types_namespaceObject.isTSInterfaceDeclaration(statement)) && types_namespaceObject.isReturnStatement(last) ? last.argument : void 0;
|
|
285
250
|
};
|
|
286
251
|
const pipe = (node, check)=>types_namespaceObject.isMemberExpression(node.callee) && !node.callee.computed && types_namespaceObject.isIdentifier(node.callee.property, {
|
|
287
252
|
name: 'pipe'
|
|
@@ -370,7 +335,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
370
335
|
if (value?.name === 'defineEffectBff' && [
|
|
371
336
|
edge,
|
|
372
337
|
nodeRuntime
|
|
373
|
-
].includes(value.specifier) || value?.name === 'assembleEffectBffRuntime' &&
|
|
338
|
+
].includes(value.specifier) || value?.name === 'assembleEffectBffRuntime' && value.specifier === assembly) {
|
|
374
339
|
if (1 !== node.arguments.length) return false;
|
|
375
340
|
const values = properties(node.arguments[0]);
|
|
376
341
|
if (!values) return false;
|
|
@@ -393,7 +358,7 @@ function strictEffectRuntimeTopologyViolation(source, resolveImport) {
|
|
|
393
358
|
const root = entry.file.program.body.find((statement)=>types_namespaceObject.isExportDefaultDeclaration(statement));
|
|
394
359
|
return root && runtime(root.declaration) ? void 0 : failure;
|
|
395
360
|
} catch (cause) {
|
|
396
|
-
if (
|
|
361
|
+
if (cause instanceof external_source_analysis_cjs_namespaceObject.SourceSyntaxError) return failure;
|
|
397
362
|
const message = 'object' == typeof cause && null !== cause && 'message' in cause && 'string' == typeof cause.message ? cause.message : String(cause);
|
|
398
363
|
throw new Error(`Strict Effect API analysis failed: ${message}`, {
|
|
399
364
|
cause
|
|
@@ -1,54 +1,24 @@
|
|
|
1
1
|
import node_fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import node_path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import traverse, { Hub, NodePath } from "@babel/traverse";
|
|
4
|
+
import { exports as external_resolve_exports_exports } from "resolve.exports";
|
|
5
5
|
import { baselinePublicIdentityIsExact } from "./microvertical-api-owner.js";
|
|
6
|
+
import { SourceSyntaxError, parseSource, traverseSource, unwrapExpression } from "./source-analysis.js";
|
|
6
7
|
import * as __rspack_external__babel_types_6e8337dd from "@babel/types";
|
|
7
|
-
const consumerParserPlugins = (filePath)=>filePath.endsWith('.tsx') || filePath.endsWith('.jsx') ? [
|
|
8
|
-
"typescript",
|
|
9
|
-
'jsx'
|
|
10
|
-
] : [
|
|
11
|
-
"typescript"
|
|
12
|
-
];
|
|
13
|
-
class ConsumerSyntaxError extends Error {
|
|
14
|
-
}
|
|
15
|
-
class ConsumerValidationHub extends Hub {
|
|
16
|
-
buildError(_node, message) {
|
|
17
|
-
return new ConsumerSyntaxError(message);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
8
|
function parseConsumer(filePath) {
|
|
21
9
|
if (node_fs.statSync(filePath).size > 1000000) throw new Error(`${filePath}: consumer source exceeds 1 MB analysis budget`);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
file = parse(node_fs.readFileSync(filePath, 'utf8'), {
|
|
25
|
-
sourceType: 'module',
|
|
26
|
-
sourceFilename: filePath,
|
|
27
|
-
plugins: consumerParserPlugins(filePath)
|
|
28
|
-
});
|
|
29
|
-
} catch (error) {
|
|
30
|
-
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));
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
const program = NodePath.get({
|
|
34
|
-
hub: new ConsumerValidationHub(),
|
|
35
|
-
parentPath: void 0,
|
|
36
|
-
parent: file,
|
|
37
|
-
container: file,
|
|
38
|
-
key: 'program'
|
|
39
|
-
});
|
|
40
|
-
program.setContext();
|
|
41
|
-
traverse(file, {
|
|
10
|
+
const file = parseSource(node_fs.readFileSync(filePath, 'utf8'), filePath);
|
|
11
|
+
traverseSource(file, {
|
|
42
12
|
AssignmentExpression (p) {
|
|
43
|
-
throw new
|
|
13
|
+
throw new SourceSyntaxError(`contract bindings must be immutable at ${p.node.start}`);
|
|
44
14
|
},
|
|
45
15
|
UpdateExpression (p) {
|
|
46
|
-
throw new
|
|
16
|
+
throw new SourceSyntaxError(`contract bindings must be immutable at ${p.node.start}`);
|
|
47
17
|
},
|
|
48
18
|
TSModuleDeclaration () {
|
|
49
|
-
throw new
|
|
19
|
+
throw new SourceSyntaxError('contract bindings must not be merged with namespaces');
|
|
50
20
|
}
|
|
51
|
-
}
|
|
21
|
+
});
|
|
52
22
|
return file;
|
|
53
23
|
}
|
|
54
24
|
const camelCaseStem = (stem)=>stem.replaceAll(/-([a-z0-9])/gu, (_match, letter)=>letter.toUpperCase());
|
|
@@ -73,11 +43,6 @@ const accessPath = (node)=>{
|
|
|
73
43
|
}
|
|
74
44
|
};
|
|
75
45
|
const isAccessPath = (node, expected)=>accessPath(node)?.join('.') === expected.join('.');
|
|
76
|
-
const unwrapExpression = (expression)=>{
|
|
77
|
-
let current = expression;
|
|
78
|
-
while(__rspack_external__babel_types_6e8337dd.isTSAsExpression(current) || __rspack_external__babel_types_6e8337dd.isParenthesizedExpression(current) || __rspack_external__babel_types_6e8337dd.isTSSatisfiesExpression(current))current = current.expression;
|
|
79
|
-
return current;
|
|
80
|
-
};
|
|
81
46
|
const stringLiteral = (expression)=>{
|
|
82
47
|
if (null == expression) return;
|
|
83
48
|
const unwrapped = unwrapExpression(expression);
|
|
@@ -118,16 +83,81 @@ const exportedConst = (sourceFile, name)=>{
|
|
|
118
83
|
}))) return localConst(sourceFile, name);
|
|
119
84
|
}
|
|
120
85
|
};
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
86
|
+
const inside = (file, boundary)=>file === boundary || file.startsWith(`${boundary}${node_path.sep}`);
|
|
87
|
+
const containingWorkspace = (file)=>{
|
|
88
|
+
for(let directory = node_path.dirname(file);; directory = node_path.dirname(directory)){
|
|
89
|
+
if (node_fs.existsSync(node_path.join(directory, 'pnpm-workspace.yaml'))) return node_fs.realpathSync(directory);
|
|
90
|
+
if (directory === node_path.dirname(directory)) return;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const sourceBoundary = (file, workspace)=>{
|
|
94
|
+
for(let directory = node_path.dirname(file);; directory = node_path.dirname(directory)){
|
|
95
|
+
if (node_fs.existsSync(node_path.join(directory, 'package.json')) && directory !== workspace) return node_fs.realpathSync(directory);
|
|
96
|
+
if (directory === workspace || directory === node_path.dirname(directory)) return node_fs.realpathSync(node_path.dirname(file));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const sourceFileAt = (target, boundary)=>{
|
|
100
|
+
const stem = target.replace(/\.(?:[cm]?[jt]sx?)$/u, '');
|
|
125
101
|
for (const candidate of [
|
|
126
102
|
`${stem}.ts`,
|
|
127
103
|
`${stem}.tsx`,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
104
|
+
`${stem}.mts`,
|
|
105
|
+
`${stem}.cts`,
|
|
106
|
+
target,
|
|
107
|
+
node_path.join(target, 'index.ts'),
|
|
108
|
+
node_path.join(target, 'index.tsx')
|
|
109
|
+
])try {
|
|
110
|
+
const real = node_fs.realpathSync(candidate);
|
|
111
|
+
if (inside(real, boundary) && node_fs.statSync(real).isFile()) return real;
|
|
112
|
+
} catch {}
|
|
113
|
+
};
|
|
114
|
+
const packageEntry = (specifier)=>{
|
|
115
|
+
if (specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('#')) return;
|
|
116
|
+
const parts = specifier.split('/');
|
|
117
|
+
const count = specifier.startsWith('@') ? 2 : 1;
|
|
118
|
+
if (parts.length < count || parts.slice(0, count).some((part)=>!part)) return;
|
|
119
|
+
return {
|
|
120
|
+
name: parts.slice(0, count).join('/'),
|
|
121
|
+
exportKey: parts.length === count ? '.' : `./${parts.slice(count).join('/')}`
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
const resolveModulePath = (module, specifier, workspace)=>{
|
|
125
|
+
if (/^\.\.?\//u.test(specifier)) {
|
|
126
|
+
const file = sourceFileAt(node_path.resolve(node_path.dirname(module.path), specifier), module.boundary);
|
|
127
|
+
return void 0 === file ? void 0 : {
|
|
128
|
+
path: file,
|
|
129
|
+
boundary: module.boundary
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const entry = packageEntry(specifier);
|
|
133
|
+
if (!entry || !workspace) return;
|
|
134
|
+
const paths = createRequire(module.path).resolve.paths(entry.name) ?? [];
|
|
135
|
+
for (const lookup of paths){
|
|
136
|
+
const directory = node_path.join(lookup, entry.name);
|
|
137
|
+
const manifest = node_path.join(directory, 'package.json');
|
|
138
|
+
if (!node_fs.existsSync(manifest)) continue;
|
|
139
|
+
const boundary = node_fs.realpathSync(directory);
|
|
140
|
+
if (!inside(boundary, workspace) || boundary.split(node_path.sep).includes('node_modules')) break;
|
|
141
|
+
const pkg = JSON.parse(node_fs.readFileSync(manifest, 'utf8'));
|
|
142
|
+
if (pkg.name !== entry.name || void 0 === pkg.exports) break;
|
|
143
|
+
let target;
|
|
144
|
+
try {
|
|
145
|
+
const targets = external_resolve_exports_exports(pkg, entry.exportKey, {
|
|
146
|
+
conditions: [
|
|
147
|
+
'modern:source'
|
|
148
|
+
]
|
|
149
|
+
});
|
|
150
|
+
target = Array.isArray(targets) ? targets[0] : void 0;
|
|
151
|
+
} catch {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (!target || !target.startsWith('./')) break;
|
|
155
|
+
const file = sourceFileAt(node_path.resolve(boundary, target), boundary);
|
|
156
|
+
return void 0 === file ? void 0 : {
|
|
157
|
+
path: file,
|
|
158
|
+
boundary
|
|
159
|
+
};
|
|
160
|
+
}
|
|
131
161
|
};
|
|
132
162
|
const createModuleReader = (root)=>{
|
|
133
163
|
const modules = new Map([
|
|
@@ -136,14 +166,15 @@ const createModuleReader = (root)=>{
|
|
|
136
166
|
root
|
|
137
167
|
]
|
|
138
168
|
]);
|
|
139
|
-
return (filePath)=>{
|
|
169
|
+
return (filePath, boundary)=>{
|
|
140
170
|
if (modules.has(filePath)) return modules.get(filePath);
|
|
141
171
|
if (modules.size >= 256) return;
|
|
142
172
|
let module;
|
|
143
173
|
try {
|
|
144
174
|
module = {
|
|
145
175
|
file: parseConsumer(filePath),
|
|
146
|
-
path: filePath
|
|
176
|
+
path: filePath,
|
|
177
|
+
boundary
|
|
147
178
|
};
|
|
148
179
|
} catch {
|
|
149
180
|
module = void 0;
|
|
@@ -173,7 +204,7 @@ const reexportedBinding = (module, name)=>{
|
|
|
173
204
|
if (!__rspack_external__babel_types_6e8337dd.isExportNamedDeclaration(statement) || 'type' === statement.exportKind) continue;
|
|
174
205
|
const specifier = statement.specifiers.find((value)=>__rspack_external__babel_types_6e8337dd.isExportSpecifier(value) && 'type' !== value.exportKind && propertyName(value.exported) === name);
|
|
175
206
|
if (void 0 !== specifier && __rspack_external__babel_types_6e8337dd.isExportSpecifier(specifier)) return {
|
|
176
|
-
local: specifier.local.name,
|
|
207
|
+
local: __rspack_external__babel_types_6e8337dd.isIdentifier(specifier.local) ? specifier.local.name : specifier.local.value,
|
|
177
208
|
...statement.source ? {
|
|
178
209
|
specifier: statement.source.value
|
|
179
210
|
} : {}
|
|
@@ -188,7 +219,7 @@ const defaultExport = (module)=>{
|
|
|
188
219
|
return __rspack_external__babel_types_6e8337dd.isExpression(declaration) ? declaration : void 0;
|
|
189
220
|
}
|
|
190
221
|
};
|
|
191
|
-
const resolveBinding = (module, name, scope, readModule, seen)=>{
|
|
222
|
+
const resolveBinding = (module, name, scope, readModule, workspace, seen)=>{
|
|
192
223
|
const key = `${scope}:${module.path}#${name}`;
|
|
193
224
|
if (seen.has(key) || seen.size >= 512) return;
|
|
194
225
|
seen.add(key);
|
|
@@ -198,9 +229,9 @@ const resolveBinding = (module, name, scope, readModule, seen)=>{
|
|
|
198
229
|
module
|
|
199
230
|
};
|
|
200
231
|
const throughModule = (specifier, imported)=>{
|
|
201
|
-
const
|
|
202
|
-
const target =
|
|
203
|
-
return void 0 === target ? void 0 : resolveBinding(target, imported, 'export', readModule, seen);
|
|
232
|
+
const resolved = resolveModulePath(module, specifier, workspace);
|
|
233
|
+
const target = resolved && readModule(resolved.path, resolved.boundary);
|
|
234
|
+
return void 0 === target ? void 0 : resolveBinding(target, imported, 'export', readModule, workspace, seen);
|
|
204
235
|
};
|
|
205
236
|
if ('local' === scope) {
|
|
206
237
|
const imported = importedBinding(module, name);
|
|
@@ -208,14 +239,14 @@ const resolveBinding = (module, name, scope, readModule, seen)=>{
|
|
|
208
239
|
}
|
|
209
240
|
if ('default' === name) {
|
|
210
241
|
const exported = defaultExport(module);
|
|
211
|
-
if ('string' == typeof exported) return resolveBinding(module, exported, 'local', readModule, seen);
|
|
242
|
+
if ('string' == typeof exported) return resolveBinding(module, exported, 'local', readModule, workspace, seen);
|
|
212
243
|
return void 0 === exported ? void 0 : {
|
|
213
244
|
expression: exported,
|
|
214
245
|
module
|
|
215
246
|
};
|
|
216
247
|
}
|
|
217
248
|
const reexported = reexportedBinding(module, name);
|
|
218
|
-
if (void 0 !== reexported) return void 0 === reexported.specifier ? resolveBinding(module, reexported.local, 'local', readModule, seen) : throughModule(reexported.specifier, reexported.local);
|
|
249
|
+
if (void 0 !== reexported) return void 0 === reexported.specifier ? resolveBinding(module, reexported.local, 'local', readModule, workspace, seen) : throughModule(reexported.specifier, reexported.local);
|
|
219
250
|
for (const statement of module.file.program.body){
|
|
220
251
|
if (!__rspack_external__babel_types_6e8337dd.isExportAllDeclaration(statement) || 'type' === statement.exportKind) continue;
|
|
221
252
|
const resolved = throughModule(statement.source.value, name);
|
|
@@ -369,6 +400,7 @@ const nonEndpointCombinators = {
|
|
|
369
400
|
};
|
|
370
401
|
const reachableEndpoints = (rootModule, declaration)=>{
|
|
371
402
|
const readModule = createModuleReader(rootModule);
|
|
403
|
+
const workspace = containingWorkspace(rootModule.path);
|
|
372
404
|
const active = new Set();
|
|
373
405
|
const endpoints = [];
|
|
374
406
|
const identities = new Set();
|
|
@@ -390,7 +422,7 @@ const reachableEndpoints = (rootModule, declaration)=>{
|
|
|
390
422
|
active.add(node);
|
|
391
423
|
try {
|
|
392
424
|
if (__rspack_external__babel_types_6e8337dd.isIdentifier(node)) {
|
|
393
|
-
const resolved = resolveBinding(module, node.name, 'local', readModule, new Set());
|
|
425
|
+
const resolved = resolveBinding(module, node.name, 'local', readModule, workspace, new Set());
|
|
394
426
|
return void 0 !== resolved && visit(resolved.expression, resolved.module, kind, group);
|
|
395
427
|
}
|
|
396
428
|
if ('endpoint' === kind) {
|
|
@@ -607,15 +639,17 @@ const configuredMicroVerticalApiStem = (verticalPath, verticals)=>{
|
|
|
607
639
|
};
|
|
608
640
|
const microVerticalApiBaselineViolation = (stem, filePath, expectation)=>{
|
|
609
641
|
try {
|
|
610
|
-
const
|
|
642
|
+
const realPath = node_fs.realpathSync(filePath);
|
|
643
|
+
const sourceFile = parseConsumer(realPath);
|
|
611
644
|
if (!baselinePublicIdentityIsExact(filePath, expectation)) return 'MicroVertical baseline imports must resolve the exact framework owner public export and schema identity';
|
|
612
645
|
return validateParsedContract({
|
|
613
646
|
file: sourceFile,
|
|
614
|
-
path:
|
|
647
|
+
path: realPath,
|
|
648
|
+
boundary: sourceBoundary(realPath, containingWorkspace(realPath))
|
|
615
649
|
}, stem, expectation);
|
|
616
650
|
} catch (error) {
|
|
617
|
-
if (error instanceof
|
|
651
|
+
if (error instanceof SourceSyntaxError) return `MicroVertical root contract must be valid TypeScript syntax (${error.message})`;
|
|
618
652
|
throw error;
|
|
619
653
|
}
|
|
620
654
|
};
|
|
621
|
-
export { configuredMicroVerticalApiStem,
|
|
655
|
+
export { configuredMicroVerticalApiStem, microVerticalApiBaselineViolation };
|