@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/dist/src/roots.js CHANGED
@@ -13,13 +13,15 @@ import { isGlobalBlock } from "./augmentations.js";
13
13
  import { filesNamedBy, outsideChain, relativeSpecifiers, } from "./configuration-files.js";
14
14
  import { conventionEntries } from "./conventions.js";
15
15
  import { entryPoints } from "./entry-points.js";
16
- import { globExpression } from "./glob.js";
17
16
  import { nodeKey } from "./inventory.js";
18
- import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
17
+ import { ancestors, dirnamePath, relativePath, resolvePath } from "./paths.js";
19
18
  import { byPosition } from "./position.js";
20
19
  import { UNANSWERED } from "./query.js";
21
20
  import { sourceFilesOf } from "./source-files.js";
22
21
  import { typeQueryAliases } from "./type-query-alias.js";
22
+ import { bytewise } from "./text/compare.js";
23
+ import { holdsManifest } from "./fs/manifest.js";
24
+ import { globExpression } from "./text/glob.js";
23
25
  /** Whether one declaration is written below the directory of a published workspace member. */
24
26
  function inPublishedMember(held, id, root, members) {
25
27
  const path = held.symbols.find((symbol) => symbol.id === id)?.position.path;
@@ -47,13 +49,8 @@ const OUTPUT_EXTENSION = /\.(?:d\.ts|d\.mts|d\.cts|js|mjs|cjs|jsx)$/u;
47
49
  const SOURCE_EXTENSION = /\.(?:d\.)?[cm]?[jt]sx?$/u;
48
50
  /** Whether no `package.json` sits between one file and the manifest's directory, which holds it. */
49
51
  function ofPackage(host, dir, file) {
50
- for (let at = dirnamePath(file); at !== dir; at = dirnamePath(at)) {
51
- if (relativePath(dir, at) === undefined ||
52
- host.kindOf(joinPath(at, "package.json")) === "file") {
53
- return false;
54
- }
55
- }
56
- return true;
52
+ const between = ancestors(dirnamePath(file), dir);
53
+ return between.length > 0 && !between.slice(0, -1).some((at) => holdsManifest(host, at));
57
54
  }
58
55
  /**
59
56
  * The rooted files one manifest target reads back to by name: its path below the
@@ -163,13 +160,6 @@ export function matchRef(pattern, ref) {
163
160
  }
164
161
  return matchGlob(Array.from(pattern), Array.from(ref));
165
162
  }
166
- /** Two strings ordered bytewise, which is the order every set of a run is read in. */
167
- function compare(a, b) {
168
- if (a === b) {
169
- return 0;
170
- }
171
- return a < b ? -1 : 1;
172
- }
173
163
  /** The members of one declaration, indexed by the container that holds them. */
174
164
  function childrenOf(held) {
175
165
  const byParent = new Map();
@@ -344,7 +334,7 @@ export function roots(project, held, targetRoot, options) {
344
334
  const left = sites.get(a.id);
345
335
  const right = sites.get(b.id);
346
336
  const site = left === undefined || right === undefined ? 0 : byPosition(left, right);
347
- return site || compare(a.kind, b.kind) || compare(a.source, b.source);
337
+ return site || bytewise(a.kind, b.kind) || bytewise(a.source, b.source);
348
338
  });
349
339
  return {
350
340
  liveUnderReachability: ordered,
package/dist/src/run.js CHANGED
@@ -1,9 +1,12 @@
1
+ import { CONFIG_MAX_BYTES, SETTINGS } from "./contract/config.generated.js";
1
2
  import { EXIT_FAILURE, EXIT_USAGE } from "./contract/contract.generated.js";
2
- import { ConfigError, REPOSITORY_DOCUMENT } from "./config.js";
3
+ import { REPOSITORY_DOCUMENT } from "./config.js";
3
4
  import { DiscoveryError, renderDiagnostic } from "./discover.js";
5
+ import { readTargetDocument, TargetDocumentError } from "./fs/document.js";
4
6
  import { joinPath, resolvePath } from "./paths.js";
5
7
  import { readScope, ScopeError, scopeForDir } from "./scope.js";
6
8
  import { SetupError, setupLine } from "./setup-failure.js";
9
+ import { UsageError } from "./usage.js";
7
10
  import { openEngine } from "./session.js";
8
11
  import { printConfigVerb } from "./verbs/print-config.js";
9
12
  import { printProjectsVerb } from "./verbs/print-projects.js";
@@ -14,6 +17,7 @@ import { describeVerb } from "./verbs/describe.js";
14
17
  import { EXPLAIN_OPTIONS, explainVerb } from "./verbs/explain.js";
15
18
  import {} from "./verbs/verb.js";
16
19
  import { versionVerb } from "./verbs/version.js";
20
+ import { diagnose, message, PRODUCT } from "./product.js";
17
21
  /** Every verb this command answers, in the order the usage text lists them. */
18
22
  const VERBS = [
19
23
  { name: "analyze", run: analyzeVerb, options: ANALYZE_OPTIONS },
@@ -25,7 +29,7 @@ const VERBS = [
25
29
  { name: "describe", run: describeVerb },
26
30
  { name: "version", run: versionVerb },
27
31
  ];
28
- const USAGE = `usage: deadset-ts <verb> [options]\nverbs: ${VERBS.map((verb) => verb.name).join(", ")}\n`;
32
+ const USAGE = `usage: ${PRODUCT} <verb> [options]\nverbs: ${VERBS.map((verb) => verb.name).join(", ")}\n`;
29
33
  /**
30
34
  * The tokens whose presence in an option's name makes that option a request to
31
35
  * edit a source file. The set is closed, and a token is matched in any position of
@@ -33,29 +37,12 @@ const USAGE = `usage: deadset-ts <verb> [options]\nverbs: ${VERBS.map((verb) =>
33
37
  */
34
38
  const SOURCE_EDIT_TOKENS = ["fix", "edit", "delete", "rewrite"];
35
39
  /**
36
- * Maps an option name to the setting of the Contract's configuration schema it supplies,
37
- * so one entry registers the option, supplies the document resolution reads, and gives
38
- * the spelling the setting's provenance names. The name is this command's vocabulary and
39
- * is never derived from the path: a setting reaches the command line only by an entry,
40
- * and a path names a key the schema declares.
40
+ * Maps an option name to the setting of the Contract's configuration schema it supplies:
41
+ * the options contract/settings.json names for a setting this analyzer reads.
41
42
  */
42
- export const SETTING_OPTIONS = new Map([
43
- ["min-confidence", "analysis.min_confidence"],
44
- ["sort", "reporters.sort"],
45
- ["cascade", "reporters.cascade"],
46
- ["max-findings", "reporters.max_findings"],
47
- ["fail-on", "reporters.fail_on"],
48
- ]);
43
+ export const SETTING_OPTIONS = new Map(SETTINGS.flatMap((row) => (row.option === undefined ? [] : [[row.option, row.key]])));
49
44
  /** The options that take a value and are not settings. */
50
45
  const PLAIN_OPTIONS = new Set(["target", "config", "central", "scope"]);
51
- /**
52
- * The setting options whose value is an integer rather than a string. A value
53
- * written other than as digits is passed on as the string it is, so resolution
54
- * refuses it by its type rather than reading `1e2` as 100.
55
- */
56
- const INTEGER_OPTIONS = new Set(["max-findings"]);
57
- /** An integer as an option writes it: an optional minus sign and digits alone. */
58
- const INTEGER_TEXT = /^-?[0-9]+$/u;
59
46
  /** No option beyond the ones every verb takes. */
60
47
  const NO_OPTIONS = { plain: [], repeatable: [] };
61
48
  /**
@@ -82,7 +69,7 @@ function readOptions(args, own) {
82
69
  const repeated = new Map();
83
70
  for (const arg of args) {
84
71
  if (!arg.startsWith("-")) {
85
- throw new ConfigError("malformed", "", `unexpected argument ${JSON.stringify(arg)}`);
72
+ throw new UsageError(`unexpected argument ${JSON.stringify(arg)}`);
86
73
  }
87
74
  const [spelled, ...rest] = arg.split("=");
88
75
  const name = (spelled ?? "").replace(/^-+/u, "");
@@ -90,10 +77,10 @@ function readOptions(args, own) {
90
77
  !SETTING_OPTIONS.has(name) &&
91
78
  !own.plain.includes(name) &&
92
79
  !own.repeatable.includes(name)) {
93
- throw new ConfigError("malformed", "", `unknown option ${JSON.stringify(spelled ?? arg)}`);
80
+ throw new UsageError(`unknown option ${JSON.stringify(spelled ?? arg)}`);
94
81
  }
95
82
  if (rest.length === 0) {
96
- throw new ConfigError("malformed", "", `option ${JSON.stringify(spelled ?? arg)} takes a value`);
83
+ throw new UsageError(`option ${JSON.stringify(spelled ?? arg)} takes a value`);
97
84
  }
98
85
  const value = rest.join("=");
99
86
  named.set(name, value);
@@ -101,45 +88,54 @@ function readOptions(args, own) {
101
88
  }
102
89
  return { named, repeated };
103
90
  }
104
- function readFileOr(host, path, orUndefined) {
91
+ /** The document an option names. */
92
+ function documentAt(host, label) {
105
93
  try {
106
- return host.readFile(resolvePath(host.workingDirectory(), path));
94
+ const path = resolvePath(host.workingDirectory(), label);
95
+ // A file past the bound reads as one byte more than it, which resolution refuses.
96
+ return { text: host.readFile(path, CONFIG_MAX_BYTES + 1), label };
107
97
  }
108
98
  catch (error) {
109
- if (orUndefined) {
110
- return undefined;
111
- }
112
- throw new ConfigError("malformed", "", `${path}: ${error instanceof Error ? error.message : String(error)}`);
99
+ throw new UsageError(`${label}: ${message(error)}`);
113
100
  }
114
101
  }
115
102
  /**
116
- * The configuration documents one invocation reads: the repository configuration
117
- * at the target root or the path an option named, the central configuration, and
118
- * the settings the options supply as one flag document.
103
+ * The repository configuration at the target root, none where it is absent. One that
104
+ * cannot be read is a configuration document that cannot be, refused with the usage code.
105
+ */
106
+ function repositoryAt(host, target) {
107
+ const label = joinPath(target, REPOSITORY_DOCUMENT);
108
+ const root = resolvePath(host.workingDirectory(), target);
109
+ try {
110
+ const text = readTargetDocument(host, root, REPOSITORY_DOCUMENT, label);
111
+ return text === undefined ? undefined : { text, label };
112
+ }
113
+ catch (error) {
114
+ throw error instanceof TargetDocumentError ? new UsageError(error.message) : error;
115
+ }
116
+ }
117
+ /**
118
+ * The configuration sources one invocation carries: the repository configuration at
119
+ * the target root or the path an option named, the central configuration, and the
120
+ * text each setting option was given.
119
121
  */
120
122
  function inputsOf(host, options) {
121
- const target = options.named.get("target") ?? ".";
122
123
  const named = options.named.get("config");
123
- const repositoryLabel = named ?? joinPath(target, REPOSITORY_DOCUMENT);
124
- const repository = readFileOr(host, repositoryLabel, named === undefined);
124
+ const target = options.named.get("target") ?? ".";
125
+ const repository = named === undefined ? repositoryAt(host, target) : documentAt(host, named);
125
126
  const centralLabel = options.named.get("central");
126
- const central = centralLabel === undefined ? undefined : readFileOr(host, centralLabel, false);
127
- const flat = {};
128
- const flagLabels = new Map();
129
- for (const [name, path] of SETTING_OPTIONS) {
127
+ const central = centralLabel === undefined ? undefined : documentAt(host, centralLabel);
128
+ const flags = new Map();
129
+ for (const [name, key] of SETTING_OPTIONS) {
130
130
  const value = options.named.get(name);
131
- if (value === undefined) {
132
- continue;
131
+ if (value !== undefined) {
132
+ flags.set(key, value);
133
133
  }
134
- flat[path] = INTEGER_OPTIONS.has(name) && INTEGER_TEXT.test(value) ? Number(value) : value;
135
- flagLabels.set(path, `--${name}`);
136
134
  }
137
- const flags = Object.keys(flat).length === 0 ? undefined : JSON.stringify(flat);
138
135
  return {
139
- ...(flags === undefined ? {} : { flags }),
140
- ...(repository === undefined ? {} : { repository, repositoryLabel }),
141
- ...(central === undefined || centralLabel === undefined ? {} : { central, centralLabel }),
142
- flagLabels,
136
+ flags,
137
+ ...(repository === undefined ? {} : { repository }),
138
+ ...(central === undefined ? {} : { central }),
143
139
  };
144
140
  }
145
141
  /** The scope one invocation analyzes: the document an option named, or the target. */
@@ -155,14 +151,12 @@ function scopeOf(host, options) {
155
151
  * the exit code: 0 for a completed verb, 1 for a finding that fails the run, 2 for a
156
152
  * usage error, a requested source edit or a refused configuration, 3 for a failure that
157
153
  * produced no answer. It writes nothing outside `out` and `err` and never exits the
158
- * process. `host` is the platform the run reads, the version it reports included, and
159
- * `openClient` opens the compiler client; a caller that watches what a run reads
160
- * supplies its own of either.
154
+ * process. A caller that watches what a run reads supplies its own `host` or `openClient`.
161
155
  */
162
156
  export function run(args, out, err, host, openClient = openEngine) {
163
157
  const editing = sourceEditOption(args);
164
158
  if (editing !== undefined) {
165
- err.write(`deadset-ts: ${editing} is not supported: deadset-ts reports and never edits a source file\n`);
159
+ diagnose(err, `${editing} is not supported: ${PRODUCT} reports and never edits a source file`);
166
160
  err.write(USAGE);
167
161
  return EXIT_USAGE;
168
162
  }
@@ -172,7 +166,7 @@ export function run(args, out, err, host, openClient = openEngine) {
172
166
  return invoke(verb.run, verb.options ?? NO_OPTIONS, args.slice(1), { out, err, host }, openClient);
173
167
  }
174
168
  if (name !== undefined) {
175
- err.write(`deadset-ts: unknown verb ${JSON.stringify(name)}\n`);
169
+ diagnose(err, `unknown verb ${JSON.stringify(name)}`);
176
170
  }
177
171
  err.write(USAGE);
178
172
  return EXIT_USAGE;
@@ -197,7 +191,7 @@ function invoke(verb, own, args, streams, openClient) {
197
191
  openClient: (config) => {
198
192
  opened = openClient({
199
193
  collectTiming: false,
200
- components: { extensions: config.ts.componentExtensions, host: streams.host },
194
+ components: { extensions: config.ts.component_extensions, host: streams.host },
201
195
  });
202
196
  return opened;
203
197
  },
@@ -210,8 +204,8 @@ function invoke(verb, own, args, streams, openClient) {
210
204
  }
211
205
  /** Turns one refusal into the exit code the Contract's table gives it. */
212
206
  function refuse(error, err) {
213
- if (error instanceof ConfigError) {
214
- err.write(`deadset-ts: ${error.message}\n`);
207
+ if (error instanceof UsageError) {
208
+ diagnose(err, error.message);
215
209
  err.write(USAGE);
216
210
  return EXIT_USAGE;
217
211
  }
@@ -219,7 +213,7 @@ function refuse(error, err) {
219
213
  for (const diagnostic of error.diagnostics) {
220
214
  err.write(`${renderDiagnostic(diagnostic)}\n`);
221
215
  }
222
- err.write(`deadset-ts: ${error.message}\n`);
216
+ diagnose(err, error.message);
223
217
  return EXIT_FAILURE;
224
218
  }
225
219
  if (error instanceof SetupError) {
@@ -228,8 +222,8 @@ function refuse(error, err) {
228
222
  }
229
223
  return EXIT_FAILURE;
230
224
  }
231
- if (error instanceof ScopeError) {
232
- err.write(`deadset-ts: ${error.message}\n`);
225
+ if (error instanceof ScopeError || error instanceof TargetDocumentError) {
226
+ diagnose(err, error.message);
233
227
  return EXIT_FAILURE;
234
228
  }
235
229
  throw error;