@cplieger/deadset-ts 8.0.0-dev.6 → 8.0.0-dev.8

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 (193) hide show
  1. package/dist/bin/mapper-connection.js +2 -1
  2. package/dist/bin/node-host.js +24 -5
  3. package/dist/src/analysis.js +37 -56
  4. package/dist/src/automatic-types.js +10 -29
  5. package/dist/src/build-scripts.js +17 -29
  6. package/dist/src/component-layer.js +4 -2
  7. package/dist/src/components.js +2 -3
  8. package/dist/src/config.js +6 -82
  9. package/dist/src/configuration-files.js +27 -168
  10. package/dist/src/configured-declarations.js +15 -20
  11. package/dist/src/consumers.js +2 -2
  12. package/dist/src/contract/config.generated.js +544 -0
  13. package/dist/src/contract/contract.generated.js +13 -0
  14. package/dist/src/contract/report.generated.js +3 -2
  15. package/dist/src/conventions.js +20 -60
  16. package/dist/src/dependencies.js +25 -43
  17. package/dist/src/discover.js +14 -40
  18. package/dist/src/edges.js +38 -122
  19. package/dist/src/element-access.js +4 -6
  20. package/dist/src/entry-point-gaps.js +2 -8
  21. package/dist/src/entry-points.js +3 -10
  22. package/dist/src/enum-group.js +3 -10
  23. package/dist/src/erased-stores.js +4 -6
  24. package/dist/src/exempt-classes.js +0 -4
  25. package/dist/src/exempt.js +6 -22
  26. package/dist/src/file-facts.js +2 -25
  27. package/dist/src/findings/completion.js +5 -4
  28. package/dist/src/findings/emitters.js +1 -1
  29. package/dist/src/findings/intra-function.js +1 -1
  30. package/dist/src/findings/non-code-artifacts.js +2 -2
  31. package/dist/src/findings/reads-and-writes.js +2 -1
  32. package/dist/src/findings/self-check.js +3 -2
  33. package/dist/src/findings/unused-declarations.js +1 -1
  34. package/dist/src/findings/visibility-narrowing.js +2 -2
  35. package/dist/src/findings-pass.js +7 -12
  36. package/dist/src/framework-lifecycle.js +7 -7
  37. package/dist/src/fs/document.js +59 -0
  38. package/dist/src/fs/manifest.js +43 -0
  39. package/dist/src/fs/tree.js +88 -0
  40. package/dist/src/git-ignore.js +34 -25
  41. package/dist/src/html-entries.js +6 -33
  42. package/dist/src/in-operands.js +2 -1
  43. package/dist/src/injection-container.js +1 -1
  44. package/dist/src/intra-function-parts.js +10 -13
  45. package/dist/src/inventory.js +2 -21
  46. package/dist/src/json-document.js +198 -67
  47. package/dist/src/keyof-comparisons.js +4 -6
  48. package/dist/src/kinds.js +0 -7
  49. package/dist/src/manifest.js +5 -43
  50. package/dist/src/mdx-entries.js +3 -26
  51. package/dist/src/partial.js +2 -1
  52. package/dist/src/paths.js +26 -15
  53. package/dist/src/position.js +2 -1
  54. package/dist/src/print.js +11 -79
  55. package/dist/src/product.js +13 -0
  56. package/dist/src/references.js +14 -27
  57. package/dist/src/report-schema.js +3 -225
  58. package/dist/src/report.js +22 -31
  59. package/dist/src/reporters/sarif.js +4 -2
  60. package/dist/src/reporters/template.js +4 -19
  61. package/dist/src/resolve.js +245 -724
  62. package/dist/src/roots.js +7 -17
  63. package/dist/src/run.js +55 -61
  64. package/dist/src/schema.js +320 -343
  65. package/dist/src/scope.js +34 -103
  66. package/dist/src/serialization-contract.js +5 -9
  67. package/dist/src/session.js +2 -1
  68. package/dist/src/suppress-file.js +21 -25
  69. package/dist/src/suppress.js +3 -3
  70. package/dist/src/symbol-keys.js +3 -5
  71. package/dist/src/template-field.js +9 -19
  72. package/dist/src/test-globals.js +6 -28
  73. package/dist/src/test-joins.js +6 -6
  74. package/dist/src/text/compare.js +26 -0
  75. package/dist/src/text/glob.js +194 -0
  76. package/dist/src/text/shell.js +159 -0
  77. package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
  78. package/dist/src/type-errors.js +14 -38
  79. package/dist/src/unseen-loads.js +2 -9
  80. package/dist/src/unwrap.js +23 -0
  81. package/dist/src/usage.js +10 -0
  82. package/dist/src/verbs/analyze.js +25 -26
  83. package/dist/src/verbs/describe.js +4 -4
  84. package/dist/src/verbs/explain.js +8 -6
  85. package/dist/src/verbs/print-projects.js +4 -3
  86. package/dist/src/verbs/print-retained.js +2 -1
  87. package/dist/src/verbs/print-roots.js +2 -1
  88. package/dist/src/verbs/version.js +2 -1
  89. package/dist/src/workflow-steps.js +9 -46
  90. package/dist/src/workspace-manifests.js +2 -2
  91. package/dist/src/workspace-programs.js +5 -3
  92. package/dist/src/workspace-resolution.js +13 -17
  93. package/dist/src/workspace.js +28 -116
  94. package/jsr.json +1 -1
  95. package/package.json +1 -1
  96. package/src/analysis.ts +55 -76
  97. package/src/automatic-types.ts +11 -29
  98. package/src/build-scripts.ts +17 -38
  99. package/src/component-layer.ts +4 -2
  100. package/src/components.ts +2 -4
  101. package/src/config.ts +31 -296
  102. package/src/configuration-files.ts +27 -170
  103. package/src/configured-declarations.ts +18 -23
  104. package/src/consumers.ts +4 -4
  105. package/src/contract/config.generated.ts +798 -0
  106. package/src/contract/contract.generated.ts +25 -0
  107. package/src/contract/report.generated.ts +3 -2
  108. package/src/conventions.ts +26 -74
  109. package/src/dependencies.ts +32 -50
  110. package/src/discover.ts +15 -40
  111. package/src/edges.ts +41 -140
  112. package/src/element-access.ts +4 -7
  113. package/src/entry-point-gaps.ts +3 -9
  114. package/src/entry-points.ts +2 -13
  115. package/src/enum-group.ts +2 -11
  116. package/src/erased-stores.ts +3 -7
  117. package/src/exempt-classes.ts +0 -5
  118. package/src/exempt.ts +8 -30
  119. package/src/file-facts.ts +6 -24
  120. package/src/findings/completion.ts +5 -6
  121. package/src/findings/emitter.ts +2 -2
  122. package/src/findings/emitters.ts +1 -1
  123. package/src/findings/intra-function.ts +1 -1
  124. package/src/findings/non-code-artifacts.ts +4 -4
  125. package/src/findings/reads-and-writes.ts +2 -1
  126. package/src/findings/self-check.ts +3 -2
  127. package/src/findings/unused-declarations.ts +1 -1
  128. package/src/findings/visibility-narrowing.ts +2 -2
  129. package/src/findings-pass.ts +9 -15
  130. package/src/framework-lifecycle.ts +7 -7
  131. package/src/fs/document.ts +74 -0
  132. package/src/fs/manifest.ts +52 -0
  133. package/src/fs/tree.ts +110 -0
  134. package/src/git-ignore.ts +38 -25
  135. package/src/host.ts +12 -5
  136. package/src/html-entries.ts +6 -33
  137. package/src/in-operands.ts +2 -1
  138. package/src/injection-container.ts +1 -1
  139. package/src/intra-function-parts.ts +10 -14
  140. package/src/inventory.ts +2 -20
  141. package/src/json-document.ts +241 -76
  142. package/src/keyof-comparisons.ts +3 -7
  143. package/src/kinds.ts +0 -8
  144. package/src/manifest.ts +5 -46
  145. package/src/mdx-entries.ts +3 -26
  146. package/src/partial.ts +2 -1
  147. package/src/paths.ts +27 -15
  148. package/src/position.ts +2 -1
  149. package/src/print.ts +12 -92
  150. package/src/product.ts +18 -0
  151. package/src/references.ts +14 -29
  152. package/src/report-schema.ts +3 -301
  153. package/src/report.ts +24 -34
  154. package/src/reporters/sarif.ts +4 -4
  155. package/src/reporters/template.ts +4 -20
  156. package/src/resolve.ts +283 -1114
  157. package/src/roots.ts +7 -20
  158. package/src/run.ts +57 -75
  159. package/src/schema.ts +391 -388
  160. package/src/scope.ts +40 -126
  161. package/src/serialization-contract.ts +5 -10
  162. package/src/session.ts +2 -1
  163. package/src/suppress-file.ts +21 -29
  164. package/src/suppress.ts +3 -3
  165. package/src/symbol-keys.ts +2 -5
  166. package/src/template-field.ts +15 -25
  167. package/src/test-globals.ts +9 -27
  168. package/src/test-joins.ts +6 -8
  169. package/src/text/compare.ts +27 -0
  170. package/src/text/glob.ts +210 -0
  171. package/src/text/shell.ts +161 -0
  172. package/src/{yaml-document.ts → text/yaml.ts} +46 -0
  173. package/src/type-errors.ts +25 -36
  174. package/src/unseen-loads.ts +1 -12
  175. package/src/unwrap.ts +34 -0
  176. package/src/usage.ts +10 -0
  177. package/src/verbs/analyze.ts +32 -42
  178. package/src/verbs/describe.ts +4 -4
  179. package/src/verbs/explain.ts +8 -10
  180. package/src/verbs/print-projects.ts +4 -3
  181. package/src/verbs/print-retained.ts +2 -1
  182. package/src/verbs/print-roots.ts +2 -1
  183. package/src/verbs/verb.ts +2 -2
  184. package/src/verbs/version.ts +2 -1
  185. package/src/workflow-steps.ts +9 -44
  186. package/src/workspace-manifests.ts +2 -2
  187. package/src/workspace-programs.ts +5 -3
  188. package/src/workspace-resolution.ts +21 -17
  189. package/src/workspace.ts +35 -121
  190. package/dist/src/glob.js +0 -65
  191. package/dist/src/pnpm-workspace.js +0 -120
  192. package/src/glob.ts +0 -67
  193. package/src/pnpm-workspace.ts +0 -135
