@proteinjs/reflection-build 1.4.7 → 1.4.9

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/modules/typescript-parser/node-parser/function-parser.js +2 -1
  3. package/dist/test/ParseTupleParams.test.d.ts +1 -0
  4. package/dist/test/ParseTupleParams.test.js +108 -0
  5. package/dist/test/ParseTupleParams.test.js.map +1 -0
  6. package/modules/typescript-parser/node-parser/function-parser.js +2 -1
  7. package/package.json +7 -5
  8. package/test/ParseTupleParams.test.ts +46 -0
  9. package/test/examples/source-repository/a/node_modules/.package-lock.json +6 -6
  10. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/CHANGELOG.md +11 -0
  11. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/dist/src/PackageUtil.d.ts +44 -1
  12. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/dist/src/PackageUtil.js +207 -142
  13. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/dist/src/PackageUtil.js.map +1 -1
  14. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/package.json +2 -2
  15. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/src/PackageUtil.ts +176 -102
  16. package/test/examples/source-repository/a/node_modules/@proteinjs/util-node/test/PackageUtil.symlinkDependencies.test.ts +76 -0
  17. package/test/examples/source-repository/a/package-lock.json +8 -8
  18. package/test/examples/source-repository/a/package.json +2 -2
  19. package/test/examples/source-repository/b/node_modules/.package-lock.json +4 -4
  20. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/CHANGELOG.md +11 -0
  21. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/dist/src/PackageUtil.d.ts +44 -1
  22. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/dist/src/PackageUtil.js +207 -142
  23. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/dist/src/PackageUtil.js.map +1 -1
  24. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/package.json +2 -2
  25. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/src/PackageUtil.ts +176 -102
  26. package/test/examples/source-repository/b/node_modules/@proteinjs/util-node/test/PackageUtil.symlinkDependencies.test.ts +76 -0
  27. package/test/examples/source-repository/b/package-lock.json +6 -6
  28. package/test/examples/source-repository/b/package.json +2 -2
  29. package/dist/modules/typescript-parser/package-lock.json +0 -16793
  30. package/dist/modules/typescript-parser/package.json +0 -55
  31. package/modules/typescript-parser/package-lock.json +0 -16793
  32. package/modules/typescript-parser/package.json +0 -55
