@cplieger/deadset-ts 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +4 -4
  2. package/dist/bin/component-mapper.js +5 -0
  3. package/dist/bin/mapper-connection.js +101 -0
  4. package/dist/bin/node-host.js +24 -2
  5. package/dist/src/analysis.js +229 -36
  6. package/dist/src/component-files.js +612 -0
  7. package/dist/src/component-layer.js +132 -0
  8. package/dist/src/config.js +9 -2
  9. package/dist/src/configuration-files.js +186 -0
  10. package/dist/src/conformance-record.js +2 -2
  11. package/dist/src/convention-rows.js +383 -0
  12. package/dist/src/conventions.js +456 -0
  13. package/dist/src/dependencies.js +30 -3
  14. package/dist/src/discover.js +10 -3
  15. package/dist/src/emit-map.js +72 -0
  16. package/dist/src/entry-point-gaps.js +81 -35
  17. package/dist/src/entry-points.js +47 -32
  18. package/dist/src/exempt.js +11 -3
  19. package/dist/src/findings/completion.js +19 -29
  20. package/dist/src/findings/emitters.js +22 -1
  21. package/dist/src/findings/unused-declarations.js +7 -2
  22. package/dist/src/graph.js +13 -5
  23. package/dist/src/inventory.js +4 -2
  24. package/dist/src/kinds.js +2 -2
  25. package/dist/src/manifest.js +37 -11
  26. package/dist/src/matrix.js +21 -13
  27. package/dist/src/partial.js +3 -1
  28. package/dist/src/pnpm-workspace.js +120 -0
  29. package/dist/src/position.js +17 -2
  30. package/dist/src/print.js +2 -0
  31. package/dist/src/references.js +209 -30
  32. package/dist/src/report.js +26 -6
  33. package/dist/src/reporters/annotations.js +10 -3
  34. package/dist/src/reporters/template.js +3 -0
  35. package/dist/src/resolve.js +31 -6
  36. package/dist/src/roots.js +37 -8
  37. package/dist/src/run.js +13 -3
  38. package/dist/src/schema.js +2 -0
  39. package/dist/src/session.js +141 -34
  40. package/dist/src/setup-failure.js +23 -0
  41. package/dist/src/source-files.js +4 -61
  42. package/dist/src/sweep.js +4 -2
  43. package/dist/src/template-field.js +38 -6
  44. package/dist/src/test-support.js +59 -0
  45. package/dist/src/type-errors.js +252 -0
  46. package/dist/src/type-query-alias.js +92 -0
  47. package/dist/src/verbs/analyze.js +24 -4
  48. package/dist/src/verbs/explain.js +4 -1
  49. package/dist/src/verbs/print-projects.js +17 -56
  50. package/dist/src/verbs/print-retained.js +7 -2
  51. package/dist/src/verbs/print-roots.js +7 -2
  52. package/dist/src/version-range.js +255 -0
  53. package/dist/src/version.js +1 -1
  54. package/dist/src/workspace-manifests.js +68 -0
  55. package/dist/src/workspace-programs.js +342 -0
  56. package/dist/src/workspace-resolution.js +307 -0
  57. package/dist/src/workspace-run.js +75 -0
  58. package/dist/src/workspace.js +358 -0
  59. package/jsr.json +1 -1
  60. package/package.json +2 -1
  61. package/src/analysis.ts +394 -70
  62. package/src/component-files.ts +718 -0
  63. package/src/component-layer.ts +160 -0
  64. package/src/config.ts +11 -2
  65. package/src/configuration-files.ts +235 -0
  66. package/src/conformance-record.ts +2 -2
  67. package/src/convention-rows.ts +440 -0
  68. package/src/conventions.ts +640 -0
  69. package/src/dependencies.ts +36 -2
  70. package/src/discover.ts +10 -6
  71. package/src/emit-map.ts +93 -0
  72. package/src/entry-point-gaps.ts +92 -38
  73. package/src/entry-points.ts +66 -36
  74. package/src/exempt.ts +21 -3
  75. package/src/findings/completion.ts +24 -33
  76. package/src/findings/emitters.ts +32 -1
  77. package/src/findings/unused-declarations.ts +9 -2
  78. package/src/graph.ts +15 -4
  79. package/src/host.ts +23 -0
  80. package/src/index.ts +1 -1
  81. package/src/inventory.ts +13 -2
  82. package/src/kinds.ts +2 -2
  83. package/src/manifest.ts +47 -14
  84. package/src/matrix.ts +43 -15
  85. package/src/partial.ts +6 -1
  86. package/src/pnpm-workspace.ts +135 -0
  87. package/src/position.ts +23 -2
  88. package/src/print.ts +2 -0
  89. package/src/references.ts +227 -28
  90. package/src/report.ts +56 -6
  91. package/src/reporters/annotations.ts +12 -3
  92. package/src/reporters/template.ts +3 -0
  93. package/src/resolve.ts +59 -6
  94. package/src/roots.ts +60 -9
  95. package/src/run.ts +15 -5
  96. package/src/schema.ts +2 -0
  97. package/src/session.ts +218 -37
  98. package/src/setup-failure.ts +39 -0
  99. package/src/source-files.ts +4 -66
  100. package/src/sweep.ts +9 -2
  101. package/src/template-field.ts +42 -7
  102. package/src/test-support.ts +77 -0
  103. package/src/type-errors.ts +340 -0
  104. package/src/type-query-alias.ts +133 -0
  105. package/src/verbs/analyze.ts +38 -4
  106. package/src/verbs/explain.ts +4 -1
  107. package/src/verbs/print-projects.ts +17 -69
  108. package/src/verbs/print-retained.ts +7 -2
  109. package/src/verbs/print-roots.ts +7 -2
  110. package/src/verbs/verb.ts +6 -3
  111. package/src/version-range.ts +309 -0
  112. package/src/version.ts +1 -1
  113. package/src/workspace-manifests.ts +100 -0
  114. package/src/workspace-programs.ts +486 -0
  115. package/src/workspace-resolution.ts +393 -0
  116. package/src/workspace-run.ts +148 -0
  117. package/src/workspace.ts +463 -0
