@rebasepro/types 0.23.0 → 0.24.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.
@@ -3,9 +3,10 @@ import type { ResourceRef } from "../types/resources.js";
3
3
  import type { RebaseSdkData } from "./data.js";
4
4
  import type { EmailService } from "./email.js";
5
5
  import type { StorageSource } from "./storage.js";
6
- import type { CronJobStatus, CronJobLogEntry } from "../types/cron.js";
7
- import type { BackupInfo, BackupDestinationKind } from "../types/backup.js";
8
- import type { ApiKeysAPI } from "../types/api_keys.js";
6
+ import type { CronJobStatus, CronJobLogEntry, CronJobListing } from "../types/cron.js";
7
+ import type { BackupListing } from "../types/backup.js";
8
+ import type { ApiKeysAPI, PersonalKeysAPI } from "../types/api_keys.js";
9
+ import type { RoleSummary } from "../types/scopes.js";
9
10
  import type { StorageSourceDefinition } from "../types/storage_source.js";
10
11
  /**
11
12
  * Event type for authentication state changes
@@ -19,6 +20,10 @@ export type AuthChangeEvent = "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "
19
20
  */
20
21
  export interface RebaseSession {
21
22
  accessToken: string;
23
+ /**
24
+ * `""` under `authFlowMode: "cookie"`: the refresh token is in an HttpOnly
25
+ * cookie that no script can read, so the session does not hold it.
26
+ */
22
27
  refreshToken: string;
23
28
  expiresAt: number;
24
29
  user: User;
@@ -134,6 +139,11 @@ export interface AdminUser {
134
139
  */
135
140
  providerId: string;
136
141
  roles: string[];
142
+ /**
143
+ * Switched off by an administrator (`PUT /admin/users/:uid { disabled }`):
144
+ * it signs in nowhere and the tokens it holds are refused.
145
+ */
146
+ disabled?: boolean;
137
147
  metadata?: Record<string, any>;
138
148
  createdAt: string;
139
149
  updatedAt: string;
@@ -191,11 +201,9 @@ export interface AdminAPI {
191
201
  invitationSent?: boolean;
192
202
  emailDeliveryFailed?: boolean;
193
203
  }>;
204
+ /** The built-in `admin` role and the app's declared roles, with the scopes each holds. */
194
205
  listRoles(): Promise<{
195
- roles: Array<{
196
- id: string;
197
- name: string;
198
- }>;
206
+ roles: RoleSummary[];
199
207
  }>;
200
208
  bootstrap(): Promise<{
201
209
  success: boolean;
@@ -211,9 +219,8 @@ export interface AdminAPI {
211
219
  * @group Cron
212
220
  */
213
221
  export interface CronAPI {
214
- listJobs(): Promise<{
215
- jobs: CronJobStatus[];
216
- }>;
222
+ /** The registered jobs, and the cron files and jobs that did not become one. */
223
+ listJobs(): Promise<CronJobListing>;
217
224
  getJob(jobId: string): Promise<{
218
225
  job: CronJobStatus;
219
226
  }>;
@@ -235,12 +242,11 @@ export interface CronAPI {
235
242
  * @group Backups
236
243
  */
237
244
  export interface BackupsAPI {
238
- /** List available backups at the configured destination, newest first. */
239
- list(): Promise<{
240
- backups: BackupInfo[];
241
- destinationKind: BackupDestinationKind;
242
- configured: boolean;
243
- }>;
245
+ /**
246
+ * List available backups at the configured destination, newest first, and
247
+ * the scheduled backup job's last run.
248
+ */
249
+ list(): Promise<BackupListing>;
244
250
  /** Fetch a backup's bytes for download (authenticated). */
245
251
  download(key: string): Promise<Blob>;
246
252
  }
@@ -280,6 +286,25 @@ export interface FunctionsAPI {
280
286
  export type HistoryConfig = boolean | {
281
287
  retention?: number;
282
288
  };
289
+ /**
290
+ * Where the realtime connection is.
291
+ *
292
+ * - `idle` — no socket, and none wanted yet (the connection is lazy), or the
293
+ * last one was dropped by a sign-out.
294
+ * - `connecting` — dialling, with no outage in progress.
295
+ * - `connected` — the socket is open.
296
+ * - `reconnecting` — the socket dropped and the client is redialling. A blip,
297
+ * so far: nothing has been reported.
298
+ * - `disconnected` — the outage has outlasted the blip budget (about 15 s).
299
+ * Every live subscription and joined channel has been told
300
+ * `CONNECTION_LOST` once, and the client keeps redialling — every 30 s at
301
+ * most — for as long as any exists. When the socket is back each is
302
+ * re-subscribed, and its next update carries what changed meanwhile.
303
+ * - `closed` — `client.close()`. Final.
304
+ *
305
+ * @group Realtime
306
+ */
307
+ export type RealtimeConnectionState = "idle" | "connecting" | "connected" | "reconnecting" | "disconnected" | "closed";
283
308
  /**
284
309
  * Minimal WebSocket client contract exposed on {@link RebaseClient}.
285
310
  *
@@ -295,6 +320,10 @@ export interface RebaseWebSocket {
295
320
  setAuthTokenGetter(getter: () => Promise<string | null>): void;
296
321
  /** Listen for connection lifecycle events. */
297
322
  on(event: "connect" | "disconnect" | "reconnect" | "error", cb: (...args: unknown[]) => void): () => void;
323
+ /** Where the connection is. See {@link RealtimeConnectionState}. */
324
+ readonly state: RealtimeConnectionState;
325
+ /** Called on every change of {@link state}. Returns the unsubscribe. */
326
+ onStateChange(listener: (state: RealtimeConnectionState) => void): () => void;
298
327
  }
299
328
  /**
300
329
  * The single, canonical Rebase client interface.
@@ -390,8 +419,10 @@ export interface RebaseClient<DB = unknown> {
390
419
  backups?: BackupsAPI;
391
420
  /** Custom backend functions API */
392
421
  functions?: FunctionsAPI;
393
- /** Service API keys management API */
422
+ /** The project's service keys. Requires `keys:read` / `keys:write`. */
394
423
  apiKeys?: ApiKeysAPI;
424
+ /** The signed-in person's own API keys, when the backend enables `auth.personalKeys`. */
425
+ personalKeys?: PersonalKeysAPI;
395
426
  /** Base HTTP URL of the backend server */
396
427
  baseUrl?: string;
397
428
  /**
@@ -31,6 +31,23 @@ export type CollectionRegistryController<DB = Record<string, unknown>, EC extend
31
31
  * This is strictly for the Visual Editor to manipulate AST code without persisting runtime state.
32
32
  */
33
33
  getRawCollection: (slugOrPath: string) => EC | undefined;
34
+ /**
35
+ * The path a collection's rows are stored under, for the path the admin
36
+ * addresses it by. A Firestore or MongoDB collection may declare a `path`
37
+ * other than its slug — `slug: "fs_diagnosis", path: "diagnosis"` — and
38
+ * `fs_diagnosis/abc/locales` is then stored at `diagnosis/abc/locales`.
39
+ * This is what a reference to one of its records stores. Unchanged for a
40
+ * collection stored under its slug.
41
+ */
42
+ resolveDataPath: (path: string) => string;
43
+ /**
44
+ * The path the admin addresses a collection by, for a path its rows are
45
+ * stored under: the inverse of {@link resolveDataPath}, for a reference
46
+ * read back. `diagnosis` may be both where a Firestore collection is stored
47
+ * and the slug of a Postgres one; `preferredDriver` — the reference's
48
+ * `driver`, or the data source of the record it was read from — decides.
49
+ */
50
+ resolveCollectionPath: (path: string, preferredDriver?: string) => string;
34
51
  /**
35
52
  * Retrieve all the related parent references for a given path
36
53
  * @param path
@@ -143,6 +143,47 @@ export interface IncludeOptions {
143
143
  * @group Data
144
144
  */
145
145
  export type IncludeSpec = string[] | Record<string, true | IncludeOptions>;
146
+ /**
147
+ * An include checked against one generated collection's relations: `R` is its
148
+ * `Relations` map (relation name → the accessor it reaches) and `DB` the
149
+ * generated `Database`, so a nested `include` is checked against the *target's*
150
+ * relations in turn.
151
+ *
152
+ * A name, a dotted path starting with one, or `"*"`; or the tree, keyed by
153
+ * relation name. A name that is not a relation is a 400 `UNKNOWN_RELATION`
154
+ * from the server, and a compile error here.
155
+ *
156
+ * @group Data
157
+ */
158
+ export type IncludeSpecFor<DB, R> = readonly (Extract<keyof R, string> | "*" | `${Extract<keyof R, string>}.${string}`)[] | {
159
+ [K in Extract<keyof R, string>]?: true | IncludeOptionsFor<DB, R[K]>;
160
+ };
161
+ /**
162
+ * {@link IncludeOptions} for a relation that reaches the generated collection
163
+ * `T`: its nested `include` is checked against `T`'s relations.
164
+ *
165
+ * @group Data
166
+ */
167
+ export interface IncludeOptionsFor<DB, T> extends Omit<IncludeOptions, "include"> {
168
+ include?: T extends keyof DB ? IncludeOf<DB[T], DB> : IncludeSpec;
169
+ }
170
+ /**
171
+ * The include a generated `Database` entry takes — {@link IncludeSpecFor} over
172
+ * its `Relations` — or the unchecked {@link IncludeSpec} for anything that does
173
+ * not declare its relations (a hand-written row type, an older generated file).
174
+ *
175
+ * @group Data
176
+ */
177
+ export type IncludeOf<Entry, DB> = Entry extends {
178
+ Relations: infer R;
179
+ } ? IncludeSpecFor<DB, R> : IncludeSpec;
180
+ /**
181
+ * One argument of the fluent `.include(...)`: an element of the include list, a
182
+ * whole list, or the tree.
183
+ *
184
+ * @group Data
185
+ */
186
+ export type IncludeArgOf<Inc> = Inc extends readonly (infer E)[] ? E | Inc : Inc;
146
187
  /**
147
188
  * Hops an {@link IncludeSpec} may nest. `comments.author` is two.
148
189
  *
@@ -178,7 +219,7 @@ export declare const MAX_INCLUDE_DEPTH = 3;
178
219
  *
179
220
  * @group Data
180
221
  */
181
- export interface FindParams<M extends Record<string, unknown> = Record<string, unknown>> {
222
+ export interface FindParams<M extends Record<string, unknown> = Record<string, unknown>, Inc = IncludeSpec> {
182
223
  /**
183
224
  * Maximum number of items to return.
184
225
  *
@@ -236,11 +277,14 @@ export interface FindParams<M extends Record<string, unknown> = Record<string, u
236
277
  * Not checked against `M` here: a relation name comes from the collection's
237
278
  * `relations`, not from its columns, so nothing in a *hand-written* row type
238
279
  * can validate one. A **generated** `Database` narrows this to the
239
- * collection's actual relation keys, recursively — see `rebase codegen`.
280
+ * collection's actual relation keys, recursively — see
281
+ * {@link IncludeSpecFor}. The row a read returns still types each relation
282
+ * as optional; the generated `RowWith<A, I>` names the row with the
283
+ * included ones required.
240
284
  *
241
285
  * An unknown name is a 400 `UNKNOWN_RELATION`. It used to be ignored.
242
286
  */
243
- include?: IncludeSpec;
287
+ include?: Inc;
244
288
  /**
245
289
  * Columns to return, instead of all of them.
246
290
  *
@@ -463,7 +507,7 @@ export interface CollectionAccessor<M extends Record<string, unknown> = Record<s
463
507
  * absent implementation in a stub that says so rather than returning a
464
508
  * number nothing counted.
465
509
  */
466
- aggregate?(params: AggregateParams<M>): Promise<AggregateRow[]>;
510
+ aggregate?(params: AggregateParams<M>): Promise<AggregateResult>;
467
511
  where<K extends keyof M & string, Op extends WhereFilterOp>(column: K, operator: Op, value: WhereValueFor<Op, M[K]>): QueryBuilderInterface<M>;
468
512
  where(logicalCondition: LogicalCondition): QueryBuilderInterface<M>;
469
513
  orderBy(column: (keyof M & string) | ComputedSortField, direction?: "asc" | "desc"): QueryBuilderInterface<M>;
@@ -605,14 +649,15 @@ export type AggregateRow = Record<string, unknown>;
605
649
  * What {@link SDKCollectionClient.aggregate} takes: the same narrowing a
606
650
  * `find()` takes, minus the parts of it that describe a *page* of rows.
607
651
  *
608
- * `limit` survives and means what it means on the REST route — a bound on the
609
- * number of **groups**, because grouping by a high-cardinality column is a whole
610
- * table's worth of rows in one response. It is ignored when there is no
611
- * `groupBy`, since an ungrouped aggregate is one row.
652
+ * `limit` and `offset` page through the **groups**, as they page a listing's
653
+ * rows, because grouping by a high-cardinality column is a whole table's worth
654
+ * of rows in one response. Over HTTP a grouped aggregate with no `limit` gets
655
+ * the listing default (50 groups) — read {@link AggregateResult.meta} to know
656
+ * when there were more. Without `groupBy` there is one row: `limit` does nothing
657
+ * there and `offset` is refused.
612
658
  *
613
- * `orderBy`, `include`, `after` and the rest are absent on purpose: an
614
- * aggregate has no rows to sort, no relations to load and no page to continue.
615
- * They were silently ignored on the REST route; here they do not typecheck.
659
+ * `include`, `after` and the rest are absent on purpose: an aggregate has no
660
+ * relations to load and no row to continue after.
616
661
  *
617
662
  * @group Data
618
663
  */
@@ -627,8 +672,36 @@ export interface AggregateParams<M extends Record<string, unknown> = Record<stri
627
672
  logical?: LogicalCondition;
628
673
  /** Text search, AND-ed with the filters. */
629
674
  searchString?: string;
630
- /** Most groups to return. Ignored without `groupBy`. */
675
+ /** Most groups to return. Grouped aggregates only. */
631
676
  limit?: number;
677
+ /** Groups to skip, to page past `limit`. Grouped aggregates only. */
678
+ offset?: number;
679
+ }
680
+ /**
681
+ * Where a grouped aggregate's page of groups sits: the `limit` it was cut at,
682
+ * the `offset` it started from, and whether more groups follow.
683
+ *
684
+ * @group Data
685
+ */
686
+ export interface AggregateMeta {
687
+ limit: number;
688
+ offset: number;
689
+ hasMore: boolean;
690
+ }
691
+ /**
692
+ * What {@link SDKCollectionClient.aggregate} resolves to: the rows, as an
693
+ * array, carrying the page they are as `meta`.
694
+ *
695
+ * `meta` is present on a grouped aggregate that was cut at a `limit` — which,
696
+ * over HTTP, is every grouped one, since the route applies the listing default
697
+ * when none is given. `hasMore: true` means the groups did not all fit: page on
698
+ * with `offset`, or raise `limit`. It is a non-enumerable property, so a spread,
699
+ * `JSON.stringify` or `Object.keys` of the result sees only the rows.
700
+ *
701
+ * @group Data
702
+ */
703
+ export interface AggregateResult extends Array<AggregateRow> {
704
+ readonly meta?: AggregateMeta;
632
705
  }
633
706
  /**
634
707
  * Which column an iteration seeks on, for keyset ("seek") pagination.
@@ -693,7 +766,7 @@ export interface PageWalkOptions<M extends Record<string, unknown> = Record<stri
693
766
  *
694
767
  * @group Data
695
768
  */
696
- export type IterateParams<M extends Record<string, unknown> = Record<string, unknown>> = Omit<FindParams<M>, "limit" | "offset" | "page"> & PageWalkOptions<M>;
769
+ export type IterateParams<M extends Record<string, unknown> = Record<string, unknown>, Inc = IncludeSpec> = Omit<FindParams<M, Inc>, "limit" | "offset" | "page"> & PageWalkOptions<M>;
697
770
  /**
698
771
  * Parameters accepted by {@link SDKCollectionClient.findAll}: the iteration
699
772
  * parameters plus the ceiling that keeps a whole collection from being pulled
@@ -701,7 +774,7 @@ export type IterateParams<M extends Record<string, unknown> = Record<string, unk
701
774
  *
702
775
  * @group Data
703
776
  */
704
- export type FindAllParams<M extends Record<string, unknown> = Record<string, unknown>> = IterateParams<M> & {
777
+ export type FindAllParams<M extends Record<string, unknown> = Record<string, unknown>, Inc = IncludeSpec> = IterateParams<M, Inc> & {
705
778
  /**
706
779
  * Most rows to materialise. Defaults to 10 000. Exceeding it **throws**
707
780
  * — a truncated array returned as if it were the whole answer is the
@@ -716,7 +789,7 @@ export type FindAllParams<M extends Record<string, unknown> = Record<string, unk
716
789
  *
717
790
  * @group Data
718
791
  */
719
- export interface SDKQueryBuilderInterface<M extends Record<string, unknown> = Record<string, unknown>> {
792
+ export interface SDKQueryBuilderInterface<M extends Record<string, unknown> = Record<string, unknown>, Inc = IncludeSpec> {
720
793
  where<K extends keyof M & string, Op extends WhereFilterOp>(column: K, operator: Op, value: WhereValueFor<Op, M[K]>): this;
721
794
  /**
722
795
  * Filter on a relation path (`author.name`) or a JSON path
@@ -761,7 +834,7 @@ export interface SDKQueryBuilderInterface<M extends Record<string, unknown> = Re
761
834
  * Load relations — names, dotted paths (`"comments.author"`), or the
762
835
  * parametrised tree. Repeated calls merge rather than replace.
763
836
  */
764
- include(...relations: (string | IncludeSpec)[]): this;
837
+ include(...relations: IncludeArgOf<Inc>[]): this;
765
838
  /**
766
839
  * Return only these columns. A real projection: the columns are what is
767
840
  * read from the database, not what survives a trim of the response.
@@ -777,9 +850,10 @@ export interface SDKQueryBuilderInterface<M extends Record<string, unknown> = Re
777
850
  *
778
851
  * The builder's `where`/`logical`/`search` narrow which rows are
779
852
  * aggregated; its `orderBy`, `include` and window do not apply and are
780
- * ignored, exactly as they are on the REST route.
853
+ * ignored, exactly as they are on the REST route. Page the groups with the
854
+ * `limit`/`offset` passed here.
781
855
  */
782
- aggregate(params: Omit<AggregateParams<M>, "where" | "logical" | "searchString">): Promise<AggregateRow[]>;
856
+ aggregate(params: Omit<AggregateParams<M>, "where" | "logical" | "searchString">): Promise<AggregateResult>;
783
857
  /**
784
858
  * Page through everything this query matches, one row at a time.
785
859
  *
@@ -944,22 +1018,40 @@ export interface BatchRef {
944
1018
  /** `<ref name>.<field>`, e.g. `order.id`. */
945
1019
  $ref: string;
946
1020
  }
947
- /** One entry of a batch request. @group Data */
1021
+ /**
1022
+ * A row's values in a batch: the collection's own columns, each of which may
1023
+ * instead be a {@link BatchRef} to a value an earlier operation produces.
1024
+ *
1025
+ * Homomorphic over the row type, so a column the row type requires is required
1026
+ * here too — a create in a batch is the same insert `create()` is. There used
1027
+ * to be an `& Record<string, unknown>` on the end, which let a misspelt column
1028
+ * compile and come back as a 400 `VALIDATION_UNKNOWN_FIELDS`.
1029
+ */
1030
+ type BatchValues<T> = {
1031
+ [F in keyof T]: T[F] | BatchRef;
1032
+ };
1033
+ /**
1034
+ * One entry of a batch request.
1035
+ *
1036
+ * `collection` is the collection's **accessor** on a typed client — the name
1037
+ * `client.data.<accessor>` takes, and the key of the generated `Database`
1038
+ * (`orderItems`). The client resolves it to the slug the route knows
1039
+ * (`order_items`) through its `collections` dictionary; a slug that is not an
1040
+ * accessor is sent as written.
1041
+ *
1042
+ * @group Data
1043
+ */
948
1044
  export type BatchOperation<DB = Record<string, unknown>> = {
949
1045
  [K in Extract<keyof DB, string>]: {
950
1046
  op: "create";
951
1047
  collection: K;
952
- values: {
953
- [F in keyof InsertOf<DB[K]>]?: InsertOf<DB[K]>[F] | BatchRef;
954
- } & Record<string, unknown>;
1048
+ values: BatchValues<InsertOf<DB[K]>>;
955
1049
  /** Name this row so a later operation can reference its columns. */
956
1050
  ref?: string;
957
1051
  } | {
958
1052
  op: "upsert";
959
1053
  collection: K;
960
- values: {
961
- [F in keyof InsertOf<DB[K]>]?: InsertOf<DB[K]>[F] | BatchRef;
962
- } & Record<string, unknown>;
1054
+ values: BatchValues<InsertOf<DB[K]>>;
963
1055
  /** See {@link UpsertOptions.onConflict}. Defaults to the primary key. */
964
1056
  onConflict?: readonly string[];
965
1057
  ref?: string;
@@ -969,7 +1061,7 @@ export type BatchOperation<DB = Record<string, unknown>> = {
969
1061
  id: string | number | BatchRef;
970
1062
  values: {
971
1063
  [F in keyof UpdateOf<DB[K]>]?: UpdateOf<DB[K]>[F] | FieldOperation | BatchRef;
972
- } & Record<string, unknown>;
1064
+ };
973
1065
  ref?: string;
974
1066
  } | {
975
1067
  op: "delete";
@@ -1021,6 +1113,10 @@ export interface WriteOptions {
1021
1113
  * attempt is still being answered gets `IDEMPOTENCY_KEY_IN_PROGRESS` (409)
1022
1114
  * and should be sent again. A server that cannot store keys ignores the
1023
1115
  * header rather than refusing the write.
1116
+ *
1117
+ * The in-process accessor (`context.data`, `rebase.data`) has no store to
1118
+ * keep keys in, and refuses one with `UNSUPPORTED_OPTION` rather than
1119
+ * writing as though it had been checked.
1024
1120
  */
1025
1121
  idempotencyKey?: string;
1026
1122
  /**
@@ -1035,7 +1131,9 @@ export interface WriteOptions {
1035
1131
  *
1036
1132
  * Reach for it on imports and fire-and-forget writes. The method resolves
1037
1133
  * to `undefined` (or `[]`) when it is set, so a caller cannot accidentally
1038
- * use a row the server never sent.
1134
+ * use a row the server never sent — and `create`, `update` and `upsert`
1135
+ * are typed `M | undefined` for a literal `returning: false`, so reading a
1136
+ * field off the result is a compile error rather than a `TypeError`.
1039
1137
  */
1040
1138
  returning?: boolean;
1041
1139
  /**
@@ -1051,11 +1149,15 @@ export interface WriteOptions {
1051
1149
  *
1052
1150
  * `"*"` asserts only that the row exists.
1053
1151
  *
1054
- * Honoured on `update` and `delete`.
1152
+ * Honoured on `update` and `delete` over HTTP. The in-process accessor
1153
+ * (`context.data`, `rebase.data`) cannot check a precondition yet, and
1154
+ * refuses one with `UNSUPPORTED_OPTION` rather than writing unconditionally.
1055
1155
  */
1056
1156
  ifMatch?: string;
1057
1157
  }
1058
- export interface SDKCollectionClient<M extends Record<string, unknown> = Record<string, unknown>, I = Partial<M>, U = Partial<M>> {
1158
+ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<string, unknown>, I = Partial<M>, U = Partial<M>,
1159
+ /** The include this collection takes; {@link IncludeOf} for a generated `Database`. */
1160
+ Inc = IncludeSpec> {
1059
1161
  /**
1060
1162
  * Find multiple records with optional filtering, pagination, and sorting.
1061
1163
  *
@@ -1079,7 +1181,7 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1079
1181
  * it is where the pagination metadata lives, and it is present exactly when
1080
1182
  * there is some.
1081
1183
  */
1082
- find(params?: FindParams<M>): Promise<FindResult<M>>;
1184
+ find(params?: FindParams<M, Inc>): Promise<FindResult<M>>;
1083
1185
  /**
1084
1186
  * Walk every record matching a query, one row at a time, fetching pages as
1085
1187
  * the consumer consumes them.
@@ -1117,7 +1219,7 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1117
1219
  * await handle(job);
1118
1220
  * }
1119
1221
  */
1120
- iterate(params?: IterateParams<M>): AsyncIterableIterator<M>;
1222
+ iterate(params?: IterateParams<M, Inc>): AsyncIterableIterator<M>;
1121
1223
  /**
1122
1224
  * {@link iterate}, collected into an array.
1123
1225
  *
@@ -1138,7 +1240,7 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1138
1240
  * cursor: "id"
1139
1241
  * });
1140
1242
  */
1141
- findAll(params?: FindAllParams<M>): Promise<M[]>;
1243
+ findAll(params?: FindAllParams<M, Inc>): Promise<M[]>;
1142
1244
  /**
1143
1245
  * Find a single record by its ID.
1144
1246
  */
@@ -1183,8 +1285,11 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1183
1285
  * on anything else (a `sku`, a composite key), there is no `id` column to
1184
1286
  * receive it — put the key in `data` instead, where it belongs among the
1185
1287
  * columns.
1186
- * @returns The created row
1288
+ * @returns The created row — or nothing, with `returning: false`.
1187
1289
  */
1290
+ create(data: I, id: string | number | undefined, options: WriteOptions & {
1291
+ returning: false;
1292
+ }): Promise<M | undefined>;
1188
1293
  create(data: I, id?: string | number, options?: WriteOptions): Promise<M>;
1189
1294
  /**
1190
1295
  * Write many records in a single request and a single transaction.
@@ -1236,6 +1341,9 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1236
1341
  * that retry from a second deliberate edit — which on a `PATCH` that
1237
1342
  * increments or appends is a second edit applied.
1238
1343
  */
1344
+ update(id: string | number, data: U | UpdateValues<U>, options: WriteOptions & {
1345
+ returning: false;
1346
+ }): Promise<M | undefined>;
1239
1347
  update(id: string | number, data: U | UpdateValues<U>, options?: WriteOptions): Promise<M>;
1240
1348
  /**
1241
1349
  * Insert the row, or replace the one already occupying its key.
@@ -1266,6 +1374,9 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1266
1374
  * );
1267
1375
  * ```
1268
1376
  */
1377
+ upsert(data: I, options: UpsertOptions & {
1378
+ returning: false;
1379
+ }): Promise<M | undefined>;
1269
1380
  upsert(data: I, options?: UpsertOptions): Promise<M>;
1270
1381
  /**
1271
1382
  * Update many records in a single request and a single transaction.
@@ -1367,7 +1478,7 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1367
1478
  * `observe()` degrades to a single fetch instead of throwing, which is the
1368
1479
  * other reason to reach for it instead.
1369
1480
  */
1370
- listen(params: FindParams<M> | undefined, onUpdate: (response: FindResult<M>) => void, onError?: (error: Error) => void): () => void;
1481
+ listen(params: FindParams<M, Inc> | undefined, onUpdate: (response: FindResult<M>) => void, onError?: (error: Error) => void): () => void;
1371
1482
  /** {@link listen} for a single row. Prefer `observeById()`. */
1372
1483
  listenById(id: string | number, onUpdate: (row: M | undefined) => void, onError?: (error: Error) => void): () => void;
1373
1484
  /**
@@ -1376,7 +1487,7 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1376
1487
  * Always present; see {@link listen} for what a transport that cannot serve
1377
1488
  * it does instead.
1378
1489
  */
1379
- count(params?: FindParams<M>): Promise<number>;
1490
+ count(params?: FindParams<M, Inc>): Promise<number>;
1380
1491
  /**
1381
1492
  * `count`/`sum`/`avg`/`min`/`max` over the matching rows, optionally
1382
1493
  * grouped — the SDK half of `GET /<collection>/aggregate`.
@@ -1401,17 +1512,17 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1401
1512
  * naming the capability rather than an empty result set, which would read
1402
1513
  * as "nothing matched".
1403
1514
  */
1404
- aggregate(params: AggregateParams<M>): Promise<AggregateRow[]>;
1405
- where<K extends keyof M & string, Op extends WhereFilterOp>(column: K, operator: Op, value: WhereValueFor<Op, M[K]>): SDKQueryBuilderInterface<M>;
1515
+ aggregate(params: AggregateParams<M>): Promise<AggregateResult>;
1516
+ where<K extends keyof M & string, Op extends WhereFilterOp>(column: K, operator: Op, value: WhereValueFor<Op, M[K]>): SDKQueryBuilderInterface<M, Inc>;
1406
1517
  /** A relation path (`author.name`) or a JSON path (`metadata->>tier`). */
1407
- where(column: NonColumnFieldPath, operator: WhereFilterOp, value: unknown): SDKQueryBuilderInterface<M>;
1408
- where(logicalCondition: LogicalCondition): SDKQueryBuilderInterface<M>;
1409
- orderBy(column: FieldPath<M> | ComputedSortField | RelationAggregateSort, direction?: "asc" | "desc", nulls?: NullsPlacement): SDKQueryBuilderInterface<M>;
1410
- limit(count: number): SDKQueryBuilderInterface<M>;
1411
- offset(count: number): SDKQueryBuilderInterface<M>;
1518
+ where(column: NonColumnFieldPath, operator: WhereFilterOp, value: unknown): SDKQueryBuilderInterface<M, Inc>;
1519
+ where(logicalCondition: LogicalCondition): SDKQueryBuilderInterface<M, Inc>;
1520
+ orderBy(column: FieldPath<M> | ComputedSortField | RelationAggregateSort, direction?: "asc" | "desc", nulls?: NullsPlacement): SDKQueryBuilderInterface<M, Inc>;
1521
+ limit(count: number): SDKQueryBuilderInterface<M, Inc>;
1522
+ offset(count: number): SDKQueryBuilderInterface<M, Inc>;
1412
1523
  search(searchString: string, options?: {
1413
1524
  explain?: boolean;
1414
- }): SDKQueryBuilderInterface<M>;
1525
+ }): SDKQueryBuilderInterface<M, Inc>;
1415
1526
  /**
1416
1527
  * Order rows by nearest-neighbour distance to `vector`, closest first.
1417
1528
  * Postgres only, over a `type: "vector"` property. See
@@ -1420,14 +1531,14 @@ export interface SDKCollectionClient<M extends Record<string, unknown> = Record<
1420
1531
  vectorSearch(property: string, vector: number[], options?: {
1421
1532
  distance?: "cosine" | "l2" | "inner_product";
1422
1533
  threshold?: number;
1423
- }): SDKQueryBuilderInterface<M>;
1424
- include(...relations: (string | IncludeSpec)[]): SDKQueryBuilderInterface<M>;
1534
+ }): SDKQueryBuilderInterface<M, Inc>;
1535
+ include(...relations: IncludeArgOf<Inc>[]): SDKQueryBuilderInterface<M, Inc>;
1425
1536
  /** {@link SDKQueryBuilderInterface.fields} */
1426
- fields(...columns: (FieldPath<M> | string)[]): SDKQueryBuilderInterface<M>;
1537
+ fields(...columns: (FieldPath<M> | string)[]): SDKQueryBuilderInterface<M, Inc>;
1427
1538
  /** {@link SDKQueryBuilderInterface.distinct} */
1428
- distinct(enabled?: boolean): SDKQueryBuilderInterface<M>;
1539
+ distinct(enabled?: boolean): SDKQueryBuilderInterface<M, Inc>;
1429
1540
  /** {@link SDKQueryBuilderInterface.after} */
1430
- after(cursor: string): SDKQueryBuilderInterface<M>;
1541
+ after(cursor: string): SDKQueryBuilderInterface<M, Inc>;
1431
1542
  }
1432
1543
  /**
1433
1544
  * The unified data access object for the **admin panel** (Entity-shaped).
@@ -1554,7 +1665,7 @@ export type RebaseSdkData<DB = unknown> = {
1554
1665
  */
1555
1666
  collection<M extends Record<string, unknown> = Record<string, unknown>>(slug: string): SDKCollectionClient<M>;
1556
1667
  } & (DB extends Record<string, unknown> ? {
1557
- [K in keyof DB]: SDKCollectionClient<RowOf<DB[K]>, InsertOf<DB[K]>, UpdateOf<DB[K]>>;
1668
+ [K in keyof DB]: SDKCollectionClient<RowOf<DB[K]>, InsertOf<DB[K]>, UpdateOf<DB[K]>, IncludeOf<DB[K], DB>>;
1558
1669
  } : {
1559
1670
  /**
1560
1671
  * Dynamic flat collection accessor.
@@ -1565,3 +1676,4 @@ export type RebaseSdkData<DB = unknown> = {
1565
1676
  */
1566
1677
  [collectionSlug: string]: SDKCollectionClient;
1567
1678
  });
1679
+ export {};