@fabrika/app 0.5.5 → 0.7.0
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/package.json +9 -9
- package/skill/SKILL.md +29 -21
- package/skill/references/app-setup.md +54 -36
- package/skill/references/dev.md +5 -5
- package/skill/references/endpoint.md +152 -25
- package/skill/references/errors.md +26 -23
- package/skill/references/files.md +187 -137
- package/skill/references/jobs.md +82 -35
- package/skill/references/public-intake.md +387 -236
- package/skill/references/spa.md +5 -5
- package/skill/references/start.md +2 -1
- package/skill/references/table-and-migration.md +24 -2
- package/skill/references/tests.md +8 -5
- package/skill/references/webhooks-links-connectors.md +65 -12
- package/src/bun.ts +3 -2
- package/src/client/contract.ts +184 -74
- package/src/client/index.ts +2 -1
- package/src/client/transport.ts +7 -2
- package/src/cloudflare.ts +2 -0
- package/src/contract/artifact-schema.ts +110 -15
- package/src/contract/build.ts +1184 -613
- package/src/contract/compile.ts +44 -10
- package/src/contract/connect.ts +71 -5
- package/src/contract/context.ts +132 -23
- package/src/contract/declaration.ts +78 -63
- package/src/contract/defaults.ts +64 -58
- package/src/contract/define.ts +76 -124
- package/src/contract/file.ts +78 -0
- package/src/contract/group.ts +244 -37
- package/src/contract/index.ts +18 -0
- package/src/contract/kit.ts +206 -126
- package/src/contract/platform.ts +8 -9
- package/src/contract/redirect.ts +49 -0
- package/src/contract/schema-from-shape.ts +7 -0
- package/src/contract/schema-shape.ts +10 -0
- package/src/contract/snapshot-source.ts +5 -0
- package/src/contract/token.ts +89 -0
- package/src/contract/webhook-binding.ts +26 -0
- package/src/contract/webhook-scheme.ts +32 -0
- package/src/files/handle.ts +22 -0
- package/src/files/kinds.ts +454 -0
- package/src/files/scan.ts +15 -9
- package/src/files/streams.ts +111 -0
- package/src/honeypot.ts +7 -0
- package/src/implement/anonymous.ts +18 -42
- package/src/implement/boot.ts +177 -159
- package/src/implement/bounded.ts +23 -0
- package/src/implement/browser-config.ts +4 -4
- package/src/implement/capability.ts +78 -2
- package/src/implement/{form-admission.ts → client-address.ts} +3 -38
- package/src/implement/dispatch.ts +810 -409
- package/src/implement/egress.ts +84 -0
- package/src/implement/faults.ts +11 -1
- package/src/implement/index.ts +3 -2
- package/src/implement/invocation.ts +135 -35
- package/src/implement/params.ts +88 -0
- package/src/implement/principal.ts +7 -0
- package/src/implement/public.ts +142 -0
- package/src/implement/tokens.ts +219 -0
- package/src/implement/types.ts +24 -3
- package/src/implement/urls.ts +78 -0
- package/src/implement/verifiers.ts +299 -0
- package/src/implement/webhook.ts +136 -55
- package/src/implement/workload.ts +16 -14
- package/src/index.ts +3 -0
- package/src/jobs/mail.ts +98 -10
- package/src/jobs/runner.ts +103 -71
- package/src/jobs/scrub.ts +4 -1
- package/src/jobs/types.ts +19 -2
- package/src/react/hooks.ts +2 -2
- package/src/react/provider.tsx +2 -2
- package/src/testing/dev.ts +2 -2
- package/src/testing/endpoint-access.ts +167 -128
- package/src/testing/kit.ts +79 -24
- package/src/testing/policy-isolation.ts +55 -29
- package/src/testing/proxy.ts +6 -2
- package/src/testing/sample-file.ts +30 -0
- package/src/client/files.ts +0 -135
- package/src/contract/file-schemas.ts +0 -25
- package/src/files/collections.ts +0 -848
package/src/contract/group.ts
CHANGED
|
@@ -2,15 +2,44 @@
|
|
|
2
2
|
// handler with `.handle(fn)` beside it. `.handle` returns the declaration without the handler's type, so a contract
|
|
3
3
|
// of many endpoints stays cheap to type-check, and an endpoint without `.handle` is not a group member.
|
|
4
4
|
|
|
5
|
-
import type { RpcCaller } from '@fabrika/auth-core'
|
|
5
|
+
import type { EndpointCache, RpcCaller } from '@fabrika/auth-core'
|
|
6
6
|
import type { AnyDbIndex, ReadOnlyUnscoped, Unavailable, UnscopedDeclaration, UnscopedMode } from '@fabrika/db/tables'
|
|
7
7
|
import type { z } from 'zod/v4'
|
|
8
8
|
import type { Snake } from '../from-row'
|
|
9
9
|
import type { ExtraKeys, HandlerInput, IsAny } from '../implement/types'
|
|
10
10
|
import type { AttachmentBrand } from './attachment'
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
CheckedAccess,
|
|
13
|
+
Declared,
|
|
14
|
+
EndpointContext,
|
|
15
|
+
ExportContext,
|
|
16
|
+
ImportOf,
|
|
17
|
+
KickContext,
|
|
18
|
+
KitTypes,
|
|
19
|
+
LinkContext,
|
|
20
|
+
PublicContext,
|
|
21
|
+
SqlMode,
|
|
22
|
+
TokensContext,
|
|
23
|
+
WebhooksContext,
|
|
24
|
+
} from './context'
|
|
12
25
|
import type { ProcedureType } from './declaration'
|
|
13
|
-
import type {
|
|
26
|
+
import type {
|
|
27
|
+
AppAccess,
|
|
28
|
+
CapabilitiesAccess,
|
|
29
|
+
CapabilityAccess,
|
|
30
|
+
ChallengeOption,
|
|
31
|
+
InputOf,
|
|
32
|
+
InputSchema,
|
|
33
|
+
LinkAccess,
|
|
34
|
+
MemberAccess,
|
|
35
|
+
MutationAccess,
|
|
36
|
+
NotLoose,
|
|
37
|
+
Procedure,
|
|
38
|
+
PublicAccess,
|
|
39
|
+
QueryAccess,
|
|
40
|
+
Schema,
|
|
41
|
+
} from './define'
|
|
42
|
+
import type { WithClaims } from './token'
|
|
14
43
|
|
|
15
44
|
/** Fields a builder sets itself: a definition that carries one does not type-check. */
|
|
16
45
|
type Owned<K extends string> = { readonly [P in K]?: never }
|
|
@@ -55,24 +84,105 @@ type OneLiteral<Is> = string extends Is ? Unavailable<"issues names one link mou
|
|
|
55
84
|
: true extends IsUnion<Is> ? Unavailable<"issues names one link mount, as a literal: issues: 'shared'">
|
|
56
85
|
: unknown
|
|
57
86
|
|
|
58
|
-
/**
|
|
59
|
-
type
|
|
60
|
-
|
|
87
|
+
/** A query writes nothing, so it has nothing to kick a job for and no binding to write. */
|
|
88
|
+
type NoKick = {
|
|
89
|
+
readonly kicks?: Unavailable<'a query kicks no job: declare kicks on a mutation'>
|
|
90
|
+
readonly binds?: Unavailable<'a query binds no webhook: declare binds on a mutation'>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** `binds` names one webhook, as a literal. */
|
|
94
|
+
type OneWebhook<Bs> = string extends Bs ? Unavailable<"binds names one webhook, as a literal: binds: 'stripe'">
|
|
95
|
+
: true extends IsUnion<Bs> ? Unavailable<"binds names one webhook, as a literal: binds: 'stripe'">
|
|
61
96
|
: unknown
|
|
62
97
|
|
|
63
|
-
/**
|
|
64
|
-
type
|
|
65
|
-
& {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
98
|
+
/** The webhook whose bindings a mutation writes (`ctx.webhooks`), inferred from its optional field and then required. */
|
|
99
|
+
type BindsField<Bs> =
|
|
100
|
+
& { readonly binds?: Bs }
|
|
101
|
+
& ([Bs] extends [never] ? unknown : { readonly binds: Bs & NoInfer<OneWebhook<Bs>> })
|
|
102
|
+
|
|
103
|
+
/** The jobs a mutation may kick (`ctx.kick`), inferred from its optional field and then required, as a literal list. */
|
|
104
|
+
export type KicksField<Ks> =
|
|
105
|
+
& { readonly kicks?: Ks }
|
|
106
|
+
& ([Ks] extends [never] ? unknown : { readonly kicks: Ks & NoInfer<LiteralList<Ks>> })
|
|
107
|
+
|
|
108
|
+
/** The token purposes a site signs (`ctx.tokens.sign`), inferred from its optional field and then required, as a literal list. */
|
|
109
|
+
export type SignsField<Sg, Purposes extends string> =
|
|
110
|
+
& { readonly signs?: Sg }
|
|
111
|
+
& ([Sg] extends [never] ? unknown : { readonly signs: Sg & NoInfer<KnownPurposes<Sg, Purposes>> })
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The HTTPS origins a site's code calls (`fetch`): each an exact origin, no path or wildcard. A guard on the global
|
|
115
|
+
* `fetch` refuses any other while the site runs; a public procedure declares none.
|
|
116
|
+
*/
|
|
117
|
+
export interface EgressField {
|
|
118
|
+
readonly egress?: readonly `https://${string}`[]
|
|
119
|
+
}
|
|
70
120
|
|
|
71
|
-
/**
|
|
72
|
-
type
|
|
121
|
+
/** Each purpose `signs` names is one of `defineApp`'s `tokens`. */
|
|
122
|
+
type KnownPurposes<Sg, Purposes extends string> = Sg extends readonly (infer P extends string)[]
|
|
123
|
+
? [Exclude<P, Purposes>] extends [never] ? LiteralList<Sg>
|
|
124
|
+
: Unavailable<`signs names ${ListOf<Exclude<P, Purposes>>}, which defineApp's tokens do not declare`>
|
|
125
|
+
: unknown
|
|
73
126
|
|
|
74
127
|
type IsUnion<T, All = T> = T extends unknown ? ([All] extends [T] ? false : true) : never
|
|
75
128
|
|
|
129
|
+
/** A bucket's calls per minute, or `null` to turn a default bucket off. */
|
|
130
|
+
type Bucket = number | null
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* How a procedure is admitted (`admission`), merged into its kind's default: a public mutation counts 10 calls per
|
|
134
|
+
* minute per client and 100 for the endpoint; every other procedure counts none unless it declares a bucket.
|
|
135
|
+
*/
|
|
136
|
+
export type AdmissionOption<Acc> = [Acc] extends [PublicAccess] ? {
|
|
137
|
+
/** `'same-origin'` by default; `'listed'` the environment's listed origins; `'any'` every origin. */
|
|
138
|
+
readonly origins?: 'same-origin' | 'listed' | 'any'
|
|
139
|
+
readonly rate?: { readonly perClient?: Bucket; readonly perEndpoint?: Bucket; readonly bytesPerHour?: Bucket }
|
|
140
|
+
/** Verified on the server before the handler; the input carries the widget's token in `challengeToken`. */
|
|
141
|
+
readonly challenge?: ChallengeOption
|
|
142
|
+
}
|
|
143
|
+
: {
|
|
144
|
+
/** `'same-origin'` by default; `'listed'` the environment's listed origins, with a key only (ADR-0022). */
|
|
145
|
+
readonly origins?: 'same-origin' | 'listed'
|
|
146
|
+
readonly rate?: { readonly perCaller?: Bucket; readonly perEndpoint?: Bucket }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** A procedure's bounds: its body in bytes (64 KiB by default, at most 1 MiB) and its handler's time (10 s, at most 60 s). */
|
|
150
|
+
export interface LimitsOption {
|
|
151
|
+
readonly maxBytes?: number
|
|
152
|
+
readonly timeoutMs?: number
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* A public procedure's workload actions, which its handler holds and nothing else; no other procedure declares them.
|
|
157
|
+
* Inferred from the optional field and then required, like a declared field.
|
|
158
|
+
*/
|
|
159
|
+
export type PublicFields<Acc, Acts> = [Acc] extends [PublicAccess] ? {
|
|
160
|
+
readonly actions:
|
|
161
|
+
& Acts
|
|
162
|
+
& NoInfer<Acts extends readonly [] ? Unavailable<"a public procedure names what its handler holds: actions: ['<action>']"> : unknown>
|
|
163
|
+
}
|
|
164
|
+
: { readonly actions?: Unavailable<'only a public procedure declares actions: its handler runs as its own workload'> }
|
|
165
|
+
|
|
166
|
+
/** The handler context of a group's procedure: a public one runs as its own workload, every other as its caller. */
|
|
167
|
+
export type ProcedureContext<
|
|
168
|
+
K extends KitTypes,
|
|
169
|
+
Caller extends RpcCaller,
|
|
170
|
+
Kind extends 'query' | 'mutation',
|
|
171
|
+
Acc,
|
|
172
|
+
Acts extends readonly string[],
|
|
173
|
+
D extends Declared<SqlMode, unknown, readonly string[], string>,
|
|
174
|
+
Ks = never,
|
|
175
|
+
Bs = never,
|
|
176
|
+
Sg = never,
|
|
177
|
+
> =
|
|
178
|
+
& ([Acc] extends [PublicAccess] ? PublicContext<K, Kind, Acts[number]>
|
|
179
|
+
: EndpointContext<K, Caller, Kind, CheckedAccess<Acc>, D> & WebhooksContext<Bs>)
|
|
180
|
+
& KickContext<Ks>
|
|
181
|
+
& TokensContext<K, Sg>
|
|
182
|
+
|
|
183
|
+
/** A group without callers holds public procedures only; any other group may hold both. */
|
|
184
|
+
export type GroupAccess<Caller extends RpcCaller, Acc> = [Caller] extends [never] ? PublicAccess : Acc | PublicAccess
|
|
185
|
+
|
|
76
186
|
/** An endpoint's declaration: its schemas, its access form and the reach it declares. */
|
|
77
187
|
export type EndpointDef<I, O, Acc, S, U, Cn, Is, Ix extends AnyDbIndex> =
|
|
78
188
|
& Owned<'~kind' | 'type'>
|
|
@@ -80,11 +190,23 @@ export type EndpointDef<I, O, Acc, S, U, Cn, Is, Ix extends AnyDbIndex> =
|
|
|
80
190
|
readonly input?: I & NotLoose<I>
|
|
81
191
|
readonly output: O & NotLoose<O>
|
|
82
192
|
readonly access: Acc
|
|
83
|
-
|
|
84
|
-
readonly
|
|
193
|
+
readonly admission?: AdmissionOption<Acc>
|
|
194
|
+
readonly limits?: LimitsOption
|
|
85
195
|
}
|
|
86
196
|
& DeclaredFields<S, U, Cn, Is, Ix>
|
|
87
197
|
|
|
198
|
+
/**
|
|
199
|
+
* A group procedure's HTTP shape, its `query` schema inferred: what its handler then reads as `query`. Only a public
|
|
200
|
+
* procedure has a path of its own.
|
|
201
|
+
*/
|
|
202
|
+
type HttpField<Q, Acc> = { readonly http?: HttpOption<Q & NoInfer<NotLoose<Q>>> & OwnPathOption<Acc> }
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* `http.path`: a public procedure served at a literal path of its own instead of `<prefix>/<name>`, so a caller outside
|
|
206
|
+
* the application keeps its URL. It lies outside every mount's prefix and under no `/__fabrika`.
|
|
207
|
+
*/
|
|
208
|
+
export type OwnPathOption<Acc> = [Acc] extends [PublicAccess] ? { readonly path?: `/${string}` } : unknown
|
|
209
|
+
|
|
88
210
|
type Returned<F> = F extends (args: never) => infer R ? Awaited<R> : never
|
|
89
211
|
|
|
90
212
|
/** The last member of a union, in the order the compiler holds it. */
|
|
@@ -120,8 +242,31 @@ export type HandlerReturn<F, O extends Schema> = [Returned<F>] extends [z.input<
|
|
|
120
242
|
: [Returned<F>] extends [RowShaped<z.input<O>>] ? RowShaped<z.input<O>>
|
|
121
243
|
: z.input<O>
|
|
122
244
|
|
|
123
|
-
/** A kit endpoint's handler, returning `R
|
|
124
|
-
export type KitHandler<In, Ctx, R> = (args: { readonly input: In; readonly ctx: Ctx }) => R | Promise<R>
|
|
245
|
+
/** A kit endpoint's handler, returning `R`; `X` adds what its HTTP shape reads beside the input (`query`). */
|
|
246
|
+
export type KitHandler<In, Ctx, R, X = unknown> = (args: { readonly input: In; readonly ctx: Ctx } & X) => R | Promise<R>
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* What a handler reads beside its input: the URL's `query` of a POST that declares `http.query`, each signed token in it
|
|
250
|
+
* as the claims of its purpose.
|
|
251
|
+
*/
|
|
252
|
+
export type QueryArgs<Q, T = Record<never, never>> = [Q] extends [never] ? unknown
|
|
253
|
+
: Q extends InputSchema ? { readonly query: WithClaims<z.output<Q>, T> }
|
|
254
|
+
: unknown
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The wire of a procedure: `POST` with a JSON body by default; a query may be `GET`, its input then flat scalar URL
|
|
258
|
+
* parameters; a POST may read a flat `query` from the URL and take a native form's `urlencoded` body.
|
|
259
|
+
*/
|
|
260
|
+
export interface HttpOption<Q> {
|
|
261
|
+
readonly method?: 'GET' | 'POST'
|
|
262
|
+
readonly query?: Q
|
|
263
|
+
readonly body?: 'json' | 'urlencoded'
|
|
264
|
+
/**
|
|
265
|
+
* A public GET query's successful answers may be reused: `{ maxAgeSeconds }`, or `'immutable'` (a year) when its
|
|
266
|
+
* input names an immutable value. Every other answer is `no-store`.
|
|
267
|
+
*/
|
|
268
|
+
readonly cache?: EndpointCache
|
|
269
|
+
}
|
|
125
270
|
|
|
126
271
|
/**
|
|
127
272
|
* What `.handle` answers: the endpoint, or a message the group refuses at the endpoint's line — when the handler
|
|
@@ -143,10 +288,24 @@ export interface Endpoint<T extends ProcedureType, I extends InputSchema | null,
|
|
|
143
288
|
readonly declared: D
|
|
144
289
|
}
|
|
145
290
|
|
|
146
|
-
/**
|
|
147
|
-
|
|
291
|
+
/**
|
|
292
|
+
* An endpoint before `.handle`: a group refuses it. `Tk` are the kit's token purposes: a signed token field of the input
|
|
293
|
+
* reaches the handler as the claims of its purpose.
|
|
294
|
+
*/
|
|
295
|
+
export interface EndpointBuilder<
|
|
296
|
+
T extends ProcedureType,
|
|
297
|
+
I extends InputSchema | null,
|
|
298
|
+
O extends Schema,
|
|
299
|
+
Acc,
|
|
300
|
+
D,
|
|
301
|
+
Ctx,
|
|
302
|
+
X = unknown,
|
|
303
|
+
Tk = Record<never, never>,
|
|
304
|
+
> extends PendingEndpoint {
|
|
148
305
|
/** The endpoint's handler, typed by its access form and declaration; it may return only the output's fields. */
|
|
149
|
-
handle<const F extends KitHandler<HandlerInput<I, Acc>, Ctx, HandlerReturn<F, O
|
|
306
|
+
handle<const F extends KitHandler<WithClaims<HandlerInput<I, Acc>, Tk>, Ctx, HandlerReturn<F, O>, X>>(
|
|
307
|
+
handler: F,
|
|
308
|
+
): ExactReturn<F, O, Endpoint<T, I, O, Acc, D>>
|
|
150
309
|
}
|
|
151
310
|
|
|
152
311
|
/** What every endpoint builder has and no handled endpoint has. */
|
|
@@ -154,44 +313,71 @@ export interface PendingEndpoint {
|
|
|
154
313
|
handle(handler: never): unknown
|
|
155
314
|
}
|
|
156
315
|
|
|
157
|
-
/**
|
|
316
|
+
/**
|
|
317
|
+
* The builders of a group's callback: they know the group's callers, so a handler knows its principal. A group without
|
|
318
|
+
* callers (`Caller` is `never`) declares public procedures only.
|
|
319
|
+
*/
|
|
158
320
|
export interface GroupKit<K extends KitTypes, Caller extends RpcCaller> {
|
|
159
321
|
query<
|
|
160
|
-
const Acc extends QueryAccess<K['action'], K['dimension'], InputOf<I
|
|
322
|
+
const Acc extends GroupAccess<Caller, QueryAccess<K['action'], K['dimension'], InputOf<I>>>,
|
|
161
323
|
O extends Schema,
|
|
162
324
|
I extends InputSchema | null = null,
|
|
163
325
|
const S extends 'read' = never,
|
|
164
326
|
const U extends UnscopedDeclaration<K['tables'], 'read'> = never,
|
|
165
327
|
const Cn extends readonly ImportOf<K>[] = never,
|
|
166
328
|
const Is extends string = never,
|
|
329
|
+
const Acts extends readonly K['action'][] = never,
|
|
330
|
+
Q extends InputSchema = never,
|
|
331
|
+
const Sg extends readonly string[] = never,
|
|
167
332
|
>(
|
|
168
|
-
def:
|
|
333
|
+
def:
|
|
334
|
+
& EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']>
|
|
335
|
+
& PublicFields<Acc, Acts>
|
|
336
|
+
& HttpField<Q, Acc>
|
|
337
|
+
& NoKick
|
|
338
|
+
& SignsField<Sg, keyof K['tokens'] & string>
|
|
339
|
+
& EgressField,
|
|
169
340
|
): EndpointBuilder<
|
|
170
341
|
'query',
|
|
171
342
|
I,
|
|
172
343
|
O,
|
|
173
344
|
Acc,
|
|
174
345
|
Declared<S, U, Cn, Is>,
|
|
175
|
-
|
|
346
|
+
ProcedureContext<K, Caller, 'query', Acc, Acts, Declared<S, U, Cn, Is>, never, never, Sg>,
|
|
347
|
+
QueryArgs<Q, K['tokens']>,
|
|
348
|
+
K['tokens']
|
|
176
349
|
>
|
|
177
350
|
mutation<
|
|
178
|
-
const Acc extends MutationAccess<K['action'], K['dimension'], K['creatable'], InputOf<I
|
|
351
|
+
const Acc extends GroupAccess<Caller, MutationAccess<K['action'], K['dimension'], K['creatable'], InputOf<I>>>,
|
|
179
352
|
O extends Schema,
|
|
180
353
|
I extends InputSchema | null = null,
|
|
181
354
|
const S extends SqlMode = never,
|
|
182
355
|
const U extends UnscopedDeclaration<K['tables'], UnscopedMode> = never,
|
|
183
356
|
const Cn extends readonly ImportOf<K>[] = never,
|
|
184
357
|
const Is extends string = never,
|
|
185
|
-
const
|
|
358
|
+
const Acts extends readonly K['action'][] = never,
|
|
359
|
+
Q extends InputSchema = never,
|
|
360
|
+
const Ks extends readonly string[] = never,
|
|
361
|
+
const Bs extends string = never,
|
|
362
|
+
const Sg extends readonly string[] = never,
|
|
186
363
|
>(
|
|
187
|
-
def:
|
|
364
|
+
def:
|
|
365
|
+
& EndpointDef<I, O, Acc, S, U, Cn, Is, K['index']>
|
|
366
|
+
& PublicFields<Acc, Acts>
|
|
367
|
+
& HttpField<Q, Acc>
|
|
368
|
+
& KicksField<Ks>
|
|
369
|
+
& BindsField<Bs>
|
|
370
|
+
& SignsField<Sg, keyof K['tokens'] & string>
|
|
371
|
+
& EgressField,
|
|
188
372
|
): EndpointBuilder<
|
|
189
373
|
'mutation',
|
|
190
374
|
I,
|
|
191
375
|
O,
|
|
192
376
|
Acc,
|
|
193
377
|
Declared<S, U, Cn, Is>,
|
|
194
|
-
|
|
378
|
+
ProcedureContext<K, Caller, 'mutation', Acc, Acts, Declared<S, U, Cn, Is>, Ks, Bs, Sg>,
|
|
379
|
+
QueryArgs<Q, K['tokens']>,
|
|
380
|
+
K['tokens']
|
|
195
381
|
>
|
|
196
382
|
}
|
|
197
383
|
|
|
@@ -229,8 +415,8 @@ export type PendingIn<T, Path extends string> = typeof failedBuild extends keyof
|
|
|
229
415
|
: string extends keyof T ? [IsPending<T[string & keyof T]>] extends [true] ? `${Path}* (its type admits an endpoint without a handler)` : never
|
|
230
416
|
: { [K in keyof T]: [IsPending<T[K]>] extends [true] ? `${Path}${K & string}` : never }[keyof T]
|
|
231
417
|
|
|
232
|
-
/** `app.group(…)`: endpoints for one set of callers
|
|
233
|
-
export interface Group<C extends readonly
|
|
418
|
+
/** `app.group(…)`: endpoints for one set of callers (none for a group of public procedures), mounted by the contract. */
|
|
419
|
+
export interface Group<C extends readonly RpcCaller[], T extends GroupInput> {
|
|
234
420
|
readonly '~kind': 'group'
|
|
235
421
|
readonly callers: C
|
|
236
422
|
readonly endpoints: T
|
|
@@ -246,21 +432,42 @@ export interface LinkGroupKit<K extends KitTypes, LD extends string, G extends s
|
|
|
246
432
|
const U extends UnscopedDeclaration<K['tables'], 'read'> = never,
|
|
247
433
|
>(
|
|
248
434
|
def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> & NoKick,
|
|
249
|
-
): EndpointBuilder<
|
|
435
|
+
): EndpointBuilder<
|
|
436
|
+
'query',
|
|
437
|
+
I,
|
|
438
|
+
O,
|
|
439
|
+
Acc,
|
|
440
|
+
Declared<S, U, never, never>,
|
|
441
|
+
LinkContext<K, 'query', LD, Acc['action'], Declared<S, U, never, never>>,
|
|
442
|
+
unknown,
|
|
443
|
+
K['tokens']
|
|
444
|
+
>
|
|
250
445
|
mutation<
|
|
251
446
|
const Acc extends LinkAccess<G>,
|
|
252
447
|
O extends Schema,
|
|
253
448
|
I extends InputSchema | null = null,
|
|
254
449
|
const S extends SqlMode = never,
|
|
255
450
|
const U extends UnscopedDeclaration<K['tables'], UnscopedMode> = never,
|
|
256
|
-
const
|
|
451
|
+
const Ks extends readonly string[] = never,
|
|
257
452
|
>(
|
|
258
|
-
def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> &
|
|
259
|
-
): EndpointBuilder<
|
|
453
|
+
def: EndpointDef<I, O, Acc, S, U, never, never, K['index']> & KicksField<Ks>,
|
|
454
|
+
): EndpointBuilder<
|
|
455
|
+
'mutation',
|
|
456
|
+
I,
|
|
457
|
+
O,
|
|
458
|
+
Acc,
|
|
459
|
+
Declared<S, U, never, never>,
|
|
460
|
+
LinkContext<K, 'mutation', LD, Acc['action'], Declared<S, U, never, never>> & KickContext<Ks>,
|
|
461
|
+
unknown,
|
|
462
|
+
K['tokens']
|
|
463
|
+
>
|
|
260
464
|
}
|
|
261
465
|
|
|
262
466
|
/** An export procedure names its action and its scope; `{ member: true }` would give the consumer's key nothing to hold. */
|
|
263
|
-
export type ExportAccess<A extends string, D extends string, In> = Exclude<
|
|
467
|
+
export type ExportAccess<A extends string, D extends string, In> = Exclude<
|
|
468
|
+
QueryAccess<A, D, In>,
|
|
469
|
+
MemberAccess | AppAccess<A> | CapabilitiesAccess<{ readonly [name: string]: CapabilityAccess<A, D, In> }>
|
|
470
|
+
>
|
|
264
471
|
|
|
265
472
|
/** The builder of an export's callback: queries only, run read-only. */
|
|
266
473
|
export interface ExportKit<K extends KitTypes> {
|
package/src/contract/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export {
|
|
|
19
19
|
exportDescription,
|
|
20
20
|
exportDescriptionSchema,
|
|
21
21
|
incompatibleChanges,
|
|
22
|
+
incompatibleMountChanges,
|
|
22
23
|
parseExportDescription,
|
|
23
24
|
type SnapshotProcedure,
|
|
24
25
|
} from './connect'
|
|
@@ -26,9 +27,26 @@ export type * from './context'
|
|
|
26
27
|
export * from './declaration'
|
|
27
28
|
export * from './defaults'
|
|
28
29
|
export * from './define'
|
|
30
|
+
export { type ClientInput, file, type FileBrand, type FileMark, fileOf, type FileRef, type FileSchema, type FileStatus } from './file'
|
|
29
31
|
export type * from './group'
|
|
30
32
|
export * from './kit'
|
|
31
33
|
export { schemaFromContract } from './platform'
|
|
32
34
|
export { ContractError } from './problems'
|
|
35
|
+
export { type Redirect, redirect, type RedirectBrand, type RedirectMark, redirectOf, type RedirectOptions } from './redirect'
|
|
33
36
|
export { SNAPSHOT_DIRECTORY, type SnapshotNames, snapshotNames, snapshotSource } from './snapshot-source'
|
|
37
|
+
export {
|
|
38
|
+
SIGNED_TOKEN_MAX_LENGTH,
|
|
39
|
+
signedToken,
|
|
40
|
+
type SignedTokenMark,
|
|
41
|
+
signedTokenOf,
|
|
42
|
+
type SignedTokenSchema,
|
|
43
|
+
token,
|
|
44
|
+
TOKEN_MAX_DAYS,
|
|
45
|
+
type TokenOptions,
|
|
46
|
+
type TokenPurpose,
|
|
47
|
+
type TokenPurposes,
|
|
48
|
+
type TokenSigning,
|
|
49
|
+
type WithClaims,
|
|
50
|
+
} from './token'
|
|
34
51
|
export * from './vocabulary'
|
|
52
|
+
export { type WebhookBindings, WebhookSecret } from './webhook-binding'
|