@aventara/client 1.0.0-rc.0 → 1.0.0-rc.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 (58) hide show
  1. package/CHANGELOG.md +504 -0
  2. package/README.md +159 -141
  3. package/dist/cli/command.parser.d.ts +5 -5
  4. package/dist/cli/command.parser.js +13 -13
  5. package/dist/cli/generation-failure.renderer.js +24 -24
  6. package/dist/config/client-config.interface.d.ts +7 -7
  7. package/dist/config/config.loader.d.ts +10 -4
  8. package/dist/config/config.loader.js +16 -7
  9. package/dist/config/config.resolver.d.ts +7 -7
  10. package/dist/config/config.resolver.js +12 -12
  11. package/dist/config/env.cascade.d.ts +2 -2
  12. package/dist/config/env.cascade.js +4 -4
  13. package/dist/config/module-style.resolver.d.ts +1 -1
  14. package/dist/config/module-style.resolver.js +2 -2
  15. package/dist/config/tsconfig.locator.d.ts +1 -1
  16. package/dist/config/tsconfig.locator.js +2 -2
  17. package/dist/contract/contract.acceptance.d.ts +4 -4
  18. package/dist/contract/contract.acceptance.js +4 -4
  19. package/dist/contract/contract.fetcher.d.ts +3 -3
  20. package/dist/contract/contract.fetcher.js +6 -6
  21. package/dist/contract/contract.loader.d.ts +6 -6
  22. package/dist/contract/contract.loader.js +2 -2
  23. package/dist/emit/client-surface.emitter.d.ts +2 -2
  24. package/dist/emit/client-surface.emitter.js +61 -40
  25. package/dist/emit/client-tree.emitter.d.ts +3 -3
  26. package/dist/emit/client-tree.emitter.js +8 -5
  27. package/dist/emit/contract-carrier.emitter.d.ts +3 -3
  28. package/dist/emit/derivation.emitter.js +1 -0
  29. package/dist/emit/descriptor.emitter.d.ts +2 -2
  30. package/dist/emit/descriptor.emitter.js +1 -1
  31. package/dist/emit/emitted-tree.interface.d.ts +1 -1
  32. package/dist/emit/enum.emitter.d.ts +2 -2
  33. package/dist/emit/field-check.emitter.d.ts +21 -0
  34. package/dist/emit/field-check.emitter.js +592 -0
  35. package/dist/emit/json-shape.emitter.d.ts +2 -2
  36. package/dist/emit/name.deriver.d.ts +6 -6
  37. package/dist/emit/name.deriver.js +14 -14
  38. package/dist/emit/named-type.emitter.d.ts +2 -2
  39. package/dist/emit/runtime.emitter.d.ts +2 -2
  40. package/dist/emit/runtime.emitter.js +166 -112
  41. package/dist/emit/scalar.codec.d.ts +1 -1
  42. package/dist/emit/scalar.codec.js +246 -29
  43. package/dist/emit/transaction.emitter.js +30 -14
  44. package/dist/generate.d.ts +2 -2
  45. package/dist/generate.js +2 -2
  46. package/dist/index.d.ts +1 -1
  47. package/dist/init/client-init.errors.d.ts +4 -4
  48. package/dist/init/client-init.errors.js +4 -4
  49. package/dist/init/client-init.orchestrator.js +7 -7
  50. package/dist/init/client-init.questions.d.ts +5 -5
  51. package/dist/init/client-init.questions.js +10 -10
  52. package/dist/init/client-project.inspector.d.ts +2 -2
  53. package/dist/init/client-project.inspector.js +3 -3
  54. package/dist/output/output.validator.d.ts +3 -4
  55. package/dist/output/output.validator.js +2 -2
  56. package/dist/output/output.writer.d.ts +5 -5
  57. package/dist/output/output.writer.js +12 -12
  58. package/package.json +4 -4
@@ -1,10 +1,10 @@
1
1
  import { resolveEntrypoint } from "../config/config.resolver.js";
2
2
  export const PACKAGE_MANAGERS = ["npm", "pnpm"];
