@_linked/cli 1.28.1 → 1.29.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/README.md +28 -0
- package/lib/esm/cli.js +24 -0
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/commands/localize.d.ts +22 -0
- package/lib/esm/commands/localize.d.ts.map +1 -0
- package/lib/esm/commands/localize.js +69 -0
- package/lib/esm/commands/localize.js.map +1 -0
- package/lib/esm/commands/start.d.ts.map +1 -1
- package/lib/esm/commands/start.js +3 -0
- package/lib/esm/commands/start.js.map +1 -1
- package/lib/esm/plugins/pin-compiled-class-names.d.ts +11 -0
- package/lib/esm/plugins/pin-compiled-class-names.d.ts.map +1 -0
- package/lib/esm/plugins/pin-compiled-class-names.js +59 -0
- package/lib/esm/plugins/pin-compiled-class-names.js.map +1 -0
- package/lib/esm/utils/shapeNames.d.ts +7 -4
- package/lib/esm/utils/shapeNames.d.ts.map +1 -1
- package/lib/esm/utils/shapeNames.js +7 -4
- package/lib/esm/utils/shapeNames.js.map +1 -1
- package/lib/esm/vite-config.d.ts +17 -0
- package/lib/esm/vite-config.d.ts.map +1 -1
- package/lib/esm/vite-config.js +34 -6
- package/lib/esm/vite-config.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** Cheap pre-filter: a self-named class expression bound to a variable. */
|
|
2
|
+
const SELF_NAMED_CLASS = /\b(?:let|var|const)\s+([\w$]+)\s*=\s*(?:[\w$]+\s*=\s*)*class\s+\1\b/;
|
|
3
|
+
const JS_ID = /\.[cm]?js$/;
|
|
4
|
+
/**
|
|
5
|
+
* Returns `code` with the runtime name of every top-level tsc-style decorated
|
|
6
|
+
* class expression pinned, or `null` when there is nothing to pin (or the
|
|
7
|
+
* module does not parse as JavaScript).
|
|
8
|
+
*/
|
|
9
|
+
export function pinDecoratedClassNames(code, parse) {
|
|
10
|
+
var _a;
|
|
11
|
+
if (!code.includes('__decorate(') || !SELF_NAMED_CLASS.test(code))
|
|
12
|
+
return null;
|
|
13
|
+
let ast;
|
|
14
|
+
try {
|
|
15
|
+
ast = parse(code);
|
|
16
|
+
}
|
|
17
|
+
catch (_b) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const pins = [];
|
|
21
|
+
for (let node of ast.body) {
|
|
22
|
+
if (node.type === 'ExportNamedDeclaration' && node.declaration)
|
|
23
|
+
node = node.declaration;
|
|
24
|
+
if (node.type !== 'VariableDeclaration')
|
|
25
|
+
continue;
|
|
26
|
+
for (const decl of node.declarations) {
|
|
27
|
+
if (decl.id.type !== 'Identifier')
|
|
28
|
+
continue;
|
|
29
|
+
// `let Foo = Foo_1 = class Foo` — tsc's form when the class refers to itself.
|
|
30
|
+
let init = decl.init;
|
|
31
|
+
while (init && init.type === 'AssignmentExpression')
|
|
32
|
+
init = init.right;
|
|
33
|
+
if ((init === null || init === void 0 ? void 0 : init.type) === 'ClassExpression' && ((_a = init.id) === null || _a === void 0 ? void 0 : _a.name) === decl.id.name) {
|
|
34
|
+
pins.push({ at: node.end, name: decl.id.name });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (pins.length === 0)
|
|
39
|
+
return null;
|
|
40
|
+
let out = code;
|
|
41
|
+
for (const { at, name } of pins.reverse()) {
|
|
42
|
+
const pin = ` Object.defineProperty(${name}, "name", {value: ${JSON.stringify(name)}, configurable: true});`;
|
|
43
|
+
out = out.slice(0, at) + pin + out.slice(at);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
export function pinCompiledClassNames() {
|
|
48
|
+
return {
|
|
49
|
+
name: 'linked:pin-compiled-class-names',
|
|
50
|
+
enforce: 'pre',
|
|
51
|
+
transform(code, id) {
|
|
52
|
+
if (!JS_ID.test(id.split('?', 1)[0]))
|
|
53
|
+
return null;
|
|
54
|
+
const pinned = pinDecoratedClassNames(code, (c) => this.parse(c));
|
|
55
|
+
return pinned === null ? null : { code: pinned, map: null };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=pin-compiled-class-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pin-compiled-class-names.js","sourceRoot":"","sources":["../../../src/plugins/pin-compiled-class-names.ts"],"names":[],"mappings":"AAoCA,2EAA2E;AAC3E,MAAM,gBAAgB,GACpB,qEAAqE,CAAC;AACxE,MAAM,KAAK,GAAG,YAAY,CAAC;AAE3B;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAY,EACZ,KAAe;;IAEf,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAiC,EAAE,CAAC;IAC9C,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,WAAW;YAC5D,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;YAAE,SAAS;QAClD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACrC,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY;gBAAE,SAAS;YAC5C,8EAA8E;YAC9E,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACrB,OAAO,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB;gBAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;YACvE,IAAI,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,MAAK,iBAAiB,IAAI,CAAA,MAAA,IAAI,CAAC,EAAE,0CAAE,IAAI,MAAK,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;gBACvE,IAAI,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAC,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,EAAC,EAAE,EAAE,IAAI,EAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,0BAA0B,IAAI,qBAAqB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,yBAAyB,CAAC;QAC7G,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,IAAI,EAAE,iCAAiC;QACvC,OAAO,EAAE,KAAK;QACd,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YAClD,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAC,CAAC;QAC5D,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// Keeps the runtime name of tsc-compiled decorated classes stable through Vite.\n//\n// A shape's IRI is built from its class name when `@linkedShape` is given no\n// explicit `name`, so anything that renames a shape class changes the shape's\n// identity. For a decorated class tsc emits\n//\n// let Foo = class Foo { ... };\n// Foo = __decorate([linkedShape], Foo);\n//\n// and esbuild, whenever it re-prints such a module, renames the inner binding\n// to avoid the shadowing: `let Foo = class Foo2`. The class is then called\n// `Foo2` at runtime — before any decorator sees it — and registers under the\n// wrong IRI. Vite re-prints a module with esbuild, without `keepNames`, in its\n// `vite:define` pass (client build: any module mentioning `process.env`,\n// `import.meta.env`, `import.meta.hot` or an app `define` key) and in the dev\n// client whenever a module mentions `process.env.NODE_ENV`. Neither pass can be\n// given `keepNames`, and `esbuild.keepNames` in the Vite config does not reach\n// them: it only reaches the minifier, which then keeps the already-wrong name.\n//\n// TypeScript source is not affected — esbuild lowers its decorators to an\n// anonymous `let Foo = class {`, which takes its name from the binding. Only\n// published lib JavaScript carries the self-named class expression.\n//\n// So before any of that runs, this plugin pins each such class's name with a\n// string literal placed right after its declaration — before the property and\n// class decorators run — which no later renaming can touch:\n//\n// let Foo = class Foo { ... }; Object.defineProperty(Foo, \"name\", {value: \"Foo\", configurable: true});\n//\n// The insertion is on the declaration's own last line and moves no code, so\n// existing source maps stay valid (`map: null`).\nimport type {Plugin} from 'vite';\n\n/** An ESTree parser — the plugin context's `this.parse` (Rollup's parser). */\nexport type ParseAst = (code: string) => any;\n\n/** Cheap pre-filter: a self-named class expression bound to a variable. */\nconst SELF_NAMED_CLASS =\n /\\b(?:let|var|const)\\s+([\\w$]+)\\s*=\\s*(?:[\\w$]+\\s*=\\s*)*class\\s+\\1\\b/;\nconst JS_ID = /\\.[cm]?js$/;\n\n/**\n * Returns `code` with the runtime name of every top-level tsc-style decorated\n * class expression pinned, or `null` when there is nothing to pin (or the\n * module does not parse as JavaScript).\n */\nexport function pinDecoratedClassNames(\n code: string,\n parse: ParseAst,\n): string | null {\n if (!code.includes('__decorate(') || !SELF_NAMED_CLASS.test(code))\n return null;\n let ast: any;\n try {\n ast = parse(code);\n } catch {\n return null;\n }\n const pins: {at: number; name: string}[] = [];\n for (let node of ast.body) {\n if (node.type === 'ExportNamedDeclaration' && node.declaration)\n node = node.declaration;\n if (node.type !== 'VariableDeclaration') continue;\n for (const decl of node.declarations) {\n if (decl.id.type !== 'Identifier') continue;\n // `let Foo = Foo_1 = class Foo` — tsc's form when the class refers to itself.\n let init = decl.init;\n while (init && init.type === 'AssignmentExpression') init = init.right;\n if (init?.type === 'ClassExpression' && init.id?.name === decl.id.name) {\n pins.push({at: node.end, name: decl.id.name});\n }\n }\n }\n if (pins.length === 0) return null;\n let out = code;\n for (const {at, name} of pins.reverse()) {\n const pin = ` Object.defineProperty(${name}, \"name\", {value: ${JSON.stringify(name)}, configurable: true});`;\n out = out.slice(0, at) + pin + out.slice(at);\n }\n return out;\n}\n\nexport function pinCompiledClassNames(): Plugin {\n return {\n name: 'linked:pin-compiled-class-names',\n enforce: 'pre',\n transform(code, id) {\n if (!JS_ID.test(id.split('?', 1)[0])) return null;\n const pinned = pinDecoratedClassNames(code, (c) => this.parse(c));\n return pinned === null ? null : {code: pinned, map: null};\n },\n };\n}\n"]}
|
|
@@ -7,10 +7,13 @@ export interface ExposedShape {
|
|
|
7
7
|
* renamed their class.
|
|
8
8
|
*
|
|
9
9
|
* A shape's IRI is built from its class name unless `@linkedShape({name})`
|
|
10
|
-
* gives one.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* when it has no explicit name and its module
|
|
10
|
+
* gives one. Source files are safe: esbuild lowers their decorators to an
|
|
11
|
+
* anonymous `let Foo = class {`, which takes its name from the binding. Only
|
|
12
|
+
* published `lib/` JavaScript carries the self-named class expression, so a
|
|
13
|
+
* compiled shape is exposed exactly when it has no explicit name and its module
|
|
14
|
+
* contains a trigger. `createViteConfig` pins these names
|
|
15
|
+
* (`plugins/pin-compiled-class-names.ts`), but other bundlers and hand-written
|
|
16
|
+
* Vite configs do not, so the explicit name is still the fix. This is how
|
|
14
17
|
* `@_linked/server`'s `LinkedServer` and `LincdAPI` came to register as
|
|
15
18
|
* `LinkedServer2` / `LincdAPI2`.
|
|
16
19
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapeNames.d.ts","sourceRoot":"","sources":["../../../src/utils/shapeNames.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"shapeNames.d.ts","sourceRoot":"","sources":["../../../src/utils/shapeNames.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,aAAS,KACR,YAAY,EASd,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,GAAG,MAAM,CA2BvB,CAAC"}
|
|
@@ -27,10 +27,13 @@ const DECORATED = /\b([A-Za-z_$][\w$]*) = __decorate\(\[([\s\S]*?)\], \1\)/g;
|
|
|
27
27
|
* renamed their class.
|
|
28
28
|
*
|
|
29
29
|
* A shape's IRI is built from its class name unless `@linkedShape({name})`
|
|
30
|
-
* gives one.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* when it has no explicit name and its module
|
|
30
|
+
* gives one. Source files are safe: esbuild lowers their decorators to an
|
|
31
|
+
* anonymous `let Foo = class {`, which takes its name from the binding. Only
|
|
32
|
+
* published `lib/` JavaScript carries the self-named class expression, so a
|
|
33
|
+
* compiled shape is exposed exactly when it has no explicit name and its module
|
|
34
|
+
* contains a trigger. `createViteConfig` pins these names
|
|
35
|
+
* (`plugins/pin-compiled-class-names.ts`), but other bundlers and hand-written
|
|
36
|
+
* Vite configs do not, so the explicit name is still the fix. This is how
|
|
34
37
|
* `@_linked/server`'s `LinkedServer` and `LincdAPI` came to register as
|
|
35
38
|
* `LinkedServer2` / `LincdAPI2`.
|
|
36
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapeNames.js","sourceRoot":"","sources":["../../../src/utils/shapeNames.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,cAAc,GAAG,wCAAwC,CAAC;AAEhE,kEAAkE;AAClE,MAAM,SAAS,GAAG,0DAA0D,CAAC;AAO7E
|
|
1
|
+
{"version":3,"file":"shapeNames.js","sourceRoot":"","sources":["../../../src/utils/shapeNames.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,cAAc,GAAG,wCAAwC,CAAC;AAEhE,kEAAkE;AAClE,MAAM,SAAS,GAAG,0DAA0D,CAAC;AAO7E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAAc,EACd,IAAI,GAAG,EAAE,EACO,EAAE;IAClB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,SAAS;QAClD,IAAI,wCAAwC,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,SAAS;QACxE,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,WAAmB,EACK,EAAE;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;QAC3B,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;iBAC/B,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpC,OAAO,CAAC,IAAI,CACV,GAAG,oBAAoB,CACrB,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAC5B,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,CAAC;IACb,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3E,OAAO,CACL,GAAG,OAAO,CAAC,MAAM,yDAAyD;QAC1E,8EAA8E;QAC9E,oBAAoB,MAAM,gCAAgC;QAC1D,sCAAsC,CACvC,CAAC;AACJ,CAAC,CAAA,CAAC","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\n/**\n * Text that makes Vite run an extra `esbuild.transform` over a compiled module.\n *\n * Vite's `vite:define` plugin transforms any module containing a `define` key\n * (`process.env` and `import.meta.env` / `import.meta.hot` are its own keys in\n * a client build), and in dev it rewrites `process.env.NODE_ENV` in client\n * modules the same way. That pass does not set `keepNames`, and esbuild\n * renames the inner binding of the class expression tsc emits for a decorated\n * class: `let Foo = class Foo` becomes `class Foo2`.\n */\nconst RENAME_TRIGGER = /process\\.env|import\\.meta\\.(?:env|hot)/;\n\n/** `Foo = __decorate([ …decorators… ], Foo)`, as tsc emits it. */\nconst DECORATED = /\\b([A-Za-z_$][\\w$]*) = __decorate\\(\\[([\\s\\S]*?)\\], \\1\\)/g;\n\nexport interface ExposedShape {\n file: string;\n className: string;\n}\n\n/**\n * Shapes in one compiled module whose identity would change if a bundler\n * renamed their class.\n *\n * A shape's IRI is built from its class name unless `@linkedShape({name})`\n * gives one. Source files are safe: esbuild lowers their decorators to an\n * anonymous `let Foo = class {`, which takes its name from the binding. Only\n * published `lib/` JavaScript carries the self-named class expression, so a\n * compiled shape is exposed exactly when it has no explicit name and its module\n * contains a trigger. `createViteConfig` pins these names\n * (`plugins/pin-compiled-class-names.ts`), but other bundlers and hand-written\n * Vite configs do not, so the explicit name is still the fix. This is how\n * `@_linked/server`'s `LinkedServer` and `LincdAPI` came to register as\n * `LinkedServer2` / `LincdAPI2`.\n */\nexport const findRenameableShapes = (\n source: string,\n file = '',\n): ExposedShape[] => {\n if (!RENAME_TRIGGER.test(source)) return [];\n const found: ExposedShape[] = [];\n for (const [, className, decorators] of source.matchAll(DECORATED)) {\n if (!/\\blinkedShape\\b/.test(decorators)) continue;\n if (/\\blinkedShape\\(\\s*\\{[\\s\\S]*?\\bname\\s*:/.test(decorators)) continue;\n found.push({file, className});\n }\n return found;\n};\n\n/**\n * Build step: warn about every exposed shape in a package's compiled ESM.\n *\n * A warning, not a failure: it is only a hazard when a consumer's bundler\n * actually rewrites the module, and naming the shape is a change to the\n * package's source that its owner has to make.\n */\nexport const checkShapeNames = async (\n packagePath: string,\n): Promise<true | string> => {\n const libDir = path.join(packagePath, 'lib', 'esm');\n if (!fs.existsSync(libDir)) return true;\n const exposed: ExposedShape[] = [];\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()) walk(full);\n else if (entry.name.endsWith('.js')) {\n exposed.push(\n ...findRenameableShapes(\n fs.readFileSync(full, 'utf8'),\n path.relative(libDir, full),\n ),\n );\n }\n }\n };\n walk(libDir);\n if (exposed.length === 0) return true;\n const listed = exposed.map((s) => `${s.className} (${s.file})`).join(', ');\n return (\n `${exposed.length} shape(s) take their identity from a class name that a ` +\n `consumer's bundler may rename, because the module also reads process.env or ` +\n `import.meta.env: ${listed}. Give each an explicit name: ` +\n `@linkedShape({name: '<ClassName>'}).`\n );\n};\n"]}
|
package/lib/esm/vite-config.d.ts
CHANGED
|
@@ -126,6 +126,22 @@ export declare function discoverLinkedSourceDependencies(cwd?: string): Promise<
|
|
|
126
126
|
* dependencies for.
|
|
127
127
|
*/
|
|
128
128
|
export declare function discoverWorkspaces(extraGlobs?: string[], cwd?: string): Promise<WorkspaceEntry[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Packages whose entry `linked start` hands to `vite.ssrLoadModule` by name
|
|
131
|
+
* (`@_linked/server/shapes/LinkedServer`, see `commands/start.ts`).
|
|
132
|
+
*
|
|
133
|
+
* Vite transforms an explicitly requested entry, and every file it reaches by
|
|
134
|
+
* RELATIVE import, whether or not the package is external. The same package's
|
|
135
|
+
* bare-specifier imports from anywhere else (the app's `src`, the storage
|
|
136
|
+
* config) are externalized to Node. Left external, the package is split across
|
|
137
|
+
* two loaders, and which copy a file ends up in depends on import order: a file
|
|
138
|
+
* the module runner has already evaluated is reused, one it has not is loaded
|
|
139
|
+
* by Node, and Node then loads that file's relative imports itself. Measured in
|
|
140
|
+
* CN: `package.js` and `ontologies/lincd-server.js` evaluated once by each
|
|
141
|
+
* loader, and `LocalFileStore.js` too once the package's `backend` was loaded.
|
|
142
|
+
* Bundling the package makes Vite the only loader for it.
|
|
143
|
+
*/
|
|
144
|
+
export declare const SSR_ENTRY_PACKAGES: string[];
|
|
129
145
|
/**
|
|
130
146
|
* `ssr.noExternal` for the dev SSR runner. With source workspaces, only those
|
|
131
147
|
* package names are bundled by Vite; everything else in node_modules (including
|
|
@@ -134,6 +150,7 @@ export declare function discoverWorkspaces(extraGlobs?: string[], cwd?: string):
|
|
|
134
150
|
* Installed packages that depend on a workspace (`dependents`, from
|
|
135
151
|
* `workspaceDependents`) are bundled too, so they share the Vite-loaded workspace.
|
|
136
152
|
* Standalone (no workspaces): the context-holding framework packages are bundled.
|
|
153
|
+
* In both modes, `SSR_ENTRY_PACKAGES` are bundled.
|
|
137
154
|
*/
|
|
138
155
|
export declare function ssrNoExternal(workspaces: {
|
|
139
156
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../../src/vite-config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAC,YAAY,EAAC,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../../src/vite-config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAC,YAAY,EAAC,MAAM,MAAM,CAAC;AAOlC,OAAO,KAAK,EAAC,MAAM,EAAa,MAAM,MAAM,CAAC;AAuB7C;;;;;;;;;;;;;;;GAeG;AACH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,KAAG,MAAM,GAAG,SAyDtD,CAAC;AAEF,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAQnD;AAED,MAAM,WAAW,uBAAuB;IACtC,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,CAAC,EAAE,UAAU,GAAG,kBAAkB,CAAC;IAC1C,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAwCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,EAAE,EAC7C,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CAsEnB;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,gCAAgC,CACpD,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAmC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,GAAE,MAAM,EAAO,EACzB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAyD3B;AAwCD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,UAAsB,CAAC;AAEtD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,EAAE,EAC5B,UAAU,GAAE,MAAM,EAAO,GACxB,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAKrB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,GAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,GAAG,MAAM,CAAM,GAC1D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAaxB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,uBAA4B,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAuXpG"}
|
package/lib/esm/vite-config.js
CHANGED
|
@@ -24,6 +24,7 @@ import fsExtra from 'fs-extra';
|
|
|
24
24
|
import path from 'node:path';
|
|
25
25
|
import { generateScopedName } from './utils.js';
|
|
26
26
|
import { parseWorkspacePatterns, isWorkspacePathNegated } from './workspace-globs.js';
|
|
27
|
+
import { pinCompiledClassNames } from './plugins/pin-compiled-class-names.js';
|
|
27
28
|
/**
|
|
28
29
|
* Framework packages that MUST be single-instance per runtime — they hold
|
|
29
30
|
* module-level state (`@_linked/core`'s shape registry, `LinkedStorage`, the query
|
|
@@ -468,6 +469,22 @@ function resolveWorkspaceSpecifier(specifier, workspaces) {
|
|
|
468
469
|
return null;
|
|
469
470
|
});
|
|
470
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Packages whose entry `linked start` hands to `vite.ssrLoadModule` by name
|
|
474
|
+
* (`@_linked/server/shapes/LinkedServer`, see `commands/start.ts`).
|
|
475
|
+
*
|
|
476
|
+
* Vite transforms an explicitly requested entry, and every file it reaches by
|
|
477
|
+
* RELATIVE import, whether or not the package is external. The same package's
|
|
478
|
+
* bare-specifier imports from anywhere else (the app's `src`, the storage
|
|
479
|
+
* config) are externalized to Node. Left external, the package is split across
|
|
480
|
+
* two loaders, and which copy a file ends up in depends on import order: a file
|
|
481
|
+
* the module runner has already evaluated is reused, one it has not is loaded
|
|
482
|
+
* by Node, and Node then loads that file's relative imports itself. Measured in
|
|
483
|
+
* CN: `package.js` and `ontologies/lincd-server.js` evaluated once by each
|
|
484
|
+
* loader, and `LocalFileStore.js` too once the package's `backend` was loaded.
|
|
485
|
+
* Bundling the package makes Vite the only loader for it.
|
|
486
|
+
*/
|
|
487
|
+
export const SSR_ENTRY_PACKAGES = ['@_linked/server'];
|
|
471
488
|
/**
|
|
472
489
|
* `ssr.noExternal` for the dev SSR runner. With source workspaces, only those
|
|
473
490
|
* package names are bundled by Vite; everything else in node_modules (including
|
|
@@ -476,11 +493,13 @@ function resolveWorkspaceSpecifier(specifier, workspaces) {
|
|
|
476
493
|
* Installed packages that depend on a workspace (`dependents`, from
|
|
477
494
|
* `workspaceDependents`) are bundled too, so they share the Vite-loaded workspace.
|
|
478
495
|
* Standalone (no workspaces): the context-holding framework packages are bundled.
|
|
496
|
+
* In both modes, `SSR_ENTRY_PACKAGES` are bundled.
|
|
479
497
|
*/
|
|
480
498
|
export function ssrNoExternal(workspaces, dependents = []) {
|
|
481
|
-
if (workspaces.length === 0)
|
|
482
|
-
return [/^@_linked\/server-utils$/, /^@_linked\/react
|
|
483
|
-
|
|
499
|
+
if (workspaces.length === 0) {
|
|
500
|
+
return [/^@_linked\/server-utils$/, /^@_linked\/react$/, ...SSR_ENTRY_PACKAGES];
|
|
501
|
+
}
|
|
502
|
+
return [...new Set([...workspaces.map((w) => w.name), ...dependents, ...SSR_ENTRY_PACKAGES])];
|
|
484
503
|
}
|
|
485
504
|
/**
|
|
486
505
|
* The `process.env.*` values inlined into the browser bundle — and only there.
|
|
@@ -615,6 +634,9 @@ export function createViteConfig(opts = {}) {
|
|
|
615
634
|
},
|
|
616
635
|
}
|
|
617
636
|
: null,
|
|
637
|
+
// Published lib JS: keep decorated shape classes named `Foo`, not the
|
|
638
|
+
// `Foo2` Vite's esbuild re-prints would give them — see the plugin.
|
|
639
|
+
pinCompiledClassNames(),
|
|
618
640
|
react({
|
|
619
641
|
babel: {
|
|
620
642
|
parserOpts: {
|
|
@@ -660,6 +682,10 @@ export function createViteConfig(opts = {}) {
|
|
|
660
682
|
// `.../BackendAPIStore`, and every Server.call on that shape 501'd.
|
|
661
683
|
// The same mangling made registration report `Shape undefined does not
|
|
662
684
|
// extend base class`.
|
|
685
|
+
//
|
|
686
|
+
// Vite honours this in the minifier only: its per-file TypeScript
|
|
687
|
+
// transform and its define pass both run esbuild with keepNames off.
|
|
688
|
+
// `pinCompiledClassNames` above covers what those passes rename.
|
|
663
689
|
keepNames: true,
|
|
664
690
|
} }, (isStandalone
|
|
665
691
|
? {
|
|
@@ -719,8 +745,9 @@ export function createViteConfig(opts = {}) {
|
|
|
719
745
|
// DIFFERENT module instances → two `AppContext` objects → `useAppContext()` sees
|
|
720
746
|
// no provider (null) → "Cannot destructure 'isNativeApp'" and a blank "SSR timed
|
|
721
747
|
// out". Bundling makes them one instance in Vite's SSR module graph (matching how
|
|
722
|
-
// workspace mode bundles everything).
|
|
723
|
-
//
|
|
748
|
+
// workspace mode bundles everything). `fuseki` stays external; `server` is bundled
|
|
749
|
+
// because `start` loads its entry through Vite (`SSR_ENTRY_PACKAGES`). Their native
|
|
750
|
+
// dependencies (e.g. `sharp`) are separate packages and stay external either way.
|
|
724
751
|
//
|
|
725
752
|
// WORKSPACE: bundle ONLY the discovered source workspaces (they resolve to `src/`
|
|
726
753
|
// for HMR). Published framework packages installed under node_modules (lib-only)
|
|
@@ -730,7 +757,8 @@ export function createViteConfig(opts = {}) {
|
|
|
730
757
|
// as `@_linked/fuseki/shapes/FusekiStore` through native `import()`, which pulled
|
|
731
758
|
// a SECOND Node-loaded core and split the shape registry. Installed packages
|
|
732
759
|
// that depend on a workspace (e.g. published fuseki when core itself is a
|
|
733
|
-
// workspace) are bundled too, so they import the Vite-loaded workspace.
|
|
760
|
+
// workspace) are bundled too, so they import the Vite-loaded workspace. The one
|
|
761
|
+
// published exception is `SSR_ENTRY_PACKAGES`, which Vite loads regardless.
|
|
734
762
|
//
|
|
735
763
|
// NOT DEV (a release build of the backend): nothing is force-bundled. The
|
|
736
764
|
// compiled backend is loaded by Node next to the installed
|