package/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.4.9](https://github.com/proteinjs/reflection/compare/@proteinjs/reflection-build@1.4.8...@proteinjs/reflection-build@1.4.9) (2026-07-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * demote the vendored typescript-parser from installable package — its own manifest+lock resurrected typescript 3.9.10 on every fresh install ([d620104](https://github.com/proteinjs/reflection/commit/d62010437759c9991aaa72373fb58325610440c4))
12
+ * parser handles tuple-typed destructured params under modern TypeScript; unify parser runtime ([6aac8b8](https://github.com/proteinjs/reflection/commit/6aac8b864cf41a14e6aaa6c5dded8b3e8fee611b))
13
+ * tuple-params parser test uses the parser's file-based API — no typescript import in the test ([d022d44](https://github.com/proteinjs/reflection/commit/d022d44b7219316e5be705ee2727c9ba73103cdf))
14
+
15
+
16
+
17
+
18
+
6
19
  ## [1.4.7](https://github.com/proteinjs/reflection/compare/@proteinjs/reflection-build@1.4.6...@proteinjs/reflection-build@1.4.7) (2026-05-21)
7
20
 
8
21
 
@@ -70,7 +70,8 @@ function parseMethodParams(node) {
70
70
  boundParam.typeReference = parse_utilities_1.getNodeType(cur.type);
71
71
  }
72
72
  else if (cur.type && typescript_1.isTupleTypeNode(cur.type)) {
73
- types = cur.type.elementTypes.map(type => parse_utilities_1.getNodeType(type));
73
+ // TS 4.0 renamed TupleTypeNode.elementTypes -> elements.
74
+ types = cur.type.elements.map(type => parse_utilities_1.getNodeType(type));
74
75
  }
75
76
  boundParam.parameters = elements.map((bindingElement, index) => new ParameterDeclaration_1.ParameterDeclaration(bindingElement.getText(), types[index], bindingElement.getStart(), bindingElement.getEnd()));
76
77
  params.push(boundParam);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
36
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ var fs = __importStar(require("fs"));
63
+ var os = __importStar(require("os"));
64
+ var path = __importStar(require("path"));
65
+ // Test the SHIPPED parser (the compiled JS that `cp -r modules/ dist/modules/` publishes) through
66
+ // its FILE-based API, so the parser creates the SourceFile with ITS OWN typescript module. The
67
+ // test must not import typescript itself: if the test's copy and the parser's copy ever resolve
68
+ // differently (hoisting varies by environment), SyntaxKind numbers diverge and every node
69
+ // mis-dispatches — that exact cross-instance skew made this suite fail in CI only.
70
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
71
+ var TypescriptParser = require('../modules/typescript-parser/TypescriptParser').TypescriptParser;
72
+ /**
73
+ * A class method with an array-destructured, tuple-typed parameter — e.g.
74
+ * `moveMouse(client: Client, [x, y]: [number, number])` — crashed the parser with
75
+ * "Cannot read properties of undefined (reading 'map')": the vendored typescript-parser predates
76
+ * TS 4.0's rename of TupleTypeNode.elementTypes to elements.
77
+ */
78
+ var TUPLE_PARAM_SOURCE = "\nexport class CursorDriver {\n private cursor = { x: 0, y: 0 };\n\n async moveMouse(client: unknown, [x, y]: [number, number]): Promise<void> {\n this.cursor = { x, y };\n }\n}\n";
79
+ test('parses array-destructured tuple-typed method params', function () { return __awaiter(void 0, void 0, void 0, function () {
80
+ var dir, filePath, file, classDeclaration, moveMouse, boundParam;
81
+ return __generator(this, function (_a) {
82
+ switch (_a.label) {
83
+ case 0:
84
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), 'parse-tuple-params-'));
85
+ filePath = path.join(dir, 'tuple-params.ts');
86
+ fs.writeFileSync(filePath, TUPLE_PARAM_SOURCE);
87
+ _a.label = 1;
88
+ case 1:
89
+ _a.trys.push([1, , 3, 4]);
90
+ return [4 /*yield*/, new TypescriptParser().parseFile(filePath, dir)];
91
+ case 2:
92
+ file = _a.sent();
93
+ classDeclaration = file.declarations.find(function (d) { return d.name === 'CursorDriver'; });
94
+ expect(classDeclaration).toBeTruthy();
95
+ moveMouse = classDeclaration.methods.find(function (m) { return m.name === 'moveMouse'; });
96
+ expect(moveMouse).toBeTruthy();
97
+ boundParam = moveMouse.parameters[moveMouse.parameters.length - 1];
98
+ expect(boundParam.parameters.map(function (p) { return p.name; })).toEqual(['x', 'y']);
99
+ expect(boundParam.parameters.map(function (p) { return p.type; })).toEqual(['number', 'number']);
100
+ return [3 /*break*/, 4];
101
+ case 3:
102
+ fs.rmdirSync(dir, { recursive: true });
103
+ return [7 /*endfinally*/];
104
+ case 4: return [2 /*return*/];
105
+ }
106
+ });
107
+ }); });
108
+ //# sourceMappingURL=ParseTupleParams.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParseTupleParams.test.js","sourceRoot":"","sources":["../../test/ParseTupleParams.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAyB;AACzB,qCAAyB;AACzB,yCAA6B;AAC7B,kGAAkG;AAClG,+FAA+F;AAC/F,gGAAgG;AAChG,0FAA0F;AAC1F,mFAAmF;AACnF,8DAA8D;AACtD,IAAA,gBAAgB,GAAK,OAAO,CAAC,+CAA+C,CAAC,iBAA7D,CAA8D;AAEtF;;;;;GAKG;AACH,IAAM,kBAAkB,GAAG,2LAQ1B,CAAC;AAEF,IAAI,CAAC,qDAAqD,EAAE;;;;;gBACpD,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;gBACpE,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;gBACnD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;;;;gBAEhC,qBAAM,IAAI,gBAAgB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAA;;gBAA5D,IAAI,GAAG,SAAqD;gBAE5D,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,UAAC,CAAoB,IAAK,OAAA,CAAC,CAAC,IAAI,KAAK,cAAc,EAAzB,CAAyB,CAAC,CAAC;gBACrG,MAAM,CAAC,gBAAgB,CAAC,CAAC,UAAU,EAAE,CAAC;gBAChC,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,UAAC,CAAmB,IAAK,OAAA,CAAC,CAAC,IAAI,KAAK,WAAW,EAAtB,CAAsB,CAAC,CAAC;gBACjG,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC;gBAEzB,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACzE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,UAAC,CAAmB,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;gBACvF,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,UAAC,CAAoB,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;;;gBAElG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;KAE1C,CAAC,CAAC"}
@@ -70,7 +70,8 @@ function parseMethodParams(node) {
70
70
  boundParam.typeReference = parse_utilities_1.getNodeType(cur.type);
71
71
  }