3
- export class ClientInitAnswerError extends Error {
4
- name = "ClientInitAnswerError";
3
+ export class AvClientInitAnswerError extends Error {
4
+ name = "AvClientInitAnswerError";
5
5
  }
6
- export class ClientInitUnansweredError extends Error {
7
- name = "ClientInitUnansweredError";
6
+ export class AvClientInitUnansweredError extends Error {
7
+ name = "AvClientInitUnansweredError";
8
8
  }
9
9
  export const DEFAULT_ENV_VAR = "AVENTARA_API_URL";
10
10
  export const CLIENT_INIT_QUESTIONS = [
@@ -19,7 +19,7 @@ export const CLIENT_INIT_QUESTIONS = [
19
19
  resolveEntrypoint(raw.trim());
20
20
  }
21
21
  catch (error) {
22
- throw new ClientInitAnswerError(error.message.replace(/\.$/, ""));
22
+ throw new AvClientInitAnswerError(error.message.replace(/\.$/, ""));
23
23
  }
24
24
  return raw.trim();
25
25
  },
@@ -33,7 +33,7 @@ export const CLIENT_INIT_QUESTIONS = [
33
33
  parse: (raw) => {
34
34
  const name = raw.trim();
35
35
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
36
- throw new ClientInitAnswerError(`${JSON.stringify(raw)} is not an environment variable name.`);
36
+ throw new AvClientInitAnswerError(`${JSON.stringify(raw)} is not an environment variable name.`);
37
37
  }
38
38
  return name;
39
39
  },
@@ -47,7 +47,7 @@ export const CLIENT_INIT_QUESTIONS = [
47
47
  parse: (raw) => {
48
48
  const directory = raw.trim();
49
49
  if (directory === "") {
50
- throw new ClientInitAnswerError("--generate-at takes a directory.");
50
+ throw new AvClientInitAnswerError("--generate-at takes a directory.");
51
51
  }
52
52
  return directory;
53
53
  },
@@ -61,7 +61,7 @@ export const CLIENT_INIT_QUESTIONS = [
61
61
  parse: (raw) => {
62
62
  const manager = PACKAGE_MANAGERS.find((candidate) => candidate === raw.trim());
63
63
  if (manager === undefined) {
64
- throw new ClientInitAnswerError(`${JSON.stringify(raw)} is not a supported package manager; choose ${PACKAGE_MANAGERS.join(" or ")}.`);
64
+ throw new AvClientInitAnswerError(`${JSON.stringify(raw)} is not a supported package manager; choose ${PACKAGE_MANAGERS.join(" or ")}.`);
65
65
  }
66
66
  return manager;
67
67
  },
@@ -90,7 +90,7 @@ export async function resolveClientInitAnswers(sources) {
90
90
  break;
91
91
  }
92
92
  catch (error) {
93
- if (!(error instanceof ClientInitAnswerError)) {
93
+ if (!(error instanceof AvClientInitAnswerError)) {
94
94
  throw error;
95
95
  }
96
96
  sources.say(error.message);
@@ -102,7 +102,7 @@ export async function resolveClientInitAnswers(sources) {
102
102
  }
103
103
  }
104
104
  if (missing.length > 0) {
105
- throw new ClientInitUnansweredError(`stdin is not a terminal, so nothing can be asked: pass ${missing.join(", ")}, or pass --yes to accept their defaults.`);
105
+ throw new AvClientInitUnansweredError(`stdin is not a terminal, so nothing can be asked: pass ${missing.join(", ")}, or pass --yes to accept their defaults.`);
106
106
  }
107
107
  return {
108
108
  entrypoint: answered.entrypoint,
@@ -1,8 +1,8 @@
1
1
  import type { PackageManager } from "./client-init.questions.js";
2
2
  /** The frontend `avclient init` serves, read before anything is asked or written. */
3
3
  /** The directory is not a project `avclient init` can set up. A refusal: nothing written. */
4
- export declare class ClientProjectRefusedError extends Error {
5
- readonly name = "ClientProjectRefusedError";
4
+ export declare class AvClientProjectRefusedError extends Error {
5
+ readonly name = "AvClientProjectRefusedError";
6
6
  }
7
7
  export type ClientProject = {
8
8
  readonly directory: string;
@@ -1,13 +1,13 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { findClientConfigFile } from "../config/config.loader.js";
4
- export class ClientProjectRefusedError extends Error {
5
- name = "ClientProjectRefusedError";
4
+ export class AvClientProjectRefusedError extends Error {
5
+ name = "AvClientProjectRefusedError";
6
6
  }
7
7
  export function inspectClientProject(directory) {
8
8
  const manifest = path.join(directory, "package.json");
9
9
  if (!existsSync(manifest)) {
10
- throw new ClientProjectRefusedError("avclient init runs in a frontend project: no package.json here; create one first.");
10
+ throw new AvClientProjectRefusedError("avclient init runs in a frontend project: no package.json here; create one first.");
11
11
  }
12
12
  const lockfiles = [
13
13
  ["package-lock.json", "npm"],
@@ -14,7 +14,7 @@ export type TypeScriptResolver = () => Promise<TypeScriptCompiler | undefined>;
14
14
  */
15
15
  export declare function typeScriptResolverFor(specifier: string, directory: string): TypeScriptResolver;
16
16
  export declare function projectTypeScriptResolver(generateAt: string): TypeScriptResolver;
17
- export declare const MINIMUM_TYPESCRIPT = "5.5.0";
17
+ export declare const MINIMUM_TYPESCRIPT = "5.7.0";
18
18
  /** How deeply the tree was judged. */
19
19
  export type OutputCheck = "types" | "syntax" | "shape";
20
20
  export interface OutputAccepted {
@@ -45,9 +45,8 @@ export declare const SYNTAX_CHECK_UNAVAILABLE_WARNING: string;
45
45
  export declare function typeScriptWithoutCompilerApiWarning(version: string, checked: "syntax" | "shape"): string;
46
46
  /**
47
47
  * The warning a run carries when the project's `typescript` is older than the
48
- * peer range: its compiler API lacks options the check sets (`Bundler`
49
- * resolution, `verbatimModuleSyntax`), so its verdict would not be the one a
50
- * supported compiler gives.
48
+ * peer range: Aventara's types are not measured under it, so its verdict
49
+ * would not be the one a supported compiler gives.
51
50
  */
52
51
  export declare function typeScriptBelowRangeWarning(version: string, checked: "syntax" | "shape"): string;
53
52
  /**
@@ -24,7 +24,7 @@ export function typeScriptResolverFor(specifier, directory) {
24
24
  export function projectTypeScriptResolver(generateAt) {
25
25
  return typeScriptResolverFor("typescript", generateAt);
26
26
  }
27
- export const MINIMUM_TYPESCRIPT = "5.5.0";
27
+ export const MINIMUM_TYPESCRIPT = "5.7.0";
28
28
  function meetsMinimum(version) {
29
29
  const parts = /^(\d+)\.(\d+)\.(\d+)/.exec(version);
30
30
  const minimum = MINIMUM_TYPESCRIPT.split(".").map(Number);
@@ -57,7 +57,7 @@ export const SYNTAX_CHECK_UNAVAILABLE_WARNING = "neither `typescript` nor Node's
57
57
  export function typeScriptWithoutCompilerApiWarning(version, checked) {
58
58
  return (`the installed \`typescript\` ${version} has no classic compiler API (\`createProgram\`), so the generated ` +
59
59
  `output was NOT type-checked${checked === "shape" ? " or parsed — only its shape was" : " — only its shape and syntax were"}. ` +
60
- "Your project's own `tsc` checks it when it compiles; a `typescript` 5.5 to 6 restores the generator's own type check.");
60
+ "Your project's own `tsc` checks it when it compiles; a `typescript` 5.7 to 6 restores the generator's own type check.");
61
61
  }
62
62
  export function typeScriptBelowRangeWarning(version, checked) {
63
63
  return (`the installed \`typescript\` ${version} is older than ${MINIMUM_TYPESCRIPT}, the lowest @aventara/client supports, so the generated ` +
@@ -5,9 +5,9 @@ import { type OutputCheck, type TypeScriptResolver } from "./output.validator.js
5
5
  /** The four stages a write passes through, in order. */
6
6
  export type OutputWriteStage = "prepare" | "temp" | "validate" | "replace";
7
7
  /** A write that stopped; the previous output is intact unless it says otherwise. */
8
- export declare class OutputWriteError extends Error {
8
+ export declare class AvOutputWriteError extends Error {
9
9
  readonly stage: OutputWriteStage;
10
- readonly name = "OutputWriteError";
10
+ readonly name = "AvOutputWriteError";
11
11
  /**
12
12
  * What the run said before it stopped, in the order a success returns its
13
13
  * warnings: the emission's, the validator's, the writer's. Printed before the
@@ -19,7 +19,7 @@ export declare class OutputWriteError extends Error {
19
19
  readonly warnings?: readonly string[];
20
20
  });
21
21
  /** The same refusal, with `earlier` said before the warnings it already carries. */
22
- precededBy(earlier: readonly string[]): OutputWriteError;
22
+ precededBy(earlier: readonly string[]): AvOutputWriteError;
23
23
  }
24
24
  /**
25
25
  * Records `earlier` as said before `defect`, ahead of anything already recorded,
@@ -49,11 +49,11 @@ export interface ClientOutputWritten {
49
49
  * Writes `emission.tree` as `<generateAt>/AvClient.ts` and
50
50
  * `<generateAt>/generated/`.
51
51
  *
52
- * @throws OutputWriteError when the write stops; the previous output is intact.
52
+ * @throws AvOutputWriteError when the write stops; the previous output is intact.
53
53
  */
54
54
  export declare function writeClientOutput(input: ClientOutputWriteInput): Promise<ClientOutputWritten>;
55
55
  /**
56
- * @throws OutputWriteError when `generateAt` is not a directory, `generated` is
56
+ * @throws AvOutputWriteError when `generateAt` is not a directory, `generated` is
57
57
  * not a directory or an entry file is not a file: no confirmation repairs that.
58
58
  */
59
59
  export declare function findForeignOutputContent(generateAt: AbsolutePath, fileSystem?: OutputFileSystem): Promise<readonly string[]>;
@@ -4,9 +4,9 @@ import path from "node:path";
4
4
  import { carriesGeneratedOwnership, GENERATED_OWNERSHIP_HEAD_BYTES, } from "../emit/banner.emitter.js";
5
5
  import { CLIENT_ENTRY_FILES, GENERATED_DIRECTORY, LEGACY_CLIENT_ENTRY_FILES, } from "../emit/emitted-tree.interface.js";
6
6
  import { projectTypeScriptResolver, validateOutputTree, } from "./output.validator.js";
7
- export class OutputWriteError extends Error {
7
+ export class AvOutputWriteError extends Error {
8
8
  stage;
9
- name = "OutputWriteError";
9
+ name = "AvOutputWriteError";
10
10
  warnings;
11
11
  constructor(stage, message, options) {
12
12
  super(message, options);
@@ -14,7 +14,7 @@ export class OutputWriteError extends Error {
14
14
  this.warnings = options?.warnings ?? [];
15
15
  }
16
16
  precededBy(earlier) {
17
- return new OutputWriteError(this.stage, this.message, {
17
+ return new AvOutputWriteError(this.stage, this.message, {
18
18
  cause: this.cause,
19
19
  warnings: [...earlier, ...this.warnings],
20
20
  });
@@ -65,7 +65,7 @@ export async function writeClientOutput(input) {
65
65
  ...validationWarnings,
66
66
  ...writerWarnings,
67
67
  ];
68
- throw error instanceof OutputWriteError
68
+ throw error instanceof AvOutputWriteError
69
69
  ? error.precededBy(said)
70
70
  : precedeDefect(error, said);
71
71
  }
@@ -99,7 +99,7 @@ export async function writeClientOutput(input) {
99
99
  validationWarnings = validation.warnings;
100
100
  }
101
101
  else {
102
- throw new OutputWriteError("validate", `the generated output failed its ${validation.checked} check, so ${LEFT_AS_THEY_WERE(paths)} ` +
102
+ throw new AvOutputWriteError("validate", `the generated output failed its ${validation.checked} check, so ${LEFT_AS_THEY_WERE(paths)} ` +
103
103
  "This is a defect in @aventara/client; please report it with these findings:\n" +
104
104
  validation.findings.map((finding) => ` ${finding}`).join("\n"));
105
105
  }
@@ -267,7 +267,7 @@ async function inspectOwnedEntries(fs, paths, generatedSource = paths.generated)
267
267
  const generatedStats = await lstatOrUndefined(fs, generatedSource);
268
268
  if (generatedStats !== undefined) {
269
269
  if (!generatedStats.isDirectory()) {
270
- throw new OutputWriteError("prepare", `refusing to replace ${generatedSource}: it is not a directory, and the generator owns ` +
270
+ throw new AvOutputWriteError("prepare", `refusing to replace ${generatedSource}: it is not a directory, and the generator owns ` +
271
271
  `${GENERATED_DIRECTORY}/ as one; move it, or choose another \`generateAt\`. Nothing was written.`);
272
272
  }
273
273
  const entries = await fs.readdir(generatedSource, {
@@ -292,7 +292,7 @@ async function inspectOwnedEntries(fs, paths, generatedSource = paths.generated)
292
292
  continue;
293
293
  }
294
294
  if (!stats.isFile()) {
295
- throw new OutputWriteError("prepare", `refusing to replace ${file}: it is not a file, and the generator owns ${name} ` +
295
+ throw new AvOutputWriteError("prepare", `refusing to replace ${file}: it is not a file, and the generator owns ${name} ` +
296
296
  "as one; move it, or choose another `generateAt`. Nothing was written.");
297
297
  }
298
298
  entries.push(name);
@@ -317,12 +317,12 @@ async function inspectOwnedEntries(fs, paths, generatedSource = paths.generated)
317
317
  }
318
318
  function foreignContentRefusal(paths, foreign) {
319
319
  const them = foreign.length === 1 ? "it" : "them";
320
- return new OutputWriteError("prepare", `refusing to generate into ${paths.generateAt}: ${foreign.join(", ")} ${foreign.length === 1 ? "was" : "were"} ` +
320
+ return new AvOutputWriteError("prepare", `refusing to generate into ${paths.generateAt}: ${foreign.join(", ")} ${foreign.length === 1 ? "was" : "were"} ` +
321
321
  `not generated by @aventara/client, and generating would overwrite or remove ${them}; confirm the ` +
322
322
  `override, move ${them} out, or choose another \`generateAt\`. Nothing was written.`);
323
323
  }
324
324
  function notADirectory(generateAt) {
325
- return new OutputWriteError("prepare", `refusing to generate into ${generateAt}: it is not a directory. ` +
325
+ return new AvOutputWriteError("prepare", `refusing to generate into ${generateAt}: it is not a directory. ` +
326
326
  "`generateAt` must name a directory; choose another `generateAt`. Nothing was written.");
327
327
  }
328
328
  async function carriesOwnershipLine(fs, file) {
@@ -341,7 +341,7 @@ async function rollBack(paths, cause, undo) {
341
341
  await undo();
342
342
  }
343
343
  catch (rollbackError) {
344
- throw new OutputWriteError("replace", `the generated output could not be moved into ${paths.generateAt} (${describe(cause)}), and the ` +
344
+ throw new AvOutputWriteError("replace", `the generated output could not be moved into ${paths.generateAt} (${describe(cause)}), and the ` +
345
345
  `previous output could not be restored (${describe(rollbackError)}). The previous ` +
346
346
  `${GENERATED_DIRECTORY}/ is intact at ${paths.previous}; the next run puts it back.`, { cause });
347
347
  }
@@ -351,10 +351,10 @@ async function stage(name, paths, run) {
351
351
  return await run();
352
352
  }
353
353
  catch (error) {
354
- if (error instanceof OutputWriteError || !isSystemError(error)) {
354
+ if (error instanceof AvOutputWriteError || !isSystemError(error)) {
355
355
  throw error;
356
356
  }
357
- throw new OutputWriteError(name, `could not ${STAGE_ACTIONS[name]} (${describe(error)}); ${LEFT_AS_THEY_WERE(paths)}`, { cause: error });
357
+ throw new AvOutputWriteError(name, `could not ${STAGE_ACTIONS[name]} (${describe(error)}); ${LEFT_AS_THEY_WERE(paths)}`, { cause: error });
358
358
  }
359
359
  }
360
360
  const STAGE_ACTIONS = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aventara/client",
3
- "version": "1.0.0-rc.0",
3
+ "version": "1.0.0-rc.2",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Development-time generator for Aventara typed remote clients.",
6
6
  "type": "module",
@@ -24,12 +24,12 @@
24
24
  "CHANGELOG.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@aventara/core": "1.0.0-rc.0",
27
+ "@aventara/core": "1.0.0-rc.2",
28
28
  "c12": "3.3.4",
29
29
  "get-tsconfig": "4.10.0"
30
30
  },
31
31
  "peerDependencies": {
32
- "typescript": ">=5.5.0"
32
+ "typescript": ">=5.7.0"
33
33
  },
34
34
  "peerDependenciesMeta": {
35
35
  "typescript": {
@@ -40,7 +40,7 @@
40
40
  "access": "public"
41
41
  },
42
42
  "devDependencies": {
43
- "@aventara/testing": "1.0.0-rc.0",
43
+ "@aventara/testing": "1.0.0-rc.2",
44
44
  "@types/node": "24.10.1",
45
45
  "typescript": "^5.9.2"
46
46
  },