package/src/roots.ts CHANGED
@@ -43,17 +43,19 @@ import {
43
43
  } from "./configuration-files.ts";
44
44
  import { conventionEntries, type Conventions } from "./conventions.ts";
45
45
  import { entryPoints, type EntryRule } from "./entry-points.ts";
46
- import { globExpression } from "./glob.ts";
47
46
  import type { Host } from "./host.ts";
48
47
  import { nodeKey, type Inventory, type InventorySymbol } from "./inventory.ts";
49
48
  import type { Manifest, ManifestEntry } from "./manifest.ts";
50
- import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.ts";
49
+ import { ancestors, dirnamePath, relativePath, resolvePath } from "./paths.ts";
51
50
  import { byPosition } from "./position.ts";
52
51
  import { UNANSWERED } from "./query.ts";
53
52
  import type { ProjectView } from "./session.ts";
54
53
  import type { Symbol as TSSymbol, Type } from "@typescript/native/sync";
55
54
  import { sourceFilesOf, type SourceFiles } from "./source-files.ts";
56
55
  import { typeQueryAliases } from "./type-query-alias.ts";
56
+ import { bytewise } from "./text/compare.ts";
57
+ import { holdsManifest } from "./fs/manifest.ts";
58
+ import { globExpression } from "./text/glob.ts";
57
59
 