72
72
  else if (cur.type && typescript_1.isTupleTypeNode(cur.type)) {
73
- types = cur.type.elementTypes.map(type => parse_utilities_1.getNodeType(type));
73
+ // TS 4.0 renamed TupleTypeNode.elementTypes -> elements.
74
+ types = cur.type.elements.map(type => parse_utilities_1.getNodeType(type));
74
75
  }
75
76
  boundParam.parameters = elements.map((bindingElement, index) => new ParameterDeclaration_1.ParameterDeclaration(bindingElement.getText(), types[index], bindingElement.getStart(), bindingElement.getEnd()));
76
77
  params.push(boundParam);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/reflection-build",
3
- "version": "1.4.7",
3
+ "version": "1.4.9",
4
4
  "description": "Build system for reflection",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,14 +31,16 @@
31
31
  "@dagrejs/graphlib": "2.1.4",
32
32
  "@proteinjs/reflection": "^1.1.11",
33
33
  "@proteinjs/util": "^1.6.0",
34
- "@proteinjs/util-node": "^1.8.1",
34
+ "@proteinjs/util-node": "^1.9.0",
35
35
  "globby": "11.0.1",
36
36
  "gulp": "4.0.2",
37
37
  "gulp-shell": "0.8.0",
38
- "jsesc": "^3.0.1"
38
+ "jsesc": "^3.0.1",
39
+ "lodash": "^4.17.10",
40
+ "tslib": "^1.9.3"
39
41
  },
40
42
  "devDependencies": {
41
- "@proteinjs/reflection-build-test-a": "^0.0.20",
43
+ "@proteinjs/reflection-build-test-a": "^0.0.21",
42
44
  "@types/graphlib": "2.1.6",
43
45
  "@types/gulp": "4.0.16",
44
46
  "@types/jest": "29.5.6",
@@ -53,5 +55,5 @@
53
55
  "ts-jest": "29.1.1",
54
56
  "typescript": "5.2.2"
55
57
  },
56
- "gitHead": "d5bd462153bc8ec9abd1ac03ed38e2540dba7b48"
58
+ "gitHead": "dd11bf2e88a24c4f09a880e8bf9e44b8c94479ea"
57
59
  }
