@aventara/client 0.1.0-pilot.1 → 0.1.0-pilot.2

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 (79) hide show
  1. package/README.md +41 -7
  2. package/dist/avclient.bin.js +0 -10
  3. package/dist/cli/command.parser.d.ts +15 -10
  4. package/dist/cli/command.parser.js +13 -19
  5. package/dist/cli/generate.command.js +0 -6
  6. package/dist/cli/generation-failure.renderer.js +0 -14
  7. package/dist/cli/generation-success.renderer.d.ts +4 -1
  8. package/dist/cli/generation-success.renderer.js +0 -13
  9. package/dist/cli/terminal.prompter.d.ts +1 -2
  10. package/dist/cli/warning.renderer.d.ts +2 -2
  11. package/dist/cli/warning.renderer.js +0 -8
  12. package/dist/cli.d.ts +8 -16
  13. package/dist/cli.js +5 -25
  14. package/dist/config/client-config.interface.d.ts +18 -16
  15. package/dist/config/client-config.interface.js +0 -13
  16. package/dist/config/config.loader.d.ts +34 -22
  17. package/dist/config/config.loader.js +49 -52
  18. package/dist/config/config.resolver.d.ts +13 -19
  19. package/dist/config/config.resolver.js +9 -48
  20. package/dist/config/env.cascade.d.ts +12 -14
  21. package/dist/config/env.cascade.js +0 -19
  22. package/dist/config/module-style.resolver.d.ts +52 -0
  23. package/dist/config/module-style.resolver.js +75 -0
  24. package/dist/config/tsconfig.locator.d.ts +45 -0
  25. package/dist/config/tsconfig.locator.js +52 -0
  26. package/dist/contract/contract.acceptance.d.ts +12 -26
  27. package/dist/contract/contract.acceptance.js +0 -54
  28. package/dist/contract/contract.fetcher.d.ts +12 -17
  29. package/dist/contract/contract.fetcher.js +0 -24
  30. package/dist/contract/contract.loader.d.ts +4 -5
  31. package/dist/contract/contract.loader.js +0 -10
  32. package/dist/emit/banner.emitter.d.ts +11 -12
  33. package/dist/emit/banner.emitter.js +0 -26
  34. package/dist/emit/client-surface.emitter.d.ts +17 -21
  35. package/dist/emit/client-surface.emitter.js +29 -55
  36. package/dist/emit/client-tree.emitter.d.ts +11 -20
  37. package/dist/emit/client-tree.emitter.js +12 -54
  38. package/dist/emit/contract-carrier.emitter.d.ts +5 -6
  39. package/dist/emit/contract-carrier.emitter.js +0 -28
  40. package/dist/emit/derivation.emitter.d.ts +7 -7
  41. package/dist/emit/derivation.emitter.js +2 -161
  42. package/dist/emit/descriptor.emitter.js +2 -28
  43. package/dist/emit/emitted-tree.interface.d.ts +40 -17
  44. package/dist/emit/emitted-tree.interface.js +6 -16
  45. package/dist/emit/enum.emitter.d.ts +4 -4
  46. package/dist/emit/enum.emitter.js +0 -24
  47. package/dist/emit/module-specifier.scanner.d.ts +25 -0
  48. package/dist/emit/module-specifier.scanner.js +160 -0
  49. package/dist/emit/module-style.interface.d.ts +58 -0
  50. package/dist/emit/module-style.interface.js +8 -0
  51. package/dist/emit/name.deriver.d.ts +33 -61
  52. package/dist/emit/name.deriver.js +0 -134
  53. package/dist/emit/named-type.emitter.d.ts +14 -21
  54. package/dist/emit/named-type.emitter.js +3 -30
  55. package/dist/emit/runtime.emitter.d.ts +23 -50
  56. package/dist/emit/runtime.emitter.js +68 -159
  57. package/dist/emit/scalar.codec.d.ts +20 -33
  58. package/dist/emit/scalar.codec.js +13 -69
  59. package/dist/emit/transaction.emitter.d.ts +6 -14
  60. package/dist/emit/transaction.emitter.js +24 -33
  61. package/dist/generate.d.ts +17 -34
  62. package/dist/generate.js +14 -22
  63. package/dist/index.js +0 -5
  64. package/dist/init/client-config.template.d.ts +6 -4
  65. package/dist/init/client-config.template.js +10 -13
  66. package/dist/init/client-init.errors.js +0 -3
  67. package/dist/init/client-init.orchestrator.js +1 -9
  68. package/dist/init/client-init.planner.d.ts +1 -9
  69. package/dist/init/client-init.planner.js +6 -24
  70. package/dist/init/client-init.questions.d.ts +8 -12
  71. package/dist/init/client-init.questions.js +0 -11
  72. package/dist/init/client-project.inspector.d.ts +6 -0
  73. package/dist/init/client-project.inspector.js +2 -2
  74. package/dist/node-version.guard.js +0 -12
  75. package/dist/output/output.validator.d.ts +22 -22
  76. package/dist/output/output.validator.js +46 -59
  77. package/dist/output/output.writer.d.ts +56 -52
  78. package/dist/output/output.writer.js +71 -133
  79. package/package.json +6 -4
