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

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 +44 -9
  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 +20 -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 +8 -9
  68. package/dist/init/client-init.planner.d.ts +1 -9
  69. package/dist/init/client-init.planner.js +16 -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 +49 -27
  76. package/dist/output/output.validator.js +113 -74
  77. package/dist/output/output.writer.d.ts +59 -52
  78. package/dist/output/output.writer.js +72 -134
  79. package/package.json +6 -4
@@ -1,33 +1,7 @@
1
+ import { importSpecifier, } from "./module-style.interface.js";
1
2
  import { ownPropertyKey } from "./name.deriver.js";
2
- /**
3
- * `generated/client.ts` — the typed surface (Phase 12-rest S4; plan §6): the class
4
- * `AvClient` (Q8), its options `AvClientOptions` and the per-call `CallOptions`
5
- * (Q9, Q17), and the ready instance `avClient`, this module's default export
6
- * (Q7).
7
- *
8
- * Every argument and result type is an instantiation of core's own derivation,
9
- * copied under `generated/derivation/` (Q1 = A): the call grammar
10
- * (`OperationGrammar`, `OperationCall`, `DeferredOperationCall`, S1) over the
11
- * carrier's contract (`ClientContractShape`, Q4), in the client's forms (Q3 = A:
12
- * core's application forms, with this tree's own `Decimal`). Nothing here
13
- * re-spells a rule. A call resolves to the data (Q11 = a: `"data"`), a
14
- * first-style miss to `null`.
15
- *
16
- * Each surface is one mapped alias over the one contract (Phase 9's variance
17
- * lesson). A Resource is reached by its contract name, except where that name is
18
- * one of the client's own members (Q12), which renames the property only.
19
- * `tx` and `transaction` exist iff the contract advertises `interactive`
20
- * transactions (P3), in the type as in the runtime.
21
- *
22
- * Also declared here, for `types.d.ts` alone, the two helpers the named types are
23
- * aliases of (Q10): `ResourceRecord` and `ResourceArgument`.
24
- *
25
- * At runtime (S5) the class builds one frozen object per Resource from the
26
- * advertised operations (P4) — each variant a function that runs the operation
27
- * through the transport, reading the fetch when it is called — and the default
28
- * entrypoint is the generated one (§15.2, Q5) unless the options name another.
29
- */
30
- export function emitClientSurfaceModule(contract, names) {
3
+ export function emitClientSurfaceModule(contract, names, style) {
4
+ const from = (module) => JSON.stringify(importSpecifier(module, style));
31
5
  const renamed = names.properties.filter((property) => property.property !== property.contractName);
32
6
  const propertyOf = renamed.length === 0
33
7
  ? "R"
@@ -48,34 +22,34 @@ export function emitClientSurfaceModule(contract, names) {
48
22
  "};\n";
49
23
  return {
50
24
  path: "client.ts",
51
- source: 'import type { ClientContractShape } from "./contract.js";\n' +
52
- 'import type { ApplicationScalarForms } from "./derivation/contracts/scalar-value-type.js";\n' +
53
- 'import type { OperationArgumentsFor, ResourceKey } from "./derivation/operations/operation-arguments.js";\n' +
54
- `import type { ${interactive ? "DeferredOperationCall, " : ""}OperationCall, OperationGrammar } from "./derivation/operations/operation-call.js";\n` +
55
- 'import type { OperationFamily, OperationIdentity } from "./derivation/operations/operation-identity.js";\n' +
56
- 'import type { AdmittedOperationResult } from "./derivation/operations/operation-result.js";\n' +
25
+ source: `import type { ClientContractShape } from ${from("./contract")};\n` +
26
+ `import type { ApplicationScalarForms } from ${from("./derivation/contracts/scalar-value-type")};\n` +
27
+ `import type { OperationArgumentsFor, ResourceKey } from ${from("./derivation/operations/operation-arguments")};\n` +
28
+ `import type { ${interactive ? "DeferredOperationCall, " : ""}OperationCall, OperationGrammar } from ${from("./derivation/operations/operation-call")};\n` +
29
+ `import type { OperationFamily, OperationIdentity } from ${from("./derivation/operations/operation-identity")};\n` +
30
+ `import type { AdmittedOperationResult } from ${from("./derivation/operations/operation-result")};\n` +
57
31
  (interactive
58
- ? 'import type { Operation, TransactionResults } from "./derivation/transactions/deferred-operation.js";\n'
32
+ ? `import type { Operation, TransactionResults } from ${from("./derivation/transactions/deferred-operation")};\n`
59
33
  : "") +
60
- 'import { DEFAULT_ENTRYPOINT } from "./metadata.js";\n' +
61
- 'import type { Decimal } from "./runtime/decimal.js";\n' +
62
- 'import { ADVERTISED_OPERATIONS } from "./runtime/descriptor.js";\n' +
34
+ `import { DEFAULT_ENTRYPOINT } from ${from("./metadata")};\n` +
35
+ `import type { Decimal } from ${from("./runtime/decimal")};\n` +
36
+ `import { ADVERTISED_OPERATIONS } from ${from("./runtime/descriptor")};\n` +
63
37
  (interactive
64
- ? 'import { deferOperation, runTransaction } from "./runtime/transaction.js";\n'
38
+ ? `import { deferOperation, runTransaction } from ${from("./runtime/transaction")};\n`
65
39
  : "") +
66
- 'import { type CallOptions, execute, type Fetch, type TransportConnection } from "./runtime/transport.js";\n' +
40
+ `import { type CallOptions, execute, type Fetch, type TransportConnection } from ${from("./runtime/transport")};\n` +
67
41
  "\n" +
68
- 'export type { CallOptions } from "./runtime/transport.js";\n' +
42
+ `export type { CallOptions } from ${from("./runtime/transport")};\n` +
69
43
  "\n" +
70
44
  "/**\n" +
71
- " * The forms this client reads and writes (§6.2, Q3): core's application forms —\n" +
45
+ " * The forms this client reads and writes: core's application forms —\n" +
72
46
  " * `bigint`, `Date`, `Uint8Array` — with this client's own `Decimal`.\n" +
73
47
  " */\n" +
74
48
  'export type ClientScalarForms = Omit<ApplicationScalarForms, "decimal"> & {\n' +
75
49
  "\treadonly decimal: Decimal;\n" +
76
50
  "};\n" +
77
51
  "\n" +
78
- "/** How an `AvClient` reaches its deployment (§15.2, §15.7). */\n" +
52
+ "/** How an `AvClient` reaches its deployment. */\n" +
79
53
  "export interface AvClientOptions {\n" +
80
54
  "\t/** Another deployment serving exactly the same ClientContract; the generated default otherwise. */\n" +
81
55
  "\treadonly entrypoint?: string;\n" +
@@ -98,7 +72,7 @@ export function emitClientSurfaceModule(contract, names) {
98
72
  "\t\t\t>") +
99
73
  (interactive
100
74
  ? "\n" +
101
- "/** `avClient.tx.<resource>.<family>.<variant>(args)`: a deferred handle; no request (§14.1). */\n" +
75
+ "/** `avClient.tx.<resource>.<family>.<variant>(args)`: a deferred handle; no request. */\n" +
102
76
  surface("AvTxSurface", "DeferredOperationCall<\n" +
103
77
  "\t\t\t\tClientContractShape,\n" +
104
78
  "\t\t\t\tR,\n" +
@@ -107,7 +81,7 @@ export function emitClientSurfaceModule(contract, names) {
107
81
  "\t\t\t\tClientScalarForms\n" +
108
82
  "\t\t\t>") +
109
83
  "\n" +
110
- "/** Sends the handles as one plan and resolves their results as a typed tuple (§14.1). */\n" +
84
+ "/** Sends the handles as one plan and resolves their results as a typed tuple. */\n" +
111
85
  "type TransactionCall = <const Steps extends readonly Operation<unknown>[]>(\n" +
112
86
  "\tsteps: Steps,\n" +
113
87
  "\toptions?: CallOptions,\n" +
@@ -117,12 +91,12 @@ export function emitClientSurfaceModule(contract, names) {
117
91
  "/** The generated client: one property per Resource this deployment's ClientContract advertises. */\n" +
118
92
  "export interface AvClient extends AvClientSurface {}\n" +
119
93
  "\n" +
120
- "/** The generated client (§15.4). */\n" +
94
+ "/** The generated client. */\n" +
121
95
  "export class AvClient {\n" +
122
96
  (interactive
123
- ? "\t/** Deferred operations, for `transaction` (§14.1). */\n" +
97
+ ? "\t/** Deferred operations, for `transaction`. */\n" +
124
98
  "\tdeclare readonly tx: AvTxSurface;\n" +
125
- "\t/** Runs deferred operations as one transaction (§14.1). */\n" +
99
+ "\t/** Runs deferred operations as one transaction. */\n" +
126
100
  "\tdeclare readonly transaction: TransactionCall;\n" +
127
101
  "\n"
128
102
  : "") +
@@ -157,7 +131,7 @@ export function emitClientSurfaceModule(contract, names) {
157
131
  "\n" +
158
132
  "/**\n" +
159
133
  " * One frozen object per Resource, one per family under it, one member per\n" +
160
- " * advertised variant (P4) — by wire name; the caller places each Resource.\n" +
134
+ " * advertised variant — by wire name; the caller places each Resource.\n" +
161
135
  " */\n" +
162
136
  "function operationTree<M>(member: (resource: string, family: string, variant: string) => M): Map<string, object> {\n" +
163
137
  "\tconst resources = new Map<string, Map<string, Record<string, M>>>();\n" +
@@ -179,7 +153,7 @@ export function emitClientSurfaceModule(contract, names) {
179
153
  "/** One advertised operation, as the runtime calls it: the types are the surface's. */\n" +
180
154
  "type OperationMethod = (args?: Readonly<Record<string, unknown>>, options?: CallOptions) => Promise<unknown>;\n" +
181
155
  "\n" +
182
- "/** The Resources reached by a property other than their wire name (Q12). */\n" +
156
+ "/** The Resources reached by a property other than their wire name. */\n" +
183
157
  `const RENAMED_PROPERTIES: Readonly<Record<string, string>> = {${renamedEntries}};\n` +
184
158
  "\n" +
185
159
  "/** The client's property for a Resource: its wire name, unless that is one of the client's own members. */\n" +
@@ -188,14 +162,14 @@ export function emitClientSurfaceModule(contract, names) {
188
162
  "}\n" +
189
163
  "\n" +
190
164
  "/**\n" +
191
- " * The fetch a call uses (§15.7): the one the client was given, else the\n" +
165
+ " * The fetch a call uses: the one the client was given, else the\n" +
192
166
  " * platform's, read when the call is made — so importing the client never\n" +
193
167
  " * fails where there is no fetch, and a call does, saying why.\n" +
194
168
  " */\n" +
195
169
  "function platformFetch(given: Fetch | undefined): Fetch {\n" +
196
170
  "\tconst found = given ?? (globalThis as { readonly fetch?: Fetch }).fetch;\n" +
197
171
  '\tif (typeof found !== "function") {\n' +
198
- '\t\tthrow new TypeError("No fetch is available here; pass one: new AvClient({ fetch }) (§15.7).");\n' +
172
+ '\t\tthrow new TypeError("No fetch is available here; pass one: new AvClient({ fetch }).");\n' +
199
173
  "\t}\n" +
200
174
  "\treturn found;\n" +
201
175
  "}\n" +
@@ -209,7 +183,7 @@ export function emitClientSurfaceModule(contract, names) {
209
183
  "\t{ readonly family: F; readonly variant: V }\n" +
210
184
  ">;\n" +
211
185
  "\n" +
212
- "/** A Resource's default record — `find.unique` with no projection (§15.6, Q10). */\n" +
186
+ "/** A Resource's default record — `find.unique` with no projection. */\n" +
213
187
  "export type ResourceRecord<R extends Resource> = AdmittedOperationResult<\n" +
214
188
  "\tClientContractShape,\n" +
215
189
  "\tR,\n" +
@@ -218,7 +192,7 @@ export function emitClientSurfaceModule(contract, names) {
218
192
  "\tClientScalarForms\n" +
219
193
  ">;\n" +
220
194
  "\n" +
221
- "/** One argument of one of a Resource's operations, present (§15.6, Q10). */\n" +
195
+ "/** One argument of one of a Resource's operations, present. */\n" +
222
196
  "export type ResourceArgument<\n" +
223
197
  "\tR extends Resource,\n" +
224
198
  "\tF extends OperationFamily,\n" +
@@ -1,17 +1,14 @@
1
1
  import type { ClientContract } from "@aventara/core";
2
2
  import type { ClientEntrypoint } from "../config/client-config.interface.js";
3
3
  import { type ClientEmission } from "./emitted-tree.interface.js";
4
+ import { type ClientModuleStyle } from "./module-style.interface.js";
4
5
  /**
5
- * §15.3's emit steps over an accepted ClientContract, as one value (plan §7).
6
- *
7
6
  * The banner, the encoding and the file order are applied HERE, once, over every
8
- * module — so no emitter can forget the banner, and byte-equality is a property
9
- * of this function rather than of each emitter's care (C-843):
7
+ * module — so no emitter can forget the banner, and byte-equality is a property of
8
+ * this function rather than of each emitter's care:
10
9
  *
11
- * - every module opens with the generated banner (M17);
10
+ * - every module opens with the generated banner;
12
11
  * - every file is UTF-8;
13
- * - the layout is the architect's (2026-10-04): `AvClient.ts` at the root of
14
- * `generateAt`, every other module under `generated/`;
15
12
  * - files come in UTF-16 code-unit order of their path, each path once.
16
13
  *
17
14
  * The name derivation's rename warnings ride on the result beside the tree; this
@@ -19,19 +16,13 @@ import { type ClientEmission } from "./emitted-tree.interface.js";
19
16
  *
20
17
  * The names and enums read the enum registry, registry NAMES and `protocol`.
21
18
  * Core's derivation is copied under `generated/derivation/` as its published
22
- * declarations (Q1 = A, `derivation.emitter.ts`): read from the installed
23
- * `@aventara/core`, never from the Contract. The contract itself reaches the
24
- * tree as three projections of the one accepted contract (plan §6): the carrier
25
- * `generated/contract.ts` (Q4), the runtime's decode table and advertised
26
- * operations `generated/runtime/descriptor.ts` (P1, P4), and `metadata.ts`'s
27
- * hash, version and default entrypoint (Q5) — the entrypoint being the run's
28
- * other input.
29
- *
30
- * The runtime (`generated/runtime/codec.ts`, `decimal.ts`, `errors.ts`,
31
- * `transport.ts`) reads nothing of the Contract at all: §6.2's codecs and
32
- * §13's codes are fixed by protocol version (M10, Q3), and the transport sends
33
- * the operation its caller names.
19
+ * declarations: read from the installed `@aventara/core`, never from the Contract.
20
+ * The contract itself reaches the tree as three projections of the one accepted
21
+ * contract: the carrier `generated/contract.ts`, the runtime's decode table and
22
+ * advertised operations `generated/runtime/descriptor.ts`, and `metadata.ts`'s
23
+ * hash, version and default entrypoint — the entrypoint being the run's other
24
+ * input.
34
25
  *
35
26
  * @throws GeneratedNameError when a name cannot be emitted, even renamed.
36
27
  */
37
- export declare function emitClientTree(contract: ClientContract, entrypoint: ClientEntrypoint): ClientEmission;
28
+ export declare function emitClientTree(contract: ClientContract, entrypoint: ClientEntrypoint, style: ClientModuleStyle): ClientEmission;
@@ -5,65 +5,32 @@ import { emitDerivationModules } from "./derivation.emitter.js";
5
5
  import { emitDescriptorModule } from "./descriptor.emitter.js";
6
6
  import { CLIENT_ENTRY_FILE, GENERATED_DIRECTORY, } from "./emitted-tree.interface.js";
7
7
  import { emitEnumsModule } from "./enum.emitter.js";
8
+ import { moduleSpecifierWriter, } from "./module-style.interface.js";
8
9
  import { deriveEmittedNames } from "./name.deriver.js";
9
10
  import { emitNamedTypesModule } from "./named-type.emitter.js";
10
11
  import { emitDecimalModule, emitErrorsModule, emitMetadataModule, emitTransportModule, errorsModuleExports, } from "./runtime.emitter.js";
11
12
  import { emitScalarCodecModule } from "./scalar.codec.js";
12
13
  import { emitTransactionModules } from "./transaction.emitter.js";
13
- /**
14
- * §15.3's emit steps over an accepted ClientContract, as one value (plan §7).
15
- *
16
- * The banner, the encoding and the file order are applied HERE, once, over every
17
- * module — so no emitter can forget the banner, and byte-equality is a property
18
- * of this function rather than of each emitter's care (C-843):
19
- *
20
- * - every module opens with the generated banner (M17);
21
- * - every file is UTF-8;
22
- * - the layout is the architect's (2026-10-04): `AvClient.ts` at the root of
23
- * `generateAt`, every other module under `generated/`;
24
- * - files come in UTF-16 code-unit order of their path, each path once.
25
- *
26
- * The name derivation's rename warnings ride on the result beside the tree; this
27
- * function prints nothing.
28
- *
29
- * The names and enums read the enum registry, registry NAMES and `protocol`.
30
- * Core's derivation is copied under `generated/derivation/` as its published
31
- * declarations (Q1 = A, `derivation.emitter.ts`): read from the installed
32
- * `@aventara/core`, never from the Contract. The contract itself reaches the
33
- * tree as three projections of the one accepted contract (plan §6): the carrier
34
- * `generated/contract.ts` (Q4), the runtime's decode table and advertised
35
- * operations `generated/runtime/descriptor.ts` (P1, P4), and `metadata.ts`'s
36
- * hash, version and default entrypoint (Q5) — the entrypoint being the run's
37
- * other input.
38
- *
39
- * The runtime (`generated/runtime/codec.ts`, `decimal.ts`, `errors.ts`,
40
- * `transport.ts`) reads nothing of the Contract at all: §6.2's codecs and
41
- * §13's codes are fixed by protocol version (M10, Q3), and the transport sends
42
- * the operation its caller names.
43
- *
44
- * @throws GeneratedNameError when a name cannot be emitted, even renamed.
45
- */
46
- export function emitClientTree(contract, entrypoint) {
14
+ export function emitClientTree(contract, entrypoint, style) {
47
15
  const names = deriveEmittedNames(contract);
48
16
  const generated = [
49
17
  ...emitDerivationModules(),
50
- emitClientSurfaceModule(contract, names),
18
+ emitClientSurfaceModule(contract, names, style),
51
19
  emitContractCarrierModule(contract),
52
20
  emitDescriptorModule(contract),
53
21
  emitEnumsModule(contract, names),
54
22
  emitMetadataModule(contract.protocol, entrypoint),
55
- emitScalarCodecModule(),
23
+ emitScalarCodecModule(style),
56
24
  emitDecimalModule(),
57
25
  emitErrorsModule(),
58
- emitTransportModule(),
59
- emitNamedTypesModule(contract, names),
60
- // P3: the builder and runner exist iff transactions are interactive.
26
+ emitTransportModule(style),
27
+ emitNamedTypesModule(contract, names, style),
61
28
  ...(contract.transactions === "interactive"
62
- ? emitTransactionModules()
29
+ ? emitTransactionModules(style)
63
30
  : []),
64
31
  ];
65
32
  const files = [
66
- { path: CLIENT_ENTRY_FILE, source: clientEntrySource() },
33
+ { path: CLIENT_ENTRY_FILE, source: clientEntrySource(style) },
67
34
  ...generated.map((module) => ({
68
35
  path: `${GENERATED_DIRECTORY}/${module.path}`,
69
36
  source: module.source,
@@ -76,20 +43,11 @@ export function emitClientTree(contract, entrypoint) {
76
43
  path: file.path,
77
44
  bytes: encoder.encode(withGeneratedBanner(file.source)),
78
45
  }));
79
- return { tree, warnings: names.warnings };
46
+ return { tree, style, warnings: names.warnings };
80
47
  }
81
- /**
82
- * `AvClient.ts`, the entry point a consumer imports (§15.4; Phase 12-rest Q7):
83
- * the ready client `avClient` as the DEFAULT export, and as named exports the
84
- * class `AvClient`, `AvClientOptions`, `CallOptions`, `Fetch`, `Operation<T>`,
85
- * the named Resource types, the enums, `Decimal`, the errors and the code unions —
86
- * re-exported from `generated/`. Never the transport's primitive (Q1 = B), never
87
- * the derived forms map (Q3: internal).
88
- *
89
- * import avClient, { AvClient, User, UserWhere } from "./AvClient";
90
- */
91
- function clientEntrySource() {
92
- const from = (module) => JSON.stringify(`./${GENERATED_DIRECTORY}/${module.replace(/\.d\.ts$|\.ts$/, ".js")}`);
48
+ function clientEntrySource(style) {
49
+ const specifier = moduleSpecifierWriter(style);
50
+ const from = (module) => specifier(`./${GENERATED_DIRECTORY}/${module.replace(/\.d\.ts$|\.ts$/, "")}`);
93
51
  return (`export { default } from ${from("client.ts")};\n` +
94
52
  `export {\n\tAvClient,\n\ttype AvClientOptions,\n\ttype CallOptions,\n} from ${from("client.ts")};\n` +
95
53
  `export type { Fetch } from ${from("runtime/transport.ts")};\n` +
@@ -3,11 +3,10 @@ import type { EmittedModule } from "./emitted-tree.interface.js";
3
3
  /** `generated/contract.ts`, before the banner. */
4
4
  export declare function emitContractCarrierModule(contract: ClientContract): EmittedModule;
5
5
  /**
6
- * The ClientContract a carrier file holds — its whole text, banner included —
7
- * or `undefined` when it is not one this generator wrote over a contract that
8
- * still verifies: a foreign prefix or suffix, bytes that are not JSON, a body
9
- * that is not a ClientContract or whose hash does not re-verify, or bytes that
10
- * are not that contract's canonical form. Never trusted otherwise (Q6: a carrier
11
- * that does not re-hash is treated as absent).
6
+ * The ClientContract a carrier file holds — its whole text, banner included — or
7
+ * `undefined` when it is not one this generator wrote over a contract that still
8
+ * verifies: a foreign prefix or suffix, bytes that are not JSON, a body that is
9
+ * not a ClientContract or whose hash does not re-verify, or bytes that are not
10
+ * that contract's canonical form. Never trusted otherwise.
12
11
  */
13
12
  export declare function parseContractCarrier(text: string): Promise<ClientContract | undefined>;
@@ -1,42 +1,14 @@
1
1
  import { canonicalizeContract } from "@aventara/core";
2
2
  import { acceptClientContract } from "../contract/contract.acceptance.js";
3
3
  import { withGeneratedBanner } from "./banner.emitter.js";
4
- /**
5
- * The carrier (Q4 = A): `generated/contract.ts` holds the ClientContract the
6
- * client was generated against, as its served canonical bytes (RFC 8785, §19.2)
7
- * verbatim — which are a valid TypeScript type literal (plan M4):
8
- *
9
- * ```ts
10
- * export type ClientContractShape = {"enums":{},…};
11
- * ```
12
- *
13
- * One artefact, three readers: the derivation's `C` (S4); the generator on a
14
- * `304` (Q6, S7), which parses it back with {@link parseContractCarrier}; and a
15
- * person auditing what the client was generated against. It costs no runtime
16
- * byte — nothing imports it as a value.
17
- *
18
- * The bytes are `canonicalizeContract`'s over the ACCEPTED contract: the body a
19
- * deployment serves is those bytes (`_contract` serves `canonicalizeContract`'s
20
- * output, and acceptance verified the hash over the same canonical form), and a
21
- * contract that arrives in another key order still emits them (C-843).
22
- */
23
4
  const CARRIER_PREFIX = "export type ClientContractShape = ";
24
5
  const CARRIER_SUFFIX = ";\n";
25
- /** `generated/contract.ts`, before the banner. */
26
6
  export function emitContractCarrierModule(contract) {
27
7
  return {
28
8
  path: "contract.ts",
29
9
  source: `${CARRIER_PREFIX}${canonicalizeContract(contract)}${CARRIER_SUFFIX}`,
30
10
  };
31
11
  }
32
- /**
33
- * The ClientContract a carrier file holds — its whole text, banner included —
34
- * or `undefined` when it is not one this generator wrote over a contract that
35
- * still verifies: a foreign prefix or suffix, bytes that are not JSON, a body
36
- * that is not a ClientContract or whose hash does not re-verify, or bytes that
37
- * are not that contract's canonical form. Never trusted otherwise (Q6: a carrier
38
- * that does not re-hash is treated as absent).
39
- */
40
12
  export async function parseContractCarrier(text) {
41
13
  const opening = withGeneratedBanner(CARRIER_PREFIX);
42
14
  if (!text.startsWith(opening) || !text.endsWith(CARRIER_SUFFIX)) {
@@ -1,14 +1,14 @@
1
1
  import type { EmittedModule } from "./emitted-tree.interface.js";
2
2
  /**
3
- * The derivation, transported (Phase 12-rest S2, Q1 = A). A generated client's
4
- * argument and result types are core's own `OperationArgumentsFor`,
5
- * `OperationResultFor` and the call grammar (`OperationCall`, …) — never a second
6
- * spelling. They reach the emitted tree as core's PUBLISHED DECLARATIONS, copied
7
- * under `generated/derivation/` at their path relative to core's `dist`:
3
+ * The derivation, transported. A generated client's argument and result types are
4
+ * core's own `OperationArgumentsFor`, `OperationResultFor` and the call grammar
5
+ * (`OperationCall`, …) — never a second spelling. They reach the emitted tree as
6
+ * core's PUBLISHED DECLARATIONS, copied under `generated/derivation/` at their
7
+ * path relative to core's `dist`:
8
8
  *
9
9
  * - declarations, not sources: the sources' closure carries value imports (the
10
- * canonicaliser, the wire grammars), the declarations' carries none (plan M1);
11
- * a `.d.ts` cannot carry runtime, so a bundler never sees one;
10
+ * canonicaliser, the wire grammars), the declarations' carries none; a `.d.ts`
11
+ * cannot carry runtime, so a bundler never sees one;
12
12
  * - under their own directory, so core's `runtime/decimal.d.ts` cannot shadow the
13
13
  * emitted `generated/runtime/decimal.ts`;
14
14
  * - byte for byte, except the trailing `//# sourceMappingURL=…` line, which names
@@ -1,34 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- /**
5
- * The derivation, transported (Phase 12-rest S2, Q1 = A). A generated client's
6
- * argument and result types are core's own `OperationArgumentsFor`,
7
- * `OperationResultFor` and the call grammar (`OperationCall`, …) — never a second
8
- * spelling. They reach the emitted tree as core's PUBLISHED DECLARATIONS, copied
9
- * under `generated/derivation/` at their path relative to core's `dist`:
10
- *
11
- * - declarations, not sources: the sources' closure carries value imports (the
12
- * canonicaliser, the wire grammars), the declarations' carries none (plan M1);
13
- * a `.d.ts` cannot carry runtime, so a bundler never sees one;
14
- * - under their own directory, so core's `runtime/decimal.d.ts` cannot shadow the
15
- * emitted `generated/runtime/decimal.ts`;
16
- * - byte for byte, except the trailing `//# sourceMappingURL=…` line, which names
17
- * a map the tree does not hold.
18
- *
19
- * The closure is walked here, at generation time, from {@link DERIVATION_ROOTS}
20
- * over whichever `@aventara/core` this package resolves — so the output is a
21
- * function of the core version the generator depends on, as the rest of it is a
22
- * function of the generator. A closure that names a package, carries a
23
- * triple-slash reference, or leaves core's declarations is refused: it cannot be
24
- * transported, and core's own gate (`emittable-closure.gate.spec.ts`) exists so
25
- * that it never is.
26
- */
27
- /**
28
- * The modules whose declarations the generated client copies — the roots of core's
29
- * `emittable-closure.gate.spec.ts`, mirrored (core cannot export a test constant,
30
- * and this package cannot read core's tests).
31
- */
4
+ import { scanModuleSpecifiers } from "./module-specifier.scanner.js";
32
5
  export const DERIVATION_ROOTS = [
33
6
  "contracts/contract",
34
7
  "contracts/scalar-value-type",
@@ -39,7 +12,6 @@ export const DERIVATION_ROOTS = [
39
12
  "transactions/deferred-operation",
40
13
  "transactions/transaction-reference",
41
14
  ];
42
- /** The published declarations of the `@aventara/core` this package resolves. */
43
15
  export function publishedCoreDeclarations() {
44
16
  const dist = path.dirname(fileURLToPath(import.meta.resolve("@aventara/core")));
45
17
  return (relative) => {
@@ -54,13 +26,6 @@ export function publishedCoreDeclarations() {
54
26
  }
55
27
  };
56
28
  }
57
- /**
58
- * Core's declaration closure from {@link DERIVATION_ROOTS}, as modules under
59
- * `derivation/`, in UTF-16 code-unit order of their path.
60
- *
61
- * @throws Error when the closure cannot be transported — a defect of the
62
- * installed `@aventara/core`, never of the consumer's input.
63
- */
64
29
  export function emitDerivationModules(read = publishedCoreDeclarations()) {
65
30
  const copied = new Map();
66
31
  const queue = DERIVATION_ROOTS.map((root) => `${root}.d.ts`);
@@ -73,7 +38,7 @@ export function emitDerivationModules(read = publishedCoreDeclarations()) {
73
38
  if (text === undefined) {
74
39
  throw new Error(`@aventara/core's declaration closure names ${file}, which it does not publish.`);
75
40
  }
76
- const scanned = scanDeclaration(text);
41
+ const scanned = scanModuleSpecifiers(text);
77
42
  if (scanned.references) {
78
43
  throw untransportable(`${file} carries a triple-slash reference, which the emitted tree cannot satisfy`);
79
44
  }
@@ -92,10 +57,6 @@ export function emitDerivationModules(read = publishedCoreDeclarations()) {
92
57
  function untransportable(reason) {
93
58
  return new Error(`@aventara/core's declarations cannot be copied into the generated client: ${reason}.`);
94
59
  }
95
- /**
96
- * The declaration file a specifier names, relative to core's `dist`: a relative
97
- * `.js` specifier inside it, as NodeNext resolves an emitted declaration's import.
98
- */
99
60
  function declarationTarget(file, specifier) {
100
61
  const leaves = () => untransportable(`${file} names ${JSON.stringify(specifier)}, which is not a declaration file beside it`);
101
62
  if (!(specifier.startsWith("./") || specifier.startsWith("../")) ||
@@ -108,126 +69,6 @@ function declarationTarget(file, specifier) {
108
69
  }
109
70
  return target.replace(/\.js$/, ".d.ts");
110
71
  }
111
- /** `text` without its final `//# sourceMappingURL=…` line, when it ends with one. */
112
72
  function withoutSourceMapTrailer(text) {
113
73
  return text.replace(/(^|\n)\/\/# sourceMappingURL=[^\n]*\n?$/, "$1");
114
74
  }
115
- /**
116
- * A word followed directly by a string literal names a module. A pattern, not two
117
- * string comparisons: the packaging gate reads shipped JavaScript lexically, and
118
- * a keyword spelled as a quoted literal would read to it as an import.
119
- */
120
- const SPECIFIER_KEYWORD = /^(?:from|import)$/;
121
- /**
122
- * The specifiers one declaration file names, read by a small lexer rather than
123
- * by `typescript` (an optional peer, absent from a consumer's install): comments,
124
- * string literals and template literals are skipped as units, so text inside them
125
- * is never mistaken for an import. Agrees with TypeScript's own pre-processor
126
- * over core's closure (`derivation.emitter.spec.ts`).
127
- */
128
- function scanDeclaration(text) {
129
- const tokens = [];
130
- let references = false;
131
- let index = 0;
132
- const readQuoted = (quote) => {
133
- let value = "";
134
- index += 1;
135
- while (index < text.length && text[index] !== quote) {
136
- if (text[index] === "\\") {
137
- value += text[index + 1] ?? "";
138
- index += 2;
139
- continue;
140
- }
141
- value += text[index];
142
- index += 1;
143
- }
144
- index += 1;
145
- return value;
146
- };
147
- /** Scans code until the end, or until the `}` closing a `${` when `inPlaceholder`. */
148
- const scanCode = (inPlaceholder) => {
149
- let depth = 0;
150
- while (index < text.length) {
151
- const character = text[index];
152
- const next = text[index + 1];
153
- if (character === "/" && next === "/") {
154
- const end = text.indexOf("\n", index);
155
- const line = text.slice(index, end === -1 ? text.length : end);
156
- if (/^\/\/\/\s*<reference\b/.test(line)) {
157
- references = true;
158
- }
159
- index = end === -1 ? text.length : end + 1;
160
- }
161
- else if (character === "/" && next === "*") {
162
- const end = text.indexOf("*/", index + 2);
163
- index = end === -1 ? text.length : end + 2;
164
- }
165
- else if (character === '"' || character === "'") {
166
- tokens.push({ kind: "string", value: readQuoted(character) });
167
- }
168
- else if (character === "`") {
169
- scanTemplate();
170
- }
171
- else if (/[A-Za-z_$]/.test(character)) {
172
- const start = index;
173
- while (index < text.length && /[\w$]/.test(text[index])) {
174
- index += 1;
175
- }
176
- tokens.push({ kind: "word", value: text.slice(start, index) });
177
- }
178
- else if (/\s/.test(character)) {
179
- index += 1;
180
- }
181
- else {
182
- if (inPlaceholder && character === "{") {
183
- depth += 1;
184
- }
185
- else if (inPlaceholder && character === "}") {
186
- if (depth === 0) {
187
- index += 1;
188
- return;
189
- }
190
- depth -= 1;
191
- }
192
- tokens.push({ kind: "punctuation", value: character });
193
- index += 1;
194
- }
195
- }
196
- };
197
- const scanTemplate = () => {
198
- index += 1;
199
- while (index < text.length && text[index] !== "`") {
200
- if (text[index] === "\\") {
201
- index += 2;
202
- }
203
- else if (text[index] === "$" && text[index + 1] === "{") {
204
- index += 2;
205
- scanCode(true);
206
- }
207
- else {
208
- index += 1;
209
- }
210
- }
211
- index += 1;
212
- // A template is one opaque token: nothing before it pairs with it.
213
- tokens.push({ kind: "punctuation", value: "`" });
214
- };
215
- scanCode(false);
216
- const specifiers = [];
217
- tokens.forEach((token, at) => {
218
- const following = tokens[at + 1];
219
- if (token.kind !== "word") {
220
- return;
221
- }
222
- if (SPECIFIER_KEYWORD.test(token.value) && following?.kind === "string") {
223
- specifiers.push(following.value);
224
- }
225
- else if (token.value === "import" &&
226
- following?.kind === "punctuation" &&
227
- following.value === "(" &&
228
- tokens[at + 2]?.kind === "string") {
229
- specifiers.push(tokens[at + 2].value);
230
- }
231
- });
232
- return { specifiers, references };
233
- }