@@ -0,0 +1,46 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ // Test the SHIPPED parser (the compiled JS that `cp -r modules/ dist/modules/` publishes) through
5
+ // its FILE-based API, so the parser creates the SourceFile with ITS OWN typescript module. The
6
+ // test must not import typescript itself: if the test's copy and the parser's copy ever resolve
7
+ // differently (hoisting varies by environment), SyntaxKind numbers diverge and every node
8
+ // mis-dispatches — that exact cross-instance skew made this suite fail in CI only.
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
10
+ const { TypescriptParser } = require('../modules/typescript-parser/TypescriptParser');
11
+
12
+ /**
13
+ * A class method with an array-destructured, tuple-typed parameter — e.g.
14
+ * `moveMouse(client: Client, [x, y]: [number, number])` — crashed the parser with
15
+ * "Cannot read properties of undefined (reading 'map')": the vendored typescript-parser predates
16
+ * TS 4.0's rename of TupleTypeNode.elementTypes to elements.
17
+ */
18
+ const TUPLE_PARAM_SOURCE = `
19
+ export class CursorDriver {
20
+ private cursor = { x: 0, y: 0 };
21
+
22
+ async moveMouse(client: unknown, [x, y]: [number, number]): Promise<void> {
23
+ this.cursor = { x, y };
24
+ }
25
+ }
26
+ `;
27
+
28
+ test('parses array-destructured tuple-typed method params', async () => {
29
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'parse-tuple-params-'));
30
+ const filePath = path.join(dir, 'tuple-params.ts');
31
+ fs.writeFileSync(filePath, TUPLE_PARAM_SOURCE);
32
+ try {
33
+ const file = await new TypescriptParser().parseFile(filePath, dir);
34
+
35
+ const classDeclaration = file.declarations.find((d: { name?: string }) => d.name === 'CursorDriver');
36
+ expect(classDeclaration).toBeTruthy();
37
+ const moveMouse = classDeclaration.methods.find((m: { name: string }) => m.name === 'moveMouse');
38
+ expect(moveMouse).toBeTruthy();
39
+ // The tuple-bound parameter parses into an array-bound declaration carrying both elements.
40
+ const boundParam = moveMouse.parameters[moveMouse.parameters.length - 1];
41
+ expect(boundParam.parameters.map((p: { name: string }) => p.name)).toEqual(['x', 'y']);
42
+ expect(boundParam.parameters.map((p: { type?: string }) => p.type)).toEqual(['number', 'number']);
43
+ } finally {
44
+ fs.rmdirSync(dir, { recursive: true });
45
+ }
46
+ });
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@proteinjs/reflection-build-test-a",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "../b": {
8
8
  "name": "@proteinjs/reflection-build-test-b",
9
- "version": "0.0.20",
9
+ "version": "0.0.21",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@dagrejs/graphlib": "2.1.4",
13
13
  "@proteinjs/reflection": "^1.1.11",
14
14
  "@proteinjs/util": "^1.6.0",
15
- "@proteinjs/util-node": "^1.8.1",
15
+ "@proteinjs/util-node": "^1.9.0",
16
16
  "globby": "11.0.1",
17
17
  "gulp": "4.0.2",
18
18
  "gulp-shell": "0.8.0",
@@ -1102,9 +1102,9 @@
1102
1102
  }
1103
1103
  },
