@aventara/client 1.0.0-rc.1 → 1.0.0-rc.11
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.
- package/CHANGELOG.md +247 -0
- package/README.md +147 -11
- package/dist/cli/command.parser.d.ts +4 -3
- package/dist/cli/command.parser.js +3 -3
- package/dist/cli/generation-failure.renderer.d.ts +2 -1
- package/dist/cli/generation-success.renderer.d.ts +2 -1
- package/dist/cli/step.reporter.d.ts +2 -1
- package/dist/cli/terminal.prompter.d.ts +2 -1
- package/dist/config/client-config.interface.d.ts +17 -0
- package/dist/config/config.loader.d.ts +8 -3
- package/dist/config/config.loader.js +20 -2
- package/dist/config/config.resolver.d.ts +10 -3
- package/dist/config/config.resolver.js +28 -0
- package/dist/config/env.cascade.d.ts +2 -6
- package/dist/config/env.cascade.js +3 -3
- package/dist/config/module-style.resolver.d.ts +3 -6
- package/dist/config/module-style.resolver.js +2 -2
- package/dist/config/tsconfig.locator.d.ts +2 -1
- package/dist/config/tsconfig.locator.js +14 -2
- package/dist/contract/contract.acceptance.d.ts +0 -1
- package/dist/contract/contract.acceptance.js +1 -1
- package/dist/contract/contract.fetcher.d.ts +2 -1
- package/dist/contract/contract.loader.d.ts +3 -2
- package/dist/emit/access.emitter.d.ts +12 -0
- package/dist/emit/access.emitter.js +263 -0
- package/dist/emit/banner.emitter.d.ts +6 -1
- package/dist/emit/banner.emitter.js +12 -8
- package/dist/emit/cached-read.emitter.d.ts +3 -0
- package/dist/emit/cached-read.emitter.js +158 -0
- package/dist/emit/client-surface.emitter.js +130 -13
- package/dist/emit/client-tree.emitter.d.ts +9 -2
- package/dist/emit/client-tree.emitter.js +51 -15
- package/dist/emit/derivation.emitter.d.ts +3 -3
- package/dist/emit/derivation.emitter.js +6 -3
- package/dist/emit/descriptor.emitter.d.ts +2 -0
- package/dist/emit/descriptor.emitter.js +28 -1
- package/dist/emit/emitted-tree.interface.d.ts +1 -1
- package/dist/emit/field-check.emitter.d.ts +2 -1
- package/dist/emit/field-check.emitter.js +2 -13
- package/dist/emit/module-specifier.scanner.d.ts +2 -1
- package/dist/emit/name.deriver.d.ts +2 -3
- package/dist/emit/name.deriver.js +6 -1
- package/dist/emit/named-type.emitter.js +12 -2
- package/dist/emit/operation-set.emitter.d.ts +3 -0
- package/dist/emit/operation-set.emitter.js +604 -0
- package/dist/emit/runtime.emitter.d.ts +5 -4
- package/dist/emit/runtime.emitter.js +484 -42
- package/dist/emit/scalar.codec.js +223 -6
- package/dist/emit/transaction.emitter.js +7 -3
- package/dist/generate.d.ts +3 -2
- package/dist/generate.js +1 -1
- package/dist/hydration/hydration-tag.format.d.ts +11 -0
- package/dist/hydration/hydration-tag.format.js +6 -0
- package/dist/init/client-init.planner.d.ts +3 -2
- package/dist/init/client-init.questions.d.ts +1 -12
- package/dist/init/client-init.questions.js +2 -2
- package/dist/internal.d.ts +25 -0
- package/dist/internal.js +11 -0
- package/dist/output/output.validator.d.ts +3 -4
- package/dist/output/output.validator.js +2 -2
- package/dist/output/output.writer.d.ts +3 -2
- package/package.json +9 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,252 @@
|
|
|
1
1
|
# @aventara/client
|
|
2
2
|
|
|
3
|
+
## 1.0.0-rc.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6197c08: `@/aventara/universal`'s calls are the generated client's own calls again. The entry no longer wraps each one in
|
|
8
|
+
`io().then(call)`, so its own `signal`, `avClient.all`'s `signal` and strict abort, and `avLazy` all reach it, in the
|
|
9
|
+
browser and on the server. Next's `io()` is now awaited before the request is sent.
|
|
10
|
+
|
|
11
|
+
In the browser, the calls made in one tick are still grouped into one `/_all`. On the server, none is grouped: each
|
|
12
|
+
call has a client of its own with grouping off, and it is sent from the async context of the code that made it. Before,
|
|
13
|
+
one queue served every request. Calls from two concurrent requests, or a call inside `unstable_cache` and one outside
|
|
14
|
+
it, could share a flush and run with the first call's headers and `state`.
|
|
15
|
+
|
|
16
|
+
`avLazy` no longer keeps one answer for every request on a server:
|
|
17
|
+
|
|
18
|
+
- The generated client's `avLazy` keeps its answer in a page. On a server (no `location`) it keeps none, and each await
|
|
19
|
+
makes the call again.
|
|
20
|
+
- `@aventara/core`'s `avLazy` keeps none: each await makes the call again.
|
|
21
|
+
- `@/aventara/universal` now exports its own `avLazy`, which keeps one answer per request inside a React render
|
|
22
|
+
(React's `cache`, which the entry now imports) and none where React keeps no request.
|
|
23
|
+
|
|
24
|
+
Before, an `avLazy` made at module scope handed the first request's answer to every request after it.
|
|
25
|
+
|
|
26
|
+
`ready()`'s in-process path now splits a cached read's GET URL into its path and its `?q=&v=` query, with an empty
|
|
27
|
+
body, so the read reaches its GET route instead of being answered as absent.
|
|
28
|
+
|
|
29
|
+
- 5ac10f7: The generated client's calls are grouped. A call runs when it is made, like `fetch` (a call never awaited still runs;
|
|
30
|
+
a transaction too), and `avLazy(() => call)`, exported beside `avClient`, makes one only when it is first awaited. The
|
|
31
|
+
calls made in one tick go out as one `POST /_all` Operation Set,
|
|
32
|
+
split at `limits.maxAll`, each resolving or throwing on its own as its streamed (NDJSON) or plain JSON answer arrives; a
|
|
33
|
+
call made alone keeps its own route. A call with `headers` or a `requestId`, a transaction, and any call made with
|
|
34
|
+
`grouping: false` (per call, or `new AvClient({ grouping: false })`) is sent alone. A server without `/_all` gets the calls
|
|
35
|
+
again one by one. A call's `signal` aborts that call only, and is never sent if it aborts first. `avClient.all({ … })`
|
|
36
|
+
awaits an object of calls: strict by default, or `{ settle: true }` for one settled entry per key, with a `signal` that
|
|
37
|
+
aborts its calls. `all` joins the client's reserved member names: a Resource named `all` is reached as `allModel`.
|
|
38
|
+
|
|
39
|
+
A read the ClientContract marks `cache` (a `cache({ for, maxAge })` stage) is sent as
|
|
40
|
+
`GET /_resources/<R>/find/<variant>?q=<args>&v=<hash>`, alone and never grouped, with only the caller's own headers: `q`
|
|
41
|
+
is the arguments' canonical JSON, percent-encoded or deflate-raw and base64url when shorter (plain where there is no
|
|
42
|
+
`CompressionStream`), and a URL longer than 4096 characters is POSTed instead. A client with a cached read carries two
|
|
43
|
+
more runtime modules, `runtime/cached-read.ts` and `runtime/canonical-json.ts` (core's writer, copied).
|
|
44
|
+
|
|
45
|
+
- Updated dependencies [6197c08]
|
|
46
|
+
- Updated dependencies [e0e89c1]
|
|
47
|
+
- Updated dependencies [186bc29]
|
|
48
|
+
- Updated dependencies [33b5f83]
|
|
49
|
+
- Updated dependencies [6d8b589]
|
|
50
|
+
- Updated dependencies [11ece49]
|
|
51
|
+
- Updated dependencies [92fd093]
|
|
52
|
+
- Updated dependencies [e5e98e6]
|
|
53
|
+
- Updated dependencies [a05d970]
|
|
54
|
+
- @aventara/core@1.0.0-rc.11
|
|
55
|
+
|
|
56
|
+
## 1.0.0-rc.10
|
|
57
|
+
|
|
58
|
+
### Patch Changes
|
|
59
|
+
|
|
60
|
+
- 7ee547b: A ClientContract whose `access` section states Aventara Access's `kiosk` verbs gives the generated client
|
|
61
|
+
`$access.switchUser`, `lock`, `setPin`, `enrollDevice` and `revokeDevice`, each a `POST` to Access's own route with its
|
|
62
|
+
arguments typed from the section's schema and its answer projected onto the result schema (`lock`, `setPin` and
|
|
63
|
+
`revokeDevice` resolve nothing). A section without them emits no member for them.
|
|
64
|
+
- d7e7369: A ClientContract with the `access` section gives the generated client `$access`: `can(questions)` (one request to
|
|
65
|
+
`/_access/can`), and exactly the Aventara Access verbs the section states (`me` with `GET` and `cache: "no-store"`,
|
|
66
|
+
`signIn`, `signUp`, `signOut`, `resetPassword`), each result projected onto the section's schema. `AvAccessMe` is
|
|
67
|
+
`me`'s result type and `AvAccessError` what a non-2xx Access answer throws. A client without the section is emitted
|
|
68
|
+
byte for byte as before. A ClientContract whose Access URL is on another origin than the
|
|
69
|
+
entrypoint's is refused unless `framework.client.ts` lists that origin in the new `accessOrigins`.
|
|
70
|
+
- 9d423f9: `avclient generate`'s reference step (a solution-style `tsconfig.json`) matches `${configDir}` entries of `files`,
|
|
71
|
+
`include` and `exclude`. `get-tsconfig` 4.10.0 makes them absolute and its file matcher joined them under the config's
|
|
72
|
+
directory again, so a referenced project including the client through `${configDir}` was passed over.
|
|
73
|
+
- 04bb39a: `engines.node` is now `^22.23.4 || >=24.22.1`, the Node security releases of 2026-10-20 (CVE-2026-105481,
|
|
74
|
+
CVE-2026-105482, CVE-2026-105483, CVE-2026-106069, CVE-2026-106072, CVE-2026-106073, CVE-2026-106074,
|
|
75
|
+
CVE-2026-111497). The bins refuse an older Node in one sentence naming that range.
|
|
76
|
+
- 88263a1: A value projected onto an `access` verb's result schema is refused with the projector's own `TypeError` when the schema
|
|
77
|
+
is outside the forms a Client Contract states (a free-form object or list, a tuple read past its length), whatever the
|
|
78
|
+
value, an empty one included. A Client Contract that passed its structure check never holds such a schema.
|
|
79
|
+
- Updated dependencies [587dd01]
|
|
80
|
+
- Updated dependencies [d7e7369]
|
|
81
|
+
- Updated dependencies [7ee547b]
|
|
82
|
+
- Updated dependencies [f52c499]
|
|
83
|
+
- Updated dependencies [2907484]
|
|
84
|
+
- Updated dependencies [a6bbdf0]
|
|
85
|
+
- Updated dependencies [3e26549]
|
|
86
|
+
- Updated dependencies [a6bbdf0]
|
|
87
|
+
- Updated dependencies [6f3f6f6]
|
|
88
|
+
- Updated dependencies [04bb39a]
|
|
89
|
+
- Updated dependencies [3fb3333]
|
|
90
|
+
- Updated dependencies [827ccb6]
|
|
91
|
+
- Updated dependencies [7f5abc3]
|
|
92
|
+
- Updated dependencies [88263a1]
|
|
93
|
+
- Updated dependencies [10341d5]
|
|
94
|
+
- Updated dependencies [8129844]
|
|
95
|
+
- Updated dependencies [88263a1]
|
|
96
|
+
- Updated dependencies [3020b5c]
|
|
97
|
+
- Updated dependencies [88263a1]
|
|
98
|
+
- Updated dependencies [88263a1]
|
|
99
|
+
- @aventara/core@1.0.0-rc.10
|
|
100
|
+
|
|
101
|
+
## 1.0.0-rc.9
|
|
102
|
+
|
|
103
|
+
### Patch Changes
|
|
104
|
+
|
|
105
|
+
- 99278e4: `aventara-build` reads a Next.js project's files from `src/aventara/` and, with `--client`, writes its browser client.
|
|
106
|
+
|
|
107
|
+
- A project whose `package.json` depends on `@aventara/next` keeps its configuration and adapter in
|
|
108
|
+
`src/aventara/config.ts` and `src/aventara/adapter.ts`; the build runs them there, and a configuration that imports no
|
|
109
|
+
Resource tree has its generated files in `src/aventara/generated/`. Every other project keeps
|
|
110
|
+
`src/aventara.config.ts` and `src/aventara.adapter.ts`, unchanged. A missing file is named with where the project's
|
|
111
|
+
host keeps it, and a project depending on both `@aventara/nest` and `@aventara/next` is refused in one sentence.
|
|
112
|
+
- `aventara-build --client` also writes the browser client from the ClientContract it has just compiled, with no
|
|
113
|
+
running server: `src/aventara/client.ts` and the client's modules under `src/aventara/generated/`, the same modules
|
|
114
|
+
`avclient generate` writes for that ClientContract except that the entrypoint is the app's own `api` on the page's
|
|
115
|
+
origin (`/api`) and the regenerate instructions. Its imports are spelled as the project's `tsconfig.json` says, and nothing it writes imports
|
|
116
|
+
`@aventara/client`.
|
|
117
|
+
- `src/aventara/client.ts` exports `avClient` and `avHydrate`, and re-exports every name `avclient generate`'s
|
|
118
|
+
`AvClient.ts` exports besides its default (`AvClient`, the Resource types, the enums, `AvDecimal`, the error
|
|
119
|
+
classes), so `import { AvDecimal } from "@/aventara/client"` works. The generated files and the contract-mismatch
|
|
120
|
+
error say to regenerate with `aventara-build --client` (the project's `aventara:prepare` script). `avClient` calls the API from the browser; a call made
|
|
121
|
+
on the server (a Client Component rendering there) rejects with one sentence pointing to `@/aventara/server` and
|
|
122
|
+
`@/aventara/universal`, and sends nothing. `avHydrate` revives data `avDehydrate` sends from the server: tagged
|
|
123
|
+
dates, `bigint`s, byte arrays and decimals become `Date`, `bigint`, `Uint8Array` and the client's own `AvDecimal`,
|
|
124
|
+
for TanStack Query's `deserializeData` or an SWR `fallback`.
|
|
125
|
+
- `aventara-build --check --client` checks those files too: a missing or stale one, or one an earlier ClientContract's
|
|
126
|
+
client left, exits 1 naming it. `--client` is refused in a NestJS project, whose frontends keep using
|
|
127
|
+
`avclient generate`, which is unchanged.
|
|
128
|
+
- `@aventara/client` gains an `@aventara/client/internal` entry, which `@aventara/build` reads the generator through.
|
|
129
|
+
It is not public API.
|
|
130
|
+
|
|
131
|
+
- Updated dependencies [205a379]
|
|
132
|
+
- Updated dependencies [a0bb05e]
|
|
133
|
+
- Updated dependencies [86ab319]
|
|
134
|
+
- Updated dependencies [fdf52e6]
|
|
135
|
+
- @aventara/core@1.0.0-rc.9
|
|
136
|
+
|
|
137
|
+
## 1.0.0-rc.8
|
|
138
|
+
|
|
139
|
+
1.0.0-rc.5, rc.6 and rc.7 were tagged but never published; 1.0.0-rc.8 contains everything listed under them and the changes below.
|
|
140
|
+
|
|
141
|
+
### Patch Changes
|
|
142
|
+
|
|
143
|
+
- A generated client's results read as their value types in an editor: `body: string | null`, `published: boolean`,
|
|
144
|
+
`publishedAt: Date | null`, where a nullable, enum or `boolean` field was shown as `AvScalarValueType<…>` with the
|
|
145
|
+
client's Contract as its argument, and a result as `ProjectedFields<…>`. Run `avclient generate` again to pick it up.
|
|
146
|
+
What the client accepts and returns is unchanged.
|
|
147
|
+
- Updated dependencies [1c8e4ee]
|
|
148
|
+
- @aventara/core@1.0.0-rc.8
|
|
149
|
+
|
|
150
|
+
## 1.0.0-rc.7
|
|
151
|
+
|
|
152
|
+
1.0.0-rc.5 and 1.0.0-rc.6 were tagged but never published; 1.0.0-rc.7 contains everything listed under them and the changes below.
|
|
153
|
+
|
|
154
|
+
### Patch Changes
|
|
155
|
+
|
|
156
|
+
- Updated dependencies [f917c1c]
|
|
157
|
+
- @aventara/core@1.0.0-rc.7
|
|
158
|
+
|
|
159
|
+
## 1.0.0-rc.6
|
|
160
|
+
|
|
161
|
+
1.0.0-rc.5 was tagged but never published. 1.0.0-rc.6 contains everything listed under 1.0.0-rc.5 and the fix below.
|
|
162
|
+
|
|
163
|
+
### Patch Changes
|
|
164
|
+
|
|
165
|
+
- Updated dependencies [1cf72e0]
|
|
166
|
+
- @aventara/core@1.0.0-rc.6
|
|
167
|
+
|
|
168
|
+
## 1.0.0-rc.5
|
|
169
|
+
|
|
170
|
+
### Patch Changes
|
|
171
|
+
|
|
172
|
+
- Updated dependencies [4795ff1]
|
|
173
|
+
- Updated dependencies [9e178ca]
|
|
174
|
+
- @aventara/core@1.0.0-rc.5
|
|
175
|
+
|
|
176
|
+
## 1.0.0-rc.4
|
|
177
|
+
|
|
178
|
+
### Patch Changes
|
|
179
|
+
|
|
180
|
+
- Updated dependencies [e3d03a7]
|
|
181
|
+
- Updated dependencies [d10639a]
|
|
182
|
+
- Updated dependencies [f67e68c]
|
|
183
|
+
- Updated dependencies [708556c]
|
|
184
|
+
- Updated dependencies [3a0dfca]
|
|
185
|
+
- Updated dependencies [99169d2]
|
|
186
|
+
- Updated dependencies [0fd2608]
|
|
187
|
+
- Updated dependencies [154e440]
|
|
188
|
+
- Updated dependencies [2fcffdb]
|
|
189
|
+
- @aventara/core@1.0.0-rc.4
|
|
190
|
+
|
|
191
|
+
## 1.0.0-rc.3
|
|
192
|
+
|
|
193
|
+
### Patch Changes
|
|
194
|
+
|
|
195
|
+
- Updated dependencies [b38034d]
|
|
196
|
+
- Updated dependencies [b38034d]
|
|
197
|
+
- Updated dependencies [b38034d]
|
|
198
|
+
- Updated dependencies [b38034d]
|
|
199
|
+
- Updated dependencies [b38034d]
|
|
200
|
+
- Updated dependencies [b38034d]
|
|
201
|
+
- @aventara/core@1.0.0-rc.3
|
|
202
|
+
|
|
203
|
+
## 1.0.0-rc.2
|
|
204
|
+
|
|
205
|
+
### Patch Changes
|
|
206
|
+
|
|
207
|
+
- The optional `typescript` peer range is `>=5.7.0` (it was `>=5.5.0`), the lowest TypeScript Aventara's types
|
|
208
|
+
compile under. `avclient generate` type-checks the client with TypeScript 5.7 or later; under an older one it parses
|
|
209
|
+
the output with Node's TypeScript parser (`checked: syntax`) and says so in one warning, as it did below 5.5.
|
|
210
|
+
- A generated client sends an `undefined` array element (or a hole) as `null`, as `JSON.stringify` writes it, and its
|
|
211
|
+
`json` codec leaves out a key holding `undefined` and writes such an element as `null`. A `json` value
|
|
212
|
+
`{ a: undefined, b: [undefined] }` is sent as `{"b":[null]}`, the value the server stores when an in-process caller
|
|
213
|
+
passes it. In rc.1 the client refused the array element with a `TypeError` before sending. Regenerate the client.
|
|
214
|
+
- A generated client's `json` values admit a key holding `undefined` in their type, as core's `AvJsonValue` now does,
|
|
215
|
+
so an object with optional properties can be passed where a `json` value is taken; the key is not sent. In rc.1 it
|
|
216
|
+
was a compile error. Regenerate the client.
|
|
217
|
+
- A generated client refuses at compile time a filter `mode` or `path` that qualifies no operator: one alone, or one
|
|
218
|
+
whose only neighbour is a `not` holding operators (`{ mode: "insensitive", not: { contains: "x" } }`). Write it
|
|
219
|
+
inside the `not`. The server refuses the same filters (`A2004`, `V1001`). Regenerate the client.
|
|
220
|
+
- A generated client types a filter's `mode` by the field: `"default"` always, and `"sensitive"` or `"insensitive"`
|
|
221
|
+
only where the ClientContract's `filterModes` lists them; any other mode is a compile error. On a `json` field an
|
|
222
|
+
operator object that names `path` takes the modes `pathFilterModes` lists instead, so on Postgres
|
|
223
|
+
`where: { meta: { stringContains: "x", mode: "insensitive" } }` is a compile error and
|
|
224
|
+
`where: { meta: { path: ["label"], stringContains: "x", mode: "insensitive" } }` compiles. `isEmpty` is typed as a boolean, `path` as an array of strings and a `json` field's `string*`
|
|
225
|
+
operand as a string. The server refuses the same values (`A2004`), so the client adds no runtime check of its own.
|
|
226
|
+
Regenerate the client: the Contract hash changes.
|
|
227
|
+
- The generated client refuses an `undefined` value in a filter before anything is sent. JSON drops `undefined`, so
|
|
228
|
+
`avClient.Post.update.many({ where: { id: undefined }, data })` reached the server as `where: {}` and updated every
|
|
229
|
+
row; the same went for `find`, `count`, `delete` and a transaction step. Now an `undefined` anywhere inside a
|
|
230
|
+
`where` (`AND`, `OR`, `NOT`, relation filters, operator objects such as `{ equals: undefined }` or
|
|
231
|
+
`{ isEmpty: undefined }`, `in` lists), a `cursor`, a unique selector, the `where` or `cursor` of a relation in
|
|
232
|
+
`select` or `include`, or a nested write's selectors (`$connect`, `$disconnect`, `$set`, `$delete`, the `where` of
|
|
233
|
+
`$update`, `$upsert` and `$connectOrCreate`) throws `AvValidationError` (`A2004`) with a `V1001` issue at the path
|
|
234
|
+
the server uses (`["arguments", "where", "id"]`, or `["operations", 0, "args", "where", "id"]` with the step's
|
|
235
|
+
`operation` for a transaction), and no request is made. A `where`, `cursor`, `limit` or `offset` that is itself
|
|
236
|
+
`undefined` is refused the same way, with the server's code (`V1001`; `V1007` for a unique selector, `V1009` for a
|
|
237
|
+
cursor), at the top level, in a relation under `select` or `include`, and in a nested write's `where`. Leave the
|
|
238
|
+
key out to mean no filter. Write data is unchanged: an `undefined` field there is not sent. Regenerate the client
|
|
239
|
+
to get the check.
|
|
240
|
+
- `avclient generate` in a directory with no config names the extensions it looks for as the docs list them:
|
|
241
|
+
`no framework.client.ts, .mts, .cts, .js, .mjs or .cjs in <directory>; …`. In rc.1 it read
|
|
242
|
+
`no framework.client.{js,ts,mjs,cjs,mts,cts} in <directory>`. `avclient --help` and `avclient generate --help` list
|
|
243
|
+
them in the same order: `framework.client.ts (or .mts, .cts, .js, .mjs, .cjs)`. Which files are read is unchanged.
|
|
244
|
+
- Updated dependencies [9366e16]
|
|
245
|
+
- Updated dependencies [9366e16]
|
|
246
|
+
- Updated dependencies [9366e16]
|
|
247
|
+
- Updated dependencies [9366e16]
|
|
248
|
+
- @aventara/core@1.0.0-rc.2
|
|
249
|
+
|
|
3
250
|
## 1.0.0-rc.1
|
|
4
251
|
|
|
5
252
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ A failed run leaves the previous output exactly as it was. The whole tree is wri
|
|
|
96
96
|
`generateAt`, validated there as one program, and only then moved into place. A run killed part-way is repaired by the
|
|
97
97
|
next run that writes, before it writes anything. A first run that fails removes the directories it created.
|
|
98
98
|
|
|
99
|
-
The validate step is a real type check when your project has the optional peer `typescript` (5.
|
|
99
|
+
The validate step is a real type check when your project has the optional peer `typescript` (5.7 to 6). It is resolved
|
|
100
100
|
from your project, so `npx @aventara/client@rc init` type-checks too, under a consumer's strictest plausible settings
|
|
101
101
|
and with nothing outside the tree resolvable. Without it, or under TypeScript 7 (which has no classic compiler API to
|
|
102
102
|
check with), the check falls back to a parse with Node's own TypeScript parser and says so in one warning. It is never
|
|
@@ -125,20 +125,112 @@ const maybe = await avClient.User.find.first({ where }); // User | null — a mi
|
|
|
125
125
|
ClientContract (tests, SSR), and `fetch` is for a custom fetch.
|
|
126
126
|
- The client has one property per Resource, one per family under it, and one per advertised variant. Only what the
|
|
127
127
|
ClientContract advertises exists, in the type and at runtime. A Resource named like one of the client's own members
|
|
128
|
-
(`tx`, `transaction`, `then`, `constructor`, `Object.prototype`'s names) is reached as `<name>Model`, with one
|
|
128
|
+
(`all`, `tx`, `transaction`, `then`, `constructor`, `Object.prototype`'s names) is reached as `<name>Model`, with one
|
|
129
129
|
warning; its wire name is unchanged.
|
|
130
130
|
- A call resolves to the data: the record, a list, a count. A first-style miss (`A1001`) is `null`. Every other
|
|
131
131
|
outcome throws the `AvError` subclass of its code (`AvNotFoundError` for a strict-unique miss,
|
|
132
132
|
`AvContractMismatchError` for a stale client, …), or `AvTransportError` when no framework answer arrived.
|
|
133
133
|
- Values are application values: `bigint`, `Date`, `Uint8Array`, the client's `AvDecimal`, JSON values as they are.
|
|
134
134
|
Arguments are encoded and results revived for you; a value that cannot be read throws `AvTransportError`.
|
|
135
|
-
- Per-call options (`AvCallOptions`) are never sent in the body: `signal` (
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
- Per-call options (`AvCallOptions`) are never sent in the body: `signal` (aborts this call only, see below),
|
|
136
|
+
`headers` (the framework's own identity headers are refused), `requestId`, sent as `Aventara-Request-Id` and winning
|
|
137
|
+
over that header in `headers`, and `grouping: false` (see below).
|
|
138
138
|
- The named types (`User`, `UserWhere`, `UserUniqueWhere`, `UserOrderBy`, `UserCreateData`, `UserUpdateData`,
|
|
139
139
|
`UserSelect`, `UserInclude`) are named exports, each only when the operation it reads is advertised. A name that would
|
|
140
140
|
clash walks the rename ladder (`User` beside a Resource `UserWhere` becomes `UserModel`), one warning each.
|
|
141
141
|
|
|
142
|
+
## Calls run when made, together
|
|
143
|
+
|
|
144
|
+
A call runs when you make it, as `fetch` does: it checks and encodes its arguments and is queued at once, and a call
|
|
145
|
+
you never await still runs. A transaction too. Awaiting a call again does not send it again.
|
|
146
|
+
|
|
147
|
+
The calls made in one tick go out as one request, `POST /_all` (an Operation Set):
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const [campaigns, unread, me] = await Promise.all([
|
|
151
|
+
avClient.Campaign.find.many({ where: { ownerId } }),
|
|
152
|
+
avClient.Message.find.count({ where: { toId: ownerId, readAt: null } }),
|
|
153
|
+
avClient.User.find.unique({ where: { id: ownerId } }),
|
|
154
|
+
]); // one request
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- Each call runs on the server exactly as it would alone (validation, exposure, policy, limits, pipelines), concurrently
|
|
158
|
+
with the others and not atomically: a write that ran stays written whatever the others answered. Each call resolves
|
|
159
|
+
or throws on its own, as soon as its own answer arrives (the client asks for a streamed answer,
|
|
160
|
+
`Accept: application/x-ndjson`, where the runtime can read one, and reads a plain JSON answer otherwise, as on React
|
|
161
|
+
Native).
|
|
162
|
+
- Together means made before the microtask queue settles: one `Promise.all`, several async functions run together,
|
|
163
|
+
`avClient.all`. No timer is involved, and a call made on its own goes to its own route as before.
|
|
164
|
+
- A group larger than the ClientContract's `limits.maxAll` (or `limits.maxRequestBytes`) is split into several
|
|
165
|
+
requests.
|
|
166
|
+
- Sent alone, never grouped: a call with `headers` or a `requestId` (they belong to one request), a call made with
|
|
167
|
+
`{ grouping: false }`, every call of a client made with `new AvClient({ grouping: false })`, and a transaction.
|
|
168
|
+
- A server without `/_all` (it answers `A2002`) gets the calls again one by one, and that client stops grouping.
|
|
169
|
+
|
|
170
|
+
### Aborting a call
|
|
171
|
+
|
|
172
|
+
A call's `signal` aborts that call and nothing else. Aborted before it is sent, it is never sent. Aborted while its
|
|
173
|
+
group is in flight, it rejects at once with the signal's reason (an `AbortError`), and the others in the request go on;
|
|
174
|
+
the request itself is aborted once no call in it still waits for an answer. Sent alone, the abort aborts its request,
|
|
175
|
+
as before. The server still finishes an operation it has already started: there is no way to cancel a database query
|
|
176
|
+
once it runs.
|
|
177
|
+
|
|
178
|
+
Nothing is aborted for you: there is no default timeout and no abort on navigation. Pass the signal your data library
|
|
179
|
+
gives you (React Query and SWR pass one per query), or your own.
|
|
180
|
+
|
|
181
|
+
### `avClient.all`
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const { campaigns, unread } = await avClient.all({
|
|
185
|
+
campaigns: avClient.Campaign.find.many({ where: { ownerId } }),
|
|
186
|
+
unread: avClient.Message.find.count({ where: { toId: ownerId, readAt: null } }),
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`all` takes an object of calls and resolves one value per key, typed per key. It is strict: the first failure rejects
|
|
191
|
+
it with that call's error and aborts its other calls. That is fail-fast, not atomic: a write that already ran stays
|
|
192
|
+
written. With `{ settle: true }` every key settles on its own, as `{ status: "fulfilled", value }` or
|
|
193
|
+
`{ status: "rejected", reason }`, and `all` never rejects for one key:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const panels = await avClient.all({ campaigns, unread }, { settle: true });
|
|
197
|
+
if (panels.unread.status === "rejected") { /* show that panel's error */ }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`{ signal }` aborts every call of that `all`; a call inside it is aborted by its own signal or by the `all`'s. Calls
|
|
201
|
+
grouped beside it but not in it are never touched. The keys are yours and are never sent.
|
|
202
|
+
|
|
203
|
+
### `avLazy`: describe now, run later
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import avClient, { avLazy } from "./api/AvClient";
|
|
207
|
+
|
|
208
|
+
const posts = avLazy(() => avClient.Post.find.many({ where: { published: true } })); // nothing sent yet
|
|
209
|
+
const list = await posts; // sent now (once, in a page)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`avLazy(() => call)` makes the call on its first `then`, `catch` or `finally`, and settles as that call does. In a
|
|
213
|
+
page it makes the call once and keeps the answer. On a server, where one module serves every request, it keeps nothing:
|
|
214
|
+
each await makes the call again. `avClient.all` accepts it as it accepts a call (its `signal` aborts that call too).
|
|
215
|
+
|
|
216
|
+
## Cached reads are GETs
|
|
217
|
+
|
|
218
|
+
A read the deployment caches (a `cache({ for, maxAge })` stage on it, which its ClientContract marks) is sent as a GET,
|
|
219
|
+
so the browser, or a CDN when the stage allows one, may keep its answer:
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
GET <entrypoint>/_resources/Product/find/many?q=<arguments>&v=<ClientContract hash>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- `q` is the arguments' canonical JSON (keys sorted, so the same read is the same URL), percent-encoded, or that JSON
|
|
226
|
+
deflate-raw'd and base64url'd when that is shorter. Where the runtime has no `CompressionStream` the plain form is sent.
|
|
227
|
+
- A cached read is never grouped into `/_all`: each keeps its own URL, its own cache entry. Your `headers` and
|
|
228
|
+
`requestId` go with the GET; it sends no header of its own, so a cross-origin read needs no CORS preflight. Its
|
|
229
|
+
`signal` aborts it as any call's does.
|
|
230
|
+
- A URL longer than 4096 characters (the whole URL) is POSTed to the same route instead, uncached, as are arguments
|
|
231
|
+
canonical JSON cannot write.
|
|
232
|
+
- The URL holds the arguments, so it lands in server and proxy logs and in browser history.
|
|
233
|
+
|
|
142
234
|
## Transactions
|
|
143
235
|
|
|
144
236
|
When the ClientContract advertises `interactive` transactions, the client has `avClient.tx` and `avClient.transaction`
|
|
@@ -170,7 +262,7 @@ Its source field must have the same type as where it is written:
|
|
|
170
262
|
|
|
171
263
|
A mismatch is a type error, and the server refuses it before anything runs (`A2007`/`V1011`).
|
|
172
264
|
|
|
173
|
-
`avClient.tx.…` builds a handle and sends nothing. `avClient.transaction([...])` sends the plan once and resolves one
|
|
265
|
+
`avClient.tx.…` builds a handle and sends nothing. `avClient.transaction([...])` sends the plan once, when made, and resolves one
|
|
174
266
|
result per handle, typed, in order; a failing step throws its error with `cause.operation` naming the step. `$ref` binds
|
|
175
267
|
to the handle's position in the list it runs with. Two mistakes are refused before anything is sent, as core refuses
|
|
176
268
|
them in process: one handle twice (`AvValidationError`, `A2004`/`V1001`), and a `$ref` to a handle not in the list
|
|
@@ -192,6 +284,42 @@ The platform `fetch` is read when a call is made, not when the client is importe
|
|
|
192
284
|
where there is no `fetch`; a call does, saying why. An entrypoint carrying credentials is refused when the config is
|
|
193
285
|
resolved.
|
|
194
286
|
|
|
287
|
+
## Aventara Access: `$access`
|
|
288
|
+
|
|
289
|
+
When the deployment's ClientContract has the `access` section (the framework is configured with `access`), the client
|
|
290
|
+
has `$access`:
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
const answers = await avClient.$access.can([
|
|
294
|
+
{ resource: "Order", action: "update", where: { id: 41 } },
|
|
295
|
+
{ resource: "Refund", action: "create" },
|
|
296
|
+
]); // [boolean, boolean], one request to /_access/can
|
|
297
|
+
await avClient.$access.signIn({ email, password }); // Access's own route
|
|
298
|
+
const me = await avClient.$access.me(); // AvAccessMe | null
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`can` is always there; `me`, `signIn`, `signUp`, `signOut` and `resetPassword`, and on Access's `kiosk` profile
|
|
302
|
+
`switchUser`, `lock`, `setPin`, `enrollDevice` and `revokeDevice`, exactly when the section states them.
|
|
303
|
+
Each verb calls Access's own route (`me` with `GET` and `cache: "no-store"`), and resolves its result projected onto the
|
|
304
|
+
section's schema: members the schema does not declare are dropped. `AvAccessMe` is `me`'s result type. A non-2xx answer
|
|
305
|
+
from Access throws `AvAccessError` (`status`, `code`, `message`); `can`'s refusals are `AvError`s, as every call's.
|
|
306
|
+
Without the section there is no `$access`.
|
|
307
|
+
|
|
308
|
+
Where Access lives decides where a sign-in's credentials go, so the generator emits an absolute Access URL only when it
|
|
309
|
+
is on the entrypoint's origin, or on an origin `framework.client.ts` lists:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
export default defineClientConfig({
|
|
313
|
+
entrypoint: env("AVENTARA_API_URL"),
|
|
314
|
+
generateAt: "./src/api",
|
|
315
|
+
accessOrigins: ["https://auth.example.com"],
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
A verb on another origin carries cookies only when your `fetch` sends them: pass one that does
|
|
320
|
+
(`new AvClient({ fetch: (url, init) => fetch(url, { ...init, credentials: "include" }) })`), and have Access allow
|
|
321
|
+
that origin with credentials (CORS).
|
|
322
|
+
|
|
195
323
|
## Up to date
|
|
196
324
|
|
|
197
325
|
A rerun asks the deployment conditionally (`If-None-Match`, the ClientContract hash of the output it finds), but only
|
|
@@ -208,7 +336,7 @@ repository uses. The `.d.ts` files are core's copied declarations under `generat
|
|
|
208
336
|
and the named types in `generated/types.d.ts`; the `.ts` sources carry their own types.
|
|
209
337
|
|
|
210
338
|
- `AvClient.ts`: the entry point you import: `avClient` (the default export), `AvClient`, `AvClientOptions`,
|
|
211
|
-
`AvCallOptions`, `AvFetch`, `AvOperation`, the named Resource types, the enums, `AvDecimal`, `AvError` and its
|
|
339
|
+
`AvCallOptions`, `AvFetch`, `AvOperation`, `avLazy`, the named Resource types, the enums, `AvDecimal`, `AvError` and its
|
|
212
340
|
subclasses, `AvTransportError`, and the types `AvCause`, `AvValidationIssue`, `AvOperationCode` and `AvValidationCode`.
|
|
213
341
|
- `generated/client.ts`: the typed client: the class `AvClient`, `AvClientOptions`, `AvCallOptions` and the ready
|
|
214
342
|
instance `avClient`. Every argument and result type is an instantiation of core's own derivation.
|
|
@@ -219,6 +347,10 @@ and the named types in `generated/types.d.ts`; the `.ts` sources carry their own
|
|
|
219
347
|
- `generated/enums.ts`: each enum as a union type and a same-named `as const` object.
|
|
220
348
|
- `generated/metadata.ts`: the ClientContract hash and protocol version the client is bound to, and the entrypoint it
|
|
221
349
|
was generated from, which is its default deployment (an entrypoint carrying credentials is refused at resolution).
|
|
350
|
+
- `generated/runtime/cached-read.ts`: a cached read's GET: its `q` (canonical JSON, plain or deflate-raw), its
|
|
351
|
+
`v`, and the POST past 4096 characters. Emitted only when the ClientContract caches a read.
|
|
352
|
+
- `generated/runtime/canonical-json.ts`: `@aventara/core`'s canonical JSON writer, its compiled source copied as it is
|
|
353
|
+
(unchecked: `// @ts-nocheck`). Emitted only when the ClientContract caches a read.
|
|
222
354
|
- `generated/runtime/codec.ts`: the nine scalars' wire codecs, and the request-body serializer.
|
|
223
355
|
- `generated/runtime/decimal.ts`: the framework's `AvDecimal`, with a constructor, `toString` and `toJSON`.
|
|
224
356
|
- `generated/runtime/descriptor.ts`: what the runtime reads of the contract: the result fields it revives and the
|
|
@@ -235,12 +367,16 @@ and the named types in `generated/types.d.ts`; the `.ts` sources carry their own
|
|
|
235
367
|
carries a check.
|
|
236
368
|
- `generated/runtime/fingerprint.ts`: the operation fingerprint (RFC 8785 canonical JSON, SHA-256, base64url),
|
|
237
369
|
dependency-free and pinned to core's. Emitted only when transactions are `interactive`.
|
|
370
|
+
- `generated/runtime/operation-set.ts`: the calls, queued when made, the grouping of the calls made together into
|
|
371
|
+
Operation Sets
|
|
372
|
+
(`POST /_all`), per-call abort, and `avClient.all`.
|
|
238
373
|
- `generated/runtime/transaction.ts`: `avClient.tx`'s deferred handles and `avClient.transaction`'s plan assembly,
|
|
239
374
|
refusals and one POST to `/_transactions`. Emitted only when transactions are `interactive`.
|
|
240
|
-
- `generated/runtime/transport.ts`: one POST per operation
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
375
|
+
- `generated/runtime/transport.ts`: one POST per operation, or one `POST /_all` per Operation Set (its answer read
|
|
376
|
+
streamed or whole), with the identity headers, and the response read by the protocol's rule. Arguments are encoded
|
|
377
|
+
by value, results revived by the decode table, and the platform's own `fetch` type is accepted. Its primitives are
|
|
378
|
+
module-private: no public file re-exports them, and `AvClient`'s methods reach them through
|
|
379
|
+
`generated/runtime/operation-set.ts`.
|
|
244
380
|
- `generated/types.d.ts`: the named Resource types, as a declaration file (`User`, `UserWhere`, `UserUniqueWhere`,
|
|
245
381
|
`UserOrderBy`, `UserCreateData`, `UserUpdateData`, `UserSelect`, `UserInclude`), each only when its operation is
|
|
246
382
|
advertised.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const USAGE = "avclient \u2014 generate a typed Aventara client from a deployed ClientContract.\n\nUsage:\n avclient generate [--yes] Read framework.client.ts (or .
|
|
2
|
-
export declare const GENERATE_USAGE = "Usage: avclient generate [--yes]\n\nRead framework.client.ts (or .
|
|
1
|
+
export declare const USAGE = "avclient \u2014 generate a typed Aventara client from a deployed ClientContract.\n\nUsage:\n avclient generate [--yes] Read framework.client.ts (or .mts, .cts, .js, .mjs,\n .cjs) in the current directory, fetch\n <entrypoint>/_contract, and write AvClient.ts and\n generated/ into its generateAt directory, its imports\n spelled as the project's tsconfig.json says.\n avclient init [options] Set up this frontend: write framework.client.ts, the\n .env entry, the avclient:generate script and the\n @aventara/client devDependency; install; generate.\n --entrypoint <url> The server's entrypoint [http://localhost:3000/api].\n --env-var <NAME> Read it from this variable [AVENTARA_API_URL].\n --no-env-var Write it into framework.client.ts as a literal.\n --generate-at <dir> Where the client goes [./src/api].\n --package-manager <npm|pnpm> [the lockfile's, else the launching one, else npm]\n --skip-install Print the install instead of running it.\n --skip-generate Do not generate now.\n -y, --yes Accept every default, and replace differing content.\n avclient --help Print this and exit 0.\n avclient <command> --help Print that command's usage and exit 0.\n avclient --version, -v Print this generator's version and exit 0.\n\nOptions:\n -y, --yes Overwrite or remove content in AvClient.ts and generated/ that the\n generator did not produce, without asking. Without it, such content\n is listed and you are asked; where nobody can answer (stdin is not a\n terminal, as in CI), the run is refused and nothing is touched.\n\nThe generator owns AvClient.ts and generated/ in generateAt, and nothing else\nthere: your own files beside them are never read, moved or removed. Generated\nfiles are replaced on every run; do not edit them.\n\nBefore framework.client.ts is evaluated, the .env cascade is read from the\ncurrent directory, highest precedence first: the process environment,\n.env.<mode>.local, .env.<mode>, .env.local, .env \u2014 where mode is NODE_ENV, or\n\"development\".\n";
|
|
2
|
+
export declare const GENERATE_USAGE = "Usage: avclient generate [--yes]\n\nRead framework.client.ts (or .mts, .cts, .js, .mjs, .cjs) in the current directory,\nfetch <entrypoint>/_contract, and write AvClient.ts and generated/ into its\ngenerateAt directory, its imports spelled as the project's tsconfig.json says.\n\nOptions:\n -y, --yes Overwrite or remove content in AvClient.ts and generated/ that the\n generator did not produce, without asking. Without it, such content\n is listed and you are asked; where nobody can answer (stdin is not a\n terminal, as in CI), the run is refused and nothing is touched.\n\nThe generator owns AvClient.ts and generated/ in generateAt, and nothing else\nthere: your own files beside them are never read, moved or removed.\n\nBefore the config is evaluated, the .env cascade is read from the current\ndirectory, highest precedence first: the process environment, .env.<mode>.local,\n.env.<mode>, .env.local, .env \u2014 where mode is NODE_ENV, or \"development\".\n";
|
|
3
3
|
export declare const INIT_USAGE = "Usage: avclient init [options]\n\nSet up this frontend: write framework.client.ts, the .env entry, the avclient:generate\nscript and the @aventara/client devDependency; install; generate.\n\nOptions:\n --entrypoint <url> The server's entrypoint [http://localhost:3000/api].\n --env-var <NAME> Read it from this variable [AVENTARA_API_URL].\n --no-env-var Write it into framework.client.ts as a literal.\n --generate-at <dir> Where the client goes [./src/api].\n --package-manager <npm|pnpm> [the lockfile's, else the launching one, else npm]\n --skip-install Print the install instead of running it.\n --skip-generate Do not generate now.\n --verbose Show the install's output as it runs.\n -y, --yes Accept every default, and replace differing content.\n\nOn a terminal every unanswered question is asked; anywhere else, pass its flag\nor --yes, or the run stops before writing anything.\n";
|
|
4
4
|
export type ClientInitCommand = {
|
|
5
5
|
readonly command: "init";
|
|
@@ -12,7 +12,7 @@ export type ClientInitCommand = {
|
|
|
12
12
|
readonly verbose?: boolean;
|
|
13
13
|
};
|
|
14
14
|
/** What the command line asked for. */
|
|
15
|
-
|
|
15
|
+
type CliCommand = {
|
|
16
16
|
readonly command: "help";
|
|
17
17
|
readonly topic?: "generate" | "init";
|
|
18
18
|
} | {
|
|
@@ -30,3 +30,4 @@ export declare class AvCliCommandError extends Error {
|
|
|
30
30
|
* `--help`/`-h` or `--version`/`-v`.
|
|
31
31
|
*/
|
|
32
32
|
export declare function parseCliCommand(argv: readonly string[]): CliCommand;
|
|
33
|
+
export {};
|
|
@@ -2,8 +2,8 @@ import { CLIENT_CONFIG_FILE } from "../config/config.loader.js";
|
|
|
2
2
|
export const USAGE = `avclient — generate a typed Aventara client from a deployed ClientContract.
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
|
-
avclient generate [--yes] Read ${CLIENT_CONFIG_FILE} (or .
|
|
6
|
-
.
|
|
5
|
+
avclient generate [--yes] Read ${CLIENT_CONFIG_FILE} (or .mts, .cts, .js, .mjs,
|
|
6
|
+
.cjs) in the current directory, fetch
|
|
7
7
|
<entrypoint>/_contract, and write AvClient.ts and
|
|
8
8
|
generated/ into its generateAt directory, its imports
|
|
9
9
|
spelled as the project's tsconfig.json says.
|
|
@@ -39,7 +39,7 @@ current directory, highest precedence first: the process environment,
|
|
|
39
39
|
`;
|
|
40
40
|
export const GENERATE_USAGE = `Usage: avclient generate [--yes]
|
|
41
41
|
|
|
42
|
-
Read ${CLIENT_CONFIG_FILE} (or .
|
|
42
|
+
Read ${CLIENT_CONFIG_FILE} (or .mts, .cts, .js, .mjs, .cjs) in the current directory,
|
|
43
43
|
fetch <entrypoint>/_contract, and write AvClient.ts and generated/ into its
|
|
44
44
|
generateAt directory, its imports spelled as the project's tsconfig.json says.
|
|
45
45
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
interface GenerationFailureReport {
|
|
2
2
|
readonly exitCode: number;
|
|
3
3
|
/** What goes to stderr, newline-terminated: the warnings carried, then the sentence. */
|
|
4
4
|
readonly text: string;
|
|
5
5
|
}
|
|
6
6
|
export declare function renderGenerationFailure(error: unknown): GenerationFailureReport;
|
|
7
|
+
export {};
|
|
@@ -6,7 +6,7 @@ import type { ClientGenerated, ClientUpToDate, ForeignOutputContent } from "../g
|
|
|
6
6
|
* them — renames, the degraded check, crash recovery — so the same run prints the
|
|
7
7
|
* same lines.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
interface GenerationSuccessReport {
|
|
10
10
|
/** What goes to stdout, newline-terminated. */
|
|
11
11
|
readonly stdout: string;
|
|
12
12
|
/** What goes to stderr: one line per warning, or nothing. */
|
|
@@ -29,3 +29,4 @@ export declare const FOREIGN_CONTENT_QUESTION = "avclient: overwrite them and ge
|
|
|
29
29
|
* are reported as a refused one's are.
|
|
30
30
|
*/
|
|
31
31
|
export declare function renderForeignContentCancellation(found: ForeignOutputContent, asked: boolean): string;
|
|
32
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type ProgressMode = "live" | "plain" | "off";
|
|
2
2
|
/** `live` only on a terminal that is not CI and accepts control sequences. */
|
|
3
3
|
export declare function progressModeOf(isTTY: boolean | undefined, env: Readonly<Record<string, string | undefined>>): Exclude<ProgressMode, "off">;
|
|
4
|
-
|
|
4
|
+
type StepReporterOptions = {
|
|
5
5
|
/** Where the lines go: the tool's stderr, so its stdout stays its result. */
|
|
6
6
|
readonly write: (text: string) => void;
|
|
7
7
|
readonly mode: ProgressMode;
|
|
@@ -29,3 +29,4 @@ export type StepReporter = {
|
|
|
29
29
|
/** `12.4s`, or `1m 02s` from a minute. */
|
|
30
30
|
export declare function formatElapsed(milliseconds: number): string;
|
|
31
31
|
export declare function createStepReporter(options: StepReporterOptions): StepReporter;
|
|
32
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
type TerminalPrompter = {
|
|
2
2
|
readonly ask: (prompt: string) => Promise<string>;
|
|
3
3
|
readonly confirm: (question: string) => Promise<boolean>;
|
|
4
4
|
readonly close: () => void;
|
|
5
5
|
};
|
|
6
6
|
export declare function createTerminalPrompter(): TerminalPrompter;
|
|
7
|
+
export {};
|
|
@@ -28,6 +28,13 @@ export interface AvClientConfigInput {
|
|
|
28
28
|
* `generateAt` is used.
|
|
29
29
|
*/
|
|
30
30
|
readonly tsconfigFile?: string;
|
|
31
|
+
/**
|
|
32
|
+
* The origins other than the entrypoint's that `$access` may send a
|
|
33
|
+
* sign-in to (`"https://auth.example.com"`): where the deployment mounted
|
|
34
|
+
* Aventara Access, when that is another origin. Absent, the generator
|
|
35
|
+
* refuses a ClientContract whose Access URL is on another origin.
|
|
36
|
+
*/
|
|
37
|
+
readonly accessOrigins?: readonly AvClientConfigValue[];
|
|
31
38
|
}
|
|
32
39
|
/** A filesystem path known to be absolute. */
|
|
33
40
|
export type AbsolutePath = string & {
|
|
@@ -44,11 +51,21 @@ export interface ClientEntrypoint {
|
|
|
44
51
|
readonly deployment: URL;
|
|
45
52
|
readonly path: EntrypointPath;
|
|
46
53
|
}
|
|
54
|
+
/** An entrypoint on the page's own origin: its mount path alone, such as `/api`. */
|
|
55
|
+
export interface SameOriginEntrypoint {
|
|
56
|
+
/** Absent: the deployment is whichever origin served the page. */
|
|
57
|
+
readonly deployment?: undefined;
|
|
58
|
+
readonly path: EntrypointPath;
|
|
59
|
+
}
|
|
60
|
+
/** The entrypoint a generated client embeds as its default: a deployment's, or the page's own origin. */
|
|
61
|
+
export type EmittedEntrypoint = ClientEntrypoint | SameOriginEntrypoint;
|
|
47
62
|
export interface ResolvedClientConfig {
|
|
48
63
|
readonly entrypoint: ClientEntrypoint;
|
|
49
64
|
/** `generateAt`, made absolute. */
|
|
50
65
|
readonly generateAt: AbsolutePath;
|
|
51
66
|
/** `tsconfigFile`, made absolute; absent when the config names none. */
|
|
52
67
|
readonly tsconfigFile?: AbsolutePath;
|
|
68
|
+
/** `accessOrigins`, each an http(s) origin (`scheme://host[:port]`); empty when the config names none. */
|
|
69
|
+
readonly accessOrigins: readonly string[];
|
|
53
70
|
readonly mode: string;
|
|
54
71
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { AvClientConfigInput } from "./client-config.interface.js";
|
|
2
2
|
/** Prisma's `SUPPORTED_EXTENSIONS`, in its order. */
|
|
3
3
|
export declare const CLIENT_CONFIG_FILE_EXTENSIONS: readonly [".js", ".ts", ".mjs", ".cjs", ".mts", ".cts"];
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The same extensions as the docs and `avclient --help` list them, TypeScript
|
|
6
|
+
* first: the order a sentence to the developer names them in. Lookup keeps
|
|
7
|
+
* {@link CLIENT_CONFIG_FILE_EXTENSIONS}' order, Prisma's.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CLIENT_CONFIG_FILE_EXTENSIONS_AS_LISTED: readonly [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
6
10
|
/** The config file `avclient init` writes when the project has none. */
|
|
7
11
|
export declare const CLIENT_CONFIG_FILE = "framework.client.ts";
|
|
8
|
-
|
|
12
|
+
interface LoadedClientConfig {
|
|
9
13
|
/** The config file's absolute path; `generateAt` resolves against its directory. */
|
|
10
14
|
readonly file: string;
|
|
11
15
|
readonly config: AvClientConfigInput;
|
|
@@ -30,3 +34,4 @@ export declare function findClientConfigFile(directory: string): string | undefi
|
|
|
30
34
|
* or the file does not evaluate, or does not default-export a client config.
|
|
31
35
|
*/
|
|
32
36
|
export declare function loadClientConfigFile(directory: string): Promise<LoadedClientConfig>;
|
|
37
|
+
export {};
|