58
60
  /** Why one declaration is a root. */
59
61
  export type RootKind =
@@ -197,15 +199,8 @@ const SOURCE_EXTENSION = /\.(?:d\.)?[cm]?[jt]sx?$/u;
197
199
 
198
200
  /** Whether no `package.json` sits between one file and the manifest's directory, which holds it. */
199
201
  function ofPackage(host: Host, dir: string, file: string): boolean {
200
- for (let at = dirnamePath(file); at !== dir; at = dirnamePath(at)) {
201
- if (
202
- relativePath(dir, at) === undefined ||
203
- host.kindOf(joinPath(at, "package.json")) === "file"
204
- ) {
205
- return false;
206
- }
207
- }
208
- return true;
202
+ const between = ancestors(dirnamePath(file), dir);
203
+ return between.length > 0 && !between.slice(0, -1).some((at) => holdsManifest(host, at));
209
204
  }
210
205
 
211
206
  /**
@@ -331,14 +326,6 @@ export function matchRef(pattern: string, ref: string): boolean {
331
326
  return matchGlob(Array.from(pattern), Array.from(ref));
332
327
  }
333
328
 
334
- /** Two strings ordered bytewise, which is the order every set of a run is read in. */
335
- function compare(a: string, b: string): number {
336
- if (a === b) {
337
- return 0;
338
- }
339
- return a < b ? -1 : 1;
340
- }
341
-
342
329
  /** The members of one declaration, indexed by the container that holds them. */
