@cplieger/deadset-ts 8.0.0-dev.1 → 8.0.0-dev.11
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/README.md +1 -1
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/analysis.js +181 -341
- package/dist/src/augmentations.js +106 -13
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +425 -0
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +2 -3
- package/dist/src/config.js +6 -82
- package/dist/src/configuration-files.js +28 -176
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +3 -30
- package/dist/src/contextual-uses.js +56 -9
- package/dist/src/contract/config.generated.js +558 -0
- package/dist/src/contract/contract.generated.js +1244 -0
- package/dist/src/contract/report.generated.js +862 -0
- package/dist/src/convention-rows.js +73 -3
- package/dist/src/conventions.js +36 -66
- package/dist/src/dependencies.js +103 -40
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +2 -8
- package/dist/src/entry-points.js +11 -27
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +1 -63
- package/dist/src/exempt.js +21 -40
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +139 -72
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +5 -5
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +13 -10
- package/dist/src/findings/non-code-artifacts.js +7 -8
- package/dist/src/findings/reads-and-writes.js +16 -13
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +41 -32
- package/dist/src/findings/visibility-narrowing.js +19 -16
- package/dist/src/findings-pass.js +8 -15
- package/dist/src/framework-lifecycle.js +7 -7
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +72 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/generated-file.js +7 -4
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/graph.js +5 -3
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/injection-container.js +1 -1
- package/dist/src/intra-function-parts.js +63 -43
- package/dist/src/inventory.js +2 -21
- package/dist/src/javascript-file.js +33 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +3 -366
- package/dist/src/load/classify.js +270 -0
- package/dist/src/load/diagnostics.js +80 -0
- package/dist/src/load/discover.js +277 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +115 -0
- package/dist/src/load/synthesize.js +140 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +23 -65
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/manifest.js +49 -54
- package/dist/src/matrix.js +76 -4
- package/dist/src/mdx-entries.js +3 -26
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +26 -15
- package/dist/src/position.js +2 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +1 -0
- package/dist/src/ref.js +1 -0
- package/dist/src/references.js +48 -30
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +57 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +245 -729
- package/dist/src/roots.js +273 -87
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +38 -115
- package/dist/src/serialization-contract.js +595 -21
- package/dist/src/session.js +34 -29
- package/dist/src/source-files.js +1 -1
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +3 -2
- package/dist/src/suppress.js +33 -51
- package/dist/src/sweep.js +7 -9
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-support.js +8 -11
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +54 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/text/yaml.js +393 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/unseen-loads.js +100 -0
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/verbs/analyze.js +166 -126
- package/dist/src/verbs/describe.js +9 -16
- package/dist/src/verbs/explain.js +10 -7
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +4 -2
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/dist/src/workflow-steps.js +62 -64
- package/jsr.json +1 -1
- package/package.json +5 -4
- package/src/analysis.ts +245 -502
- package/src/augmentations.ts +135 -17
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +543 -0
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +31 -302
- package/src/configuration-files.ts +34 -179
- package/src/configured-declarations.ts +18 -23
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +6 -57
- package/src/contextual-uses.ts +64 -12
- package/src/contract/config.generated.ts +818 -0
- package/src/contract/contract.generated.ts +1308 -0
- package/src/contract/report.generated.ts +1237 -0
- package/src/convention-rows.ts +85 -3
- package/src/conventions.ts +46 -84
- package/src/dependencies.ts +118 -46
- package/src/edges.ts +41 -140
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +3 -9
- package/src/entry-points.ts +12 -38
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +1 -75
- package/src/exempt.ts +36 -50
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +9 -24
- package/src/finding.ts +14 -9
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +181 -84
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +8 -9
- package/src/findings/emitters.ts +7 -7
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +13 -11
- package/src/findings/non-code-artifacts.ts +9 -11
- package/src/findings/reads-and-writes.ts +20 -16
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +45 -32
- package/src/findings/visibility-narrowing.ts +20 -17
- package/src/findings-pass.ts +10 -19
- package/src/framework-lifecycle.ts +7 -7
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +92 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +7 -4
- package/src/git-ignore.ts +50 -26
- package/src/graph.ts +5 -3
- package/src/host.ts +12 -5
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/injection-container.ts +1 -1
- package/src/intra-function-parts.ts +73 -44
- package/src/inventory.ts +2 -20
- package/src/javascript-file.ts +37 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +5 -413
- package/src/load/classify.ts +397 -0
- package/src/load/diagnostics.ts +144 -0
- package/src/load/discover.ts +455 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +188 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/plan.ts +504 -0
- package/src/load/specifiers.ts +168 -0
- package/src/load/synthesize.ts +211 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +33 -76
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/manifest.ts +81 -75
- package/src/matrix.ts +122 -4
- package/src/mdx-entries.ts +3 -26
- package/src/outside-tests.ts +1 -1
- package/src/partial.ts +3 -2
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +11 -0
- package/src/ref.ts +1 -0
- package/src/references.ts +52 -31
- package/src/report-schema.ts +68 -0
- package/src/report.ts +101 -224
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +283 -1114
- package/src/roots.ts +339 -104
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +763 -22
- package/src/session.ts +70 -54
- package/src/source-files.ts +1 -1
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +2 -2
- package/src/suppress.ts +43 -58
- package/src/sweep.ts +23 -9
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +15 -25
- package/src/test-support.ts +17 -13
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.inputs.json +1522 -0
- package/src/text/named-files.ts +68 -0
- package/src/text/shell.ts +161 -0
- package/src/text/yaml.ts +423 -0
- package/src/type-errors.ts +18 -288
- package/src/unseen-loads.ts +134 -0
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +224 -162
- package/src/verbs/describe.ts +14 -15
- package/src/verbs/explain.ts +10 -11
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/src/workflow-steps.ts +74 -64
- package/dist/src/base-url.js +0 -18
- package/dist/src/discover.js +0 -468
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/src/base-url.ts +0 -24
- package/src/discover.ts +0 -653
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/setup-failure.ts +0 -39
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
|
@@ -7,22 +7,34 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { ModuleKind, ModuleResolutionKind } from "@typescript/native/sync";
|
|
9
9
|
import { isStringLiteralLikeNode } from "@typescript/native/ast";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import { JAVASCRIPT_FILE } from "../javascript-file.js";
|
|
11
|
+
import { isRecord } from "../json-document.js";
|
|
12
|
+
import { dirnamePath, resolvePath } from "../paths.js";
|
|
13
|
+
import { batched } from "../session.js";
|
|
14
|
+
import { bytewise } from "../text/compare.js";
|
|
15
|
+
import { PRODUCT } from "../product.js";
|
|
14
16
|
/**
|
|
15
|
-
* The options a configuration's program is built with:
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* the compiler refuses under such a layout.
|
|
17
|
+
* The options a configuration's program is built with: the plan's, less the ones that lay
|
|
18
|
+
* out an emitted program's inputs and outputs. The analysis emits nothing, and a member's
|
|
19
|
+
* source is outside the importer's root directory by construction, which the compiler
|
|
20
|
+
* refuses under such a layout.
|
|
20
21
|
*/
|
|
21
|
-
function analysisOptions(
|
|
22
|
-
const { composite, rootDir: _rootDir, outDir: _outDir, declarationDir: _declarationDir, tsBuildInfoFile: _tsBuildInfoFile, ...kept } =
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
function analysisOptions(options, readsJavaScript) {
|
|
23
|
+
const { composite, rootDir: _rootDir, outDir: _outDir, declarationDir: _declarationDir, tsBuildInfoFile: _tsBuildInfoFile, ...kept } = options;
|
|
24
|
+
const read = readsJavaScript ? { ...kept, allowJs: true } : kept;
|
|
25
|
+
return composite === true ? { ...read, declaration: true } : read;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Whether one reading answers a member import with a JavaScript file, which its program reads
|
|
29
|
+
* as source only where it allows JavaScript, a program formed for a JavaScript member being the
|
|
30
|
+
* member's source.
|
|
31
|
+
*/
|
|
32
|
+
function readsJavaScript(reading) {
|
|
33
|
+
return (reading.options.allowJs !== true &&
|
|
34
|
+
reading.entries.some((entry) => {
|
|
35
|
+
const file = entry.result.resolvedFileName;
|
|
36
|
+
return typeof file === "string" && JAVASCRIPT_FILE.test(file);
|
|
37
|
+
}));
|
|
26
38
|
}
|
|
27
39
|
/** The conditions an `exports` lookup under one configuration and one resolution mode reads. */
|
|
28
40
|
function conditionsOf(parsed, mode) {
|
|
@@ -51,33 +63,45 @@ function unstatable(reading) {
|
|
|
51
63
|
}
|
|
52
64
|
return undefined;
|
|
53
65
|
}
|
|
54
|
-
/** The path beside `configFile` its written configuration takes, which no file has. */
|
|
55
|
-
export function writtenPath(host, configFile) {
|
|
66
|
+
/** The path beside `configFile` its written configuration takes, which no file and none of `taken` has. */
|
|
67
|
+
export function writtenPath(host, configFile, taken = new Set()) {
|
|
56
68
|
const stem = configFile.replace(/\.json$/u, "");
|
|
57
69
|
for (let counter = 0;; counter += 1) {
|
|
58
|
-
const path = `${stem}
|
|
59
|
-
if (host.kindOf(path) === "absent") {
|
|
70
|
+
const path = `${stem}.${PRODUCT}${counter === 0 ? "" : `-${String(counter)}`}.json`;
|
|
71
|
+
if (host.kindOf(path) === "absent" && !taken.has(path)) {
|
|
60
72
|
return path;
|
|
61
73
|
}
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
76
|
/**
|
|
65
|
-
* The
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
* The path the snapshot holds one configuration's written form at: a formed configuration's
|
|
78
|
+
* own path, else a free one beside it that no configuration of `formed` holds, because a formed
|
|
79
|
+
* program in a directory with a `jsconfig.json` takes the name that file's written form would.
|
|
80
|
+
*/
|
|
81
|
+
export function writtenFileOf(host, configuration, formed) {
|
|
82
|
+
return configuration.written === undefined
|
|
83
|
+
? writtenPath(host, configuration.configFile, formed)
|
|
84
|
+
: configuration.configFile;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The configuration that reads as one configuration's program: it extends it, lays out no output
|
|
88
|
+
* ({@link analysisOptions}), maps each answered specifier to its file and keeps its references.
|
|
89
|
+
* Where the file list moves, the default `exclude` the dropped output directories are named in is
|
|
90
|
+
* restated, and one that {@link readsJavaScript} lists its files outright, as `allowJs` widens its
|
|
91
|
+
* `include` to JavaScript; a list that still differs, or answers `paths` cannot state, are a
|
|
92
|
+
* reason. A formed configuration, which no file holds to extend, is its own value with `paths`.
|
|
70
93
|
*/
|
|
71
|
-
function configurationOf(engine, host, reading) {
|
|
94
|
+
function configurationOf(engine, host, reading, formed) {
|
|
72
95
|
const reason = unstatable(reading);
|
|
73
96
|
if (reason !== undefined) {
|
|
74
97
|
return { kind: "unread", reason };
|
|
75
98
|
}
|
|
76
|
-
const { options
|
|
99
|
+
const { options } = reading;
|
|
100
|
+
const references = reading.parsed.projectReferences ?? [];
|
|
77
101
|
const raw = options["pathsBasePath"];
|
|
78
102
|
const base = typeof raw === "string" ? raw : dirnamePath(reading.configFile);
|
|
79
103
|
const paths = {};
|
|
80
|
-
for (const [key, targets] of Object.entries(
|
|
104
|
+
for (const [key, targets] of Object.entries(options.paths ?? {})) {
|
|
81
105
|
paths[key] = targets.map((target) => resolvePath(base, target));
|
|
82
106
|
}
|
|
83
107
|
for (const entry of reading.entries) {
|
|
@@ -86,6 +110,17 @@ function configurationOf(engine, host, reading) {
|
|
|
86
110
|
paths[entry.moduleName] = [file];
|
|
87
111
|
}
|
|
88
112
|
}
|
|
113
|
+
if (reading.written !== undefined) {
|
|
114
|
+
const held = reading.written["compilerOptions"];
|
|
115
|
+
return {
|
|
116
|
+
kind: "configuration",
|
|
117
|
+
value: {
|
|
118
|
+
...reading.written,
|
|
119
|
+
compilerOptions: { ...(isRecord(held) ? held : {}), paths },
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const javascript = readsJavaScript(reading);
|
|
89
124
|
const json = (exclude) => ({
|
|
90
125
|
extends: reading.configFile,
|
|
91
126
|
compilerOptions: {
|
|
@@ -94,18 +129,20 @@ function configurationOf(engine, host, reading) {
|
|
|
94
129
|
declarationDir: null,
|
|
95
130
|
tsBuildInfoFile: null,
|
|
96
131
|
...(options.composite === true ? { composite: false, declaration: true } : {}),
|
|
132
|
+
...(javascript ? { allowJs: true } : {}),
|
|
97
133
|
paths,
|
|
98
134
|
},
|
|
99
135
|
...(references.length > 0
|
|
100
136
|
? { references: references.map((reference) => ({ path: reference.path })) }
|
|
101
137
|
: {}),
|
|
138
|
+
...(javascript ? { files: [...reading.parsed.fileNames], include: [] } : {}),
|
|
102
139
|
...(exclude === undefined ? {} : { exclude }),
|
|
103
140
|
});
|
|
104
|
-
const file =
|
|
105
|
-
const expected = [...reading.parsed.fileNames].sort().join("\u0000");
|
|
141
|
+
const file = writtenFileOf(host, reading, formed);
|
|
142
|
+
const expected = [...reading.parsed.fileNames].sort(bytewise).join("\u0000");
|
|
106
143
|
const listed = (value) => {
|
|
107
144
|
try {
|
|
108
|
-
return [...engine.parseConfigJson(value, file).fileNames].sort().join("\u0000");
|
|
145
|
+
return [...engine.parseConfigJson(value, file).fileNames].sort(bytewise).join("\u0000");
|
|
109
146
|
}
|
|
110
147
|
catch {
|
|
111
148
|
return undefined;
|
|
@@ -124,11 +161,11 @@ function configurationOf(engine, host, reading) {
|
|
|
124
161
|
};
|
|
125
162
|
}
|
|
126
163
|
}
|
|
127
|
-
return { kind: "configuration",
|
|
164
|
+
return { kind: "configuration", value };
|
|
128
165
|
}
|
|
129
166
|
/** The program one configuration is built as, under the answers it holds so far. */
|
|
130
167
|
function programOf(engine, reading) {
|
|
131
|
-
const compilerOptions = analysisOptions(reading.
|
|
168
|
+
const compilerOptions = analysisOptions(reading.options, readsJavaScript(reading));
|
|
132
169
|
const references = reading.parsed.projectReferences ?? [];
|
|
133
170
|
const resolver = engine.createModuleResolver(compilerOptions, reading.entries);
|
|
134
171
|
return {
|
|
@@ -144,17 +181,6 @@ function programOf(engine, reading) {
|
|
|
144
181
|
},
|
|
145
182
|
};
|
|
146
183
|
}
|
|
147
|
-
function chunks(items) {
|
|
148
|
-
const found = [];
|
|
149
|
-
for (let at = 0; at < items.length; at += BATCH) {
|
|
150
|
-
found.push(items.slice(at, at + BATCH));
|
|
151
|
-
}
|
|
152
|
-
return found;
|
|
153
|
-
}
|
|
154
|
-
/** Asks one question of every item, in round trips of at most {@link BATCH}. */
|
|
155
|
-
function batched(engine, items, question) {
|
|
156
|
-
return chunks(items).flatMap((run) => engine.batch(run.map(question)));
|
|
157
|
-
}
|
|
158
184
|
/** One round over one program: answers the member imports no earlier round asked about. */
|
|
159
185
|
function scan(engine, program, reading, resolver) {
|
|
160
186
|
const names = program.getSourceFileNames().filter((name) => !name.includes("/node_modules/"));
|
|
@@ -215,6 +241,13 @@ function scan(engine, program, reading, resolver) {
|
|
|
215
241
|
});
|
|
216
242
|
return added;
|
|
217
243
|
}
|
|
244
|
+
function configurationText(value) {
|
|
245
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
246
|
+
}
|
|
247
|
+
/** One configuration value as the snapshot holds it, at `file`, which no file on disk holds. */
|
|
248
|
+
export function writtenConfiguration(file, value) {
|
|
249
|
+
return { kind: "configuration", file, text: configurationText(value) };
|
|
250
|
+
}
|
|
218
251
|
/**
|
|
219
252
|
* Answers the member imports of every reading `build` describes, round by round, all
|
|
220
253
|
* the readings still adding answers built in one snapshot per round. A reading `build`
|
|
@@ -256,35 +289,25 @@ function readRounds(engine, readings, resolver, build) {
|
|
|
256
289
|
* the rounds go on over each reading's configuration, which reads them, for the imports
|
|
257
290
|
* only they make.
|
|
258
291
|
*/
|
|
259
|
-
export function workspacePrograms(engine, host,
|
|
260
|
-
const readings =
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
return [
|
|
270
|
-
{
|
|
271
|
-
configFile,
|
|
272
|
-
parsed,
|
|
273
|
-
entries: [],
|
|
274
|
-
seen: new Set(),
|
|
275
|
-
bound: new Map(),
|
|
276
|
-
unresolved: [],
|
|
277
|
-
},
|
|
278
|
-
];
|
|
279
|
-
});
|
|
292
|
+
export function workspacePrograms(engine, host, configurations, resolver) {
|
|
293
|
+
const readings = configurations.map((configuration) => ({
|
|
294
|
+
...configuration,
|
|
295
|
+
entries: [],
|
|
296
|
+
seen: new Set(),
|
|
297
|
+
bound: new Map(),
|
|
298
|
+
unresolved: [],
|
|
299
|
+
}));
|
|
300
|
+
const formed = new Set(configurations.filter((one) => one.written !== undefined).map((one) => one.configFile));
|
|
280
301
|
readRounds(engine, readings, resolver, (reading) => ({
|
|
281
302
|
kind: "program",
|
|
282
303
|
...programOf(engine, reading),
|
|
283
304
|
}));
|
|
284
305
|
if (engine.readsComponents) {
|
|
285
306
|
readRounds(engine, readings, resolver, (reading) => {
|
|
286
|
-
const one = configurationOf(engine, host, reading);
|
|
287
|
-
return one.kind === "configuration"
|
|
307
|
+
const one = configurationOf(engine, host, reading, formed);
|
|
308
|
+
return one.kind === "configuration"
|
|
309
|
+
? writtenConfiguration(writtenFileOf(host, reading, formed), one.value)
|
|
310
|
+
: undefined;
|
|
288
311
|
});
|
|
289
312
|
}
|
|
290
313
|
const programs = new Map();
|
|
@@ -293,7 +316,7 @@ export function workspacePrograms(engine, host, configFiles, resolver) {
|
|
|
293
316
|
if (reading.entries.length === 0) {
|
|
294
317
|
continue;
|
|
295
318
|
}
|
|
296
|
-
const one = engine.readsComponents ? configurationOf(engine, host, reading) : undefined;
|
|
319
|
+
const one = engine.readsComponents ? configurationOf(engine, host, reading, formed) : undefined;
|
|
297
320
|
if (one !== undefined && one.kind !== "unread") {
|
|
298
321
|
programs.set(reading.configFile, one);
|
|
299
322
|
continue;
|
|
@@ -6,38 +6,17 @@
|
|
|
6
6
|
* the package neither compiles nor writes is read as installed, and the rest is unresolved.
|
|
7
7
|
*/
|
|
8
8
|
import { emittedFrom } from "./emit-map.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { packageOfSpecifier } from "../dependencies.js";
|
|
10
|
+
import { gitIgnored } from "../git-ignore.js";
|
|
11
|
+
import { ancestors, dirnamePath, joinPath, relativePath, resolvePath } from "../paths.js";
|
|
12
|
+
import { satisfies } from "../version-range.js";
|
|
13
|
+
import { isRecord } from "../json-document.js";
|
|
14
|
+
import { MANIFEST } from "../fs/manifest.js";
|
|
15
|
+
import { dependencySpecifiers, installedPackage, manifestsAbove, } from "./module-lookup.js";
|
|
12
16
|
/** The manifest members that name an entry point for the subpath `.` without `exports`. */
|
|
13
17
|
const LEGACY_MEMBERS = ["types", "typings", "module", "main"];
|
|
14
|
-
/** The dependency members a manifest declares other packages under. */
|
|
15
|
-
const DEPENDENCY_MEMBERS = [
|
|
16
|
-
"dependencies",
|
|
17
|
-
"devDependencies",
|
|
18
|
-
"peerDependencies",
|
|
19
|
-
"optionalDependencies",
|
|
20
|
-
];
|
|
21
18
|
const SOURCE = /(?<!\.d)\.(?:[mc]?ts|tsx)$/u;
|
|
22
19
|
const OUTPUT = /(?:\.d\.[mc]?ts|\.[mc]?js|\.jsx)$/u;
|
|
23
|
-
function isRecord(value) {
|
|
24
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
-
}
|
|
26
|
-
/** The package name a bare specifier names, or `undefined` for any other specifier. */
|
|
27
|
-
export function packageNameOf(specifier) {
|
|
28
|
-
if (specifier === "" ||
|
|
29
|
-
specifier.startsWith(".") ||
|
|
30
|
-
specifier.startsWith("#") ||
|
|
31
|
-
isAbsolutePath(specifier) ||
|
|
32
|
-
specifier.includes(":")) {
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
const [first, second] = specifier.split("/");
|
|
36
|
-
if (specifier.startsWith("@")) {
|
|
37
|
-
return second === undefined || second === "" ? undefined : `${first ?? ""}/${second}`;
|
|
38
|
-
}
|
|
39
|
-
return first;
|
|
40
|
-
}
|
|
41
20
|
function inside(dir, path) {
|
|
42
21
|
return relativePath(dir, path) !== undefined;
|
|
43
22
|
}
|
|
@@ -140,49 +119,32 @@ function dependsOn(specifier, member, fromDir) {
|
|
|
140
119
|
/** The member imports of one workspace, read from the members' sources. */
|
|
141
120
|
export function workspaceResolver(host, workspace) {
|
|
142
121
|
const links = new Map();
|
|
143
|
-
/** The directory `
|
|
122
|
+
/** The directory the package `name` installed for one directory is, links followed. */
|
|
144
123
|
const linkedFrom = (name, dir) => {
|
|
145
124
|
const key = `${name}\u0000${dir}`;
|
|
146
|
-
if (links.has(key)) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const candidate = joinPath(dir, "node_modules", name);
|
|
150
|
-
let found;
|
|
151
|
-
if (host.kindOf(candidate) === "absent") {
|
|
152
|
-
const up = dirnamePath(dir);
|
|
153
|
-
found = up === dir ? undefined : linkedFrom(name, up);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
125
|
+
if (!links.has(key)) {
|
|
126
|
+
const installed = installedPackage(host, dir, name);
|
|
127
|
+
let found;
|
|
156
128
|
try {
|
|
157
|
-
found = host.realPath(
|
|
129
|
+
found = installed === undefined ? undefined : host.realPath(installed);
|
|
158
130
|
}
|
|
159
131
|
catch {
|
|
160
132
|
found = undefined;
|
|
161
133
|
}
|
|
134
|
+
links.set(key, found);
|
|
162
135
|
}
|
|
163
|
-
links.
|
|
164
|
-
return found;
|
|
136
|
+
return links.get(key);
|
|
165
137
|
};
|
|
166
138
|
const root = workspace.members[0]?.dir;
|
|
167
139
|
const ignored = root === undefined ? () => false : gitIgnored(host, root);
|
|
168
140
|
const manifests = new Map();
|
|
169
141
|
/** The nearest manifest at or above one directory, up to the workspace's root. */
|
|
170
142
|
const nearestManifest = (dir) => {
|
|
171
|
-
if (manifests.has(dir)) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
let found;
|
|
175
|
-
try {
|
|
176
|
-
const value = JSON.parse(host.readFile(joinPath(dir, "package.json")));
|
|
177
|
-
found = isRecord(value) ? { dir, manifest: value } : undefined;
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
const up = dirnamePath(dir);
|
|
181
|
-
found =
|
|
182
|
-
up === dir || root === undefined || !inside(root, up) ? undefined : nearestManifest(up);
|
|
143
|
+
if (!manifests.has(dir)) {
|
|
144
|
+
const [nearest] = manifestsAbove(host, dir, root ?? dir);
|
|
145
|
+
manifests.set(dir, nearest);
|
|
183
146
|
}
|
|
184
|
-
manifests.
|
|
185
|
-
return found;
|
|
147
|
+
return manifests.get(dir);
|
|
186
148
|
};
|
|
187
149
|
const linkOf = (candidates, fromDir) => {
|
|
188
150
|
const name = candidates[0]?.name ?? "";
|
|
@@ -191,18 +153,14 @@ export function workspaceResolver(host, workspace) {
|
|
|
191
153
|
const member = candidates.find((one) => one.dir === linked);
|
|
192
154
|
return member === undefined ? { kind: "none" } : { kind: "member", member };
|
|
193
155
|
}
|
|
194
|
-
const scope = workspace.memberOf(joinPath(fromDir,
|
|
156
|
+
const scope = workspace.memberOf(joinPath(fromDir, MANIFEST));
|
|
195
157
|
if (scope?.name === name) {
|
|
196
158
|
return { kind: "member", member: scope };
|
|
197
159
|
}
|
|
198
160
|
// A package below the root that no workspace lists depends on a member as a member does.
|
|
199
161
|
const owner = scope ?? nearestManifest(fromDir);
|
|
200
162
|
const manifest = owner?.manifest;
|
|
201
|
-
const declared =
|
|
202
|
-
const held = manifest?.[field];
|
|
203
|
-
const specifier = isRecord(held) ? held[name] : undefined;
|
|
204
|
-
return typeof specifier === "string" ? [specifier] : [];
|
|
205
|
-
});
|
|
163
|
+
const declared = (manifest === undefined ? [] : dependencySpecifiers(manifest, name)).filter((specifier) => typeof specifier === "string");
|
|
206
164
|
const matched = candidates.filter((member) => declared.some((specifier) => dependsOn(specifier, member, owner?.dir ?? fromDir)));
|
|
207
165
|
const [one, two] = matched;
|
|
208
166
|
if (one === undefined) {
|
|
@@ -221,7 +179,7 @@ export function workspaceResolver(host, workspace) {
|
|
|
221
179
|
* directory however its configuration writes it.
|
|
222
180
|
*/
|
|
223
181
|
const mirrored = (member, path) => {
|
|
224
|
-
for (
|
|
182
|
+
for (const dir of ancestors(dirnamePath(path), member.dir).filter((at) => at !== member.dir)) {
|
|
225
183
|
const found = emittedFrom(path, { outDir: dir, sourceDirs: [member.dir] }).find((candidate) => SOURCE.test(candidate) && !ignored(candidate) && host.kindOf(candidate) === "file");
|
|
226
184
|
if (found !== undefined) {
|
|
227
185
|
return found;
|
|
@@ -288,11 +246,11 @@ export function workspaceResolver(host, workspace) {
|
|
|
288
246
|
workspace,
|
|
289
247
|
sourceOf,
|
|
290
248
|
names: (specifier) => {
|
|
291
|
-
const name =
|
|
249
|
+
const name = packageOfSpecifier(specifier);
|
|
292
250
|
return name !== undefined && workspace.named.has(name);
|
|
293
251
|
},
|
|
294
252
|
resolve(specifier, fromDir, conditions, answered) {
|
|
295
|
-
const name =
|
|
253
|
+
const name = packageOfSpecifier(specifier);
|
|
296
254
|
const candidates = name === undefined ? undefined : workspace.named.get(name);
|
|
297
255
|
if (name === undefined || candidates === undefined) {
|
|
298
256
|
return { kind: "default" };
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* the files each configuration holds only for their references, and the entry points
|
|
5
5
|
* the members' manifests name. A target in no workspace reads none of it.
|
|
6
6
|
*/
|
|
7
|
-
import { relativePath } from "
|
|
8
|
-
import {
|
|
7
|
+
import { relativePath } from "../paths.js";
|
|
8
|
+
import { referenceOnlyIn } from "./workspace.js";
|
|
9
9
|
import { memberEntries, targetManifestIn } from "./workspace-manifests.js";
|
|
10
10
|
import { workspacePrograms, } from "./workspace-programs.js";
|
|
11
11
|
import { workspaceResolver } from "./workspace-resolution.js";
|
|
12
|
-
|
|
12
|
+
/** What one member's configuration file says of its layout, or `undefined` where it does not parse. */
|
|
13
|
+
export function layoutOf(engine, configFile) {
|
|
13
14
|
try {
|
|
14
15
|
const parsed = engine.parseConfigFile(configFile);
|
|
15
16
|
return {
|
|
@@ -42,16 +43,16 @@ function unbuildableReason(reading, referenceOnly, targetRoot) {
|
|
|
42
43
|
* The workspace the target at `targetRoot` sits in, read for the configurations named,
|
|
43
44
|
* or `undefined` where the target sits in none.
|
|
44
45
|
*/
|
|
45
|
-
export function workspaceRun(engine, host, targetRoot,
|
|
46
|
-
const workspace = findWorkspace(host, targetRoot, (configFile) => layoutOf(engine, configFile));
|
|
46
|
+
export function workspaceRun(engine, host, targetRoot, configurations, manifest, workspace) {
|
|
47
47
|
if (workspace === undefined) {
|
|
48
48
|
return undefined;
|
|
49
49
|
}
|
|
50
50
|
const resolver = workspaceResolver(host, workspace);
|
|
51
|
-
const read = workspacePrograms(engine, host,
|
|
51
|
+
const read = workspacePrograms(engine, host, configurations, resolver);
|
|
52
52
|
const readings = new Map(read.readings.map((reading) => [reading.configFile, reading]));
|
|
53
53
|
const referenceOnly = (configFile, compiled = []) => referenceOnlyIn(workspace, new Set([...(readings.get(configFile)?.fileNames ?? []), ...compiled]));
|
|
54
54
|
return {
|
|
55
|
+
workspace,
|
|
55
56
|
programs: read.programs,
|
|
56
57
|
componentsUnread: read.readings.flatMap(({ configFile, componentsUnread }) => componentsUnread === undefined ? [] : [{ configFile, reason: componentsUnread }]),
|
|
57
58
|
unbuildable: (configFile) => {
|
|
@@ -66,7 +67,6 @@ export function workspaceRun(engine, host, targetRoot, configFiles, manifest) {
|
|
|
66
67
|
: !fromExternalLibrary,
|
|
67
68
|
manifest: targetManifestIn(resolver, targetRoot, manifest),
|
|
68
69
|
entries: memberEntries(host, resolver, targetRoot),
|
|
69
|
-
memberDirs: workspace.members.map((member) => member.dir),
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
/** The errors one configuration answers for: none in a file it holds only for its references. */
|