@proteinjs/reflection-build 1.5.0 → 2.0.1

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 (97) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/modules/typescript-parser/declarations/ClassDeclaration.d.ts +1 -0
  3. package/dist/modules/typescript-parser/declarations/ClassDeclaration.js +1 -0
  4. package/dist/modules/typescript-parser/node-parser/class-parser.js +6 -0
  5. package/dist/src/BuildContract.d.ts +69 -0
  6. package/dist/src/BuildContract.js +393 -0
  7. package/dist/src/BuildContract.js.map +1 -0
  8. package/dist/src/ReflectionDoctor.d.ts +95 -0
  9. package/dist/src/ReflectionDoctor.js +588 -0
  10. package/dist/src/ReflectionDoctor.js.map +1 -0
  11. package/dist/src/build.d.ts +5 -1
  12. package/dist/src/build.js +13 -77
  13. package/dist/src/build.js.map +1 -1
  14. package/dist/src/codegen/writeGeneratedIndex.d.ts +18 -0
  15. package/dist/src/codegen/writeGeneratedIndex.js +58 -15
  16. package/dist/src/codegen/writeGeneratedIndex.js.map +1 -1
  17. package/dist/src/parser/createGraphBuilder.js +30 -5
  18. package/dist/src/parser/createGraphBuilder.js.map +1 -1
  19. package/dist/src/parser/types/createClassDeclaration.js +1 -4
  20. package/dist/src/parser/types/createClassDeclaration.js.map +1 -1
  21. package/dist/src/runBuild.js +12 -2
  22. package/dist/src/runBuild.js.map +1 -1
  23. package/dist/src/runDoctor.d.ts +2 -0
  24. package/dist/src/runDoctor.js +83 -0
  25. package/dist/src/runDoctor.js.map +1 -0
  26. package/dist/test/AbstractClassDeclaration.test.d.ts +1 -0
  27. package/dist/test/AbstractClassDeclaration.test.js +121 -0
  28. package/dist/test/AbstractClassDeclaration.test.js.map +1 -0
  29. package/dist/test/GraphEmitRelativePaths.test.d.ts +1 -0
  30. package/dist/test/GraphEmitRelativePaths.test.js +162 -0
  31. package/dist/test/GraphEmitRelativePaths.test.js.map +1 -0
  32. package/dist/test/ReflectionDoctor.test.d.ts +1 -0
  33. package/dist/test/ReflectionDoctor.test.js +316 -0
  34. package/dist/test/ReflectionDoctor.test.js.map +1 -0
  35. package/dist/test/TestSubpathContract.test.d.ts +1 -0
  36. package/dist/test/TestSubpathContract.test.js +260 -0
  37. package/dist/test/TestSubpathContract.test.js.map +1 -0
  38. package/dist/test/ValidateDontMutate.test.d.ts +1 -0
  39. package/dist/test/ValidateDontMutate.test.js +238 -0
  40. package/dist/test/ValidateDontMutate.test.js.map +1 -0
  41. package/dist/test/examples/source-repository/a/generated/index.js +1 -1
  42. package/dist/test/examples/source-repository/a/generated/index.js.map +1 -1
  43. package/dist/test/examples/source-repository/b/generated/index.js +1 -1
  44. package/dist/test/examples/source-repository/b/generated/index.js.map +1 -1
  45. package/modules/typescript-parser/declarations/ClassDeclaration.d.ts +1 -0
  46. package/modules/typescript-parser/declarations/ClassDeclaration.js +1 -0
  47. package/modules/typescript-parser/node-parser/class-parser.js +6 -0
  48. package/package.json +6 -5
  49. package/src/BuildContract.ts +384 -0
  50. package/src/ReflectionDoctor.ts +589 -0
  51. package/src/build.ts +19 -56
  52. package/src/codegen/writeGeneratedIndex.ts +51 -13
  53. package/src/parser/createGraphBuilder.ts +9 -4
  54. package/src/parser/types/createClassDeclaration.ts +5 -5
  55. package/src/runBuild.ts +7 -1
  56. package/src/runDoctor.ts +34 -0
  57. package/test/AbstractClassDeclaration.test.ts +97 -0
  58. package/test/GraphEmitRelativePaths.test.ts +95 -0
  59. package/test/ReflectionDoctor.test.ts +193 -0
  60. package/test/TestSubpathContract.test.ts +148 -0
  61. package/test/ValidateDontMutate.test.ts +126 -0
  62. package/test/examples/source-repository/a/dist/BuildContract.d.ts +69 -0
  63. package/test/examples/source-repository/a/dist/BuildContract.js +393 -0
  64. package/test/examples/source-repository/a/dist/BuildContract.js.map +1 -0
  65. package/test/examples/source-repository/a/dist/build.d.ts +5 -1
  66. package/test/examples/source-repository/a/dist/build.js +13 -77
  67. package/test/examples/source-repository/a/dist/build.js.map +1 -1
  68. package/test/examples/source-repository/a/dist/codegen/writeGeneratedIndex.d.ts +18 -0
  69. package/test/examples/source-repository/a/dist/codegen/writeGeneratedIndex.js +58 -15
  70. package/test/examples/source-repository/a/dist/codegen/writeGeneratedIndex.js.map +1 -1
  71. package/test/examples/source-repository/a/dist/generated/index.js +1 -1
  72. package/test/examples/source-repository/a/dist/generated/index.js.map +1 -1
  73. package/test/examples/source-repository/a/dist/parser/createGraphBuilder.js +30 -5
  74. package/test/examples/source-repository/a/dist/parser/createGraphBuilder.js.map +1 -1
  75. package/test/examples/source-repository/a/dist/parser/types/createClassDeclaration.js +1 -4
  76. package/test/examples/source-repository/a/dist/parser/types/createClassDeclaration.js.map +1 -1
  77. package/test/examples/source-repository/a/dist/runBuild.js +12 -2
  78. package/test/examples/source-repository/a/dist/runBuild.js.map +1 -1
  79. package/test/examples/source-repository/a/generated/index.ts +1 -1
  80. package/test/examples/source-repository/b/dist/BuildContract.d.ts +69 -0
  81. package/test/examples/source-repository/b/dist/BuildContract.js +393 -0
  82. package/test/examples/source-repository/b/dist/BuildContract.js.map +1 -0
  83. package/test/examples/source-repository/b/dist/build.d.ts +5 -1
  84. package/test/examples/source-repository/b/dist/build.js +13 -77
  85. package/test/examples/source-repository/b/dist/build.js.map +1 -1
  86. package/test/examples/source-repository/b/dist/codegen/writeGeneratedIndex.d.ts +18 -0
  87. package/test/examples/source-repository/b/dist/codegen/writeGeneratedIndex.js +58 -15
  88. package/test/examples/source-repository/b/dist/codegen/writeGeneratedIndex.js.map +1 -1
  89. package/test/examples/source-repository/b/dist/generated/index.js +1 -1
  90. package/test/examples/source-repository/b/dist/generated/index.js.map +1 -1
  91. package/test/examples/source-repository/b/dist/parser/createGraphBuilder.js +30 -5
  92. package/test/examples/source-repository/b/dist/parser/createGraphBuilder.js.map +1 -1
  93. package/test/examples/source-repository/b/dist/parser/types/createClassDeclaration.js +1 -4
  94. package/test/examples/source-repository/b/dist/parser/types/createClassDeclaration.js.map +1 -1
  95. package/test/examples/source-repository/b/dist/runBuild.js +12 -2
  96. package/test/examples/source-repository/b/dist/runBuild.js.map +1 -1
  97. package/test/examples/source-repository/b/generated/index.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,46 @@
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
+ ## [2.0.1](https://github.com/proteinjs/reflection/compare/@proteinjs/reflection-build@2.0.0...@proteinjs/reflection-build@2.0.1) (2026-08-22)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * never instantiate abstract classes from objects(); stamp class-level isAbstract in the parser ([b971030](https://github.com/proteinjs/reflection/commit/b971030f42b8660cc2f0688848ecfe8599ca1dcf))
12
+
13
+
14
+
15
+
16
+
17
+ # [2.0.0](https://github.com/proteinjs/reflection/compare/@proteinjs/reflection-build@1.5.0...@proteinjs/reflection-build@2.0.0) (2026-08-18)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **reflection-build:** emit package-relative filePaths in the source graph — kills the build-machine path disclosure ([df453e5](https://github.com/proteinjs/reflection/commit/df453e5433a6d085686c0818ec66d4826a7de6f2))
23
+
24
+
25
+ ### Features
26
+
27
+ * **reflection-build:** reflection-doctor CLI — inventory, orphan detection, --explain parent-edge traces ([ab53c39](https://github.com/proteinjs/reflection/commit/ab53c39df976feeb46ce9d6130bcf397b0d48a5e))
28
+ * **reflection-build:** validate-don't-mutate package-config contract + generalized ./test subpath contract (BuildContract, --fix) ([88b0a2b](https://github.com/proteinjs/reflection/commit/88b0a2b011fcf817fad6fbdff7fa5078422f4ba1))
29
+
30
+
31
+ ### BREAKING CHANGES
32
+
33
+ * **reflection-build:** reflection-build no longer rewrites package.json/tsconfig.json on
34
+ every build. It validates them as a contract: absent config is completed (including
35
+ the ./test subpath's root stubs, exports/typesVersions, tsconfig excludes), but
36
+ CONFLICTING config now FAILS the build with a friendly error (nothing changed on
37
+ disk) instead of being silently overwritten. Run `reflection-build --fix` once to
38
+ adopt the contract on out-of-sync packages.
39
+
40
+ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
41
+
42
+
43
+
44
+
45
+
6
46
  # [1.5.0](https://github.com/proteinjs/reflection/compare/@proteinjs/reflection-build@1.4.12...@proteinjs/reflection-build@1.5.0) (2026-08-14)
7
47
 
8
48
 
@@ -18,6 +18,7 @@ export declare class ClassDeclaration implements ClassLikeDeclaration, Exportabl
18
18
  start?: number | undefined;
19
19
  end?: number | undefined;
20
20
  ctor: ConstructorDeclaration | undefined;
21
+ isAbstract: boolean;
21
22
  accessors: AccessorDeclaration[];
22
23
  properties: PropertyDeclaration[];
23
24
  methods: MethodDeclaration[];
@@ -16,6 +16,7 @@ class ClassDeclaration {
16
16
  this.isExported = isExported;
17
17
  this.start = start;
18
18
  this.end = end;
19
+ this.isAbstract = false;
19
20
  this.accessors = [];
20
21
  this.properties = [];
21
22
  this.methods = [];
@@ -78,6 +78,12 @@ exports.parseCtorParams = parseCtorParams;
78
78
  function parseClass(tsResource, node) {
79
79
  const name = node.name ? node.name.text : parse_utilities_1.getDefaultResourceIdentifier(tsResource);
80
80
  const classDeclaration = new ClassDeclaration_1.ClassDeclaration(name, parse_utilities_1.isNodeExported(node), node.getStart(), node.getEnd());
81
+ // The class-level `abstract` keyword lives in the class node's own modifiers — member scans
82
+ // (abstract accessors/methods/properties) are NOT a substitute: an abstract class need not
83
+ // declare any abstract member, and consumers (reflection's SourceRepository) must know the
84
+ // class itself is not instantiable.
85
+ classDeclaration.isAbstract =
86
+ node.modifiers !== undefined && node.modifiers.some(m => m.kind === typescript_1.SyntaxKind.AbstractKeyword);
81
87
  if (parse_utilities_1.isNodeDefaultExported(node)) {
82
88
  classDeclaration.isExported = false;
83
89
  tsResource.declarations.push(new DefaultDeclaration_1.DefaultDeclaration(classDeclaration.name, tsResource));
@@ -0,0 +1,69 @@
1
+ export interface BuildContractOptions {
2
+ /** Root of the package being built (contains package.json) */
3
+ packageDir: string;
4
+ /** First REFLECTION_SOURCE_DIRS entry; 'src' for prod builds */
5
+ primaryRoot: string;
6
+ /** REFLECTION_DIST_DIR or 'dist' */
7
+ distDirRel: string;
8
+ /** Absolute path to the generated index .ts this invocation emits */
9
+ generatedIndexPath: string;
10
+ /** Write conflicting values to the contract instead of failing the build */
11
+ fix: boolean;
12
+ }
13
+ /**
14
+ * The package-config contract of a reflection build (task #104 §3.3, validate-don't-mutate).
15
+ *
16
+ * A build's artifact is only usable if the package's config points at it, so reflection-build
17
+ * owns that config as a contract instead of silently rewriting files on every build:
18
+ *
19
+ * - ABSENT config is completed in place (a fresh or copied package gets main/types, subpath
20
+ * mappings, stubs — the zero-ceremony workflow survives).
21
+ * - EXISTING config that conflicts with the contract fails the build with a friendly error
22
+ * (plain words, why it matters, the exact lines to paste, `--fix` offered first) and leaves
23
+ * every file untouched.
24
+ * - `reflection-build --fix` writes the contract over conflicting values; it is idempotent.
25
+ *
26
+ * Prod builds (primary root 'src') own main/types + the tsconfig include. Subpath builds
27
+ * (primary root e.g. 'test') own the complete subpath contract — root <root>.js/<root>.d.ts
28
+ * stubs, exports/typesVersions mappings, files[] entries, tsconfig excludes (the d51556f0
29
+ * class, generalized): consumers must resolve the subpath to built dist in every install
30
+ * shape and resolution mode, never to sources.
31
+ */
32
+ export declare class BuildContract {
33
+ private readonly options;
34
+ constructor(options: BuildContractOptions);
35
+ apply(): Promise<void>;
36
+ private applyPackageJson;
37
+ /** Prod builds: main/types point at the built reflection artifact. */
38
+ private settleEntryPoints;
39
+ /** Subpath builds: exports map "." and "./<root>" to the built artifacts. */
40
+ private settleSubpathExports;
41
+ /** Subpath builds: typesVersions carries the subpath's types for node10 resolution. */
42
+ private settleTypesVersions;
43
+ /** Subpath builds: an existing files allowlist must keep shipping the root stubs. */
44
+ private settleFilesAllowlist;
45
+ /**
46
+ * Subpath builds: root stubs that win the node10/paths-mapped file lookup, so every install
47
+ * shape resolves the subpath to built dist — never to sources (the TS6059/ts-jest class).
48
+ */
49
+ private applyStubs;
50
+ /**
51
+ * tsconfig: include the generated index; on subpath builds, exclude the root stubs from
52
+ * compilation. List membership only — nothing here can conflict.
53
+ */
54
+ private applyTsconfig;
55
+ /**
56
+ * Settle one string field: absent → set; equal → ok; a dangling value (points at a file
57
+ * that does not exist — npm init's boilerplate `"main": "index.js"`, a stale copy) → set;
58
+ * a value that points at a real, different file is a deliberate setting → conflict.
59
+ */
60
+ private settleString;
61
+ private formatConflicts;
62
+ private isProd;
63
+ private prodIndexJs;
64
+ private prodIndexDts;
65
+ private subpathIndexJs;
66
+ private subpathIndexDts;
67
+ private stubJsName;
68
+ private stubDtsName;
69
+ }
@@ -0,0 +1,393 @@
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
+ exports.BuildContract = void 0;
63
+ var fs = __importStar(require("fs"));
64
+ var path = __importStar(require("path"));
65
+ var tsconfigTemplate = require('./tsconfigTemplate.json');
66
+ /**
67
+ * The package-config contract of a reflection build (task #104 §3.3, validate-don't-mutate).
68
+ *
69
+ * A build's artifact is only usable if the package's config points at it, so reflection-build
70
+ * owns that config as a contract instead of silently rewriting files on every build:
71
+ *
72
+ * - ABSENT config is completed in place (a fresh or copied package gets main/types, subpath
73
+ * mappings, stubs — the zero-ceremony workflow survives).
74
+ * - EXISTING config that conflicts with the contract fails the build with a friendly error
75
+ * (plain words, why it matters, the exact lines to paste, `--fix` offered first) and leaves
76
+ * every file untouched.
77
+ * - `reflection-build --fix` writes the contract over conflicting values; it is idempotent.
78
+ *
79
+ * Prod builds (primary root 'src') own main/types + the tsconfig include. Subpath builds
80
+ * (primary root e.g. 'test') own the complete subpath contract — root <root>.js/<root>.d.ts
81
+ * stubs, exports/typesVersions mappings, files[] entries, tsconfig excludes (the d51556f0
82
+ * class, generalized): consumers must resolve the subpath to built dist in every install
83
+ * shape and resolution mode, never to sources.
84
+ */
85
+ var BuildContract = /** @class */ (function () {
86
+ function BuildContract(options) {
87
+ this.options = options;
88
+ }
89
+ BuildContract.prototype.apply = function () {
90
+ return __awaiter(this, void 0, void 0, function () {
91
+ var conflicts, writes, _i, writes_1, write;
92
+ return __generator(this, function (_a) {
93
+ conflicts = [];
94
+ writes = [];
95
+ this.applyPackageJson(conflicts, writes);
96
+ this.applyStubs(conflicts, writes);
97
+ this.applyTsconfig(writes);
98
+ if (conflicts.length > 0) {
99
+ throw new Error(this.formatConflicts(conflicts));
100
+ }
101
+ for (_i = 0, writes_1 = writes; _i < writes_1.length; _i++) {
102
+ write = writes_1[_i];
103
+ fs.writeFileSync(write.filePath, write.content);
104
+ }
105
+ return [2 /*return*/];
106
+ });
107
+ });
108
+ };
109
+ BuildContract.prototype.applyPackageJson = function (conflicts, writes) {
110
+ var packageJsonPath = path.join(this.options.packageDir, 'package.json');
111
+ if (!fs.existsSync(packageJsonPath)) {
112
+ throw new Error("package.json does not exist, run `npm init -y` to create one");
113
+ }
114
+ var original = fs.readFileSync(packageJsonPath, 'utf-8');
115
+ var packageJson = JSON.parse(original);
116
+ if (this.isProd()) {
117
+ this.settleEntryPoints(packageJson, conflicts);
118
+ }
119
+ else {
120
+ this.settleSubpathExports(packageJson, conflicts);
121
+ this.settleTypesVersions(packageJson, conflicts);
122
+ this.settleFilesAllowlist(packageJson);
123
+ }
124
+ var updated = JSON.stringify(packageJson, null, 2);
125
+ if (updated !== JSON.stringify(JSON.parse(original), null, 2)) {
126
+ writes.push({ filePath: packageJsonPath, content: updated });
127
+ }
128
+ };
129
+ /** Prod builds: main/types point at the built reflection artifact. */
130
+ BuildContract.prototype.settleEntryPoints = function (packageJson, conflicts) {
131
+ var pasteBlock = [" \"main\": \"".concat(this.prodIndexJs(), "\","), " \"types\": \"".concat(this.prodIndexDts(), "\"")].join('\n');
132
+ var whyItMatters = 'Every consumer loads this package through main/types; pointing them anywhere but the ' +
133
+ 'built reflection artifact ships a package that loads the wrong code.';
134
+ this.settleString(packageJson, 'main', this.prodIndexJs(), conflicts, whyItMatters, pasteBlock);
135
+ this.settleString(packageJson, 'types', this.prodIndexDts(), conflicts, whyItMatters, pasteBlock);
136
+ };
137
+ /** Subpath builds: exports map "." and "./<root>" to the built artifacts. */
138
+ BuildContract.prototype.settleSubpathExports = function (packageJson, conflicts) {
139
+ var _a;
140
+ var root = this.options.primaryRoot;
141
+ var expectedExports = (_a = {
142
+ '.': { types: this.prodIndexDts(), default: this.prodIndexJs() }
143
+ },
144
+ _a["./".concat(root)] = { types: this.subpathIndexDts(), default: this.subpathIndexJs() },
145
+ _a);
146
+ var whyItMatters = "Consumers import '<package>/".concat(root, "' through these mappings; a wrong mapping resolves ") +
147
+ 'to the wrong files (or to sources), breaking consumer builds.';
148
+ if (packageJson.exports == null) {
149
+ packageJson.exports = expectedExports;
150
+ return;
151
+ }
152
+ for (var _i = 0, _b = Object.keys(expectedExports); _i < _b.length; _i++) {
153
+ var subpath = _b[_i];
154
+ var expected = expectedExports[subpath];
155
+ var current = packageJson.exports[subpath];
156
+ if (current == null) {
157
+ packageJson.exports[subpath] = expected;
158
+ }
159
+ else if (JSON.stringify(current) !== JSON.stringify(expected)) {
160
+ if (this.options.fix) {
161
+ packageJson.exports[subpath] = expected;
162
+ }
163
+ else {
164
+ conflicts.push({
165
+ file: 'package.json',
166
+ found: "\"exports\" maps \"".concat(subpath, "\" to ").concat(JSON.stringify(current)),
167
+ expected: JSON.stringify(expected),
168
+ whyItMatters: whyItMatters,
169
+ pasteBlock: " \"exports\": ".concat(JSON.stringify(expectedExports, null, 2).replace(/\n/g, '\n ')),
170
+ });
171
+ }
172
+ }
173
+ }
174
+ };
175
+ /** Subpath builds: typesVersions carries the subpath's types for node10 resolution. */
176
+ BuildContract.prototype.settleTypesVersions = function (packageJson, conflicts) {
177
+ var _a;
178
+ var root = this.options.primaryRoot;
179
+ // No leading './' by typesVersions convention.
180
+ var expected = [this.subpathIndexDts().replace(/^\.\//, '')];
181
+ var expectedBlock = { '*': (_a = {}, _a[root] = expected, _a) };
182
+ if (packageJson.typesVersions == null) {
183
+ packageJson.typesVersions = expectedBlock;
184
+ return;
185
+ }
186
+ if (packageJson.typesVersions['*'] == null) {
187
+ packageJson.typesVersions['*'] = expectedBlock['*'];
188
+ return;
189
+ }
190
+ var current = packageJson.typesVersions['*'][root];
191
+ if (current == null) {
192
+ packageJson.typesVersions['*'][root] = expected;
193
+ }
194
+ else if (JSON.stringify(current) !== JSON.stringify(expected)) {
195
+ if (this.options.fix) {
196
+ packageJson.typesVersions['*'][root] = expected;
197
+ }
198
+ else {
199
+ conflicts.push({
200
+ file: 'package.json',
201
+ found: "\"typesVersions\" maps \"".concat(root, "\" to ").concat(JSON.stringify(current)),
202
+ expected: JSON.stringify(expected),
203
+ whyItMatters: "Editors and node10-resolution consumers find '<package>/".concat(root, "' types through this ") +
204
+ 'mapping; a wrong mapping breaks type resolution for every consumer.',
205
+ pasteBlock: " \"typesVersions\": ".concat(JSON.stringify(expectedBlock, null, 2).replace(/\n/g, '\n ')),
206
+ });
207
+ }
208
+ }
209
+ };
210
+ /** Subpath builds: an existing files allowlist must keep shipping the root stubs. */
211
+ BuildContract.prototype.settleFilesAllowlist = function (packageJson) {
212
+ if (!Array.isArray(packageJson.files)) {
213
+ // No allowlist means npm publishes the stubs already; adding one would change what
214
+ // gets published, which is not this contract's call.
215
+ return;
216
+ }
217
+ for (var _i = 0, _a = [this.stubJsName(), this.stubDtsName()]; _i < _a.length; _i++) {
218
+ var stub = _a[_i];
219
+ if (!packageJson.files.includes(stub)) {
220
+ packageJson.files.push(stub);
221
+ }
222
+ }
223
+ };
224
+ /**
225
+ * Subpath builds: root stubs that win the node10/paths-mapped file lookup, so every install
226
+ * shape resolves the subpath to built dist — never to sources (the TS6059/ts-jest class).
227
+ */
228
+ BuildContract.prototype.applyStubs = function (conflicts, writes) {
229
+ if (this.isProd()) {
230
+ return;
231
+ }
232
+ var root = this.options.primaryRoot;
233
+ var targetNoExt = "./".concat(this.options.distDirRel, "/generated/").concat(root, "/index");
234
+ var whyItMatters = "Consumers compiled with node10/classic resolution (or a tsconfig paths mapping) resolve " +
235
+ "'<package>/".concat(root, "' as a file path, bypassing the exports map; without a root stub that ") +
236
+ 'lands on sources in workspace-symlinked installs (TS6059 breaks the consumer build).';
237
+ var stubJs = {
238
+ file: this.stubJsName(),
239
+ content: "// Node10/classic-resolution stub for the `./".concat(root, "` subpath, owned by reflection-build.\n") +
240
+ "// Consumers that bypass the exports map (node10 resolution, tsconfig paths mappings) resolve\n" +
241
+ "// this file path first, so every install shape loads the built dist \u2014 never sources.\n" +
242
+ "module.exports = require('".concat(targetNoExt, ".js');\n"),
243
+ };
244
+ var stubDts = {
245
+ file: this.stubDtsName(),
246
+ content: "// Types counterpart of ".concat(this.stubJsName(), " \u2014 see that file for why this stub exists.\n") +
247
+ "export * from '".concat(targetNoExt, "';\n"),
248
+ };
249
+ for (var _i = 0, _a = [stubJs, stubDts]; _i < _a.length; _i++) {
250
+ var stub = _a[_i];
251
+ var stubPath = path.join(this.options.packageDir, stub.file);
252
+ if (!fs.existsSync(stubPath)) {
253
+ writes.push({ filePath: stubPath, content: stub.content });
254
+ continue;
255
+ }
256
+ var current = fs.readFileSync(stubPath, 'utf-8');
257
+ if (current.includes(targetNoExt)) {
258
+ continue;
259
+ }
260
+ if (this.options.fix) {
261
+ writes.push({ filePath: stubPath, content: stub.content });
262
+ }
263
+ else {
264
+ conflicts.push({
265
+ file: stub.file,
266
+ found: "".concat(stub.file, " exists but does not point at ").concat(targetNoExt),
267
+ expected: targetNoExt,
268
+ whyItMatters: whyItMatters,
269
+ pasteBlock: stub.content.replace(/^/gm, ' ').trimRight(),
270
+ });
271
+ }
272
+ }
273
+ };
274
+ /**
275
+ * tsconfig: include the generated index; on subpath builds, exclude the root stubs from
276
+ * compilation. List membership only — nothing here can conflict.
277
+ */
278
+ BuildContract.prototype.applyTsconfig = function (writes) {
279
+ var tsconfigPath = path.join(this.options.packageDir, 'tsconfig.json');
280
+ var includePath = "./".concat(path.relative(this.options.packageDir, this.options.generatedIndexPath));
281
+ if (!fs.existsSync(tsconfigPath)) {
282
+ var tsconfig_1 = Object.assign({}, tsconfigTemplate);
283
+ tsconfig_1.include = [includePath];
284
+ if (!this.isProd()) {
285
+ // Fresh exclude must carry node_modules: an explicit exclude replaces the default one.
286
+ tsconfig_1.exclude = ['node_modules', this.stubJsName(), this.stubDtsName()];
287
+ }
288
+ writes.push({ filePath: tsconfigPath, content: JSON.stringify(tsconfig_1, null, 4) });
289
+ return;
290
+ }
291
+ var original = fs.readFileSync(tsconfigPath, 'utf-8');
292
+ var tsconfig = JSON.parse(original);
293
+ if (tsconfig.include && !tsconfig.include.includes(includePath)) {
294
+ tsconfig.include.push(includePath);
295
+ }
296
+ if (!this.isProd()) {
297
+ if (!Array.isArray(tsconfig.exclude)) {
298
+ tsconfig.exclude = ['node_modules'];
299
+ }
300
+ for (var _i = 0, _a = [this.stubJsName(), this.stubDtsName()]; _i < _a.length; _i++) {
301
+ var stub = _a[_i];
302
+ if (!tsconfig.exclude.includes(stub)) {
303
+ tsconfig.exclude.push(stub);
304
+ }
305
+ }
306
+ }
307
+ var updated = JSON.stringify(tsconfig, null, 4);
308
+ if (updated !== JSON.stringify(JSON.parse(original), null, 4)) {
309
+ writes.push({ filePath: tsconfigPath, content: updated });
310
+ }
311
+ };
312
+ /**
313
+ * Settle one string field: absent → set; equal → ok; a dangling value (points at a file
314
+ * that does not exist — npm init's boilerplate `"main": "index.js"`, a stale copy) → set;
315
+ * a value that points at a real, different file is a deliberate setting → conflict.
316
+ */
317
+ BuildContract.prototype.settleString = function (packageJson, field, expected, conflicts, whyItMatters, pasteBlock) {
318
+ var current = packageJson[field];
319
+ if (current === expected) {
320
+ return;
321
+ }
322
+ if (typeof current === 'string' && fs.existsSync(path.join(this.options.packageDir, current))) {
323
+ if (this.options.fix) {
324
+ packageJson[field] = expected;
325
+ }
326
+ else {
327
+ conflicts.push({
328
+ file: 'package.json',
329
+ found: "\"".concat(field, "\" is \"").concat(current, "\""),
330
+ expected: expected,
331
+ whyItMatters: whyItMatters,
332
+ pasteBlock: pasteBlock,
333
+ });
334
+ }
335
+ return;
336
+ }
337
+ packageJson[field] = expected;
338
+ };
339
+ BuildContract.prototype.formatConflicts = function (conflicts) {
340
+ var lines = [];
341
+ lines.push("reflection-build: this package's config conflicts with what the build produces.");
342
+ lines.push("Nothing was changed on disk.");
343
+ lines.push('');
344
+ for (var _i = 0, conflicts_1 = conflicts; _i < conflicts_1.length; _i++) {
345
+ var conflict = conflicts_1[_i];
346
+ lines.push("- ".concat(conflict.file, ": ").concat(conflict.found));
347
+ lines.push(" the build's artifact is ".concat(conflict.expected));
348
+ lines.push(" Why it matters: ".concat(conflict.whyItMatters));
349
+ }
350
+ lines.push('');
351
+ lines.push("The quickest fix \u2014 rewrite just these fields to match the build:");
352
+ lines.push('');
353
+ lines.push(" npx reflection-build --fix");
354
+ lines.push('');
355
+ lines.push("Or paste the expected values in yourself:");
356
+ lines.push('');
357
+ var seen = {};
358
+ for (var _a = 0, conflicts_2 = conflicts; _a < conflicts_2.length; _a++) {
359
+ var conflict = conflicts_2[_a];
360
+ if (seen[conflict.pasteBlock]) {
361
+ continue;
362
+ }
363
+ seen[conflict.pasteBlock] = true;
364
+ lines.push(conflict.pasteBlock);
365
+ lines.push('');
366
+ }
367
+ return lines.join('\n');
368
+ };
369
+ BuildContract.prototype.isProd = function () {
370
+ return this.options.primaryRoot === 'src';
371
+ };
372
+ BuildContract.prototype.prodIndexJs = function () {
373
+ return "./".concat(path.join(this.options.distDirRel, 'generated', 'index.js'));
374
+ };
375
+ BuildContract.prototype.prodIndexDts = function () {
376
+ return "./".concat(path.join(this.options.distDirRel, 'generated', 'index.d.ts'));
377
+ };
378
+ BuildContract.prototype.subpathIndexJs = function () {
379
+ return "./".concat(path.join(this.options.distDirRel, 'generated', this.options.primaryRoot, 'index.js'));
380
+ };
381
+ BuildContract.prototype.subpathIndexDts = function () {
382
+ return "./".concat(path.join(this.options.distDirRel, 'generated', this.options.primaryRoot, 'index.d.ts'));
383
+ };
384
+ BuildContract.prototype.stubJsName = function () {
385
+ return "".concat(this.options.primaryRoot, ".js");
386
+ };
387
+ BuildContract.prototype.stubDtsName = function () {
388
+ return "".concat(this.options.primaryRoot, ".d.ts");
389
+ };
390
+ return BuildContract;
391
+ }());
392
+ exports.BuildContract = BuildContract;
393
+ //# sourceMappingURL=BuildContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuildContract.js","sourceRoot":"","sources":["../../src/BuildContract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ export interface DoctorReport {
2
+ text: string;
3
+ healthy: boolean;
4
+ dependencies: {
5
+ /** reflection-built deps whose graphs load at runtime */
6
+ loaded: string[];
7
+ /** declared deps that ship no graph (normal for non-reflection deps) */
8
+ withoutGraph: string[];
9
+ /** deps opted out via SKIP_REFLECTION_LOAD */
10
+ skipped: string[];
11
+ };
12
+ nodeCount: number;
13
+ edgeCount: number;
14
+ sourceLinkCount: number;
15
+ drift: {
16
+ /** declarations in current sources missing from the built artifact (stale dist) */
17
+ missingFromDist: string[];
18
+ /** declarations in the built artifact no longer in sources (stale dist) */
19
+ onlyInDist: string[];
20
+ };
21
+ orphans: Orphan[];
22
+ }
23
+ export interface Orphan {
24
+ qualifiedName: string;
25
+ unresolvedParent: string;
26
+ cause: string;
27
+ }
28
+ export interface Explanation {
29
+ text: string;
30
+ verdict: string;
31
+ }
32
+ /**
33
+ * reflection-doctor (task #104 §3.1): purely analytical diagnostics for a reflection-built
34
+ * package, run from the package dir. Executes NO dependency code — its own graph and every
35
+ * dependency graph are harvested statically from `dist/generated/index.js` artifacts (the
36
+ * same upward node_modules walk the build's import gate uses, transitively, mirroring what
37
+ * the runtime would merge).
38
+ *
39
+ * - `diagnose()` prints the registered inventory (deps with graphs / without / skip-listed),
40
+ * this package's node+edge+sourceLink counts, emitted-vs-source drift (stale dist), and
41
+ * ORPHANS: nodes the build kept because a parent is foreign, whose parent's package
42
+ * resolves to no loadable graph — the undeclared-dep / typo footgun that the runtime
43
+ * silently prunes today.
44
+ * - `explain(name)` prints the parent-edge resolution trace for one declaration — how (or
45
+ * why not) it becomes Loadable — naming the broken hop and its cause.
46
+ */
47
+ export declare class ReflectionDoctor {
48
+ private readonly packageDir;
49
+ private readonly skipList;
50
+ constructor(packageDir: string, options?: {
51
+ skipList?: string[];
52
+ });
53
+ diagnose(): Promise<DoctorReport>;
54
+ explain(nameOrQualifiedName: string): Promise<Explanation>;
55
+ /**
56
+ * Recursive parent-edge trace. Returns the first Loadable-reaching direct parent (for the
57
+ * objects() verdict) and the first broken hop encountered, if any.
58
+ */
59
+ private trace;
60
+ private classifyUnresolvedParent;
61
+ /** Why a package contributes no graph, from the consuming package's point of view. */
62
+ private classifyPackage;
63
+ /**
64
+ * Orphans: nodes this package's build kept (foreign parent ⇒ benefit of the doubt), whose
65
+ * parent's package contributes NO graph at runtime — the runtime will silently prune them.
66
+ * Parents living in loaded graphs that simply aren't Loadable are not orphans (that pruning
67
+ * is by design); `explain` covers those.
68
+ */
69
+ private findOrphans;
70
+ /** Emitted-vs-source drift: rebuild-needed detection for the prod graph. */
71
+ private computeDrift;
72
+ /**
73
+ * Statically harvest this package's graph and, transitively, every reflection-built
74
+ * dependency's graph — the same set the runtime merges.
75
+ */
76
+ private harvestUniverse;
77
+ private addToUniverse;
78
+ /** Extract the serialized graph from a generated index without executing it. */
79
+ private parseArtifactGraph;
80
+ private parseSourceLinkKeys;
81
+ private dependencyInventory;
82
+ private resolveTarget;
83
+ /** The declaration is in no harvested graph — diagnose why from this package's sources. */
84
+ private explainNotFound;
85
+ /** Raw parser pass over src — sees non-exported declarations the graph never contains. */
86
+ private findDeclarationInSources;
87
+ private checkSourceLink;
88
+ private findValuedNode;
89
+ private describeKind;
90
+ private formatReport;
91
+ /** True for shapes a qualified name can take; inline type expressions (unions, literals, comments) fail this. */
92
+ private isResolvableQualifiedName;
93
+ private dependencyNames;
94
+ private readPackageJson;
95
+ }