@_linked/cli 1.31.0 → 1.32.0
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/CHANGELOG.md +30 -0
- package/defaults/app-react-native/packages/app-shapes/src/index.ts +2 -0
- package/defaults/app-react-native/packages/app-shapes/src/shapes/index.ts +5 -0
- package/defaults/package/src/shapes/index.ts +3 -1
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +144 -118
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/utils/shapeReferences.d.ts +10 -7
- package/lib/esm/utils/shapeReferences.d.ts.map +1 -1
- package/lib/esm/utils/shapeReferences.js +13 -18
- package/lib/esm/utils/shapeReferences.js.map +1 -1
- package/lib/esm/utils/shapesIndex.d.ts +21 -0
- package/lib/esm/utils/shapesIndex.d.ts.map +1 -0
- package/lib/esm/utils/shapesIndex.js +204 -0
- package/lib/esm/utils/shapesIndex.js.map +1 -0
- package/package.json +1 -1
|
@@ -50,6 +50,13 @@ export interface ShapeReferenceReport {
|
|
|
50
50
|
unresolved: UnresolvedShapeReference[];
|
|
51
51
|
/** Unresolved references that match {@link KNOWN_UNRESOLVED}. */
|
|
52
52
|
known: UnresolvedShapeReference[];
|
|
53
|
+
/**
|
|
54
|
+
* The package's own shapes (by IRI) registered after loading each module on
|
|
55
|
+
* its own, keyed like {@link modules}. Read before the probe loads any entry
|
|
56
|
+
* for its second look, so it is exactly what that one module registers.
|
|
57
|
+
* Modules that threw are absent.
|
|
58
|
+
*/
|
|
59
|
+
registered: Record<string, string[]>;
|
|
53
60
|
/** Set when the registry could not be inspected, so nothing was checked. */
|
|
54
61
|
skipped?: string;
|
|
55
62
|
}
|
|
@@ -61,12 +68,8 @@ export interface ShapeReferenceReport {
|
|
|
61
68
|
* accepted design. No package was found with a legitimate reason to leave a
|
|
62
69
|
* reference unresolved; add an opt-out mechanism when one turns up.
|
|
63
70
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* loads `List`, so a process that deep-imports core without its entry cannot
|
|
67
|
-
* traverse `sh:in`. Tracked as core's backlog-045; core builds with `linked
|
|
68
|
-
* build-all`, which must not fail on it meanwhile. Remove this entry once
|
|
69
|
-
* core registers `List` wherever `PropertyShape` is registered.
|
|
71
|
+
* Empty: `@_linked/core`'s `PropertyShape.in -> List`, the one entry this held,
|
|
72
|
+
* is fixed in core (List is registered wherever PropertyShape is).
|
|
70
73
|
*/
|
|
71
74
|
export declare const KNOWN_UNRESOLVED: {
|
|
72
75
|
package: string;
|
|
@@ -91,7 +94,7 @@ export declare const inspectShapeReferences: (packagePath: string, { concurrency
|
|
|
91
94
|
* bug the package would ship, and it only surfaces in a consumer's bundle. The
|
|
92
95
|
* references in {@link KNOWN_UNRESOLVED} warn instead.
|
|
93
96
|
*/
|
|
94
|
-
export declare const checkShapeReferences: (packagePath: string, options?: Parameters<typeof inspectShapeReferences>[1]) => Promise<true | string | {
|
|
97
|
+
export declare const checkShapeReferences: (packagePath: string, options?: Parameters<typeof inspectShapeReferences>[1], inspection?: Promise<ShapeReferenceReport>) => Promise<true | string | {
|
|
95
98
|
error: string;
|
|
96
99
|
}>;
|
|
97
100
|
//# sourceMappingURL=shapeReferences.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapeReferences.d.ts","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC;IAClE,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,UAAU,EAAE,wBAAwB,EAAE,CAAC;IACvC,iEAAiE;IACjE,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"shapeReferences.d.ts","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC;IAClE,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,UAAU,EAAE,wBAAwB,EAAE,CAAC;IACvC,iEAAiE;IACjE,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAClC;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,EAAO,CAAC;AAET,mGAAmG;AACnG,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,MAKtC,CAAC;AA0InB,uGAAuG;AACvG,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAAM,EAuBvD,CAAC;AAoBF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,MAAM,EACnB;;;CAGM,KACL,OAAO,CAAC,oBAAoB,CA6F9B,CAAC;AAsBF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,EACnB,UAAU,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,EACtD,aAAa,OAAO,CAAC,oBAAoB,CAAC,KACzC,OAAO,CAAC,IAAI,GAAG,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA4BzC,CAAC"}
|
|
@@ -20,21 +20,10 @@ import { declaresShape } from './shapeNames.js';
|
|
|
20
20
|
* accepted design. No package was found with a legitimate reason to leave a
|
|
21
21
|
* reference unresolved; add an opt-out mechanism when one turns up.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* loads `List`, so a process that deep-imports core without its entry cannot
|
|
26
|
-
* traverse `sh:in`. Tracked as core's backlog-045; core builds with `linked
|
|
27
|
-
* build-all`, which must not fail on it meanwhile. Remove this entry once
|
|
28
|
-
* core registers `List` wherever `PropertyShape` is registered.
|
|
23
|
+
* Empty: `@_linked/core`'s `PropertyShape.in -> List`, the one entry this held,
|
|
24
|
+
* is fixed in core (List is registered wherever PropertyShape is).
|
|
29
25
|
*/
|
|
30
|
-
export const KNOWN_UNRESOLVED = [
|
|
31
|
-
{
|
|
32
|
-
package: '@_linked/core',
|
|
33
|
-
shape: '/shape/core/PropertyShape',
|
|
34
|
-
property: 'in',
|
|
35
|
-
valueShape: '/shape/core/List',
|
|
36
|
-
},
|
|
37
|
-
];
|
|
26
|
+
export const KNOWN_UNRESOLVED = [];
|
|
38
27
|
/** arch-02: the `{slug}` in `{baseUri}shape/{slug}/{Name}`. Mirrors core's `packageNameToSlug`. */
|
|
39
28
|
export const packageNameToSlug = (packageName) => packageName
|
|
40
29
|
.replace(/^@[^/]+\//, '')
|
|
@@ -72,7 +61,7 @@ const PROBE = `
|
|
|
72
61
|
import {register} from 'node:module';
|
|
73
62
|
register('data:text/javascript,' + encodeURIComponent(${JSON.stringify(ASSET_HOOK)}));
|
|
74
63
|
const MARK = '__LINKED_SHAPE_REFERENCES__';
|
|
75
|
-
const out = {error: null, unresolved: [], registry: true};
|
|
64
|
+
const out = {error: null, unresolved: [], registry: true, registered: []};
|
|
76
65
|
const reg = () => globalThis.__linkedShapeRegistry;
|
|
77
66
|
const ownSlug = process.env.LINKED_PROBE_SLUG;
|
|
78
67
|
const report = () => {
|
|
@@ -84,6 +73,10 @@ try {
|
|
|
84
73
|
if (!r || !r.nodeShapeRegistry) {
|
|
85
74
|
out.registry = false;
|
|
86
75
|
} else {
|
|
76
|
+
// Before the second look below: that loads whole entries and would add theirs.
|
|
77
|
+
for (const id of r.nodeShapeRegistry.keys()) {
|
|
78
|
+
if (id.includes('/shape/' + ownSlug + '/')) out.registered.push(id);
|
|
79
|
+
}
|
|
87
80
|
for (const [id, ns] of r.nodeShapeRegistry) {
|
|
88
81
|
if (!id.includes('/shape/' + ownSlug + '/')) continue;
|
|
89
82
|
for (const ps of ns.propertyShapes || []) {
|
|
@@ -135,7 +128,7 @@ const runProbe = (modulePath, packagePath, env, timeoutMs) => new Promise((resol
|
|
|
135
128
|
? `did not finish loading within ${timeoutMs}ms`
|
|
136
129
|
: String(stderr).trim().split('\n').slice(-4).join('\n') ||
|
|
137
130
|
String(err || 'exited without reporting');
|
|
138
|
-
resolve({ error: why, registry: true, unresolved: [] });
|
|
131
|
+
resolve({ error: why, registry: true, registered: [], unresolved: [] });
|
|
139
132
|
});
|
|
140
133
|
});
|
|
141
134
|
/** Every compiled module that declares a shape: all of `shapes/`, plus decorated classes elsewhere. */
|
|
@@ -191,6 +184,7 @@ export const inspectShapeReferences = (packagePath_1, ...args_1) => __awaiter(vo
|
|
|
191
184
|
loadErrors: [],
|
|
192
185
|
unresolved: [],
|
|
193
186
|
known: [],
|
|
187
|
+
registered: {},
|
|
194
188
|
};
|
|
195
189
|
if (modules.length === 0)
|
|
196
190
|
return report;
|
|
@@ -242,6 +236,7 @@ export const inspectShapeReferences = (packagePath_1, ...args_1) => __awaiter(vo
|
|
|
242
236
|
report.loadErrors.push({ module, error: r.error });
|
|
243
237
|
return;
|
|
244
238
|
}
|
|
239
|
+
report.registered[module] = r.registered;
|
|
245
240
|
for (const u of r.unresolved) {
|
|
246
241
|
const key = `${u.shape}\u0000${u.property}\u0000${u.valueShape}`;
|
|
247
242
|
const existing = byReference.get(key);
|
|
@@ -280,8 +275,8 @@ const describeReference = (ref) => {
|
|
|
280
275
|
* bug the package would ship, and it only surfaces in a consumer's bundle. The
|
|
281
276
|
* references in {@link KNOWN_UNRESOLVED} warn instead.
|
|
282
277
|
*/
|
|
283
|
-
export const checkShapeReferences = (packagePath, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
284
|
-
const report = yield inspectShapeReferences(packagePath, options);
|
|
278
|
+
export const checkShapeReferences = (packagePath, options, inspection) => __awaiter(void 0, void 0, void 0, function* () {
|
|
279
|
+
const report = yield (inspection !== null && inspection !== void 0 ? inspection : inspectShapeReferences(packagePath, options));
|
|
285
280
|
if (report.skipped)
|
|
286
281
|
return `skipped: ${report.skipped}`;
|
|
287
282
|
const problems = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapeReferences.js","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {execFile} from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport {declaresShape} from './shapeNames.js';\n\n/**\n * Checking shape references: does loading a compiled shape module, on its own,\n * register every shape its properties point at?\n *\n * A property can name its value shape by `[package, name]` instead of by class\n * (`shape: ['@_linked/schema', 'ImageObject']`), usually because importing the\n * class would close an import cycle. That names the shape without loading it.\n * A shape registers only when its module is evaluated, and consumers deep-import\n * single shape modules (`@_linked/schema/shapes/Thing`), so nothing guarantees\n * the named shape is registered when a query traverses the property. The query\n * then throws `Shape class not found for …/ImageObject` — in a production bundle,\n * far from the cause. A reference to a package under an old name\n * (`['lincd-sioc', …]`) can never resolve at all.\n *\n * So each module is loaded the way a consumer's fresh process would load it: in\n * a child `node` of its own, with nothing else imported first. Separate processes\n * rather than one process re-importing: ESM has no module-cache eviction, and the\n * shape registry lives on `globalThis`, so a second module in the same process\n * would see every shape the first one registered.\n */\n\n/** One module that could not be evaluated. */\nexport interface ShapeModuleLoadError {\n module: string;\n error: string;\n}\n\n/**\n * A property whose value shape was not registered after loading `modules`\n * (each on its own). One entry per distinct reference, however many modules\n * showed it.\n */\nexport interface UnresolvedShapeReference {\n shape: string;\n property: string;\n valueShape: string;\n modules: string[];\n /**\n * What the target package's entry does for it: `registered` — loading the\n * entry registers it, so the referencing module just does not import it;\n * `missing` — not even the entry registers it, so the name or package is\n * wrong; `not-a-dependency` — the IRI's package is neither this package nor\n * one of its dependencies; `unknown` — the entry could not be loaded.\n */\n target: 'registered' | 'missing' | 'not-a-dependency' | 'unknown';\n /** The package the IRI's slug maps to, when one does. */\n targetPackage?: string;\n}\n\nexport interface ShapeReferenceReport {\n modules: string[];\n loadErrors: ShapeModuleLoadError[];\n unresolved: UnresolvedShapeReference[];\n /** Unresolved references that match {@link KNOWN_UNRESOLVED}. */\n known: UnresolvedShapeReference[];\n /** Set when the registry could not be inspected, so nothing was checked. */\n skipped?: string;\n}\n\n/**\n * References known to be unresolved, reported as warnings rather than failures.\n *\n * This is deliberately a list in the CLI rather than an opt-out a package can\n * write for itself: every entry is a shipped bug with a tracked fix, not an\n * accepted design. No package was found with a legitimate reason to leave a\n * reference unresolved; add an opt-out mechanism when one turns up.\n *\n * - `@_linked/core`: `PropertyShape.in` names `List` by `[package, name]`\n * because `List`'s module depends on the SHACL shapes. Only core's entry\n * loads `List`, so a process that deep-imports core without its entry cannot\n * traverse `sh:in`. Tracked as core's backlog-045; core builds with `linked\n * build-all`, which must not fail on it meanwhile. Remove this entry once\n * core registers `List` wherever `PropertyShape` is registered.\n */\nexport const KNOWN_UNRESOLVED: {\n package: string;\n shape: string;\n property: string;\n valueShape: string;\n}[] = [\n {\n package: '@_linked/core',\n shape: '/shape/core/PropertyShape',\n property: 'in',\n valueShape: '/shape/core/List',\n },\n];\n\n/** arch-02: the `{slug}` in `{baseUri}shape/{slug}/{Name}`. Mirrors core's `packageNameToSlug`. */\nexport const packageNameToSlug = (packageName: string): string =>\n packageName\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n\n/** The slug in a node-shape IRI, or undefined when it is not shaped like one. */\nconst slugOf = (iri: string): string | undefined =>\n iri.match(/\\/shape\\/([^/]+)\\/[^/]+$/)?.[1];\n\n/**\n * A loader hook for the child: asset imports (`import styles from\n * './X.module.css'`) evaluate to a stub. Node cannot load them and a consumer's\n * bundler always can, so without this a shape module whose file also holds a\n * component would look broken when it is not. A CSS-module stub maps every\n * class name to itself.\n */\nconst ASSET_HOOK = `\nconst ASSET = /\\\\.(css|scss|sass|less|styl|svg|png|jpe?g|gif|webp|avif|ico|woff2?|ttf|otf|eot)$/i;\nexport async function load(url, context, next) {\n if (url.startsWith('file:') && ASSET.test(new URL(url).pathname)) {\n return {format: 'module', shortCircuit: true,\n source: 'export default new Proxy({}, {get: (_, k) => typeof k === \"string\" ? k : undefined});'};\n }\n return next(url, context);\n}\n`;\n\n/**\n * The script each child runs. Plain JS, passed with `-e`, so it runs the same\n * from `src` under a test runner as from the published `lib`.\n *\n * It reads the registry from `globalThis.__linkedShapeRegistry` rather than\n * importing `@_linked/core`: the module under test decides which copy of core\n * it loads, and the registry is shared by every copy.\n */\nconst PROBE = `\nimport {register} from 'node:module';\nregister('data:text/javascript,' + encodeURIComponent(${JSON.stringify(ASSET_HOOK)}));\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\nconst out = {error: null, unresolved: [], registry: true};\nconst reg = () => globalThis.__linkedShapeRegistry;\nconst ownSlug = process.env.LINKED_PROBE_SLUG;\nconst report = () => {\n process.stdout.write('\\\\n' + MARK + JSON.stringify(out) + '\\\\n', () => process.exit(0));\n};\ntry {\n await import(process.env.LINKED_PROBE_MODULE);\n const r = reg();\n if (!r || !r.nodeShapeRegistry) {\n out.registry = false;\n } else {\n for (const [id, ns] of r.nodeShapeRegistry) {\n if (!id.includes('/shape/' + ownSlug + '/')) continue;\n for (const ps of ns.propertyShapes || []) {\n const v = ps.valueShape && ps.valueShape.id;\n if (v && !r.nodeShapeRegistry.has(v)) {\n out.unresolved.push({shape: id, property: ps.label, valueShape: v});\n }\n }\n }\n // For each unresolved target, load its package's entry and look again: that\n // tells a missing import apart from a name that can never resolve.\n const entries = JSON.parse(process.env.LINKED_PROBE_ENTRIES || '{}');\n const tried = {};\n for (const u of out.unresolved) {\n const slug = (u.valueShape.match(/\\\\/shape\\\\/([^/]+)\\\\/[^/]+$/) || [])[1];\n const entry = entries[slug];\n if (!entry) { u.target = 'not-a-dependency'; continue; }\n u.targetPackage = entry.name;\n if (!(slug in tried)) {\n try { await import(entry.specifier); tried[slug] = true; }\n catch (e) { tried[slug] = false; }\n }\n u.target = !tried[slug] ? 'unknown'\n : reg().nodeShapeRegistry.has(u.valueShape) ? 'registered' : 'missing';\n }\n }\n} catch (e) {\n out.error = e && e.stack ? e.stack.split('\\\\n').slice(0, 4).join('\\\\n') : String(e);\n}\nreport();\n`;\n\ninterface ProbeResult {\n error: string | null;\n registry: boolean;\n unresolved: {\n shape: string;\n property: string;\n valueShape: string;\n target: UnresolvedShapeReference['target'];\n targetPackage?: string;\n }[];\n}\n\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\n\nconst runProbe = (\n modulePath: string,\n packagePath: string,\n env: Record<string, string>,\n timeoutMs: number,\n): Promise<ProbeResult> =>\n new Promise((resolve) => {\n execFile(\n process.execPath,\n ['--input-type=module', '-e', PROBE],\n {\n cwd: packagePath,\n env: {\n ...process.env,\n ...env,\n LINKED_PROBE_MODULE: 'file://' + modulePath,\n },\n timeout: timeoutMs,\n maxBuffer: 64 * 1024 * 1024,\n },\n (err, stdout, stderr) => {\n const line = String(stdout)\n .split('\\n')\n .reverse()\n .find((l) => l.startsWith(MARK));\n if (line) {\n resolve(JSON.parse(line.slice(MARK.length)));\n return;\n }\n const why =\n err && (err as any).killed\n ? `did not finish loading within ${timeoutMs}ms`\n : String(stderr).trim().split('\\n').slice(-4).join('\\n') ||\n String(err || 'exited without reporting');\n resolve({error: why, registry: true, unresolved: []});\n },\n );\n });\n\n/** Every compiled module that declares a shape: all of `shapes/`, plus decorated classes elsewhere. */\nexport const findShapeModules = (libEsm: string): string[] => {\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (\n entry.name.endsWith('.js') &&\n !/\\.(test|spec|class)\\.js$/.test(entry.name)\n ) {\n const rel = path.relative(libEsm, full);\n if (\n rel.split(path.sep)[0] === 'shapes' ||\n declaresShape(fs.readFileSync(full, 'utf8'))\n ) {\n found.push(full);\n }\n }\n }\n };\n if (fs.existsSync(libEsm)) walk(libEsm);\n return found.sort();\n};\n\n/** The name the package registers its shapes under: `linkedPackage('<name>')` in `package.js`. */\nconst runtimePackageName = (libEsm: string, pkgJson: any): string => {\n const pkgModule = path.join(libEsm, 'package.js');\n if (fs.existsSync(pkgModule)) {\n const m = fs\n .readFileSync(pkgModule, 'utf8')\n .match(/linkedPackage\\(\\s*['\"]([^'\"]+)['\"]/);\n if (m) return m[1];\n }\n return pkgJson.name;\n};\n\nconst DEPENDENCY_FIELDS = [\n 'dependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Load each shape module of the package at `packagePath` in isolation and\n * collect load errors and unresolved property value shapes.\n */\nexport const inspectShapeReferences = async (\n packagePath: string,\n {\n concurrency = Math.min(8, Math.max(1, os.cpus().length - 1)),\n timeoutMs = 60000,\n } = {},\n): Promise<ShapeReferenceReport> => {\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const modules = findShapeModules(libEsm);\n const report: ShapeReferenceReport = {\n modules: modules.map((m) => path.relative(libEsm, m)),\n loadErrors: [],\n unresolved: [],\n known: [],\n };\n if (modules.length === 0) return report;\n\n const ownName = runtimePackageName(libEsm, pkgJson);\n // The entry each slug's package is loaded through for the second look. This\n // package's own entry is loaded by path: a package cannot always import\n // itself by name.\n const entries: Record<string, {name: string; specifier: string}> = {};\n for (const field of DEPENDENCY_FIELDS) {\n for (const dep of Object.keys(pkgJson[field] || {})) {\n entries[packageNameToSlug(dep)] = {name: dep, specifier: dep};\n }\n }\n const ownEntry = path.join(\n packagePath,\n pkgJson.module || pkgJson.main || 'lib/esm/index.js',\n );\n for (const name of new Set([ownName, pkgJson.name])) {\n entries[packageNameToSlug(name)] = {\n name,\n specifier: fs.existsSync(ownEntry) ? 'file://' + ownEntry : name,\n };\n }\n const env = {\n LINKED_PROBE_SLUG: packageNameToSlug(ownName),\n LINKED_PROBE_ENTRIES: JSON.stringify(entries),\n };\n\n const results: ProbeResult[] = new Array(modules.length);\n let next = 0;\n await Promise.all(\n Array.from({length: Math.min(concurrency, modules.length)}, async () => {\n while (next < modules.length) {\n const i = next++;\n results[i] = await runProbe(modules[i], packagePath, env, timeoutMs);\n }\n }),\n );\n\n // No registry on `globalThis` after loading a module that declares a shape\n // means a core older than 2.22.3, whose registry is module-scoped. A module\n // under `shapes/` that declares none (a store, a helper) registers nothing.\n const stale = results.findIndex(\n (r, i) =>\n !r.error &&\n !r.registry &&\n declaresShape(fs.readFileSync(modules[i], 'utf8')),\n );\n if (stale !== -1) {\n report.skipped =\n `no shape registry on globalThis after loading ${report.modules[stale]}: the ` +\n '@_linked/core it loads is older than 2.22.3, whose registry cannot be inspected from outside';\n return report;\n }\n\n const byReference = new Map<string, UnresolvedShapeReference>();\n results.forEach((r, i) => {\n const module = report.modules[i];\n if (r.error) {\n report.loadErrors.push({module, error: r.error});\n return;\n }\n for (const u of r.unresolved) {\n const key = `${u.shape}\\u0000${u.property}\\u0000${u.valueShape}`;\n const existing = byReference.get(key);\n if (existing) existing.modules.push(module);\n else byReference.set(key, {...u, modules: [module]});\n }\n });\n for (const ref of byReference.values()) {\n const isKnown = KNOWN_UNRESOLVED.some(\n (k) =>\n k.package === ownName &&\n ref.shape.endsWith(k.shape) &&\n ref.property === k.property &&\n ref.valueShape.endsWith(k.valueShape),\n );\n (isKnown ? report.known : report.unresolved).push(ref);\n }\n return report;\n};\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\nconst modulesList = (modules: string[]) =>\n modules.length <= 3\n ? modules.join(', ')\n : `${modules.slice(0, 3).join(', ')} and ${modules.length - 3} more`;\n\nconst describeReference = (ref: UnresolvedShapeReference): string => {\n const label = `${shortIri(ref.shape)}.${ref.property} -> ${ref.valueShape}`;\n const fix =\n ref.target === 'registered'\n ? `${ref.targetPackage}'s entry registers it, so the module that declares the property must import the module that declares ${shortIri(ref.valueShape)}`\n : ref.target === 'missing'\n ? `not registered even by ${ref.targetPackage}'s entry: the shape name is wrong or ${ref.targetPackage} does not define it`\n : ref.target === 'not-a-dependency'\n ? `'${slugOf(ref.valueShape)}' is neither this package nor one of its dependencies (an old package name?)`\n : `${ref.targetPackage}'s entry could not be loaded to tell why`;\n return ` ${label}\\n unresolved after loading ${modulesList(ref.modules)}\\n ${fix}`;\n};\n\n/**\n * Build step. Load errors and unresolved references fail the build: each is a\n * bug the package would ship, and it only surfaces in a consumer's bundle. The\n * references in {@link KNOWN_UNRESOLVED} warn instead.\n */\nexport const checkShapeReferences = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n): Promise<true | string | {error: string}> => {\n const report = await inspectShapeReferences(packagePath, options);\n if (report.skipped) return `skipped: ${report.skipped}`;\n const problems: string[] = [];\n if (report.loadErrors.length > 0) {\n problems.push(\n `${report.loadErrors.length} shape module(s) throw when loaded on their own:\\n` +\n report.loadErrors\n .map((e) => ` ${e.module}: ${e.error.split('\\n').join('\\n ')}`)\n .join('\\n'),\n );\n }\n if (report.unresolved.length > 0) {\n problems.push(\n `${report.unresolved.length} property value shape(s) are not registered when the module that ` +\n `declares the property is loaded on its own, so a query traversing them throws ` +\n `\"Shape class not found\":\\n` +\n report.unresolved.map(describeReference).join('\\n'),\n );\n }\n if (problems.length > 0) return {error: problems.join('\\n')};\n if (report.known.length > 0) {\n return (\n `${report.known.length} known unresolved reference(s), tracked for a fix:\\n` +\n report.known.map(describeReference).join('\\n')\n );\n }\n return true;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"shapeReferences.js","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {execFile} from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport {declaresShape} from './shapeNames.js';\n\n/**\n * Checking shape references: does loading a compiled shape module, on its own,\n * register every shape its properties point at?\n *\n * A property can name its value shape by `[package, name]` instead of by class\n * (`shape: ['@_linked/schema', 'ImageObject']`), usually because importing the\n * class would close an import cycle. That names the shape without loading it.\n * A shape registers only when its module is evaluated, and consumers deep-import\n * single shape modules (`@_linked/schema/shapes/Thing`), so nothing guarantees\n * the named shape is registered when a query traverses the property. The query\n * then throws `Shape class not found for …/ImageObject` — in a production bundle,\n * far from the cause. A reference to a package under an old name\n * (`['lincd-sioc', …]`) can never resolve at all.\n *\n * So each module is loaded the way a consumer's fresh process would load it: in\n * a child `node` of its own, with nothing else imported first. Separate processes\n * rather than one process re-importing: ESM has no module-cache eviction, and the\n * shape registry lives on `globalThis`, so a second module in the same process\n * would see every shape the first one registered.\n */\n\n/** One module that could not be evaluated. */\nexport interface ShapeModuleLoadError {\n module: string;\n error: string;\n}\n\n/**\n * A property whose value shape was not registered after loading `modules`\n * (each on its own). One entry per distinct reference, however many modules\n * showed it.\n */\nexport interface UnresolvedShapeReference {\n shape: string;\n property: string;\n valueShape: string;\n modules: string[];\n /**\n * What the target package's entry does for it: `registered` — loading the\n * entry registers it, so the referencing module just does not import it;\n * `missing` — not even the entry registers it, so the name or package is\n * wrong; `not-a-dependency` — the IRI's package is neither this package nor\n * one of its dependencies; `unknown` — the entry could not be loaded.\n */\n target: 'registered' | 'missing' | 'not-a-dependency' | 'unknown';\n /** The package the IRI's slug maps to, when one does. */\n targetPackage?: string;\n}\n\nexport interface ShapeReferenceReport {\n modules: string[];\n loadErrors: ShapeModuleLoadError[];\n unresolved: UnresolvedShapeReference[];\n /** Unresolved references that match {@link KNOWN_UNRESOLVED}. */\n known: UnresolvedShapeReference[];\n /**\n * The package's own shapes (by IRI) registered after loading each module on\n * its own, keyed like {@link modules}. Read before the probe loads any entry\n * for its second look, so it is exactly what that one module registers.\n * Modules that threw are absent.\n */\n registered: Record<string, string[]>;\n /** Set when the registry could not be inspected, so nothing was checked. */\n skipped?: string;\n}\n\n/**\n * References known to be unresolved, reported as warnings rather than failures.\n *\n * This is deliberately a list in the CLI rather than an opt-out a package can\n * write for itself: every entry is a shipped bug with a tracked fix, not an\n * accepted design. No package was found with a legitimate reason to leave a\n * reference unresolved; add an opt-out mechanism when one turns up.\n *\n * Empty: `@_linked/core`'s `PropertyShape.in -> List`, the one entry this held,\n * is fixed in core (List is registered wherever PropertyShape is).\n */\nexport const KNOWN_UNRESOLVED: {\n package: string;\n shape: string;\n property: string;\n valueShape: string;\n}[] = [];\n\n/** arch-02: the `{slug}` in `{baseUri}shape/{slug}/{Name}`. Mirrors core's `packageNameToSlug`. */\nexport const packageNameToSlug = (packageName: string): string =>\n packageName\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n\n/** The slug in a node-shape IRI, or undefined when it is not shaped like one. */\nconst slugOf = (iri: string): string | undefined =>\n iri.match(/\\/shape\\/([^/]+)\\/[^/]+$/)?.[1];\n\n/**\n * A loader hook for the child: asset imports (`import styles from\n * './X.module.css'`) evaluate to a stub. Node cannot load them and a consumer's\n * bundler always can, so without this a shape module whose file also holds a\n * component would look broken when it is not. A CSS-module stub maps every\n * class name to itself.\n */\nconst ASSET_HOOK = `\nconst ASSET = /\\\\.(css|scss|sass|less|styl|svg|png|jpe?g|gif|webp|avif|ico|woff2?|ttf|otf|eot)$/i;\nexport async function load(url, context, next) {\n if (url.startsWith('file:') && ASSET.test(new URL(url).pathname)) {\n return {format: 'module', shortCircuit: true,\n source: 'export default new Proxy({}, {get: (_, k) => typeof k === \"string\" ? k : undefined});'};\n }\n return next(url, context);\n}\n`;\n\n/**\n * The script each child runs. Plain JS, passed with `-e`, so it runs the same\n * from `src` under a test runner as from the published `lib`.\n *\n * It reads the registry from `globalThis.__linkedShapeRegistry` rather than\n * importing `@_linked/core`: the module under test decides which copy of core\n * it loads, and the registry is shared by every copy.\n */\nconst PROBE = `\nimport {register} from 'node:module';\nregister('data:text/javascript,' + encodeURIComponent(${JSON.stringify(ASSET_HOOK)}));\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\nconst out = {error: null, unresolved: [], registry: true, registered: []};\nconst reg = () => globalThis.__linkedShapeRegistry;\nconst ownSlug = process.env.LINKED_PROBE_SLUG;\nconst report = () => {\n process.stdout.write('\\\\n' + MARK + JSON.stringify(out) + '\\\\n', () => process.exit(0));\n};\ntry {\n await import(process.env.LINKED_PROBE_MODULE);\n const r = reg();\n if (!r || !r.nodeShapeRegistry) {\n out.registry = false;\n } else {\n // Before the second look below: that loads whole entries and would add theirs.\n for (const id of r.nodeShapeRegistry.keys()) {\n if (id.includes('/shape/' + ownSlug + '/')) out.registered.push(id);\n }\n for (const [id, ns] of r.nodeShapeRegistry) {\n if (!id.includes('/shape/' + ownSlug + '/')) continue;\n for (const ps of ns.propertyShapes || []) {\n const v = ps.valueShape && ps.valueShape.id;\n if (v && !r.nodeShapeRegistry.has(v)) {\n out.unresolved.push({shape: id, property: ps.label, valueShape: v});\n }\n }\n }\n // For each unresolved target, load its package's entry and look again: that\n // tells a missing import apart from a name that can never resolve.\n const entries = JSON.parse(process.env.LINKED_PROBE_ENTRIES || '{}');\n const tried = {};\n for (const u of out.unresolved) {\n const slug = (u.valueShape.match(/\\\\/shape\\\\/([^/]+)\\\\/[^/]+$/) || [])[1];\n const entry = entries[slug];\n if (!entry) { u.target = 'not-a-dependency'; continue; }\n u.targetPackage = entry.name;\n if (!(slug in tried)) {\n try { await import(entry.specifier); tried[slug] = true; }\n catch (e) { tried[slug] = false; }\n }\n u.target = !tried[slug] ? 'unknown'\n : reg().nodeShapeRegistry.has(u.valueShape) ? 'registered' : 'missing';\n }\n }\n} catch (e) {\n out.error = e && e.stack ? e.stack.split('\\\\n').slice(0, 4).join('\\\\n') : String(e);\n}\nreport();\n`;\n\ninterface ProbeResult {\n error: string | null;\n registry: boolean;\n registered: string[];\n unresolved: {\n shape: string;\n property: string;\n valueShape: string;\n target: UnresolvedShapeReference['target'];\n targetPackage?: string;\n }[];\n}\n\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\n\nconst runProbe = (\n modulePath: string,\n packagePath: string,\n env: Record<string, string>,\n timeoutMs: number,\n): Promise<ProbeResult> =>\n new Promise((resolve) => {\n execFile(\n process.execPath,\n ['--input-type=module', '-e', PROBE],\n {\n cwd: packagePath,\n env: {\n ...process.env,\n ...env,\n LINKED_PROBE_MODULE: 'file://' + modulePath,\n },\n timeout: timeoutMs,\n maxBuffer: 64 * 1024 * 1024,\n },\n (err, stdout, stderr) => {\n const line = String(stdout)\n .split('\\n')\n .reverse()\n .find((l) => l.startsWith(MARK));\n if (line) {\n resolve(JSON.parse(line.slice(MARK.length)));\n return;\n }\n const why =\n err && (err as any).killed\n ? `did not finish loading within ${timeoutMs}ms`\n : String(stderr).trim().split('\\n').slice(-4).join('\\n') ||\n String(err || 'exited without reporting');\n resolve({error: why, registry: true, registered: [], unresolved: []});\n },\n );\n });\n\n/** Every compiled module that declares a shape: all of `shapes/`, plus decorated classes elsewhere. */\nexport const findShapeModules = (libEsm: string): string[] => {\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (\n entry.name.endsWith('.js') &&\n !/\\.(test|spec|class)\\.js$/.test(entry.name)\n ) {\n const rel = path.relative(libEsm, full);\n if (\n rel.split(path.sep)[0] === 'shapes' ||\n declaresShape(fs.readFileSync(full, 'utf8'))\n ) {\n found.push(full);\n }\n }\n }\n };\n if (fs.existsSync(libEsm)) walk(libEsm);\n return found.sort();\n};\n\n/** The name the package registers its shapes under: `linkedPackage('<name>')` in `package.js`. */\nconst runtimePackageName = (libEsm: string, pkgJson: any): string => {\n const pkgModule = path.join(libEsm, 'package.js');\n if (fs.existsSync(pkgModule)) {\n const m = fs\n .readFileSync(pkgModule, 'utf8')\n .match(/linkedPackage\\(\\s*['\"]([^'\"]+)['\"]/);\n if (m) return m[1];\n }\n return pkgJson.name;\n};\n\nconst DEPENDENCY_FIELDS = [\n 'dependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Load each shape module of the package at `packagePath` in isolation and\n * collect load errors and unresolved property value shapes.\n */\nexport const inspectShapeReferences = async (\n packagePath: string,\n {\n concurrency = Math.min(8, Math.max(1, os.cpus().length - 1)),\n timeoutMs = 60000,\n } = {},\n): Promise<ShapeReferenceReport> => {\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const modules = findShapeModules(libEsm);\n const report: ShapeReferenceReport = {\n modules: modules.map((m) => path.relative(libEsm, m)),\n loadErrors: [],\n unresolved: [],\n known: [],\n registered: {},\n };\n if (modules.length === 0) return report;\n\n const ownName = runtimePackageName(libEsm, pkgJson);\n // The entry each slug's package is loaded through for the second look. This\n // package's own entry is loaded by path: a package cannot always import\n // itself by name.\n const entries: Record<string, {name: string; specifier: string}> = {};\n for (const field of DEPENDENCY_FIELDS) {\n for (const dep of Object.keys(pkgJson[field] || {})) {\n entries[packageNameToSlug(dep)] = {name: dep, specifier: dep};\n }\n }\n const ownEntry = path.join(\n packagePath,\n pkgJson.module || pkgJson.main || 'lib/esm/index.js',\n );\n for (const name of new Set([ownName, pkgJson.name])) {\n entries[packageNameToSlug(name)] = {\n name,\n specifier: fs.existsSync(ownEntry) ? 'file://' + ownEntry : name,\n };\n }\n const env = {\n LINKED_PROBE_SLUG: packageNameToSlug(ownName),\n LINKED_PROBE_ENTRIES: JSON.stringify(entries),\n };\n\n const results: ProbeResult[] = new Array(modules.length);\n let next = 0;\n await Promise.all(\n Array.from({length: Math.min(concurrency, modules.length)}, async () => {\n while (next < modules.length) {\n const i = next++;\n results[i] = await runProbe(modules[i], packagePath, env, timeoutMs);\n }\n }),\n );\n\n // No registry on `globalThis` after loading a module that declares a shape\n // means a core older than 2.22.3, whose registry is module-scoped. A module\n // under `shapes/` that declares none (a store, a helper) registers nothing.\n const stale = results.findIndex(\n (r, i) =>\n !r.error &&\n !r.registry &&\n declaresShape(fs.readFileSync(modules[i], 'utf8')),\n );\n if (stale !== -1) {\n report.skipped =\n `no shape registry on globalThis after loading ${report.modules[stale]}: the ` +\n '@_linked/core it loads is older than 2.22.3, whose registry cannot be inspected from outside';\n return report;\n }\n\n const byReference = new Map<string, UnresolvedShapeReference>();\n results.forEach((r, i) => {\n const module = report.modules[i];\n if (r.error) {\n report.loadErrors.push({module, error: r.error});\n return;\n }\n report.registered[module] = r.registered;\n for (const u of r.unresolved) {\n const key = `${u.shape}\\u0000${u.property}\\u0000${u.valueShape}`;\n const existing = byReference.get(key);\n if (existing) existing.modules.push(module);\n else byReference.set(key, {...u, modules: [module]});\n }\n });\n for (const ref of byReference.values()) {\n const isKnown = KNOWN_UNRESOLVED.some(\n (k) =>\n k.package === ownName &&\n ref.shape.endsWith(k.shape) &&\n ref.property === k.property &&\n ref.valueShape.endsWith(k.valueShape),\n );\n (isKnown ? report.known : report.unresolved).push(ref);\n }\n return report;\n};\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\nconst modulesList = (modules: string[]) =>\n modules.length <= 3\n ? modules.join(', ')\n : `${modules.slice(0, 3).join(', ')} and ${modules.length - 3} more`;\n\nconst describeReference = (ref: UnresolvedShapeReference): string => {\n const label = `${shortIri(ref.shape)}.${ref.property} -> ${ref.valueShape}`;\n const fix =\n ref.target === 'registered'\n ? `${ref.targetPackage}'s entry registers it, so the module that declares the property must import the module that declares ${shortIri(ref.valueShape)}`\n : ref.target === 'missing'\n ? `not registered even by ${ref.targetPackage}'s entry: the shape name is wrong or ${ref.targetPackage} does not define it`\n : ref.target === 'not-a-dependency'\n ? `'${slugOf(ref.valueShape)}' is neither this package nor one of its dependencies (an old package name?)`\n : `${ref.targetPackage}'s entry could not be loaded to tell why`;\n return ` ${label}\\n unresolved after loading ${modulesList(ref.modules)}\\n ${fix}`;\n};\n\n/**\n * Build step. Load errors and unresolved references fail the build: each is a\n * bug the package would ship, and it only surfaces in a consumer's bundle. The\n * references in {@link KNOWN_UNRESOLVED} warn instead.\n */\nexport const checkShapeReferences = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n inspection?: Promise<ShapeReferenceReport>,\n): Promise<true | string | {error: string}> => {\n const report = await (inspection ?? inspectShapeReferences(packagePath, options));\n if (report.skipped) return `skipped: ${report.skipped}`;\n const problems: string[] = [];\n if (report.loadErrors.length > 0) {\n problems.push(\n `${report.loadErrors.length} shape module(s) throw when loaded on their own:\\n` +\n report.loadErrors\n .map((e) => ` ${e.module}: ${e.error.split('\\n').join('\\n ')}`)\n .join('\\n'),\n );\n }\n if (report.unresolved.length > 0) {\n problems.push(\n `${report.unresolved.length} property value shape(s) are not registered when the module that ` +\n `declares the property is loaded on its own, so a query traversing them throws ` +\n `\"Shape class not found\":\\n` +\n report.unresolved.map(describeReference).join('\\n'),\n );\n }\n if (problems.length > 0) return {error: problems.join('\\n')};\n if (report.known.length > 0) {\n return (\n `${report.known.length} known unresolved reference(s), tracked for a fix:\\n` +\n report.known.map(describeReference).join('\\n')\n );\n }\n return true;\n};\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { inspectShapeReferences, type ShapeReferenceReport } from './shapeReferences.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh
|
|
4
|
+
* process, register every one of this package's shapes that loading its
|
|
5
|
+
* shape modules one by one registers?
|
|
6
|
+
*
|
|
7
|
+
* Fails when the package has shapes but no shapes/index, when the index throws
|
|
8
|
+
* on load, or when it misses a shape. A package without shapes passes.
|
|
9
|
+
*/
|
|
10
|
+
export declare const checkShapesIndex: (packagePath: string, options?: Parameters<typeof inspectShapeReferences>[1], inspection?: Promise<ShapeReferenceReport>) => Promise<true | string | {
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Build step: `package.json` must not declare any `lib/esm/shapes` module
|
|
15
|
+
* side-effect-free. A pure match of the field against the emitted files; no
|
|
16
|
+
* bundling.
|
|
17
|
+
*/
|
|
18
|
+
export declare const checkShapesSideEffects: (packagePath: string) => true | {
|
|
19
|
+
error: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=shapesIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapesIndex.d.ts","sourceRoot":"","sources":["../../../src/utils/shapesIndex.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAoE9B;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,MAAM,EACnB,UAAU,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,EACtD,aAAa,OAAO,CAAC,oBAAoB,CAAC,KACzC,OAAO,CAAC,IAAI,GAAG,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAkEzC,CAAC;AA6BF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,MAAM,KAClB,IAAI,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CA+CvB,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { minimatch } from 'minimatch';
|
|
13
|
+
import { inspectShapeReferences, } from './shapeReferences.js';
|
|
14
|
+
/**
|
|
15
|
+
* The shape-registration standard, checked against a package's build output.
|
|
16
|
+
*
|
|
17
|
+
* Every package has `src/shapes/index.ts`: side-effect-only imports of every
|
|
18
|
+
* shape module, so an app can register the whole set with one import
|
|
19
|
+
* (`import '@_linked/<pkg>/shapes/index'`). A shape registers only when its
|
|
20
|
+
* module is evaluated, so a shape the index forgets is a shape an app that
|
|
21
|
+
* trusts the index never has, and a query naming it throws "Shape class not
|
|
22
|
+
* found" in that app's bundle. And a bundler that believes a package's
|
|
23
|
+
* `sideEffects` drops a side-effect-only import outright, so declaring shape
|
|
24
|
+
* modules side-effect-free empties the index in production while dev (which
|
|
25
|
+
* does not tree-shake) keeps working.
|
|
26
|
+
*/
|
|
27
|
+
/** The index, relative to lib/esm, as the per-module inspection keys it. */
|
|
28
|
+
const INDEX = path.join('shapes', 'index.js');
|
|
29
|
+
const shortIri = (iri) => iri.replace(/^.*\/shape\//, '');
|
|
30
|
+
/** `lib/esm/shapes/X.js` → `src/shapes/X.ts`, for messages. */
|
|
31
|
+
const srcPath = (module) => path.join('src', module).replace(/\.js$/, '.ts');
|
|
32
|
+
/** The line shapes/index.ts needs to load `module` (relative to lib/esm). */
|
|
33
|
+
const importLine = (module) => {
|
|
34
|
+
let rel = path
|
|
35
|
+
.relative('shapes', module)
|
|
36
|
+
.split(path.sep)
|
|
37
|
+
.join('/');
|
|
38
|
+
if (!rel.startsWith('.'))
|
|
39
|
+
rel = './' + rel;
|
|
40
|
+
return `import '${rel}';`;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* For each shape, the module the fix should import: the one named after the
|
|
44
|
+
* shape, else the one whose source declares its class, else the module
|
|
45
|
+
* registering the fewest shapes (the most specific).
|
|
46
|
+
*/
|
|
47
|
+
const moduleFor = (shape, registered, libEsm) => {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const name = shape.replace(/^.*\//, '');
|
|
50
|
+
const declares = (m) => {
|
|
51
|
+
try {
|
|
52
|
+
return new RegExp(`\\b(?:class ${name}|${name} = class)\\b`).test(fs.readFileSync(path.join(libEsm, m), 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
catch (_a) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const candidates = Object.keys(registered)
|
|
59
|
+
.filter((m) => m !== INDEX && registered[m].includes(shape))
|
|
60
|
+
.sort((a, b) => registered[a].length - registered[b].length || a.localeCompare(b));
|
|
61
|
+
return ((_b = (_a = candidates.find((m) => path.basename(m, '.js') === name)) !== null && _a !== void 0 ? _a : candidates.find(declares)) !== null && _b !== void 0 ? _b : candidates[0]);
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh
|
|
65
|
+
* process, register every one of this package's shapes that loading its
|
|
66
|
+
* shape modules one by one registers?
|
|
67
|
+
*
|
|
68
|
+
* Fails when the package has shapes but no shapes/index, when the index throws
|
|
69
|
+
* on load, or when it misses a shape. A package without shapes passes.
|
|
70
|
+
*/
|
|
71
|
+
export const checkShapesIndex = (packagePath, options, inspection) => __awaiter(void 0, void 0, void 0, function* () {
|
|
72
|
+
const report = yield (inspection !== null && inspection !== void 0 ? inspection : inspectShapeReferences(packagePath, options));
|
|
73
|
+
if (report.skipped)
|
|
74
|
+
return `skipped: ${report.skipped}`;
|
|
75
|
+
const libEsm = path.join(packagePath, 'lib', 'esm');
|
|
76
|
+
const all = new Set();
|
|
77
|
+
for (const [module, shapes] of Object.entries(report.registered)) {
|
|
78
|
+
if (module !== INDEX)
|
|
79
|
+
shapes.forEach((s) => all.add(s));
|
|
80
|
+
}
|
|
81
|
+
if (all.size === 0)
|
|
82
|
+
return true;
|
|
83
|
+
const hasIndex = report.modules.includes(INDEX);
|
|
84
|
+
const indexError = report.loadErrors.find((e) => e.module === INDEX);
|
|
85
|
+
if (indexError) {
|
|
86
|
+
return {
|
|
87
|
+
error: `lib/esm/shapes/index.js throws when loaded on its own, so an app importing ` +
|
|
88
|
+
`'<package>/shapes/index' registers nothing:\n ${indexError.error.split('\n').join('\n ')}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const covered = new Set(hasIndex ? report.registered[INDEX] : []);
|
|
92
|
+
const missing = [...all].filter((s) => !covered.has(s)).sort();
|
|
93
|
+
if (missing.length === 0)
|
|
94
|
+
return true;
|
|
95
|
+
const lines = [
|
|
96
|
+
...new Set(missing.map((s) => {
|
|
97
|
+
const m = moduleFor(s, report.registered, libEsm);
|
|
98
|
+
return m ? importLine(m) : `// ${shortIri(s)}: no single module registers it`;
|
|
99
|
+
})),
|
|
100
|
+
].sort();
|
|
101
|
+
const listing = missing
|
|
102
|
+
.map((s) => {
|
|
103
|
+
const m = moduleFor(s, report.registered, libEsm);
|
|
104
|
+
return ` ${shortIri(s)}${m ? ` (${srcPath(m)})` : ''}`;
|
|
105
|
+
})
|
|
106
|
+
.join('\n');
|
|
107
|
+
const outside = missing
|
|
108
|
+
.map((s) => moduleFor(s, report.registered, libEsm))
|
|
109
|
+
.filter((m) => m && m.split(path.sep)[0] !== 'shapes');
|
|
110
|
+
const moveNote = outside.length > 0
|
|
111
|
+
? `\nShapes declared outside src/shapes/ belong in src/shapes/; until they move, the index imports their module.`
|
|
112
|
+
: '';
|
|
113
|
+
if (!hasIndex) {
|
|
114
|
+
return {
|
|
115
|
+
error: `This package declares ${all.size} shape(s) but has no src/shapes/index.ts, so an app ` +
|
|
116
|
+
`cannot register them with import '<package>/shapes/index':\n${listing}\n` +
|
|
117
|
+
`Create src/shapes/index.ts holding only side-effect imports (no exports):\n` +
|
|
118
|
+
lines.map((l) => ` ${l}`).join('\n') +
|
|
119
|
+
`\nand import it from src/index.ts: import './shapes/index.js';` +
|
|
120
|
+
moveNote,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
error: `${missing.length} shape(s) are not registered by loading lib/esm/shapes/index.js on its own, ` +
|
|
125
|
+
`so an app that imports '<package>/shapes/index' never has them:\n${listing}\n` +
|
|
126
|
+
`Add to src/shapes/index.ts:\n` +
|
|
127
|
+
lines.map((l) => ` ${l}`).join('\n') +
|
|
128
|
+
moveNote,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
/** Every emitted module under lib/esm/shapes, relative to the package root, `/`-separated. */
|
|
132
|
+
const emittedShapeModules = (packagePath) => {
|
|
133
|
+
const root = path.join(packagePath, 'lib', 'esm', 'shapes');
|
|
134
|
+
const out = [];
|
|
135
|
+
const walk = (dir) => {
|
|
136
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
137
|
+
const full = path.join(dir, e.name);
|
|
138
|
+
if (e.isDirectory())
|
|
139
|
+
walk(full);
|
|
140
|
+
else if (e.name.endsWith('.js'))
|
|
141
|
+
out.push(path.relative(packagePath, full).split(path.sep).join('/'));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
if (fs.existsSync(root))
|
|
145
|
+
walk(root);
|
|
146
|
+
return out.sort();
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Whether a `sideEffects` pattern matches a package-relative path, the way
|
|
150
|
+
* webpack and Rollup's node-resolve read it: a leading `./` is dropped and a
|
|
151
|
+
* pattern without a `/` matches the file name anywhere.
|
|
152
|
+
*/
|
|
153
|
+
const sideEffectsMatch = (pattern, file) => {
|
|
154
|
+
let p = pattern.replace(/^\.\//, '');
|
|
155
|
+
if (!p.includes('/'))
|
|
156
|
+
p = '**/' + p;
|
|
157
|
+
return minimatch(file, p, { dot: true });
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Build step: `package.json` must not declare any `lib/esm/shapes` module
|
|
161
|
+
* side-effect-free. A pure match of the field against the emitted files; no
|
|
162
|
+
* bundling.
|
|
163
|
+
*/
|
|
164
|
+
export const checkShapesSideEffects = (packagePath) => {
|
|
165
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'));
|
|
166
|
+
const sideEffects = pkgJson.sideEffects;
|
|
167
|
+
if (sideEffects === undefined || sideEffects === true)
|
|
168
|
+
return true;
|
|
169
|
+
const files = emittedShapeModules(packagePath);
|
|
170
|
+
if (files.length === 0)
|
|
171
|
+
return true;
|
|
172
|
+
const fix = `Remove the "sideEffects" field, or list the shape modules in it:\n` +
|
|
173
|
+
` "sideEffects": ["lib/esm/shapes/index.js", "lib/esm/shapes/*.js"]` +
|
|
174
|
+
(files.some((f) => f.split('/').length > 4)
|
|
175
|
+
? `\n (with "lib/esm/shapes/**/*.js" for the nested folders)`
|
|
176
|
+
: '');
|
|
177
|
+
const why = `A bundler drops a side-effect-only import of a module it is told is side-effect-free, ` +
|
|
178
|
+
`so shapes/index would register nothing in a production build.`;
|
|
179
|
+
if (sideEffects === false) {
|
|
180
|
+
return {
|
|
181
|
+
error: `package.json declares "sideEffects": false, which marks every shape module side-effect-free. ${why}\n${fix}`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (!Array.isArray(sideEffects) ||
|
|
185
|
+
sideEffects.some((p) => typeof p !== 'string')) {
|
|
186
|
+
return {
|
|
187
|
+
error: `package.json "sideEffects" must be true, false or a list of globs; found ${JSON.stringify(sideEffects)}.\n${fix}`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const unmatched = files.filter((f) => !sideEffects.some((p) => sideEffectsMatch(p, f)));
|
|
191
|
+
if (unmatched.length === 0)
|
|
192
|
+
return true;
|
|
193
|
+
return {
|
|
194
|
+
error: `package.json "sideEffects" does not cover ${unmatched.length} shape module(s), so they are declared ` +
|
|
195
|
+
`side-effect-free:\n` +
|
|
196
|
+
unmatched
|
|
197
|
+
.slice(0, 10)
|
|
198
|
+
.map((f) => ` ${f}`)
|
|
199
|
+
.join('\n') +
|
|
200
|
+
(unmatched.length > 10 ? `\n and ${unmatched.length - 10} more` : '') +
|
|
201
|
+
`\n${why}\n${fix}`,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=shapesIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapesIndex.js","sourceRoot":"","sources":["../../../src/utils/shapesIndex.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport {minimatch} from 'minimatch';\nimport {\n inspectShapeReferences,\n type ShapeReferenceReport,\n} from './shapeReferences.js';\n\n/**\n * The shape-registration standard, checked against a package's build output.\n *\n * Every package has `src/shapes/index.ts`: side-effect-only imports of every\n * shape module, so an app can register the whole set with one import\n * (`import '@_linked/<pkg>/shapes/index'`). A shape registers only when its\n * module is evaluated, so a shape the index forgets is a shape an app that\n * trusts the index never has, and a query naming it throws \"Shape class not\n * found\" in that app's bundle. And a bundler that believes a package's\n * `sideEffects` drops a side-effect-only import outright, so declaring shape\n * modules side-effect-free empties the index in production while dev (which\n * does not tree-shake) keeps working.\n */\n\n/** The index, relative to lib/esm, as the per-module inspection keys it. */\nconst INDEX = path.join('shapes', 'index.js');\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\n/** `lib/esm/shapes/X.js` → `src/shapes/X.ts`, for messages. */\nconst srcPath = (module: string) =>\n path.join('src', module).replace(/\\.js$/, '.ts');\n\n/** The line shapes/index.ts needs to load `module` (relative to lib/esm). */\nconst importLine = (module: string) => {\n let rel = path\n .relative('shapes', module)\n .split(path.sep)\n .join('/');\n if (!rel.startsWith('.')) rel = './' + rel;\n return `import '${rel}';`;\n};\n\n/**\n * For each shape, the module the fix should import: the one named after the\n * shape, else the one whose source declares its class, else the module\n * registering the fewest shapes (the most specific).\n */\nconst moduleFor = (\n shape: string,\n registered: Record<string, string[]>,\n libEsm: string,\n): string | undefined => {\n const name = shape.replace(/^.*\\//, '');\n const declares = (m: string) => {\n try {\n return new RegExp(`\\\\b(?:class ${name}|${name} = class)\\\\b`).test(\n fs.readFileSync(path.join(libEsm, m), 'utf8'),\n );\n } catch {\n return false;\n }\n };\n const candidates = Object.keys(registered)\n .filter((m) => m !== INDEX && registered[m].includes(shape))\n .sort(\n (a, b) =>\n registered[a].length - registered[b].length || a.localeCompare(b),\n );\n return (\n candidates.find((m) => path.basename(m, '.js') === name) ??\n candidates.find(declares) ??\n candidates[0]\n );\n};\n\n/**\n * Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh\n * process, register every one of this package's shapes that loading its\n * shape modules one by one registers?\n *\n * Fails when the package has shapes but no shapes/index, when the index throws\n * on load, or when it misses a shape. A package without shapes passes.\n */\nexport const checkShapesIndex = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n inspection?: Promise<ShapeReferenceReport>,\n): Promise<true | string | {error: string}> => {\n const report = await (inspection ??\n inspectShapeReferences(packagePath, options));\n if (report.skipped) return `skipped: ${report.skipped}`;\n\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const all = new Set<string>();\n for (const [module, shapes] of Object.entries(report.registered)) {\n if (module !== INDEX) shapes.forEach((s) => all.add(s));\n }\n if (all.size === 0) return true;\n\n const hasIndex = report.modules.includes(INDEX);\n const indexError = report.loadErrors.find((e) => e.module === INDEX);\n if (indexError) {\n return {\n error:\n `lib/esm/shapes/index.js throws when loaded on its own, so an app importing ` +\n `'<package>/shapes/index' registers nothing:\\n ${indexError.error.split('\\n').join('\\n ')}`,\n };\n }\n const covered = new Set(hasIndex ? report.registered[INDEX] : []);\n const missing = [...all].filter((s) => !covered.has(s)).sort();\n if (missing.length === 0) return true;\n\n const lines = [\n ...new Set(\n missing.map((s) => {\n const m = moduleFor(s, report.registered, libEsm);\n return m ? importLine(m) : `// ${shortIri(s)}: no single module registers it`;\n }),\n ),\n ].sort();\n const listing = missing\n .map((s) => {\n const m = moduleFor(s, report.registered, libEsm);\n return ` ${shortIri(s)}${m ? ` (${srcPath(m)})` : ''}`;\n })\n .join('\\n');\n const outside = missing\n .map((s) => moduleFor(s, report.registered, libEsm))\n .filter((m) => m && m.split(path.sep)[0] !== 'shapes');\n const moveNote =\n outside.length > 0\n ? `\\nShapes declared outside src/shapes/ belong in src/shapes/; until they move, the index imports their module.`\n : '';\n\n if (!hasIndex) {\n return {\n error:\n `This package declares ${all.size} shape(s) but has no src/shapes/index.ts, so an app ` +\n `cannot register them with import '<package>/shapes/index':\\n${listing}\\n` +\n `Create src/shapes/index.ts holding only side-effect imports (no exports):\\n` +\n lines.map((l) => ` ${l}`).join('\\n') +\n `\\nand import it from src/index.ts: import './shapes/index.js';` +\n moveNote,\n };\n }\n return {\n error:\n `${missing.length} shape(s) are not registered by loading lib/esm/shapes/index.js on its own, ` +\n `so an app that imports '<package>/shapes/index' never has them:\\n${listing}\\n` +\n `Add to src/shapes/index.ts:\\n` +\n lines.map((l) => ` ${l}`).join('\\n') +\n moveNote,\n };\n};\n\n/** Every emitted module under lib/esm/shapes, relative to the package root, `/`-separated. */\nconst emittedShapeModules = (packagePath: string): string[] => {\n const root = path.join(packagePath, 'lib', 'esm', 'shapes');\n const out: string[] = [];\n const walk = (dir: string) => {\n for (const e of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, e.name);\n if (e.isDirectory()) walk(full);\n else if (e.name.endsWith('.js'))\n out.push(path.relative(packagePath, full).split(path.sep).join('/'));\n }\n };\n if (fs.existsSync(root)) walk(root);\n return out.sort();\n};\n\n/**\n * Whether a `sideEffects` pattern matches a package-relative path, the way\n * webpack and Rollup's node-resolve read it: a leading `./` is dropped and a\n * pattern without a `/` matches the file name anywhere.\n */\nconst sideEffectsMatch = (pattern: string, file: string): boolean => {\n let p = pattern.replace(/^\\.\\//, '');\n if (!p.includes('/')) p = '**/' + p;\n return minimatch(file, p, {dot: true});\n};\n\n/**\n * Build step: `package.json` must not declare any `lib/esm/shapes` module\n * side-effect-free. A pure match of the field against the emitted files; no\n * bundling.\n */\nexport const checkShapesSideEffects = (\n packagePath: string,\n): true | {error: string} => {\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const sideEffects = pkgJson.sideEffects;\n if (sideEffects === undefined || sideEffects === true) return true;\n const files = emittedShapeModules(packagePath);\n if (files.length === 0) return true;\n\n const fix =\n `Remove the \"sideEffects\" field, or list the shape modules in it:\\n` +\n ` \"sideEffects\": [\"lib/esm/shapes/index.js\", \"lib/esm/shapes/*.js\"]` +\n (files.some((f) => f.split('/').length > 4)\n ? `\\n (with \"lib/esm/shapes/**/*.js\" for the nested folders)`\n : '');\n const why =\n `A bundler drops a side-effect-only import of a module it is told is side-effect-free, ` +\n `so shapes/index would register nothing in a production build.`;\n\n if (sideEffects === false) {\n return {\n error: `package.json declares \"sideEffects\": false, which marks every shape module side-effect-free. ${why}\\n${fix}`,\n };\n }\n if (\n !Array.isArray(sideEffects) ||\n sideEffects.some((p) => typeof p !== 'string')\n ) {\n return {\n error: `package.json \"sideEffects\" must be true, false or a list of globs; found ${JSON.stringify(sideEffects)}.\\n${fix}`,\n };\n }\n const unmatched = files.filter(\n (f) => !sideEffects.some((p: string) => sideEffectsMatch(p, f)),\n );\n if (unmatched.length === 0) return true;\n return {\n error:\n `package.json \"sideEffects\" does not cover ${unmatched.length} shape module(s), so they are declared ` +\n `side-effect-free:\\n` +\n unmatched\n .slice(0, 10)\n .map((f) => ` ${f}`)\n .join('\\n') +\n (unmatched.length > 10 ? `\\n and ${unmatched.length - 10} more` : '') +\n `\\n${why}\\n${fix}`,\n };\n};\n"]}
|