@@ -1,6 +1,7 @@
1
1
  import { runSweep } from "../analysis.ts";
2
2
  import { retainedLines } from "../exempt.ts";
3
3
  import { partialNotes } from "../partial.ts";
4
+ import { resolvePath } from "../paths.ts";
4
5
  import { resolve } from "../resolve.ts";
5
6
  import { EXIT_CLEAN, type Verb } from "./verb.ts";
6
7
 
@@ -14,14 +15,18 @@ import { EXIT_CLEAN, type Verb } from "./verb.ts";
14
15
  export const printRetainedVerb: Verb = ({ out, err, host, inputs, scope, openClient }) => {
15
16
  const { config } = resolve(inputs());
16
17
  const scoped = scope();
17
- const swept = runSweep(openClient(false), host, scoped, config, {
18
+ const swept = runSweep(openClient(config), host, scoped, config, {
18
19
  marked: [],
19
20
  mode: { production: true },
20
21
  });
21
22
  for (const line of retainedLines(swept.matrix.union.symbols, swept.retained)) {
22
23
  out.write(`${line}\n`);
23
24
  }
24
- for (const note of partialNotes({ notBuilt: swept.notBuilt, unanswered: swept.unanswered })) {
25
+ for (const note of partialNotes({
26
+ notBuilt: swept.notBuilt,
27
+ unanswered: swept.unanswered,
28
+ targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
29
+ })) {
25
30
  err.write(`deadset-ts: ${note}\n`);
26
31
  }
27
32
  return EXIT_CLEAN;
@@ -1,5 +1,6 @@
1
1
  import { runRoots, type RunRoot } from "../analysis.ts";
2
2
  import { partialNotes } from "../partial.ts";
3
+ import { resolvePath } from "../paths.ts";
3
4
  import { resolve } from "../resolve.ts";
4
5
  import { EXIT_CLEAN, EXIT_FINDINGS, type Verb } from "./verb.ts";
5
6
 
@@ -27,7 +28,7 @@ function rootLine(root: RunRoot, several: boolean): string {
27
28
  export const printRootsVerb: Verb = ({ out, err, host, inputs, scope, openClient }) => {
28
29
  const { config, provenance } = resolve(inputs());
29
30
  const scoped = scope();
30
- const answer = runRoots(openClient(false), host, scoped, config, provenance);
31
+ const answer = runRoots(openClient(config), host, scoped, config, provenance);
31
32
  const several = answer.configurations.length > 1;
32
33
  for (const root of answer.roots) {
33
34
  out.write(`${rootLine(root, several)}\n`);
@@ -35,7 +36,11 @@ export const printRootsVerb: Verb = ({ out, err, host, inputs, scope, openClient
35
36
  for (const finding of answer.findings) {
36
37
  err.write(`${finding.code}: roots.patterns names nothing: ${finding.symbol.ref}\n`);
37
38
  }
38
- for (const note of partialNotes({ notBuilt: answer.notBuilt, unanswered: answer.unanswered })) {
39
+ for (const note of partialNotes({
40
+ notBuilt: answer.notBuilt,
41
+ unanswered: answer.unanswered,
42
+ targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
43
+ })) {
39
44
  err.write(`deadset-ts: ${note}\n`);
40
45
  }
41
46
  return answer.findings.length > 0 ? EXIT_FINDINGS : EXIT_CLEAN;
package/src/verbs/verb.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Inputs } from "../config.ts";
1
+ import type { Config, Inputs } from "../config.ts";
2
2
  import type { Emitters } from "../findings/emitter.ts";
3
3
  import type { Host } from "../host.ts";
4
4
  import type { Writer } from "../run.ts";
@@ -24,8 +24,11 @@ export interface Invocation {
24
24
  readonly inputs: () => Inputs;
25
25
  /** The scope the options name: the document `--scope` names, or the target. */
26
26
  readonly scope: () => Scope;
27
- /** Opens the compiler client. A client the verb opened is closed if the verb throws. */
28
- readonly openClient: (collectTiming: boolean) => Engine;
27
+ /**
28
+ * Opens the compiler client for a run under `config`. A client the verb opened is
29
+ * closed if the verb throws.
30
+ */
31
+ readonly openClient: (config: Config) => Engine;
29
32
  /** The emitter of every kind family, which a verb that reports findings runs. */
30
33
  readonly emitters: Emitters;
31
34
  /** The arguments after the verb's name, as written. */
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Whether a version satisfies a dependency range, under the grammar npm, pnpm and yarn
3
+ * share: `||` alternatives of hyphen ranges or comparator runs, `x` and missing parts
4
+ * standing for any value, and a prerelease admitted only where a comparator names one
5
+ * of the same version. A range this grammar does not read is satisfied by nothing.
6
+ */
7
+
8
+ /** A version: three numbers and the prerelease identifiers, build metadata dropped. */
9
+ interface Version {
10
+ readonly major: number;
11
+ readonly minor: number;
12
+ readonly patch: number;
13
+ readonly prerelease: readonly string[];
14
+ }
15
+
16
+ /** One comparison a version must pass. */
17
+ interface Comparator {
18
+ readonly operator: "<" | "<=" | ">" | ">=" | "=";
19
+ readonly version: Version;
20
+ }
21
+
22
+ /** A version whose parts may be missing or a wildcard, as a range writes one. */
23
+ interface Partial {
24
+ readonly major?: number | undefined;
25
+ readonly minor?: number | undefined;
26
+ readonly patch?: number | undefined;
27
+ readonly prerelease: readonly string[];
28
+ }
29
+
30
+ const NUMBER = /^(?:0|[1-9]\d*)$/u;
31
+ const IDENTIFIER = /^[0-9A-Za-z-]+$/u;
32
+ const WILDCARD = new Set(["x", "X", "*"]);
33
+
34
+ /** The prerelease identifiers after a hyphen, or `undefined` where one is malformed. */
35
+ function prereleaseOf(text: string | undefined): readonly string[] | undefined {
36
+ if (text === undefined) {
37
+ return [];
38
+ }
39
+ const parts = text.split(".");
40
+ return parts.every((part) => IDENTIFIER.test(part)) ? parts : undefined;
41
+ }
42
+
43
+ /**
44
+ * One version as a range writes it, a leading `v` or `=` allowed, or `undefined`
45
+ * where it is not one.
46
+ */
47
+ function partialOf(text: string): Partial | undefined {
48
+ const match =
49
+ /^[v=]?([^.+-]+)(?:\.([^.+-]+)(?:\.([^.+-]+)(?:-([^+]+))?)?)?(?:\+[0-9A-Za-z.-]+)?$/u.exec(
50
+ text,
51
+ );
52
+ if (match === null) {
53
+ return undefined;
54
+ }
55
+ const parts: (number | undefined)[] = [];
56
+ let wild = false;
57
+ for (const part of [match[1], match[2], match[3]]) {
58
+ if (part === undefined || WILDCARD.has(part)) {
59
+ wild = true;
60
+ parts.push(undefined);
61
+ continue;
62
+ }
63
+ if (wild || !NUMBER.test(part)) {
64
+ return undefined;
65
+ }
66
+ parts.push(Number(part));
67
+ }
68
+ const prerelease = prereleaseOf(match[4]);
69
+ if (prerelease === undefined || (prerelease.length > 0 && wild)) {
70
+ return undefined;
71
+ }
72
+ return { major: parts[0], minor: parts[1], patch: parts[2], prerelease };
73
+ }
74
+
75
+ /** One exact version, or `undefined` where the text is not one. */
76
+ function versionOf(text: string): Version | undefined {
77
+ const partial = partialOf(text.trim());
78
+ if (partial?.major === undefined || partial.minor === undefined || partial.patch === undefined) {
79
+ return undefined;
80
+ }
81
+ return {
82
+ major: partial.major,
83
+ minor: partial.minor,
84
+ patch: partial.patch,
85
+ prerelease: partial.prerelease,
86
+ };
87
+ }
88
+
89
+ function exact(
90
+ major: number,
91
+ minor: number,
92
+ patch: number,
93
+ prerelease: readonly string[] = [],
94
+ ): Version {
95
+ return { major, minor, patch, prerelease };
96
+ }
97
+
98
+ /** The lowest prerelease of one version, which bounds a range from above. */
99
+ function floorOf(major: number, minor: number, patch: number): Version {
100
+ return exact(major, minor, patch, ["0"]);
101
+ }
102
+
103
+ function compareIdentifiers(a: string, b: string): number {
104
+ const numericA = NUMBER.test(a);
105
+ const numericB = NUMBER.test(b);
106
+ if (numericA && numericB) {
107
+ return Math.sign(Number(a) - Number(b));
108
+ }
109
+ if (numericA !== numericB) {
110
+ return numericA ? -1 : 1;
111
+ }
112
+ return a === b ? 0 : a < b ? -1 : 1;
113
+ }
114
+
115
+ /** Two versions ordered by precedence. */
116
+ function compare(a: Version, b: Version): number {
117
+ const core =
118
+ Math.sign(a.major - b.major) || Math.sign(a.minor - b.minor) || Math.sign(a.patch - b.patch);
119
+ if (core !== 0) {
120
+ return core;
121
+ }
122
+ if (a.prerelease.length === 0 || b.prerelease.length === 0) {
123
+ return Math.sign(b.prerelease.length - a.prerelease.length);
124
+ }
125
+ for (let at = 0; at < Math.max(a.prerelease.length, b.prerelease.length); at += 1) {
126
+ const left = a.prerelease[at];
127
+ const right = b.prerelease[at];
128
+ if (left === undefined || right === undefined) {
129
+ return left === undefined ? -1 : 1;
130
+ }
131
+ const order = compareIdentifiers(left, right);
132
+ if (order !== 0) {
133
+ return order;
134
+ }
135
+ }
136
+ return 0;
137
+ }
138
+
139
+ function passes(version: Version, comparator: Comparator): boolean {
140
+ const order = compare(version, comparator.version);
141
+ switch (comparator.operator) {
142
+ case "<":
143
+ return order < 0;
144
+ case "<=":
145
+ return order <= 0;
146
+ case ">":
147
+ return order > 0;
148
+ case ">=":
149
+ return order >= 0;
150
+ case "=":
151
+ return order === 0;
152
+ }
153
+ }
154
+
155
+ /** The comparators a version with missing parts stands for: any value of each. */
156
+ function anyOf(partial: Partial): Comparator[] {
157
+ const { major, minor } = partial;
158
+ if (major === undefined) {
159
+ return [{ operator: ">=", version: exact(0, 0, 0) }];
160
+ }
161
+ if (minor === undefined) {
162
+ return [
163
+ { operator: ">=", version: exact(major, 0, 0) },
164
+ { operator: "<", version: floorOf(major + 1, 0, 0) },
165
+ ];
166
+ }
167
+ if (partial.patch === undefined) {
168
+ return [
169
+ { operator: ">=", version: exact(major, minor, 0) },
170
+ { operator: "<", version: floorOf(major, minor + 1, 0) },
171
+ ];
172
+ }
173
+ return [{ operator: "=", version: exact(major, minor, partial.patch, partial.prerelease) }];
174
+ }
175
+
176
+ /** The lowest version a partial version stands for. */
177
+ function lowest(partial: Partial): Version {
178
+ return exact(partial.major ?? 0, partial.minor ?? 0, partial.patch ?? 0, partial.prerelease);
179
+ }
180
+
181
+ function tilde(partial: Partial): Comparator[] {
182
+ const { major, minor } = partial;
183
+ if (major === undefined || minor === undefined) {
184
+ return anyOf(partial);
185
+ }
186
+ return [
187
+ { operator: ">=", version: lowest(partial) },
188
+ { operator: "<", version: floorOf(major, minor + 1, 0) },
189
+ ];
190
+ }
191
+
192
+ function caret(partial: Partial): Comparator[] {
193
+ const { major, minor, patch } = partial;
194
+ if (major === undefined) {
195
+ return anyOf(partial);
196
+ }
197
+ const from = { operator: ">=" as const, version: lowest(partial) };
198
+ if (major > 0 || minor === undefined) {
199
+ return [from, { operator: "<", version: floorOf(major + 1, 0, 0) }];
200
+ }
201
+ if (minor > 0 || patch === undefined) {
202
+ return [from, { operator: "<", version: floorOf(0, minor + 1, 0) }];
203
+ }
204
+ return [from, { operator: "<", version: floorOf(0, 0, patch + 1) }];
205
+ }
206
+
207
+ /** The comparators one primitive comparison stands for, a partial version filled in. */
208
+ function primitive(operator: "<" | "<=" | ">" | ">=", partial: Partial): Comparator[] {
209
+ const { major, minor, patch } = partial;
210
+ if (major === undefined) {
211
+ return operator === "<" || operator === ">"
212
+ ? [{ operator: "<", version: floorOf(0, 0, 0) }]
213
+ : [{ operator: ">=", version: exact(0, 0, 0) }];
214
+ }
215
+ if (minor !== undefined && patch !== undefined) {
216
+ return [{ operator, version: lowest(partial) }];
217
+ }
218
+ const next = minor === undefined ? exact(major + 1, 0, 0) : exact(major, minor + 1, 0);
219
+ switch (operator) {
220
+ case ">":
221
+ return [{ operator: ">=", version: next }];
222
+ case ">=":
223
+ return [{ operator: ">=", version: lowest(partial) }];
224
+ case "<":
225
+ return [{ operator: "<", version: floorOf(major, minor ?? 0, 0) }];
226
+ case "<=":
227
+ return [{ operator: "<", version: floorOf(next.major, next.minor, 0) }];
228
+ }
229
+ }
230
+
231
+ /** The comparators one written comparator stands for, or `undefined` where it is none. */
232
+ function comparatorsOf(token: string): Comparator[] | undefined {
233
+ const match = /^(<=|>=|<|>|=|~>|~|\^)?(.*)$/u.exec(token);
234
+ const operator = match?.[1] ?? "";
235
+ const partial = partialOf(match?.[2] ?? "");
236
+ if (partial === undefined) {
237
+ return undefined;
238
+ }
239
+ switch (operator) {
240
+ case "~":
241
+ case "~>":
242
+ return tilde(partial);
243
+ case "^":
244
+ return caret(partial);
245
+ case "<":
246
+ case "<=":
247
+ case ">":
248
+ case ">=":
249
+ return primitive(operator, partial);
250
+ default:
251
+ return anyOf(partial);
252
+ }
253
+ }
254
+
255
+ /** The comparators of one alternative, or `undefined` where it does not read. */
256
+ function alternativeOf(text: string): Comparator[] | undefined {
257
+ const spaced = text.trim().replaceAll(/(<=|>=|<|>|=|~>|~|\^)\s+/gu, "$1");
258
+ if (spaced === "") {
259
+ return anyOf({ prerelease: [] });
260
+ }
261
+ const hyphen = /^(\S+)\s+-\s+(\S+)$/u.exec(spaced);
262
+ if (hyphen !== null) {
263
+ const from = partialOf(hyphen[1] ?? "");
264
+ const to = partialOf(hyphen[2] ?? "");
265
+ if (from === undefined || to === undefined) {
266
+ return undefined;
267
+ }
268
+ return [...primitive(">=", from), ...(to.major === undefined ? [] : primitive("<=", to))];
269
+ }
270
+ const found: Comparator[] = [];
271
+ for (const token of spaced.split(/\s+/u)) {
272
+ const comparators = comparatorsOf(token);
273
+ if (comparators === undefined) {
274
+ return undefined;
275
+ }
276
+ found.push(...comparators);
277
+ }
278
+ return found;
279
+ }
280
+
281
+ /** Whether one alternative admits one version, its prerelease rule included. */
282
+ function admits(alternative: readonly Comparator[], version: Version): boolean {
283
+ if (!alternative.every((comparator) => passes(version, comparator))) {
284
+ return false;
285
+ }
286
+ if (version.prerelease.length === 0) {
287
+ return true;
288
+ }
289
+ return alternative.some(
290
+ ({ version: bound }) =>
291
+ bound.prerelease.length > 0 &&
292
+ bound.major === version.major &&
293
+ bound.minor === version.minor &&
294
+ bound.patch === version.patch,
295
+ );
296
+ }
297
+
298
+ /** Whether `version` satisfies `range`; `false` where either does not read. */
299
+ export function satisfies(version: string, range: string): boolean {
300
+ const parsed = versionOf(version);
301
+ if (parsed === undefined) {
302
+ return false;
303
+ }
304
+ const alternatives = range.split("||").map(alternativeOf);
305
+ return (
306
+ alternatives.every((alternative) => alternative !== undefined) &&
307
+ alternatives.some((alternative) => admits(alternative, parsed))
308
+ );
309
+ }
package/src/version.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  * independently of the analyzer's own version, which is the one the host answers
5
5
  * from the package the analyzer was installed from.
6
6
  */
7
- export const CONTRACT_VERSION = "4.0.0";
7
+ export const CONTRACT_VERSION = "5.1.0";
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The entry points the manifests of a workspace name, read back to the members'
3
+ * sources. Each member's manifest is read the way the target's own is, and each target
4
+ * is read back to the source file its member's configurations compile it from. A
5
+ * member whose manifest forbids publishing it exports nothing anyone outside the
6
+ * workspace imports, so only its commands are entry points.
7
+ */
8
+
9
+ import { emittedFrom } from "./emit-map.ts";
10
+ import type { Host } from "./host.ts";
11
+ import { readManifest, type Manifest, type ManifestEntry } from "./manifest.ts";
12
+ import { joinPath, relativePath } from "./paths.ts";
13
+ import type { WorkspaceMember } from "./workspace.ts";
14
+ import type { WorkspaceResolver } from "./workspace-resolution.ts";
15
+
16
+ /** The one character a subpath pattern of a manifest's `exports` holds. */
17
+ const SUBPATH_WILDCARD = "*";
18
+
19
+ /** The paths one written target stands for in its member's sources, itself included. */
20
+ function sourcesOf(
21
+ resolver: WorkspaceResolver,
22
+ member: WorkspaceMember,
23
+ path: string,
24
+ ): readonly string[] {
25
+ if (!path.includes(SUBPATH_WILDCARD)) {
26
+ const source = resolver.sourceOf(member, path);
27
+ return source === undefined ? [path] : [source];
28
+ }
29
+ const patterns = member.configurations.flatMap(({ layout }) =>
30
+ layout === undefined ? [] : emittedFrom(path, layout),
31
+ );
32
+ return [...new Set([path, ...patterns])];
33
+ }
34
+
35
+ /** One manifest's entries with every target read back to its member's sources. */
36
+ function sourceEntries(
37
+ resolver: WorkspaceResolver,
38
+ member: WorkspaceMember,
39
+ entries: readonly ManifestEntry[],
40
+ spelled: (entry: ManifestEntry) => string,
41
+ ): readonly ManifestEntry[] {
42
+ return entries.flatMap((entry) =>
43
+ sourcesOf(resolver, member, entry.path).map((path) => ({
44
+ ...entry,
45
+ member: spelled(entry),
46
+ path,
47
+ })),
48
+ );
49
+ }
50
+
51
+ /**
52
+ * The target's own manifest with its targets read back to the sources of the member
53
+ * the target is, where it is one.
54
+ */
55
+ export function targetManifestIn(
56
+ resolver: WorkspaceResolver,
57
+ targetRoot: string,
58
+ manifest: Manifest,
59
+ ): Manifest {
60
+ const member = resolver.workspace.members.find((one) => one.dir === targetRoot);
61
+ return member === undefined
62
+ ? manifest
63
+ : {
64
+ ...manifest,
65
+ entries: sourceEntries(resolver, member, manifest.entries, (entry) => entry.member),
66
+ };
67
+ }
68
+
69
+ /**
70
+ * The entry points every other member's manifest names, each spelled as the member
71
+ * that named it under the manifest's path below the target root, a private member's
72
+ * `exports` left out: only the workspace imports a private package, and the workspace
73
+ * is analyzed. An entry is published where its member is not private and the member
74
+ * named in its own manifest is one a consumer imports.
75
+ */
76
+ export function memberEntries(
77
+ host: Host,
78
+ resolver: WorkspaceResolver,
79
+ targetRoot: string,
80
+ ): readonly ManifestEntry[] {
81
+ return resolver.workspace.members.flatMap((member) => {
82
+ if (member.dir === targetRoot) {
83
+ return [];
84
+ }
85
+ const manifest = readManifest(host, member.dir);
86
+ const where =
87
+ relativePath(targetRoot, joinPath(member.dir, "package.json")) ??
88
+ joinPath(member.dir, "package.json");
89
+ const kept = manifest.entries.flatMap((entry): ManifestEntry[] => {
90
+ const exported = entry.member.startsWith("exports");
91
+ if (member.private && exported) {
92
+ return [];
93
+ }
94
+ const published =
95
+ !member.private && entry.published && (manifest.declaresExports ? exported : true);
96
+ return [{ ...entry, published }];
97
+ });
98
+ return sourceEntries(resolver, member, kept, (entry) => `${where} ${entry.member}`);
99
+ });
100
+ }