@@ -2,24 +2,17 @@ import { randomBytes } from "node:crypto";
2
2
  import * as fsPromises from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { carriesGeneratedOwnership, GENERATED_OWNERSHIP_HEAD_BYTES, } from "../emit/banner.emitter.js";
5
- import { CLIENT_ENTRY_FILE, GENERATED_DIRECTORY, } from "../emit/emitted-tree.interface.js";
5
+ import { CLIENT_ENTRY_FILES, GENERATED_DIRECTORY, LEGACY_CLIENT_ENTRY_FILES, } from "../emit/emitted-tree.interface.js";
6
6
  import { resolveInstalledTypeScript, validateOutputTree, } from "./output.validator.js";
7
- /** A write that stopped; the previous output is intact unless it says otherwise. */
8
7
  export class OutputWriteError extends Error {
9
8
  stage;
10
9
  name = "OutputWriteError";
11
- /**
12
- * What the run said before it stopped, in the order a success returns its
13
- * warnings: the emission's, the validator's, the writer's. Printed before the
14
- * refusal's sentence.
15
- */
16
10
  warnings;
17
11
  constructor(stage, message, options) {
18
12
  super(message, options);
19
13
  this.stage = stage;
20
14
  this.warnings = options?.warnings ?? [];
21
15
  }
22
- /** The same refusal, with `earlier` said before the warnings it already carries. */
23
16
  precededBy(earlier) {
24
17
  return new OutputWriteError(this.stage, this.message, {
25
18
  cause: this.cause,
@@ -27,18 +20,7 @@ export class OutputWriteError extends Error {
27
20
  });
28
21
  }
29
22
  }
30
- /**
31
- * What a run said before a defect stopped it, kept beside the defect rather than
32
- * on a wrapper: a defect propagates as the very error thrown, with its own stack,
33
- * so a caller matching it by identity or type still can. Keyed weakly, so it
34
- * lives exactly as long as the error does. A thrown primitive cannot be a key;
35
- * what was said before one is not kept.
36
- */
37
23
  const WARNINGS_BEFORE_DEFECT = new WeakMap();
38
- /**
39
- * Records `earlier` as said before `defect`, ahead of anything already recorded,
40
- * and returns `defect` unchanged so the caller rethrows the same error.
41
- */
42
24
  export function precedeDefect(defect, earlier) {
43
25
  if (earlier.length > 0 && typeof defect === "object" && defect !== null) {
44
26
  WARNINGS_BEFORE_DEFECT.set(defect, [
@@ -48,10 +30,6 @@ export function precedeDefect(defect, earlier) {
48
30
  }
49
31
  return defect;
50
32
  }
51
- /**
52
- * What the run said before `defect` stopped it, in the order a success returns
53
- * its warnings; empty when nothing was, or for an error no run threw.
54
- */
55
33
  export function warningsRaisedBeforeDefect(defect) {
56
34
  return typeof defect === "object" && defect !== null
57
35
  ? (WARNINGS_BEFORE_DEFECT.get(defect) ?? [])
@@ -60,23 +38,20 @@ export function warningsRaisedBeforeDefect(defect) {
60
38
  const NEXT_PREFIX = ".aventara-next-";
61
39
  const READY_PREFIX = ".aventara-ready-";
62
40
  const PREVIOUS_GENERATED = `.${GENERATED_DIRECTORY}.aventara-previous`;
63
- /**
64
- * Writes `emission.tree` as `<generateAt>/AvClient.ts` and `<generateAt>/generated/`.
65
- *
66
- * @throws OutputWriteError when the write stops; the previous output is intact.
67
- */
68
- export async function writeClientOutput(input) {
69
- const fs = input.fileSystem ?? fsPromises;
70
- const generateAt = path.resolve(input.generateAt);
71
- const paths = {
41
+ const PREVIOUS_ENTRIES = ".previous-entries";
42
+ function outputPathsOf(generateAt) {
43
+ return {
72
44
  generateAt,
73
45
  generated: path.join(generateAt, GENERATED_DIRECTORY),
74
- entry: path.join(generateAt, CLIENT_ENTRY_FILE),
75
46
  previous: path.join(generateAt, PREVIOUS_GENERATED),
76
47
  };
48
+ }
49
+ export async function writeClientOutput(input) {
50
+ const fs = input.fileSystem ?? fsPromises;
51
+ const generateAt = path.resolve(input.generateAt);
52
+ const paths = outputPathsOf(generateAt);
77
53
  const writerWarnings = [];
78
54
  let validationWarnings = [];
79
- /** The outermost directory this run created on the way to `generateAt`, if any. */
80
55
  let created;
81
56
  try {
82
57
  return await writeStagedOutput();
@@ -95,7 +70,6 @@ export async function writeClientOutput(input) {
95
70
  : precedeDefect(error, said);
96
71
  }
97
72
  async function writeStagedOutput() {
98
- // prepare — recover a killed run, then decide whether the two entries are ours.
99
73
  const state = await stage("prepare", paths, async () => {
100
74
  created = await ensureDirectory(fs, generateAt);
101
75
  writerWarnings.push(...(await recoverInterruptedRun(fs, paths)));
@@ -107,14 +81,11 @@ export async function writeClientOutput(input) {
107
81
  }
108
82
  return inspection;
109
83
  });
110
- // temp — the whole tree, AvClient.ts and generated/ together, staged in generateAt.
111
84
  const suffix = randomBytes(6).toString("hex");
112
85
  let staging = path.join(generateAt, `${NEXT_PREFIX}${suffix}`);
113
86
  let stagingExists = false;
114
87
  try {
115
88
  await stage("temp", paths, async () => {
116
- // `mkdir`, not `mkdtemp`: generated/ is moved out of this directory and
117
- // takes the mode any directory the user creates takes (`mkdtemp` makes 0700).
118
89
  await fs.mkdir(staging);
119
90
  stagingExists = true;
120
91
  for (const file of input.emission.tree) {
@@ -123,8 +94,7 @@ export async function writeClientOutput(input) {
123
94
  await fs.writeFile(target, file.bytes);
124
95
  }
125
96
  });
126
- // validate — Q6, over AvClient.ts and generated/ as one program.
127
- const validation = await stage("validate", paths, () => validateOutputTree(staging, input.emission.tree, input.resolveTypeScript ?? resolveInstalledTypeScript));
97
+ const validation = await stage("validate", paths, () => validateOutputTree(staging, input.emission, input.resolveTypeScript ?? resolveInstalledTypeScript));
128
98
  if (validation.accepted) {
129
99
  validationWarnings = validation.warnings;
130
100
  }
@@ -133,7 +103,6 @@ export async function writeClientOutput(input) {
133
103
  "This is a defect in @aventara/client; please report it with these findings:\n" +
134
104
  validation.findings.map((finding) => ` ${finding}`).join("\n"));
135
105
  }
136
- // replace — the order and its rollbacks are the module doc's.
137
106
  await stage("replace", paths, async () => {
138
107
  const ready = path.join(generateAt, `${READY_PREFIX}${suffix}`);
139
108
  await fs.rename(staging, ready);
@@ -151,11 +120,28 @@ export async function writeClientOutput(input) {
151
120
  }
152
121
  throw error;
153
122
  }
123
+ const aside = path.join(staging, PREVIOUS_ENTRIES);
124
+ const movedOut = [];
125
+ const movedIn = [];
154
126
  try {
155
- await fs.rename(path.join(staging, CLIENT_ENTRY_FILE), paths.entry);
127
+ await fs.mkdir(aside);
128
+ for (const name of [...state.entries, ...state.legacy]) {
129
+ await fs.rename(path.join(generateAt, name), path.join(aside, name));
130
+ movedOut.push(name);
131
+ }
132
+ for (const name of CLIENT_ENTRY_FILES) {
133
+ await fs.rename(path.join(staging, name), path.join(generateAt, name));
134
+ movedIn.push(name);
135
+ }
156
136
  }
157
137
  catch (error) {
158
138
  await rollBack(paths, error, async () => {
139
+ for (const name of movedIn.reverse()) {
140
+ await fs.rename(path.join(generateAt, name), path.join(staging, name));
141
+ }
142
+ for (const name of movedOut.reverse()) {
143
+ await fs.rename(path.join(aside, name), path.join(generateAt, name));
144
+ }
159
145
  await fs.rename(paths.generated, path.join(staging, GENERATED_DIRECTORY));
160
146
  if (movedAside) {
161
147
  await fs.rename(paths.previous, paths.generated);
@@ -186,23 +172,14 @@ export async function writeClientOutput(input) {
186
172
  finally {
187
173
  if (stagingExists) {
188
174
  await fs.rm(staging, { recursive: true, force: true }).catch(() => {
189
- // The next run removes it by name; the error being thrown matters more.
190
175
  });
191
176
  }
192
177
  }
193
178
  }
194
179
  }
195
- /** The sentence's ending when the previous output was not changed. */
196
180
  function LEFT_AS_THEY_WERE(paths) {
197
- return `${CLIENT_ENTRY_FILE} and ${GENERATED_DIRECTORY}/ in ${paths.generateAt} were left exactly as they were.`;
181
+ return `${CLIENT_ENTRY_FILES.join(", ")} and ${GENERATED_DIRECTORY}/ in ${paths.generateAt} were left exactly as they were.`;
198
182
  }
199
- /**
200
- * Creates `generateAt` when missing; refuses when something other than a
201
- * directory is there.
202
- *
203
- * @returns the outermost directory it created — `generateAt` or an ancestor —
204
- * or `undefined` when `generateAt` already existed.
205
- */
206
183
  async function ensureDirectory(fs, generateAt) {
207
184
  const stats = await lstatOrUndefined(fs, generateAt);
208
185
  if (stats === undefined) {
@@ -213,12 +190,6 @@ async function ensureDirectory(fs, generateAt) {
213
190
  }
214
191
  return undefined;
215
192
  }
216
- /**
217
- * Removes, after a failed run, the directories it created: `generateAt` and each
218
- * parent up to `outermost`, innermost first. `rmdir` removes only an empty
219
- * directory, so nothing anyone else put there meanwhile is lost; the first one
220
- * that cannot be removed ends the walk, and is named in the warning returned.
221
- */
222
193
  async function removeCreatedDirectories(fs, generateAt, outermost) {
223
194
  for (let directory = generateAt;; directory = path.dirname(directory)) {
224
195
  try {
@@ -235,29 +206,23 @@ async function removeCreatedDirectories(fs, generateAt, outermost) {
235
206
  }
236
207
  }
237
208
  }
238
- /**
239
- * Leftovers of a run that was killed, recognised only by the names this writer
240
- * gives them:
241
- *
242
- * - a staging directory that never became ready was not validated: removed;
243
- * - a ready one whose `generated/` was already moved in but whose `AvClient.ts`
244
- * was not: its `AvClient.ts` is moved in, completing the new pair;
245
- * - any other ready one: removed;
246
- * - a previous `generated/` moved aside: put back when nothing replaced it,
247
- * removed when something did.
248
- */
249
209
  async function recoverInterruptedRun(fs, paths) {
250
210
  const warnings = [];
251
211
  for (const entry of (await fs.readdir(paths.generateAt)).sort()) {
252
212
  const leftover = path.join(paths.generateAt, entry);
253
213
  if (entry.startsWith(READY_PREFIX)) {
254
- const stagedEntry = path.join(leftover, CLIENT_ENTRY_FILE);
255
214
  const generatedMovedIn = (await lstatOrUndefined(fs, path.join(leftover, GENERATED_DIRECTORY))) === undefined;
256
- if (generatedMovedIn &&
257
- (await lstatOrUndefined(fs, stagedEntry)) !== undefined) {
258
- await fs.rename(stagedEntry, paths.entry);
259
- warnings.push(`an interrupted run had moved its generated/ in but not its AvClient.ts; ` +
260
- `the validated AvClient.ts was moved in at ${paths.entry} before generating.`);
215
+ const completed = [];
216
+ for (const name of generatedMovedIn ? CLIENT_ENTRY_FILES : []) {
217
+ const staged = path.join(leftover, name);
218
+ if ((await lstatOrUndefined(fs, staged)) !== undefined) {
219
+ await fs.rename(staged, path.join(paths.generateAt, name));
220
+ completed.push(name);
221
+ }
222
+ }
223
+ if (completed.length > 0) {
224
+ warnings.push(`an interrupted run had moved its generated/ in but not all of its entry files; ` +
225
+ `the validated ${completed.join(", ")} ${completed.length === 1 ? "was" : "were"} moved in at ${paths.generateAt} before generating.`);
261
226
  }
262
227
  await fs.rm(leftover, { recursive: true, force: true });
263
228
  }
@@ -277,35 +242,12 @@ async function recoverInterruptedRun(fs, paths) {
277
242
  }
278
243
  return warnings;
279
244
  }
280
- /**
281
- * Where the `generated/` a run works with comes from once a killed run is
282
- * recovered: the previous one moved aside when nothing replaced it — recovery
283
- * puts it back — and `generated/` otherwise. One answer for the recovery and for
284
- * the read-only look ahead of it, so the two cannot disagree.
285
- */
286
245
  async function generatedAfterRecovery(fs, paths) {
287
246
  return (await lstatOrUndefined(fs, paths.generated)) === undefined &&
288
247
  (await lstatOrUndefined(fs, paths.previous)) !== undefined
289
248
  ? paths.previous
290
249
  : paths.generated;
291
250
  }
292
- /**
293
- * Lists what in `<generateAt>/AvClient.ts` and `<generateAt>/generated/` the
294
- * generator did not produce — a file without the ownership line, a symbolic link,
295
- * anything that is not a regular file — so the person running it can be asked
296
- * before a generation overwrites or removes it (architect, 2026-10-04). Reads
297
- * only; looks at nothing else in `generateAt`. Empty when `generateAt` does not
298
- * exist yet.
299
- *
300
- * It sees what the write will see once it has recovered a killed run, without
301
- * recovering it: a `generated/` the killed run moved aside with nothing in its
302
- * place is read where it lies and its files named where recovery puts them back
303
- * (`generated/…`). So the question asked, and `--yes`, cover them too — and a
304
- * run that stops here has still touched nothing.
305
- *
306
- * @throws OutputWriteError when `generateAt` is not a directory, `generated` is
307
- * not a directory or `AvClient.ts` is not a file: no confirmation repairs that.
308
- */
309
251
  export async function findForeignOutputContent(generateAt, fileSystem = fsPromises) {
310
252
  const root = path.resolve(generateAt);
311
253
  const stats = await lstatOrUndefined(fileSystem, root);
@@ -315,21 +257,10 @@ export async function findForeignOutputContent(generateAt, fileSystem = fsPromis
315
257
  if (!stats.isDirectory()) {
316
258
  throw notADirectory(root);
317
259
  }
318
- const paths = {
319
- generateAt: root,
320
- generated: path.join(root, GENERATED_DIRECTORY),
321
- entry: path.join(root, CLIENT_ENTRY_FILE),
322
- previous: path.join(root, PREVIOUS_GENERATED),
323
- };
260
+ const paths = outputPathsOf(root);
324
261
  const inspection = await inspectOwnedEntries(fileSystem, paths, await generatedAfterRecovery(fileSystem, paths));
325
262
  return inspection.foreign;
326
263
  }
327
- /**
328
- * What stands at the two owned entries. `generatedSource` is the directory read
329
- * as `generated/` — `generated/` itself, or the previous one a killed run moved
330
- * aside, which recovery will put back there — and its files are named as
331
- * `generated/…` either way.
332
- */
333
264
  async function inspectOwnedEntries(fs, paths, generatedSource = paths.generated) {
334
265
  const foreign = [];
335
266
  const relative = (file) => path.relative(paths.generateAt, file).split(path.sep).join("/");
@@ -353,23 +284,37 @@ async function inspectOwnedEntries(fs, paths, generatedSource = paths.generated)
353
284
  }
354
285
  }
355
286
  }
356
- const entryStats = await lstatOrUndefined(fs, paths.entry);
357
- if (entryStats !== undefined) {
358
- if (!entryStats.isFile()) {
359
- throw new OutputWriteError("prepare", `refusing to replace ${paths.entry}: it is not a file, and the generator owns ${CLIENT_ENTRY_FILE} ` +
287
+ const entries = [];
288
+ for (const name of CLIENT_ENTRY_FILES) {
289
+ const file = path.join(paths.generateAt, name);
290
+ const stats = await lstatOrUndefined(fs, file);
291
+ if (stats === undefined) {
292
+ continue;
293
+ }
294
+ if (!stats.isFile()) {
295
+ throw new OutputWriteError("prepare", `refusing to replace ${file}: it is not a file, and the generator owns ${name} ` +
360
296
  "as one; move it, or choose another `generateAt`. Nothing was written.");
361
297
  }
362
- if (!(await carriesOwnershipLine(fs, paths.entry))) {
363
- foreign.push(relative(paths.entry));
298
+ entries.push(name);
299
+ if (!(await carriesOwnershipLine(fs, file))) {
300
+ foreign.push(relative(file));
301
+ }
302
+ }
303
+ const legacy = [];
304
+ for (const name of LEGACY_CLIENT_ENTRY_FILES) {
305
+ const file = path.join(paths.generateAt, name);
306
+ if ((await lstatOrUndefined(fs, file))?.isFile() === true &&
307
+ (await carriesOwnershipLine(fs, file))) {
308
+ legacy.push(name);
364
309
  }
365
310
  }
366
311
  return {
367
312
  generated: generatedStats === undefined ? "absent" : "present",
368
- entry: entryStats === undefined ? "absent" : "present",
313
+ entries,
314
+ legacy,
369
315
  foreign: foreign.sort(),
370
316
  };
371
317
  }
372
- /** Foreign content nobody confirmed may be overwritten. */
373
318
  function foreignContentRefusal(paths, foreign) {
374
319
  const them = foreign.length === 1 ? "it" : "them";
375
320
  return new OutputWriteError("prepare", `refusing to generate into ${paths.generateAt}: ${foreign.join(", ")} ${foreign.length === 1 ? "was" : "were"} ` +
@@ -391,10 +336,6 @@ async function carriesOwnershipLine(fs, file) {
391
336
  await handle.close();
392
337
  }
393
338
  }
394
- /**
395
- * Undoes a replace that stopped part-way. When the undo itself fails, the
396
- * sentence says where the previous `generated/` is: the next run puts it back.
397
- */
398
339
  async function rollBack(paths, cause, undo) {
399
340
  try {
400
341
  await undo();
@@ -405,11 +346,6 @@ async function rollBack(paths, cause, undo) {
405
346
  `${GENERATED_DIRECTORY}/ is intact at ${paths.previous}; the next run puts it back.`, { cause });
406
347
  }
407
348
  }
408
- /**
409
- * Runs one stage, turning a filesystem error into that stage's sentence. An
410
- * `OutputWriteError` passes through; anything without a `code` is a defect and
411
- * keeps its stack.
412
- */
413
349
  async function stage(name, paths, run) {
414
350
  try {
415
351
  return await run();
@@ -447,16 +383,18 @@ function describe(error) {
447
383
  ? `${error.code}: ${error.message}`
448
384
  : String(error);
449
385
  }
450
- /**
451
- * Whether `AvClient.ts` and `generated/` in `generateAt` hold exactly `tree` —
452
- * every file byte for byte, no other file, and nothing a killed run moved aside —
453
- * so that writing `tree` would change nothing (Phase 12-rest Q6: "up to date").
454
- */
455
386
  export async function ownedOutputMatches(generateAt, tree) {
456
387
  const root = path.resolve(generateAt);
457
388
  if ((await lstatOrUndefined(fsPromises, path.join(root, PREVIOUS_GENERATED))) !== undefined) {
458
389
  return false;
459
390
  }
391
+ for (const name of LEGACY_CLIENT_ENTRY_FILES) {
392
+ const file = path.join(root, name);
393
+ if ((await lstatOrUndefined(fsPromises, file))?.isFile() === true &&
394
+ (await carriesOwnershipLine(fsPromises, file))) {
395
+ return false;
396
+ }
397
+ }
460
398
  let present;
461
399
  try {
462
400
  present = (await fsPromises.readdir(path.join(root, GENERATED_DIRECTORY), {
@@ -476,7 +414,7 @@ export async function ownedOutputMatches(generateAt, tree) {
476
414
  throw error;
477
415
  }
478
416
  const expected = new Set(tree.map((file) => file.path));
479
- if (present.length + 1 !== expected.size ||
417
+ if (present.length + CLIENT_ENTRY_FILES.length !== expected.size ||
480
418
  present.some((file) => !expected.has(file))) {
481
419
  return false;
482
420
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aventara/client",
3
- "version": "0.1.0-pilot.1",
3
+ "version": "0.1.0-pilot.2",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Development-time generator for Aventara typed remote clients.",
6
6
  "type": "module",
@@ -23,7 +23,9 @@
23
23
  "LICENSE-ADDITIONAL-PERMISSION.md"
24
24
  ],
25
25
  "dependencies": {
26
- "@aventara/core": "0.1.0-pilot.1"
26
+ "@aventara/core": "0.1.0-pilot.2",
27
+ "c12": "3.3.4",
28
+ "get-tsconfig": "4.10.0"
27
29
  },
28
30
  "peerDependencies": {
29
31
  "typescript": ">=5.5.0"
@@ -37,12 +39,12 @@
37
39
  "access": "public"
38
40
  },
39
41
  "devDependencies": {
40
- "@aventara/testing": "0.1.0-pilot.1",
42
+ "@aventara/testing": "0.1.0-pilot.2",
41
43
  "@types/node": "24.10.1",
42
44
  "typescript": "^5.9.2"
43
45
  },
44
46
  "scripts": {
45
- "build": "tsc -p tsconfig.json",
47
+ "build": "tsc -p tsconfig.json --removeComments --declaration false && tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/build/declaration-comments.sanitizer.ts dist",
46
48
  "typecheck": "tsc -p tsconfig.typecheck.json --noEmit",
47
49
  "test": "vitest run --typecheck --config ../../vitest.config.mts --root .",
48
50
  "lint": "biome lint src"