@rebasepro/types 0.19.1 → 0.19.2-canary.g09316f6
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/dist/controllers/data.d.ts +515 -14
- package/dist/controllers/data_driver.d.ts +166 -4
- package/dist/controllers/storage.d.ts +30 -0
- package/dist/index.es.js +163 -3
- package/dist/index.es.js.map +1 -1
- package/dist/types/collections.d.ts +59 -0
- package/dist/types/filter-operators.d.ts +37 -6
- package/dist/types/index.d.ts +1 -0
- package/dist/types/policy.d.ts +39 -1
- package/dist/types/properties.d.ts +205 -8
- package/dist/types/relations.d.ts +71 -0
- package/dist/types/schema_editing.d.ts +6 -0
- package/dist/types/tenancy.d.ts +147 -0
- package/dist/types/websockets.d.ts +37 -0
- package/dist/users/user.d.ts +21 -0
- package/package.json +1 -1
|
@@ -3,7 +3,8 @@ import type { EntityStatus, EntityValues } from "../types/entities.js";
|
|
|
3
3
|
import type { CollectionConfig, FilterValues } from "../types/collections.js";
|
|
4
4
|
import type { OrderByTuple } from "../types/filter-operators.js";
|
|
5
5
|
import type { RebaseCallContext } from "../call_context.js";
|
|
6
|
-
import type { LogicalCondition } from "./data.js";
|
|
6
|
+
import type { IncludeSpec, LogicalCondition } from "./data.js";
|
|
7
|
+
import type { CollectionUpdateMeta } from "../types/websockets.js";
|
|
7
8
|
/**
|
|
8
9
|
* @internal
|
|
9
10
|
*/
|
|
@@ -12,6 +13,13 @@ export interface FetchOneProps<M extends Record<string, unknown> = Record<string
|
|
|
12
13
|
id: string | number;
|
|
13
14
|
databaseId?: string;
|
|
14
15
|
collection?: CollectionConfig<M>;
|
|
16
|
+
/**
|
|
17
|
+
* See {@link FetchCollectionProps.withDeleted}. A soft-deleted row is a 404
|
|
18
|
+
* here by default, so `findById` and `find` agree about which rows exist —
|
|
19
|
+
* a row you cannot find in a listing and can still open by id is the kind
|
|
20
|
+
* of inconsistency that makes a feature untrustworthy.
|
|
21
|
+
*/
|
|
22
|
+
withDeleted?: boolean | "only";
|
|
15
23
|
}
|
|
16
24
|
/**
|
|
17
25
|
* @internal
|
|
@@ -121,12 +129,50 @@ export interface FetchCollectionProps<M extends Record<string, unknown> = Record
|
|
|
121
129
|
order?: "desc" | "asc";
|
|
122
130
|
/** Vector similarity search configuration */
|
|
123
131
|
vectorSearch?: VectorSearchParams;
|
|
132
|
+
/**
|
|
133
|
+
* What to do about rows a soft delete has stamped.
|
|
134
|
+
*
|
|
135
|
+
* Unset (the default) hides them, which is the whole point of the feature:
|
|
136
|
+
* a deleted row is deleted as far as the application is concerned. `true`
|
|
137
|
+
* includes them alongside the live ones — a trash view, an admin audit.
|
|
138
|
+
* `"only"` returns nothing but them, which is the trash view proper and is
|
|
139
|
+
* not expressible as a filter, because the field is not part of the
|
|
140
|
+
* caller's vocabulary.
|
|
141
|
+
*
|
|
142
|
+
* Ignored by collections that do not declare {@link
|
|
143
|
+
* PostgresCollectionConfig.softDelete}: there is no stamp to look at, and
|
|
144
|
+
* silently returning nothing for `"only"` on such a collection would be a
|
|
145
|
+
* worse answer than ignoring it.
|
|
146
|
+
*/
|
|
147
|
+
withDeleted?: boolean | "only";
|
|
148
|
+
/**
|
|
149
|
+
* Relations to load — see {@link IncludeSpec}.
|
|
150
|
+
*
|
|
151
|
+
* Absent means *no* relations, the same as it does over REST. It used to be
|
|
152
|
+
* absent from this contract entirely, and the driver's own fetch then loaded
|
|
153
|
+
* every relation of every row unconditionally: `find()` returned a row with
|
|
154
|
+
* a foreign key and `listen()` returned the same row with a nested object
|
|
155
|
+
* where that key was, for the same query.
|
|
156
|
+
*/
|
|
157
|
+
include?: IncludeSpec;
|
|
158
|
+
/** Columns to read, as a projection. See `FindParams.fields`. */
|
|
159
|
+
fields?: string[];
|
|
160
|
+
/** `SELECT DISTINCT` over the projection. See `FindParams.distinct`. */
|
|
161
|
+
distinct?: boolean;
|
|
124
162
|
}
|
|
125
163
|
/**
|
|
126
164
|
* @internal
|
|
127
165
|
*/
|
|
128
166
|
export type ListenCollectionProps<M extends Record<string, unknown> = Record<string, unknown>> = FetchCollectionProps<M> & {
|
|
129
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Page number (1-indexed), as `FindParams.page`.
|
|
169
|
+
*
|
|
170
|
+
* A subscription could name a `limit` and an `offset` but not a `page`,
|
|
171
|
+
* so a live list on page three had to compute the offset itself — and
|
|
172
|
+
* the two spellings then disagreed about what a page was.
|
|
173
|
+
*/
|
|
174
|
+
page?: number;
|
|
175
|
+
onUpdate: (rows: Record<string, unknown>[], meta?: CollectionUpdateMeta) => void;
|
|
130
176
|
onError?: (error: Error) => void;
|
|
131
177
|
};
|
|
132
178
|
/**
|
|
@@ -149,6 +195,22 @@ export interface SaveProps<M extends Record<string, unknown> = Record<string, un
|
|
|
149
195
|
* them there is no conflict target and the row is inserted normally.
|
|
150
196
|
*/
|
|
151
197
|
upsert?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* The columns the upsert matches a conflict on, instead of the primary key.
|
|
200
|
+
*
|
|
201
|
+
* The key is the only target that always exists, and it is the wrong one
|
|
202
|
+
* for the write an upsert is usually reached for: "this user, identified by
|
|
203
|
+
* their email, exists with these values". Keyed on the primary key that is
|
|
204
|
+
* an insert, because the caller does not know the serial id — so the row is
|
|
205
|
+
* duplicated on every run.
|
|
206
|
+
*
|
|
207
|
+
* Only column sets carrying a uniqueness guarantee are legal here; Postgres
|
|
208
|
+
* refuses anything else with 42P10, from inside a transaction. The REST
|
|
209
|
+
* layer checks the target against the collection's declarations first (see
|
|
210
|
+
* `resolveConflictTarget`), so the answer is a 400 naming the available
|
|
211
|
+
* targets rather than a 500 naming a constraint the caller never wrote.
|
|
212
|
+
*/
|
|
213
|
+
onConflict?: readonly string[];
|
|
152
214
|
}
|
|
153
215
|
/**
|
|
154
216
|
* @internal
|
|
@@ -163,6 +225,8 @@ export interface SaveManyProps<M extends Record<string, unknown> = Record<string
|
|
|
163
225
|
collection?: CollectionConfig<M>;
|
|
164
226
|
/** Apply every row as INSERT ... ON CONFLICT DO UPDATE. See {@link SaveProps.upsert}. */
|
|
165
227
|
upsert?: boolean;
|
|
228
|
+
/** The conflict target for those upserts. See {@link SaveProps.onConflict}. */
|
|
229
|
+
onConflict?: readonly string[];
|
|
166
230
|
}
|
|
167
231
|
/**
|
|
168
232
|
* @internal
|
|
@@ -193,6 +257,17 @@ export interface DeleteProps<M extends Record<string, unknown> = Record<string,
|
|
|
193
257
|
values?: Partial<EntityValues<M>>;
|
|
194
258
|
};
|
|
195
259
|
collection?: CollectionConfig<M>;
|
|
260
|
+
/**
|
|
261
|
+
* Issue a real `DELETE` on a collection that declares
|
|
262
|
+
* {@link PostgresCollectionConfig.softDelete}.
|
|
263
|
+
*
|
|
264
|
+
* The row and every cascade behind it go. It needs the same permission an
|
|
265
|
+
* ordinary delete does and nothing more: it is the same verb, and a second
|
|
266
|
+
* access-control surface for one operation is a second thing to get wrong.
|
|
267
|
+
* No effect on a collection without soft delete, where every delete is
|
|
268
|
+
* already this one.
|
|
269
|
+
*/
|
|
270
|
+
hard?: boolean;
|
|
196
271
|
}
|
|
197
272
|
/**
|
|
198
273
|
* @internal
|
|
@@ -201,6 +276,34 @@ export interface DeleteManyProps<M extends Record<string, unknown> = Record<stri
|
|
|
201
276
|
path: string;
|
|
202
277
|
ids: (string | number)[];
|
|
203
278
|
collection?: CollectionConfig<M>;
|
|
279
|
+
/** See {@link DeleteProps.hard}. */
|
|
280
|
+
hard?: boolean;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* One operation of a {@link DataDriver.batchWrite}.
|
|
284
|
+
*
|
|
285
|
+
* `path` rather than a slug, because a batch entry addresses rows exactly as
|
|
286
|
+
* the single-row props do and a nested path is a legal address there.
|
|
287
|
+
*
|
|
288
|
+
* @internal
|
|
289
|
+
*/
|
|
290
|
+
export interface BatchWriteOperation<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
291
|
+
op: "create" | "update" | "upsert" | "delete";
|
|
292
|
+
path: string;
|
|
293
|
+
/** Required for `update` and `delete`. May be a `$ref` marker; see `batchWrite`. */
|
|
294
|
+
id?: unknown;
|
|
295
|
+
values?: Partial<EntityValues<M>>;
|
|
296
|
+
collection?: CollectionConfig<M>;
|
|
297
|
+
/** See {@link SaveProps.onConflict}. `upsert` only. */
|
|
298
|
+
onConflict?: readonly string[];
|
|
299
|
+
/** Names this operation's result, for a later `$ref`. */
|
|
300
|
+
ref?: string;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* @internal
|
|
304
|
+
*/
|
|
305
|
+
export interface BatchWriteProps<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
306
|
+
operations: BatchWriteOperation<M>[];
|
|
204
307
|
}
|
|
205
308
|
export type FilterCombinationValidProps = {
|
|
206
309
|
path: string;
|
|
@@ -333,6 +436,31 @@ export interface DataDriver {
|
|
|
333
436
|
* {@link SDKCollectionClient.deleteMany}. Optional, as `saveMany` is.
|
|
334
437
|
*/
|
|
335
438
|
deleteMany?<M extends Record<string, unknown> = Record<string, unknown>>(props: DeleteManyProps<M>): Promise<void>;
|
|
439
|
+
/**
|
|
440
|
+
* Apply a mixed list of writes across collections as one unit of work.
|
|
441
|
+
*
|
|
442
|
+
* The capability `saveMany` and `deleteMany` cannot express between them: a
|
|
443
|
+
* batch that touches two tables. Sent as two requests those can
|
|
444
|
+
* half-succeed, and the recovery — read back, work out which half landed,
|
|
445
|
+
* undo it — is code nobody writes.
|
|
446
|
+
*
|
|
447
|
+
* Every operation runs the pipeline its single-row equivalent runs, in
|
|
448
|
+
* order, in one transaction, under the caller's own role. Operations may
|
|
449
|
+
* carry `{ "$ref": "<name>.<field>" }` markers in `values` or `id`, which
|
|
450
|
+
* the driver resolves against the rows earlier operations wrote — the
|
|
451
|
+
* driver, because inside the transaction is the only place those rows
|
|
452
|
+
* exist. `@rebasepro/server` exports `resolveBatchRefs` so the resolution
|
|
453
|
+
* is one implementation rather than one per driver.
|
|
454
|
+
*
|
|
455
|
+
* Resolves to one entry per operation, aligned to the input: the written
|
|
456
|
+
* row for a create, update or upsert, and `null` for a delete.
|
|
457
|
+
*
|
|
458
|
+
* Optional for the same reason `saveMany` is: a driver that cannot make it
|
|
459
|
+
* atomic must not pretend to. The REST layer answers `BATCH_UNSUPPORTED`
|
|
460
|
+
* rather than falling back to a loop, which would be the non-atomic
|
|
461
|
+
* sequence the caller reached for this to avoid.
|
|
462
|
+
*/
|
|
463
|
+
batchWrite?<M extends Record<string, unknown> = Record<string, unknown>>(props: BatchWriteProps<M>): Promise<(Record<string, unknown> | null)[]>;
|
|
336
464
|
/**
|
|
337
465
|
* Check if the given property is unique in the given collection
|
|
338
466
|
* @param path Collection path
|
|
@@ -420,7 +548,34 @@ export interface RestFetchService {
|
|
|
420
548
|
searchExplain?: boolean;
|
|
421
549
|
databaseId?: string;
|
|
422
550
|
vectorSearch?: VectorSearchParams;
|
|
423
|
-
|
|
551
|
+
/** See {@link FetchCollectionProps.withDeleted}. */
|
|
552
|
+
withDeleted?: boolean | "only";
|
|
553
|
+
/**
|
|
554
|
+
* Columns to read. A projection pushed into the SELECT, not a trim
|
|
555
|
+
* of the response — `excludeFromApi` still applies on top, and the
|
|
556
|
+
* primary key is always read whether or not it is named.
|
|
557
|
+
*/
|
|
558
|
+
fields?: string[];
|
|
559
|
+
/** `SELECT DISTINCT` over the projection. See `FindParams.distinct`. */
|
|
560
|
+
distinct?: boolean;
|
|
561
|
+
}, include?: IncludeSpec): Promise<Record<string, unknown>[]>;
|
|
562
|
+
/**
|
|
563
|
+
* The opaque cursor that continues a listing after `row`.
|
|
564
|
+
*
|
|
565
|
+
* On the driver rather than the route because deriving it needs the
|
|
566
|
+
* collection's primary key — which may be named anything and span several
|
|
567
|
+
* columns — and that is the driver's knowledge. The route holds the last
|
|
568
|
+
* row and the sort keys and asks for the string.
|
|
569
|
+
*
|
|
570
|
+
* `undefined` where no cursor can describe the page: an ordering with no
|
|
571
|
+
* stored value to compare against (relevance), or a row missing a value for
|
|
572
|
+
* one of the sort keys. The listing then reports no `nextCursor` and the
|
|
573
|
+
* caller pages by offset, which is what it did before cursors existed.
|
|
574
|
+
*
|
|
575
|
+
* Optional: a driver that cannot seek simply never issues one, and
|
|
576
|
+
* `meta.nextCursor` is absent for every read it serves.
|
|
577
|
+
*/
|
|
578
|
+
cursorFor?(collectionPath: string, row: Record<string, unknown>, orderBy?: OrderByTuple[]): string | undefined;
|
|
424
579
|
/**
|
|
425
580
|
* `count`/`sum`/`avg`/`min`/`max` over the rows a filter selects,
|
|
426
581
|
* optionally grouped.
|
|
@@ -445,9 +600,16 @@ export interface RestFetchService {
|
|
|
445
600
|
logical?: LogicalCondition;
|
|
446
601
|
searchString?: string;
|
|
447
602
|
limit?: number;
|
|
603
|
+
/** See {@link FetchCollectionProps.withDeleted}. */
|
|
604
|
+
withDeleted?: boolean | "only";
|
|
448
605
|
}): Promise<Record<string, unknown>[]>;
|
|
449
606
|
/**
|
|
450
607
|
* Fetch a single flattened entity with optional relation includes.
|
|
451
608
|
*/
|
|
452
|
-
fetchOneForRest(collectionPath: string, id: string | number, include?:
|
|
609
|
+
fetchOneForRest(collectionPath: string, id: string | number, include?: IncludeSpec, databaseId?: string, options?: {
|
|
610
|
+
/** See `FetchCollectionProps.fields`. */
|
|
611
|
+
fields?: string[];
|
|
612
|
+
/** See {@link FetchOneProps.withDeleted}. */
|
|
613
|
+
withDeleted?: boolean | "only";
|
|
614
|
+
}): Promise<Record<string, unknown> | null>;
|
|
453
615
|
}
|
|
@@ -30,6 +30,36 @@ export interface UploadFileProps {
|
|
|
30
30
|
* Defaults to `false` (private, short-lived signed URLs).
|
|
31
31
|
*/
|
|
32
32
|
public?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Which property this file is being uploaded *for* — the collection's slug
|
|
35
|
+
* and the property path within it (`coverImage`, `meta.avatar`,
|
|
36
|
+
* `gallery` for an array of files).
|
|
37
|
+
*
|
|
38
|
+
* The server reads it to enforce that property's own `storage.maxSize` and
|
|
39
|
+
* `storage.acceptedFiles`, which were declared per property, published in
|
|
40
|
+
* the generated types, rendered by the panel's file picker, and until now
|
|
41
|
+
* enforced by nothing on the server — so a `curl` past the picker put a
|
|
42
|
+
* 40 MB executable in a bucket whose config said "images, under 200 KB".
|
|
43
|
+
*
|
|
44
|
+
* Advisory in one direction only. The rules are resolved from the server's
|
|
45
|
+
* own registry by slug, so naming a property can make an upload *stricter*
|
|
46
|
+
* or leave it at the global cap; it can never widen anything.
|
|
47
|
+
*
|
|
48
|
+
* Omitted, the upload is checked against the deployment's global
|
|
49
|
+
* `maxFileSize` exactly as before.
|
|
50
|
+
*/
|
|
51
|
+
context?: UploadPropertyContext;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The property an upload is destined for.
|
|
55
|
+
*
|
|
56
|
+
* @group Models
|
|
57
|
+
*/
|
|
58
|
+
export interface UploadPropertyContext {
|
|
59
|
+
/** The collection's slug, as the server registered it. */
|
|
60
|
+
collection: string;
|
|
61
|
+
/** Dotted path to the property — `coverImage`, `meta.avatar`. */
|
|
62
|
+
property: string;
|
|
33
63
|
}
|
|
34
64
|
/**
|
|
35
65
|
* @group Models
|
package/dist/index.es.js
CHANGED
|
@@ -345,6 +345,21 @@ var REST_TO_CANONICAL = {
|
|
|
345
345
|
*/
|
|
346
346
|
var NULL_OPS = /* @__PURE__ */ new Set(["is-null", "is-not-null"]);
|
|
347
347
|
/**
|
|
348
|
+
* Operators whose operand is a **list** of values rather than one value.
|
|
349
|
+
*
|
|
350
|
+
* On the wire that list is always parenthesised — `in.(draft,review)` — which
|
|
351
|
+
* is what lets the REST codec tell `?status=in.(a,b)` (the operator) from
|
|
352
|
+
* `?status=in.progress` (a value that happens to start with an operator's
|
|
353
|
+
* name). See `deserializeSingle` in `@rebasepro/common`.
|
|
354
|
+
*
|
|
355
|
+
* @group Models
|
|
356
|
+
*/
|
|
357
|
+
var LIST_OPS = /* @__PURE__ */ new Set([
|
|
358
|
+
"in",
|
|
359
|
+
"not-in",
|
|
360
|
+
"array-contains-any"
|
|
361
|
+
]);
|
|
362
|
+
/**
|
|
348
363
|
* Every canonical operator, in a stable order. Useful for engine capability
|
|
349
364
|
* declarations ({@link DataSourceCapabilities.filterOperators}) and for
|
|
350
365
|
* building operator subsets.
|
|
@@ -799,6 +814,24 @@ var DEFAULT_FUZZY_THRESHOLD = .3;
|
|
|
799
814
|
var RELEVANCE_SORT_FIELD = "_score";
|
|
800
815
|
//#endregion
|
|
801
816
|
//#region src/types/relations.ts
|
|
817
|
+
/**
|
|
818
|
+
* The key a junction row's own columns are carried under, in both directions.
|
|
819
|
+
*
|
|
820
|
+
* A read that includes a `manyToMany` relation serves each related row with its
|
|
821
|
+
* link's columns nested here — `{ id: 5, name: "ts", _pivot: { role: "owner" } }`
|
|
822
|
+
* — and a membership write may name the same key on an element to state what
|
|
823
|
+
* the link should hold. One constant because the two have to be the same word:
|
|
824
|
+
* a wire name that differs between the read and the write it round-trips
|
|
825
|
+
* through is a shape no client can echo back.
|
|
826
|
+
*
|
|
827
|
+
* Leading underscore, like `_matches`: it reads as metadata about the row
|
|
828
|
+
* rather than as one of its columns. A payload property may not be named
|
|
829
|
+
* `_pivot` either — `checkJunctionPayload` refuses it — so the key means one
|
|
830
|
+
* thing wherever it appears.
|
|
831
|
+
*
|
|
832
|
+
* @group Models
|
|
833
|
+
*/
|
|
834
|
+
var JUNCTION_PIVOT_KEY = "_pivot";
|
|
802
835
|
/** @group Models */
|
|
803
836
|
function hasForeignKeyOnTarget(relation) {
|
|
804
837
|
return relation.kind === "hasOne" || relation.kind === "hasMany";
|
|
@@ -919,7 +952,11 @@ var policy = {
|
|
|
919
952
|
value
|
|
920
953
|
}),
|
|
921
954
|
authUid: () => ({ kind: "authUid" }),
|
|
922
|
-
authRoles: () => ({ kind: "authRoles" })
|
|
955
|
+
authRoles: () => ({ kind: "authRoles" }),
|
|
956
|
+
authClaim: (name) => ({
|
|
957
|
+
kind: "authClaim",
|
|
958
|
+
name
|
|
959
|
+
})
|
|
923
960
|
};
|
|
924
961
|
//#endregion
|
|
925
962
|
//#region src/types/rls-functions.ts
|
|
@@ -1023,6 +1060,27 @@ function usesLegacyRlsFunctions(sql) {
|
|
|
1023
1060
|
return /\bauth\.(uid|jwt|roles)\s*\(\s*\)/i.test(sql);
|
|
1024
1061
|
}
|
|
1025
1062
|
//#endregion
|
|
1063
|
+
//#region src/types/tenancy.ts
|
|
1064
|
+
/** Narrow a {@link TenantSource} to its claim form. @group Models */
|
|
1065
|
+
function isTenantClaimSource(source) {
|
|
1066
|
+
return typeof source.claim === "string";
|
|
1067
|
+
}
|
|
1068
|
+
/** Narrow a {@link TenantSource} to its membership form. @group Models */
|
|
1069
|
+
function isTenantMembershipSource(source) {
|
|
1070
|
+
return typeof source.membership === "object" && source.membership !== null;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* The roles tenancy does not apply to, when the collection names none.
|
|
1074
|
+
*
|
|
1075
|
+
* `admin`, mirroring the security baseline every collection already carries
|
|
1076
|
+
* (`<table>_default_admin_read` / `_write`): the Studio, `dataAsAdmin` and a
|
|
1077
|
+
* support operator all run with it, and a tenancy rule that locked them out
|
|
1078
|
+
* would make the admin panel show an empty table on a collection full of rows.
|
|
1079
|
+
*
|
|
1080
|
+
* @group Models
|
|
1081
|
+
*/
|
|
1082
|
+
var DEFAULT_TENANT_BYPASS_ROLES = ["admin"];
|
|
1083
|
+
//#endregion
|
|
1026
1084
|
//#region src/types/backend.ts
|
|
1027
1085
|
/**
|
|
1028
1086
|
* Type guard: can this admin plan a live schema change?
|
|
@@ -1073,7 +1131,8 @@ var DEFAULT_COMMIT_PATHS = {
|
|
|
1073
1131
|
ddlFile: "drizzle/schema.sql",
|
|
1074
1132
|
policiesFile: "drizzle/policies.sql",
|
|
1075
1133
|
searchFile: "drizzle/search.sql",
|
|
1076
|
-
vectorFile: "drizzle/vector.sql"
|
|
1134
|
+
vectorFile: "drizzle/vector.sql",
|
|
1135
|
+
triggersFile: "drizzle/triggers.sql"
|
|
1077
1136
|
};
|
|
1078
1137
|
//#endregion
|
|
1079
1138
|
//#region src/types/channel_bus.ts
|
|
@@ -2174,6 +2233,107 @@ function computeSchemaVersion(collections) {
|
|
|
2174
2233
|
return `v1:${hex(h1)}${hex(h2)}`;
|
|
2175
2234
|
}
|
|
2176
2235
|
//#endregion
|
|
2236
|
+
//#region src/controllers/data.ts
|
|
2237
|
+
/**
|
|
2238
|
+
* Hops an {@link IncludeSpec} may nest. `comments.author` is two.
|
|
2239
|
+
*
|
|
2240
|
+
* @group Data
|
|
2241
|
+
*/
|
|
2242
|
+
var MAX_INCLUDE_DEPTH = 3;
|
|
2243
|
+
/**
|
|
2244
|
+
* SDK collection client — returns flat rows, no Entity wrapper.
|
|
2245
|
+
*
|
|
2246
|
+
* This is the public API surface for app developers using
|
|
2247
|
+
* `createRebaseClient()`. admin internals use `CollectionAccessor` instead.
|
|
2248
|
+
*
|
|
2249
|
+
* Type parameters:
|
|
2250
|
+
* - `M` — the **Row** shape returned by reads (`find`, `findById`, `listen`).
|
|
2251
|
+
* - `I` — the **Insert** shape accepted by {@link create}. Defaults to
|
|
2252
|
+
* `Partial<M>`; the generated SDK supplies a dedicated `Insert` type where
|
|
2253
|
+
* required columns are required and auto-generated / read-only columns are
|
|
2254
|
+
* omitted, so `create({})` on a table with required fields is a compile error.
|
|
2255
|
+
* - `U` — the **Update** shape accepted by {@link update}. Defaults to
|
|
2256
|
+
* `Partial<M>`; the generated SDK supplies a dedicated `Update` type.
|
|
2257
|
+
*
|
|
2258
|
+
* @example
|
|
2259
|
+
* const { data: posts } = await rebase.data.posts.find();
|
|
2260
|
+
* console.log(posts[0].title); // flat access
|
|
2261
|
+
* console.log(posts[0].id); // id at top level
|
|
2262
|
+
*
|
|
2263
|
+
* const post = await rebase.data.posts.findById(1);
|
|
2264
|
+
* console.log(post?.title); // no .values needed
|
|
2265
|
+
*
|
|
2266
|
+
* @group Data
|
|
2267
|
+
*/
|
|
2268
|
+
/**
|
|
2269
|
+
* A change expressed as an operation on the column's current value, rather than
|
|
2270
|
+
* as the value to store.
|
|
2271
|
+
*
|
|
2272
|
+
* `{ views: 5 }` says what the number becomes; `{ views: { $inc: 1 } }` says
|
|
2273
|
+
* what happens to it. The difference is the read the caller no longer has to
|
|
2274
|
+
* make — and the race that read opens. Two requests that each read `4`, add one
|
|
2275
|
+
* and write `5` lose an increment between them; `SET views = views + 1` cannot,
|
|
2276
|
+
* because the arithmetic happens inside the statement holding the row lock.
|
|
2277
|
+
*
|
|
2278
|
+
* Exactly one operator per field. `{ views: { $inc: 1, $push: "x" } }` is
|
|
2279
|
+
* refused rather than applied in an order the caller cannot see.
|
|
2280
|
+
*
|
|
2281
|
+
* @group Data
|
|
2282
|
+
*/
|
|
2283
|
+
/**
|
|
2284
|
+
* The operator names, as a value.
|
|
2285
|
+
*
|
|
2286
|
+
* A runtime list beside the type because three layers have to *recognise* an
|
|
2287
|
+
* operation, not just accept one: the REST validator, the driver that compiles
|
|
2288
|
+
* it, and the offline queue that must refuse to apply one locally. Three copies
|
|
2289
|
+
* of four strings is three chances for one of them to miss an operator added to
|
|
2290
|
+
* the other two, and the failure is silent in the worst direction — an
|
|
2291
|
+
* unrecognised marker is written to the column as a JSON document.
|
|
2292
|
+
*
|
|
2293
|
+
* @group Data
|
|
2294
|
+
*/
|
|
2295
|
+
var FIELD_OPERATORS = [
|
|
2296
|
+
"$inc",
|
|
2297
|
+
"$push",
|
|
2298
|
+
"$pull",
|
|
2299
|
+
"$merge"
|
|
2300
|
+
];
|
|
2301
|
+
/**
|
|
2302
|
+
* The key of a {@link BatchRef}. Declared here, beside the field operators,
|
|
2303
|
+
* because the two share one namespace: a `$`-prefixed key in a write payload is
|
|
2304
|
+
* a marker, and every reader of that namespace has to know all of it.
|
|
2305
|
+
*
|
|
2306
|
+
* @group Data
|
|
2307
|
+
*/
|
|
2308
|
+
var BATCH_REF_KEY = "$ref";
|
|
2309
|
+
/**
|
|
2310
|
+
* Whether a value is *trying* to be a field operation — including a misspelled
|
|
2311
|
+
* one, which is the case worth catching.
|
|
2312
|
+
*
|
|
2313
|
+
* Any `$`-prefixed key counts, because `{ $increment: 1 }` written to a number
|
|
2314
|
+
* column as a JSON document is the failure this exists to prevent. No collection
|
|
2315
|
+
* can declare a column whose value legitimately has a key beginning with `$`: a
|
|
2316
|
+
* `map` property's sub-keys are declared, and `$` is not valid in the
|
|
2317
|
+
* identifiers the DDL generators emit.
|
|
2318
|
+
*
|
|
2319
|
+
* The one exception is `{ $ref: … }`, the batch's backward reference. It stands
|
|
2320
|
+
* where a *value* goes and is resolved to one before the row is written, so it
|
|
2321
|
+
* is not an operation on a column — reading it as a misspelled operator refused
|
|
2322
|
+
* every `$ref` in a batch with "unknown field operator '$ref'".
|
|
2323
|
+
*
|
|
2324
|
+
* @group Data
|
|
2325
|
+
*/
|
|
2326
|
+
function isFieldOperation(value) {
|
|
2327
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Date) return false;
|
|
2328
|
+
const keys = Object.keys(value);
|
|
2329
|
+
if (keys.length === 1 && keys[0] === "$ref") return false;
|
|
2330
|
+
return keys.some((key) => key.startsWith("$"));
|
|
2331
|
+
}
|
|
2332
|
+
/** True when any value in a write payload is (or is attempting to be) one. @group Data */
|
|
2333
|
+
function hasFieldOperation(values) {
|
|
2334
|
+
return !!values && Object.values(values).some(isFieldOperation);
|
|
2335
|
+
}
|
|
2336
|
+
//#endregion
|
|
2177
2337
|
//#region src/controllers/data_driver.ts
|
|
2178
2338
|
/** Rows returned for a plain / text-search list read when the client sends no `limit`. */
|
|
2179
2339
|
var DEFAULT_LIST_LIMIT = 50;
|
|
@@ -2255,6 +2415,6 @@ function isPublicStoragePath(path) {
|
|
|
2255
2415
|
return p.startsWith("public/") || p.startsWith(`default/public/`);
|
|
2256
2416
|
}
|
|
2257
2417
|
//#endregion
|
|
2258
|
-
export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_COMMIT_PATHS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, DEFAULT_RESOURCE_KEY, DEFAULT_SEARCH_COLUMN, DEFAULT_SEARCH_LANGUAGE, DEFAULT_SEARCH_WEIGHT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, LEGACY_RLS_JWT_SQL, LEGACY_RLS_ROLES_SQL, LEGACY_RLS_SCHEMA, LEGACY_RLS_UID_SQL, ListLimitError, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REBASE_SCHEMA, RELEVANCE_SORT_FIELD, RESERVED_BACKEND_PREFIXES, RESOURCE_GRAPH_VERSION, REST_TO_CANONICAL, RLS_IS_ANONYMOUS_SQL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, amendResourceKind, bucket, buildResourceGraph, canonicalSchemaPayload, computeSchemaVersion, database, declareCron, declareFunction, declareResource, declaredDataSources, declaredDatabaseExtensions, declaredQueueConsumers, declaredResources, declaredStorageSources, declaredSubscriptions, deserializeCollections, encodeRelationAggregateSort, envBasesForResource, findEnvSuffixCollision, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationAggregateSort, isRelationalCollectionConfig, isResourceHandle, isSQLAdmin, isSchemaAdmin, isSchemaEditingAdmin, isSerializedCollectionRef, isToMany, isUnsupported, isValidEngine, nestAdminCollectionKeys, nestAdminKeysOf, nestAdminPropertyKeys, parseRelationAggregateSort, policy, queue, registerDataSourceCapabilities, registerResourceKind, reservedPrefixFor, resetDeclaredQueueConsumers, resetDeclaredResources, resetDeclaredSubscriptions, resolveClientListLimit, resolveResourceRefs, resourceEnvSuffix, resourceId, resourceKeyOf, resourceKind, resourceKinds, resourceToDataSource, resourceToStorageSource, rewriteLegacyRlsFunctions, serializeCollections, setQueueRuntime, setTopicRuntime, sortKeyToString, storageEnvSuffix, toCanonicalOp, topic, unsupportedMethod, usesLegacyRlsFunctions };
|
|
2418
|
+
export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BATCH_REF_KEY, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_COMMIT_PATHS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, DEFAULT_RESOURCE_KEY, DEFAULT_SEARCH_COLUMN, DEFAULT_SEARCH_LANGUAGE, DEFAULT_SEARCH_WEIGHT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_TENANT_BYPASS_ROLES, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIELD_OPERATORS, FIREBASE_CAPABILITIES, GeoPoint, JUNCTION_PIVOT_KEY, LEGACY_RLS_JWT_SQL, LEGACY_RLS_ROLES_SQL, LEGACY_RLS_SCHEMA, LEGACY_RLS_UID_SQL, LIST_OPS, ListLimitError, MAX_INCLUDE_DEPTH, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REBASE_SCHEMA, RELEVANCE_SORT_FIELD, RESERVED_BACKEND_PREFIXES, RESOURCE_GRAPH_VERSION, REST_TO_CANONICAL, RLS_IS_ANONYMOUS_SQL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, amendResourceKind, bucket, buildResourceGraph, canonicalSchemaPayload, computeSchemaVersion, database, declareCron, declareFunction, declareResource, declaredDataSources, declaredDatabaseExtensions, declaredQueueConsumers, declaredResources, declaredStorageSources, declaredSubscriptions, deserializeCollections, encodeRelationAggregateSort, envBasesForResource, findEnvSuffixCollision, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasFieldOperation, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFieldOperation, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationAggregateSort, isRelationalCollectionConfig, isResourceHandle, isSQLAdmin, isSchemaAdmin, isSchemaEditingAdmin, isSerializedCollectionRef, isTenantClaimSource, isTenantMembershipSource, isToMany, isUnsupported, isValidEngine, nestAdminCollectionKeys, nestAdminKeysOf, nestAdminPropertyKeys, parseRelationAggregateSort, policy, queue, registerDataSourceCapabilities, registerResourceKind, reservedPrefixFor, resetDeclaredQueueConsumers, resetDeclaredResources, resetDeclaredSubscriptions, resolveClientListLimit, resolveResourceRefs, resourceEnvSuffix, resourceId, resourceKeyOf, resourceKind, resourceKinds, resourceToDataSource, resourceToStorageSource, rewriteLegacyRlsFunctions, serializeCollections, setQueueRuntime, setTopicRuntime, sortKeyToString, storageEnvSuffix, toCanonicalOp, topic, unsupportedMethod, usesLegacyRlsFunctions };
|
|
2259
2419
|
|
|
2260
2420
|
//# sourceMappingURL=index.es.js.map
|