1104
1104
  "node_modules/@proteinjs/util-node": {
1105
- "version": "1.8.1",
1106
- "resolved": "https://registry.npmjs.org/@proteinjs/util-node/-/util-node-1.8.1.tgz",
1107
- "integrity": "sha512-F4BEBmroyTuRjQGYkJQhs2JoTg6VUIeEveMZbHzV5mG8jIyF2zbIF+qQCJ0cV2pdQg2PLhi61VlstTwJrEIKdQ==",
1105
+ "version": "1.9.0",
1106
+ "resolved": "https://registry.npmjs.org/@proteinjs/util-node/-/util-node-1.9.0.tgz",
1107
+ "integrity": "sha512-kn9zzmm7tUmlZiiJxGjkekhwsNprUzZM2r5rWZYgDD/BWdGCTA1QCfKEhmjCHLJutR1J+i4NmWcSfuYdyt+hjw==",
1108
1108
  "license": "ISC",
1109
1109
  "dependencies": {
1110
1110
  "@dagrejs/graphlib": "2.1.4",
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.9.0](https://github.com/proteinjs/util/compare/@proteinjs/util-node@1.8.1...@proteinjs/util-node@1.9.0) (2026-06-24)
7
+
8
+
9
+ ### Features
10
+
11
+ * symlink-workspace links each package's transitive workspace-dep closure ([55a7c25](https://github.com/proteinjs/util/commit/55a7c2541f500bec4e12bb05454acadd6b4c4b66))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [1.8.1](https://github.com/proteinjs/util/compare/@proteinjs/util-node@1.8.0...@proteinjs/util-node@1.8.1) (2026-04-14)
7
18
 
8
19
 
@@ -101,9 +101,52 @@ export declare class PackageUtil {
101
101
  static getWorkspaceMetadata(workspacePath: string): Promise<WorkspaceMetadata>;
102
102
  /**
103
103
  * Symlink the dependencies of `localPackage` to other local packages in the workspace.
104
+ *
105
+ * This links the package's full TRANSITIVE closure of workspace dependencies,
106
+ * not just its directly-declared ones. A package's `package.json` only lists
107
+ * its direct deps, but those deps pull in workspace packages of their own
108
+ * (e.g. `flow-server` declares `@n3xah/space-server`, which itself depends on
109
+ * `@n3xah/space-common`). Node resolves a transitive dep like `space-common`
110
+ * out of the consumer's own `node_modules` first, so if we only symlinked
111
+ * direct deps, npm would satisfy `space-common` with a stale registry copy
112
+ * that lags the live workspace source — causing schema/version drift. By
113
+ * linking the whole closure, every workspace package a package can reach at
114
+ * runtime resolves to the live source tree.
115
+ *
104
116
  * @param localPackage package to symlink the dependencies of
105
117
  * @param localPackageMap `LocalPackageMap` of the workspace
106
- * @param logger optionally provide a logger to capture this method's logging
107
118
  */
108
119
  static symlinkDependencies(localPackage: LocalPackage, localPackageMap: LocalPackageMap): Promise<void>;
120
+ /**
121
+ * Compute the transitive closure of workspace dependencies for `localPackage`.
122
+ *
123
+ * Reuses `getPackageDependencyGraph`, which already crawls `dependencies` and
124
+ * `devDependencies` (transitively, across the whole workspace) and adds an
125
+ * edge `consumer -> dependency` for each. So the workspace deps reachable from
126
+ * a package are exactly the nodes reachable by following `successors` from its
127
+ * node. We do a cycle-safe traversal (a `visited` set), since the dependency
128
+ * graph can contain cycles. The package itself is excluded from the result.
129
+ *
130
+ * Only names present in `localPackageMap` are returned — i.e. packages that
131
+ * actually live in the workspace and can be symlinked (the graph already
132
+ * filters to file:/relative/workspace deps in `addDependencies`, but we filter
133
+ * again here so the result is exactly the set of linkable packages).
134
+ *
135
+ * @returns workspace package names this package transitively depends on
136
+ */
137
+ private static getTransitiveWorkspaceDependencies;
138
+ /**
139
+ * Symlink a single workspace package into `nodeModulesPath`, and create
140
+ * `node_modules/.bin/<name>` shims for any `bin` it declares.
141
+ *
142
+ * This is the per-dependency linking logic used by `symlinkDependencies` for
143
+ * each package in the transitive closure. The caller is responsible for
144
+ * deciding WHICH packages to link; this method just links the one named.
145
+ *
146
+ * @param dependencyPackageName name of the workspace package to link
147
+ * @param nodeModulesPath absolute path to the consumer's `node_modules`
148
+ * @param packageDir absolute path to the consumer package's directory (cwd for `ln`)
149
+ * @param localPackageMap `LocalPackageMap` of the workspace
150
+ */
151
+ private static symlinkPackage;
109
152
  }