@_linked/cli 1.30.1 → 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.
@@ -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
- * - `@_linked/core`: `PropertyShape.in` names `List` by `[package, name]`
65
- * because `List`'s module depends on the SHACL shapes. Only core's entry
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;;;;;;;;;;;;;;GAcG;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,EAOA,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,MAKtC,CAAC;AAqInB,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,CA2F9B,CAAC;AAsBF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,EACnB,UAAU,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,KACrD,OAAO,CAAC,IAAI,GAAG,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA4BzC,CAAC"}
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
- * - `@_linked/core`: `PropertyShape.in` names `List` by `[package, name]`
24
- * because `List`'s module depends on the SHACL shapes. Only core's entry
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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.30.1",
3
+ "version": "1.32.0",
4
4
  "packageManager": "npm@11.19.1",
5
5
  "description": "Command line tools for the @_linked/* packages and apps",
6
6
  "main": "lib/esm/index.js",