343
330
  function childrenOf(held: Inventory): ReadonlyMap<string, readonly InventorySymbol[]> {
344
331
  const byParent = new Map<string, InventorySymbol[]>();
@@ -561,7 +548,7 @@ export function roots<Brand>(
561
548
  const left = sites.get(a.id);
562
549
  const right = sites.get(b.id);
563
550
  const site = left === undefined || right === undefined ? 0 : byPosition(left, right);
564
- return site || compare(a.kind, b.kind) || compare(a.source, b.source);
551
+ return site || bytewise(a.kind, b.kind) || bytewise(a.source, b.source);
565
552
  });
566
553
 
567
554
  return {
package/src/run.ts CHANGED
@@ -1,10 +1,13 @@
1
+ import { CONFIG_MAX_BYTES, SETTINGS } from "./contract/config.generated.ts";
1
2
  import { EXIT_FAILURE, EXIT_USAGE } from "./contract/contract.generated.ts";
2
- import { ConfigError, REPOSITORY_DOCUMENT, type Inputs } from "./config.ts";
3
+ import { REPOSITORY_DOCUMENT, type Document, type Inputs } from "./config.ts";
3
4
  import { DiscoveryError, renderDiagnostic } from "./discover.ts";
5
+ import { readTargetDocument, TargetDocumentError } from "./fs/document.ts";
4
6
  import type { Host } from "./host.ts";
5
7
  import { joinPath, resolvePath } from "./paths.ts";
6
8
  import { readScope, ScopeError, scopeForDir, type Scope } from "./scope.ts";
7
9
  import { SetupError, setupLine } from "./setup-failure.ts";
10
+ import { UsageError } from "./usage.ts";
8
11
  import { openEngine, type Engine, type EngineOptions } from "./session.ts";
9
12
  import { printConfigVerb } from "./verbs/print-config.ts";
10
13
  import { printProjectsVerb } from "./verbs/print-projects.ts";
@@ -15,6 +18,7 @@ import { describeVerb } from "./verbs/describe.ts";
15
18
  import { EXPLAIN_OPTIONS, explainVerb } from "./verbs/explain.ts";
16
19
  import { type Verb, type VerbOptions } from "./verbs/verb.ts";
17
20
  import { versionVerb } from "./verbs/version.ts";
21
+ import { diagnose, message, PRODUCT } from "./product.ts";
18
22
 
19
23
  /** One output stream of the command line. `process.stdout` and `process.stderr` satisfy it. */
20
24
  export interface Writer {
@@ -37,7 +41,7 @@ const VERBS: readonly {
37
41
  { name: "version", run: versionVerb },
38
42
  ];
39
43
 
40
- const USAGE = `usage: deadset-ts <verb> [options]\nverbs: ${VERBS.map((verb) => verb.name).join(", ")}\n`;
44
+ const USAGE = `usage: ${PRODUCT} <verb> [options]\nverbs: ${VERBS.map((verb) => verb.name).join(", ")}\n`;
41
45
 
42
46
  /**
43
47
  * The tokens whose presence in an option's name makes that option a request to
@@ -47,33 +51,16 @@ const USAGE = `usage: deadset-ts <verb> [options]\nverbs: ${VERBS.map((verb) =>
47
51
  const SOURCE_EDIT_TOKENS = ["fix", "edit", "delete", "rewrite"] as const;
48
52
 
49
53
  /**
50
- * Maps an option name to the setting of the Contract's configuration schema it supplies,
51
- * so one entry registers the option, supplies the document resolution reads, and gives
52
- * the spelling the setting's provenance names. The name is this command's vocabulary and
53
- * is never derived from the path: a setting reaches the command line only by an entry,
54
- * and a path names a key the schema declares.
54
+ * Maps an option name to the setting of the Contract's configuration schema it supplies:
55
+ * the options contract/settings.json names for a setting this analyzer reads.
55
56
  */
56
- export const SETTING_OPTIONS: ReadonlyMap<string, string> = new Map([
57
- ["min-confidence", "analysis.min_confidence"],
58
- ["sort", "reporters.sort"],
59
- ["cascade", "reporters.cascade"],
60
- ["max-findings", "reporters.max_findings"],
61
- ["fail-on", "reporters.fail_on"],
62
- ]);
57
+ export const SETTING_OPTIONS: ReadonlyMap<string, string> = new Map(
58
+ SETTINGS.flatMap((row) => (row.option === undefined ? [] : [[row.option, row.key] as const])),
59
+ );
63
60
 
64
61
  /** The options that take a value and are not settings. */
65
62
  const PLAIN_OPTIONS: ReadonlySet<string> = new Set(["target", "config", "central", "scope"]);
66
63
 
67
- /**
68
- * The setting options whose value is an integer rather than a string. A value
69
- * written other than as digits is passed on as the string it is, so resolution
70
- * refuses it by its type rather than reading `1e2` as 100.
71
- */
72
- const INTEGER_OPTIONS: ReadonlySet<string> = new Set(["max-findings"]);
73
-
74
- /** An integer as an option writes it: an optional minus sign and digits alone. */
75
- const INTEGER_TEXT = /^-?[0-9]+$/u;
76
-
77
64
  /** One invocation's options, by name: the last value of each, and every value of a repeatable one. */
78
65
  interface Options {
79
66
  readonly named: ReadonlyMap<string, string>;
@@ -108,7 +95,7 @@ function readOptions(args: readonly string[], own: VerbOptions): Options {
108
95
  const repeated = new Map<string, string[]>();
109
96
  for (const arg of args) {
110
97
  if (!arg.startsWith("-")) {
111
- throw new ConfigError("malformed", "", `unexpected argument ${JSON.stringify(arg)}`);
98
+ throw new UsageError(`unexpected argument ${JSON.stringify(arg)}`);
112
99
  }
113
100
  const [spelled, ...rest] = arg.split("=");
114
101
  const name = (spelled ?? "").replace(/^-+/u, "");
@@ -118,14 +105,10 @@ function readOptions(args: readonly string[], own: VerbOptions): Options {
118
105
  !own.plain.includes(name) &&
119
106
  !own.repeatable.includes(name)
120
107
  ) {
121
- throw new ConfigError("malformed", "", `unknown option ${JSON.stringify(spelled ?? arg)}`);
108
+ throw new UsageError(`unknown option ${JSON.stringify(spelled ?? arg)}`);
122
109
  }
123
110
  if (rest.length === 0) {
124
- throw new ConfigError(
125
- "malformed",
126
- "",
127
- `option ${JSON.stringify(spelled ?? arg)} takes a value`,
128
- );
111
+ throw new UsageError(`option ${JSON.stringify(spelled ?? arg)} takes a value`);
129
112
  }
130
113
  const value = rest.join("=");
131
114
  named.set(name, value);
@@ -134,51 +117,54 @@ function readOptions(args: readonly string[], own: VerbOptions): Options {
134
117
  return { named, repeated };
135
118
  }
136
119
 
137
- function readFileOr(host: Host, path: string, orUndefined: boolean): string | undefined {
120
+ /** The document an option names. */
121
+ function documentAt(host: Host, label: string): Document {
138
122
  try {
139
- return host.readFile(resolvePath(host.workingDirectory(), path));
123
+ const path = resolvePath(host.workingDirectory(), label);
124
+ // A file past the bound reads as one byte more than it, which resolution refuses.
125
+ return { text: host.readFile(path, CONFIG_MAX_BYTES + 1), label };
140
126
  } catch (error: unknown) {
141
- if (orUndefined) {
142
- return undefined;
143
- }
144
- throw new ConfigError(
145
- "malformed",
146
- "",
147
- `${path}: ${error instanceof Error ? error.message : String(error)}`,
148
- );
127
+ throw new UsageError(`${label}: ${message(error)}`);
149
128
  }
150
129
  }
151
130
 
152
131
  /**
153
- * The configuration documents one invocation reads: the repository configuration
154
- * at the target root or the path an option named, the central configuration, and
155
- * the settings the options supply as one flag document.
132
+ * The repository configuration at the target root, none where it is absent. One that
133
+ * cannot be read is a configuration document that cannot be, refused with the usage code.
134
+ */
135
+ function repositoryAt(host: Host, target: string): Document | undefined {
136
+ const label = joinPath(target, REPOSITORY_DOCUMENT);
137
+ const root = resolvePath(host.workingDirectory(), target);
138
+ try {
139
+ const text = readTargetDocument(host, root, REPOSITORY_DOCUMENT, label);
140
+ return text === undefined ? undefined : { text, label };
141
+ } catch (error: unknown) {
142
+ throw error instanceof TargetDocumentError ? new UsageError(error.message) : error;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * The configuration sources one invocation carries: the repository configuration at
148
+ * the target root or the path an option named, the central configuration, and the
149
+ * text each setting option was given.
156
150
  */
157
151
  function inputsOf(host: Host, options: Options): Inputs {
158
- const target = options.named.get("target") ?? ".";
159
152
  const named = options.named.get("config");
160
- const repositoryLabel = named ?? joinPath(target, REPOSITORY_DOCUMENT);
161
- const repository = readFileOr(host, repositoryLabel, named === undefined);
153
+ const target = options.named.get("target") ?? ".";
154
+ const repository = named === undefined ? repositoryAt(host, target) : documentAt(host, named);
162
155
  const centralLabel = options.named.get("central");
163
- const central = centralLabel === undefined ? undefined : readFileOr(host, centralLabel, false);
164
-
165
- const flat: Record<string, unknown> = {};
166
- const flagLabels = new Map<string, string>();
167
- for (const [name, path] of SETTING_OPTIONS) {
156
+ const central = centralLabel === undefined ? undefined : documentAt(host, centralLabel);
157
+ const flags = new Map<string, string>();
158
+ for (const [name, key] of SETTING_OPTIONS) {
168
159
  const value = options.named.get(name);
169
- if (value === undefined) {
170
- continue;
160
+ if (value !== undefined) {
161
+ flags.set(key, value);
171
162
  }
172
- flat[path] = INTEGER_OPTIONS.has(name) && INTEGER_TEXT.test(value) ? Number(value) : value;
173
- flagLabels.set(path, `--${name}`);
174
163
  }
175
- const flags = Object.keys(flat).length === 0 ? undefined : JSON.stringify(flat);
176
-
177
164
  return {
178
- ...(flags === undefined ? {} : { flags }),
179
- ...(repository === undefined ? {} : { repository, repositoryLabel }),
180
- ...(central === undefined || centralLabel === undefined ? {} : { central, centralLabel }),
181
- flagLabels,
165
+ flags,
166
+ ...(repository === undefined ? {} : { repository }),
167
+ ...(central === undefined ? {} : { central }),
182
168
  };
183
169
  }
184
170
 
@@ -196,9 +182,7 @@ function scopeOf(host: Host, options: Options): Scope {
196
182
  * the exit code: 0 for a completed verb, 1 for a finding that fails the run, 2 for a
197
183
  * usage error, a requested source edit or a refused configuration, 3 for a failure that
198
184
  * produced no answer. It writes nothing outside `out` and `err` and never exits the
199
- * process. `host` is the platform the run reads, the version it reports included, and
200
- * `openClient` opens the compiler client; a caller that watches what a run reads
201
- * supplies its own of either.
185
+ * process. A caller that watches what a run reads supplies its own `host` or `openClient`.
202
186
  */
203
187
  export function run(
204
188
  args: readonly string[],
@@ -209,9 +193,7 @@ export function run(
209
193
  ): number {
210
194
  const editing = sourceEditOption(args);
211
195
  if (editing !== undefined) {
212
- err.write(
213
- `deadset-ts: ${editing} is not supported: deadset-ts reports and never edits a source file\n`,
214
- );
196
+ diagnose(err, `${editing} is not supported: ${PRODUCT} reports and never edits a source file`);
215
197
  err.write(USAGE);
216
198
  return EXIT_USAGE;
217
199
  }
@@ -228,7 +210,7 @@ export function run(
228
210
  );
229
211
  }
230
212
  if (name !== undefined) {
231
- err.write(`deadset-ts: unknown verb ${JSON.stringify(name)}\n`);
213
+ diagnose(err, `unknown verb ${JSON.stringify(name)}`);
232
214
  }
233
215
  err.write(USAGE);
234
216
  return EXIT_USAGE;
@@ -260,7 +242,7 @@ function invoke(
260
242
  openClient: (config) => {
261
243
  opened = openClient({
262
244
  collectTiming: false,
263
- components: { extensions: config.ts.componentExtensions, host: streams.host },
245
+ components: { extensions: config.ts.component_extensions, host: streams.host },
264
246
  });
265
247
  return opened;
266
248
  },
@@ -273,8 +255,8 @@ function invoke(
273
255
 
274
256
  /** Turns one refusal into the exit code the Contract's table gives it. */
275
257
  function refuse(error: unknown, err: Writer): number {
276
- if (error instanceof ConfigError) {
277
- err.write(`deadset-ts: ${error.message}\n`);
258
+ if (error instanceof UsageError) {
259
+ diagnose(err, error.message);
278
260
  err.write(USAGE);
279
261
  return EXIT_USAGE;
280
262
  }
@@ -282,7 +264,7 @@ function refuse(error: unknown, err: Writer): number {
282
264
  for (const diagnostic of error.diagnostics) {
283
265
  err.write(`${renderDiagnostic(diagnostic)}\n`);
284
266
  }
285
- err.write(`deadset-ts: ${error.message}\n`);
267
+ diagnose(err, error.message);
286
268
  return EXIT_FAILURE;
287
269
  }
288
270
  if (error instanceof SetupError) {
@@ -291,8 +273,8 @@ function refuse(error: unknown, err: Writer): number {
291
273
  }
292
274
  return EXIT_FAILURE;
293
275
  }
294
- if (error instanceof ScopeError) {
295
- err.write(`deadset-ts: ${error.message}\n`);
276
+ if (error instanceof ScopeError || error instanceof TargetDocumentError) {
277
+ diagnose(err, error.message);
296
278
  return EXIT_FAILURE;
297
279
  }
298
280
  throw error;