@rebasepro/server-postgres 0.11.1-canary.gfd39654 → 0.12.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/dist/PostgresBootstrapper.d.ts +8 -0
- package/dist/collections/buildRegistry.d.ts +1 -1
- package/dist/{ensure-collection-tables-DGMYK0fr.js → ensure-collection-tables-CNTcZGvn.js} +3 -3
- package/dist/{ensure-collection-tables-DGMYK0fr.js.map → ensure-collection-tables-CNTcZGvn.js.map} +1 -1
- package/dist/history/HistoryService.d.ts +9 -29
- package/dist/index.es.js +397 -53
- package/dist/index.es.js.map +1 -1
- package/dist/schema/dynamic-tables.d.ts +1 -1
- package/dist/schema/introspect-runtime.d.ts +1 -1
- package/dist/services/FetchService.d.ts +36 -1
- package/dist/services/row-pipeline.d.ts +3 -1
- package/dist/{src-3VmUJ8Xn.js → src-BbFOPJ1S.js} +197 -18
- package/dist/src-BbFOPJ1S.js.map +1 -0
- package/dist/{src-D5xBTl32.js → src-Zqwaw3P5.js} +136 -90
- package/dist/src-Zqwaw3P5.js.map +1 -0
- package/dist/utils/drizzle-conditions.d.ts +157 -3
- package/dist/utils/pg-error-utils.d.ts +6 -3
- package/package.json +6 -6
- package/src/PostgresBootstrapper.ts +23 -6
- package/src/collections/buildRegistry.ts +1 -1
- package/src/history/HistoryService.ts +13 -31
- package/src/schema/dynamic-tables.ts +1 -1
- package/src/schema/generate-drizzle-schema-logic.ts +10 -2
- package/src/schema/introspect-runtime.ts +1 -1
- package/src/services/FetchService.ts +79 -11
- package/src/services/row-pipeline.ts +3 -1
- package/src/utils/drizzle-conditions.ts +509 -45
- package/src/utils/pg-error-utils.ts +52 -3
- package/dist/src-3VmUJ8Xn.js.map +0 -1
- package/dist/src-D5xBTl32.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Build drizzle tables at runtime from an introspected schema.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* A project with declared collections gets its drizzle tables from a generated `schema.generated.ts` that
|
|
5
5
|
* the developer commits. BaaS mode has no such file — it points at a database
|
|
6
6
|
* and serves it — so the equivalent table objects are constructed here from
|
|
7
7
|
* `information_schema` metadata.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* single config file.
|
|
8
8
|
*
|
|
9
9
|
* Distinct from `introspect-db.ts`, which runs the same queries but emits
|
|
10
|
-
* TypeScript *source* for a developer to edit and commit (
|
|
10
|
+
* TypeScript *source* for a developer to edit and commit (declared collections). The two
|
|
11
11
|
* share the mapping helpers in `introspect-db-logic.ts` so a table is described
|
|
12
12
|
* the same way whether it was generated or introspected.
|
|
13
13
|
*/
|
|
@@ -20,6 +20,32 @@ export declare class FetchService {
|
|
|
20
20
|
* Safely narrows the DrizzleClient union type to access db.query[tableName].
|
|
21
21
|
*/
|
|
22
22
|
private getQueryBuilder;
|
|
23
|
+
/**
|
|
24
|
+
* The context the condition builder needs to compile a filter key that is
|
|
25
|
+
* not a column name outright.
|
|
26
|
+
*
|
|
27
|
+
* Two such keys. An owning relation's key resolves through the collection's
|
|
28
|
+
* relations to its foreign-key column; a relation whose link lives on the
|
|
29
|
+
* target table or in a junction resolves to a correlated `EXISTS`, which
|
|
30
|
+
* needs the registry to reach that other table and this table's key column
|
|
31
|
+
* to correlate back.
|
|
32
|
+
*
|
|
33
|
+
* Looked up rather than passed: every read path already has the path, only
|
|
34
|
+
* some have the collection, and a path that names no registered collection
|
|
35
|
+
* (a nested/derived one) is not an error here — the builder simply falls
|
|
36
|
+
* back to guessing the default key shapes, and a relation filter it cannot
|
|
37
|
+
* compile stays unresolvable and so fails closed.
|
|
38
|
+
*/
|
|
39
|
+
private filterContext;
|
|
40
|
+
/**
|
|
41
|
+
* The table column this collection's rows are keyed by, or `undefined`.
|
|
42
|
+
*
|
|
43
|
+
* `getPrimaryKeys` rather than `requirePrimaryKeys`: a collection with no
|
|
44
|
+
* resolvable key is not an error on the filter path — it only means the
|
|
45
|
+
* relation filters that would correlate on it cannot be compiled, which
|
|
46
|
+
* the builder already handles by failing that field closed.
|
|
47
|
+
*/
|
|
48
|
+
private resolveIdColumn;
|
|
23
49
|
/**
|
|
24
50
|
* Build filter conditions from FilterValues
|
|
25
51
|
* Delegates to DrizzleConditionBuilder.buildFilterConditions
|
|
@@ -28,6 +54,15 @@ export declare class FetchService {
|
|
|
28
54
|
/**
|
|
29
55
|
* Resolves the correct Drizzle column for sorting.
|
|
30
56
|
* Automatically maps owning relation property keys to their underlying foreign key column.
|
|
57
|
+
*
|
|
58
|
+
* The relation's own `localKey` is the authority for that foreign key, not
|
|
59
|
+
* `<field>_id`. The default local key comes from `generateForeignKeyName`,
|
|
60
|
+
* which snake-cases *and singularises* — `userProfile` → `user_profile_id`,
|
|
61
|
+
* `users` → `user_id` — and an author can override it outright. A wrong
|
|
62
|
+
* guess resolves to nothing, the caller drops the `ORDER BY`, and the rows
|
|
63
|
+
* come back in whatever order Postgres pleases: paging over that repeats
|
|
64
|
+
* and skips rows rather than erroring. The guesses stay, last, for a
|
|
65
|
+
* caller that hands over no collection to resolve against.
|
|
31
66
|
*/
|
|
32
67
|
private resolveOrderByField;
|
|
33
68
|
/**
|
|
@@ -35,7 +70,7 @@ export declare class FetchService {
|
|
|
35
70
|
* Converts collection relations to a Drizzle-compatible `with` object.
|
|
36
71
|
*
|
|
37
72
|
* When `include` is provided, only those relations are loaded.
|
|
38
|
-
* When `include` is absent, ALL relations are loaded (
|
|
73
|
+
* When `include` is absent, ALL relations are loaded (the admin path).
|
|
39
74
|
*
|
|
40
75
|
* Automatically detects many-to-many junction tables and nests
|
|
41
76
|
* the target relation so actual row data is returned.
|
|
@@ -10,7 +10,9 @@ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionReg
|
|
|
10
10
|
*
|
|
11
11
|
* - `"ref"` — a `{ id, path, __type: "relation" }` reference carrying the
|
|
12
12
|
* target's values. This is what the admin renders.
|
|
13
|
-
* - `"inline"` — the target's own columns, flat. This is what REST serves
|
|
13
|
+
* - `"inline"` — the target's own columns, flat. This is what REST serves, and
|
|
14
|
+
* — since the in-process SDK reads through the same pipeline — what
|
|
15
|
+
* `rebase.data` / `context.data` serve too. A developer never sees a ref.
|
|
14
16
|
*
|
|
15
17
|
* They used to be two functions that happened to agree, and the agreement was
|
|
16
18
|
* not enforced by anything: the row-identity bug had to be fixed five times
|
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
|
|
|
2
2
|
import "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
4
|
import { r as __require, t as __commonJSMin } from "./chunk-DSJWtz9O.js";
|
|
5
|
-
import {
|
|
5
|
+
import { a as policy, c as getDeclaredSubcollections, f as getDataSourceCapabilities, g as EntityRelation, h as toCanonicalOp, i as ANONYMOUS_USER_ID, l as isPostgresCollectionConfig, m as REST_TO_CANONICAL, p as NULL_OPS, s as isManyToMany, u as isRelationalCollectionConfig } from "./src-Zqwaw3P5.js";
|
|
6
6
|
//#region ../common/src/util/common.ts
|
|
7
7
|
var DEFAULT_ONE_OF_TYPE = "type";
|
|
8
8
|
var DEFAULT_ONE_OF_VALUE = "value";
|
|
@@ -1264,7 +1264,7 @@ function traverseValueProperty(inputValue, property, operation) {
|
|
|
1264
1264
|
return value;
|
|
1265
1265
|
}
|
|
1266
1266
|
/**
|
|
1267
|
-
* Create a lightweight relation stub for
|
|
1267
|
+
* Create a lightweight relation stub for admin views.
|
|
1268
1268
|
* Replaces inline `{ id, path, __type: "relation" }` object literals.
|
|
1269
1269
|
*/
|
|
1270
1270
|
function createRelationRef(id, path) {
|
|
@@ -1527,7 +1527,7 @@ var _resolvedRelationsCache = /* @__PURE__ */ new WeakMap();
|
|
|
1527
1527
|
function resolveCollectionRelations(collection) {
|
|
1528
1528
|
const cached = _resolvedRelationsCache.get(collection);
|
|
1529
1529
|
if (cached) return cached;
|
|
1530
|
-
if (!
|
|
1530
|
+
if (!isRelationalCollectionConfig(collection)) return {};
|
|
1531
1531
|
const relations = {};
|
|
1532
1532
|
for (const relation of collection.relations ?? []) {
|
|
1533
1533
|
const resolved = resolveRelation(relation, collection);
|
|
@@ -1543,7 +1543,7 @@ function resolveCollectionRelations(collection) {
|
|
|
1543
1543
|
return relations;
|
|
1544
1544
|
}
|
|
1545
1545
|
function getTableName(collection) {
|
|
1546
|
-
if (
|
|
1546
|
+
if (isRelationalCollectionConfig(collection)) return collection.table ?? toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
1547
1547
|
return toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
1548
1548
|
}
|
|
1549
1549
|
function getTableVarName(tableName) {
|
|
@@ -2152,8 +2152,8 @@ function getIdPropertyName$1(collection) {
|
|
|
2152
2152
|
* Collections that opt out via `disableDefaultPolicies` are returned unchanged.
|
|
2153
2153
|
*/
|
|
2154
2154
|
function getEffectiveSecurityRules(collection) {
|
|
2155
|
-
const explicit = [...
|
|
2156
|
-
if (collection.disableDefaultPolicies) return explicit;
|
|
2155
|
+
const explicit = [...collection.securityRules ?? []];
|
|
2156
|
+
if (isPostgresCollectionConfig(collection) && collection.disableDefaultPolicies) return explicit;
|
|
2157
2157
|
const tableName = getTableName(collection);
|
|
2158
2158
|
const injected = [];
|
|
2159
2159
|
injected.push({
|
|
@@ -2324,7 +2324,7 @@ function coversUpdate(rule) {
|
|
|
2324
2324
|
* stays locked (RLS is still enabled) until they write policies for it.
|
|
2325
2325
|
*/
|
|
2326
2326
|
function getJunctionSecurityRules(spec) {
|
|
2327
|
-
if (spec.declaringSides.every((side) => side.collection.disableDefaultPolicies)) return [];
|
|
2327
|
+
if (spec.declaringSides.every((side) => isPostgresCollectionConfig(side.collection) && side.collection.disableDefaultPolicies)) return [];
|
|
2328
2328
|
const rules = [];
|
|
2329
2329
|
rules.push({
|
|
2330
2330
|
name: `${spec.table}_default_admin_read`,
|
|
@@ -3444,6 +3444,136 @@ var QueryBuilder = class {
|
|
|
3444
3444
|
return this.collection.listen(this.params, onUpdate, onError);
|
|
3445
3445
|
}
|
|
3446
3446
|
};
|
|
3447
|
+
/** Rows `findAll()` will materialise before it refuses to continue. */
|
|
3448
|
+
var DEFAULT_FIND_ALL_MAX_ROWS = 1e4;
|
|
3449
|
+
/**
|
|
3450
|
+
* Requests one walk may make before it gives up on the server ever saying
|
|
3451
|
+
* `hasMore: false`. At the default page size that is two million rows — far
|
|
3452
|
+
* past any legitimate walk, and short of running forever.
|
|
3453
|
+
*/
|
|
3454
|
+
var DEFAULT_MAX_PAGES = 1e4;
|
|
3455
|
+
/**
|
|
3456
|
+
* Thrown when a walk stops for a reason the caller needs to know about.
|
|
3457
|
+
*
|
|
3458
|
+
* Every one of these is a case where the alternative would be silent: a
|
|
3459
|
+
* truncated array that looks complete, or a loop that never returns. Check
|
|
3460
|
+
* {@link code} to tell them apart.
|
|
3461
|
+
*/
|
|
3462
|
+
var RebasePaginationError = class RebasePaginationError extends Error {
|
|
3463
|
+
code;
|
|
3464
|
+
constructor(code, message) {
|
|
3465
|
+
super(message);
|
|
3466
|
+
this.name = "RebasePaginationError";
|
|
3467
|
+
this.code = code;
|
|
3468
|
+
Object.setPrototypeOf(this, RebasePaginationError.prototype);
|
|
3469
|
+
}
|
|
3470
|
+
};
|
|
3471
|
+
function normalizePageSize(raw) {
|
|
3472
|
+
if (raw === void 0 || !Number.isFinite(raw)) return 200;
|
|
3473
|
+
return Math.max(1, Math.floor(raw));
|
|
3474
|
+
}
|
|
3475
|
+
function normalizeMaxPages(raw) {
|
|
3476
|
+
if (raw === void 0) return DEFAULT_MAX_PAGES;
|
|
3477
|
+
if (raw === Number.POSITIVE_INFINITY) return raw;
|
|
3478
|
+
if (!Number.isFinite(raw)) return DEFAULT_MAX_PAGES;
|
|
3479
|
+
return Math.max(1, Math.floor(raw));
|
|
3480
|
+
}
|
|
3481
|
+
function normalizeMaxRows(raw) {
|
|
3482
|
+
if (raw === void 0) return DEFAULT_FIND_ALL_MAX_ROWS;
|
|
3483
|
+
if (raw === Number.POSITIVE_INFINITY) return raw;
|
|
3484
|
+
if (!Number.isFinite(raw)) return DEFAULT_FIND_ALL_MAX_ROWS;
|
|
3485
|
+
return Math.max(0, Math.floor(raw));
|
|
3486
|
+
}
|
|
3487
|
+
/**
|
|
3488
|
+
* Add one condition to a `where` map without disturbing what is already there.
|
|
3489
|
+
*
|
|
3490
|
+
* The caller's own filter on the cursor column has to survive — dropping it
|
|
3491
|
+
* would widen the query, which is the silent-filter-loss failure mode — so a
|
|
3492
|
+
* second condition on the same column becomes the array-of-tuples form that
|
|
3493
|
+
* `FindParams.where` already accepts, and both are AND-ed.
|
|
3494
|
+
*/
|
|
3495
|
+
function appendCondition(where, column, condition) {
|
|
3496
|
+
const next = { ...where ?? {} };
|
|
3497
|
+
const existing = next[column];
|
|
3498
|
+
if (existing === void 0) next[column] = condition;
|
|
3499
|
+
else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) next[column] = [...existing, condition];
|
|
3500
|
+
else next[column] = [existing, condition];
|
|
3501
|
+
return next;
|
|
3502
|
+
}
|
|
3503
|
+
function cursorEquals(a, b) {
|
|
3504
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
3505
|
+
return Object.is(a, b);
|
|
3506
|
+
}
|
|
3507
|
+
/**
|
|
3508
|
+
* Walk every row a query matches, yielding one row at a time and fetching the
|
|
3509
|
+
* next page only when the consumer asks for it.
|
|
3510
|
+
*
|
|
3511
|
+
* See {@link SDKCollectionClient.iterate} for the caller-facing contract,
|
|
3512
|
+
* including the offset-drift caveat and the `cursor` alternative.
|
|
3513
|
+
*
|
|
3514
|
+
* @param find the transport's single-page read
|
|
3515
|
+
* @param params `find()` parameters minus the window, plus the walk options
|
|
3516
|
+
* @param label the collection name, so an error says which walk failed
|
|
3517
|
+
*/
|
|
3518
|
+
async function* paginateFind(find, params, label = "collection") {
|
|
3519
|
+
const { pageSize, cursor, maxPages, ...rest } = params ?? {};
|
|
3520
|
+
const findParams = { ...rest };
|
|
3521
|
+
const size = normalizePageSize(pageSize);
|
|
3522
|
+
const pageCap = normalizeMaxPages(maxPages);
|
|
3523
|
+
const cursorField = typeof cursor === "string" ? cursor : cursor?.field;
|
|
3524
|
+
const requestedDirection = typeof cursor === "object" && cursor !== null ? cursor.direction : void 0;
|
|
3525
|
+
let direction = "asc";
|
|
3526
|
+
if (cursorField) {
|
|
3527
|
+
const orderBy = findParams.orderBy;
|
|
3528
|
+
if (orderBy && orderBy[0] !== cursorField) throw new RebasePaginationError("cursor-order-mismatch", `Cannot seek on "${cursorField}" while ordering "${label}" by "${orderBy[0]}": keyset pagination only advances along the column the query is sorted by. Order by "${cursorField}", or drop the cursor and page by offset.`);
|
|
3529
|
+
direction = requestedDirection ?? orderBy?.[1] ?? "asc";
|
|
3530
|
+
findParams.orderBy = [cursorField, direction];
|
|
3531
|
+
}
|
|
3532
|
+
const seekOp = direction === "desc" ? "<" : ">";
|
|
3533
|
+
const baseWhere = findParams.where;
|
|
3534
|
+
let offset = 0;
|
|
3535
|
+
let pages = 0;
|
|
3536
|
+
let cursorValue;
|
|
3537
|
+
let seeking = false;
|
|
3538
|
+
for (;;) {
|
|
3539
|
+
if (pages >= pageCap) throw new RebasePaginationError("max-pages", `Iterating "${label}" made ${pages} requests without the server reporting the end of the collection. Stopping rather than looping forever — raise \`maxPages\` if the walk is genuinely this long, or check that the backend sets \`meta.hasMore\`.`);
|
|
3540
|
+
const pageParams = {
|
|
3541
|
+
...findParams,
|
|
3542
|
+
limit: size
|
|
3543
|
+
};
|
|
3544
|
+
if (cursorField) {
|
|
3545
|
+
if (seeking) pageParams.where = appendCondition(baseWhere, cursorField, [seekOp, cursorValue]);
|
|
3546
|
+
} else pageParams.offset = offset;
|
|
3547
|
+
const page = await find(pageParams);
|
|
3548
|
+
pages += 1;
|
|
3549
|
+
const rows = page?.data ?? [];
|
|
3550
|
+
if (rows.length === 0) return;
|
|
3551
|
+
for (const row of rows) yield row;
|
|
3552
|
+
if (page?.meta?.hasMore !== true) return;
|
|
3553
|
+
if (cursorField) {
|
|
3554
|
+
const nextValue = rows[rows.length - 1]?.[cursorField];
|
|
3555
|
+
if (nextValue === void 0 || nextValue === null) throw new RebasePaginationError("cursor-missing", `Cannot seek past the last row of "${label}": it has no value for the cursor column "${cursorField}". Pick a column that is present and non-null on every row.`);
|
|
3556
|
+
if (seeking && cursorEquals(nextValue, cursorValue)) throw new RebasePaginationError("cursor-stalled", `Iterating "${label}" is stuck: two pages in a row ended at ${cursorField}=${String(nextValue)}. The cursor column has to be unique — a repeated value cannot be seeked past, and continuing would either loop forever or skip the duplicates. Use the primary key, or page by offset.`);
|
|
3557
|
+
cursorValue = nextValue;
|
|
3558
|
+
seeking = true;
|
|
3559
|
+
} else offset += rows.length;
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* {@link paginateFind}, collected into an array under a ceiling.
|
|
3564
|
+
*
|
|
3565
|
+
* See {@link SDKCollectionClient.findAll}.
|
|
3566
|
+
*/
|
|
3567
|
+
async function collectAllPages(find, params, label = "collection") {
|
|
3568
|
+
const { maxRows, ...rest } = params ?? {};
|
|
3569
|
+
const cap = normalizeMaxRows(maxRows);
|
|
3570
|
+
const out = [];
|
|
3571
|
+
for await (const row of paginateFind(find, rest, label)) {
|
|
3572
|
+
out.push(row);
|
|
3573
|
+
if (out.length > cap) throw new RebasePaginationError("max-rows", `findAll("${label}") matched more than ${cap} rows. Returning the first ${cap} would look like the whole answer and quietly not be one, so this throws instead. Raise \`maxRows\` if you meant to load them all, or stream with \`iterate()\`.`);
|
|
3574
|
+
}
|
|
3575
|
+
return out;
|
|
3576
|
+
}
|
|
3447
3577
|
//#endregion
|
|
3448
3578
|
//#region ../common/src/data/filter-dialect.ts
|
|
3449
3579
|
/**
|
|
@@ -3593,6 +3723,42 @@ function rowToEntity(row, slug, primaryKeys = []) {
|
|
|
3593
3723
|
values: row
|
|
3594
3724
|
};
|
|
3595
3725
|
}
|
|
3726
|
+
/**
|
|
3727
|
+
* The relation envelope `toCmsRow` writes where a relation was:
|
|
3728
|
+
* `{ id, path, __type: "relation", data: { id, path, values } }`. It is the
|
|
3729
|
+
* admin's view-model, and the only pipeline that produces one is postgres'.
|
|
3730
|
+
*/
|
|
3731
|
+
function isRelationEnvelope(value) {
|
|
3732
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && value.__type === "relation";
|
|
3733
|
+
}
|
|
3734
|
+
/** The target's own columns, as `toRestRow` would have inlined them. */
|
|
3735
|
+
function inlineEnvelope(envelope) {
|
|
3736
|
+
return envelope.data?.values ?? {};
|
|
3737
|
+
}
|
|
3738
|
+
/**
|
|
3739
|
+
* Replace every relation envelope on a row with the target's flat columns.
|
|
3740
|
+
*
|
|
3741
|
+
* The SDK serves one relation shape — the inlined one (see
|
|
3742
|
+
* {@link RestFetchService}) — and reads that come back through a *driver*
|
|
3743
|
+
* method rather than the REST pipeline still carry envelopes. Realtime is the
|
|
3744
|
+
* one such read left: there is no `listenForRest`, so the rows arrive shaped
|
|
3745
|
+
* for the admin and are flattened here instead.
|
|
3746
|
+
*
|
|
3747
|
+
* Only applied where the REST pipeline is the contract (see `find`); a driver
|
|
3748
|
+
* without a `restFetchService` keeps whatever it returns, so the admin's own
|
|
3749
|
+
* path through {@link buildRebaseData} is untouched.
|
|
3750
|
+
*/
|
|
3751
|
+
function inlineRelationRefs(row) {
|
|
3752
|
+
let out;
|
|
3753
|
+
for (const [key, value] of Object.entries(row)) if (isRelationEnvelope(value)) {
|
|
3754
|
+
out = out ?? { ...row };
|
|
3755
|
+
out[key] = inlineEnvelope(value);
|
|
3756
|
+
} else if (Array.isArray(value) && value.some(isRelationEnvelope)) {
|
|
3757
|
+
out = out ?? { ...row };
|
|
3758
|
+
out[key] = value.map((item) => isRelationEnvelope(item) ? inlineEnvelope(item) : item);
|
|
3759
|
+
}
|
|
3760
|
+
return out ?? row;
|
|
3761
|
+
}
|
|
3596
3762
|
function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
3597
3763
|
const accessor = {
|
|
3598
3764
|
async find(params) {
|
|
@@ -3600,14 +3766,14 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3600
3766
|
const limit = params?.limit ?? 20;
|
|
3601
3767
|
const offset = params?.offset ?? 0;
|
|
3602
3768
|
const fetchService = driver.restFetchService;
|
|
3603
|
-
const rows = fetchService
|
|
3769
|
+
const rows = fetchService ? await fetchService.fetchCollectionForRest(slug, {
|
|
3604
3770
|
filter,
|
|
3605
3771
|
limit: params?.limit,
|
|
3606
3772
|
offset: params?.offset,
|
|
3607
3773
|
orderBy: params?.orderBy?.[0],
|
|
3608
3774
|
order: params?.orderBy?.[1],
|
|
3609
3775
|
searchString: params?.searchString
|
|
3610
|
-
}, params
|
|
3776
|
+
}, params?.include) : await driver.fetchCollection({
|
|
3611
3777
|
path: slug,
|
|
3612
3778
|
limit: params?.limit,
|
|
3613
3779
|
offset: params?.offset,
|
|
@@ -3636,7 +3802,8 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3636
3802
|
};
|
|
3637
3803
|
},
|
|
3638
3804
|
async findById(id) {
|
|
3639
|
-
const
|
|
3805
|
+
const fetchService = driver.restFetchService;
|
|
3806
|
+
const row = fetchService ? await fetchService.fetchOneForRest(slug, id) : await driver.fetchOne({
|
|
3640
3807
|
path: slug,
|
|
3641
3808
|
id
|
|
3642
3809
|
});
|
|
@@ -3682,6 +3849,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3682
3849
|
listen: driver.listenCollection ? (params, onUpdate, onError) => {
|
|
3683
3850
|
const limit = params?.limit ?? 20;
|
|
3684
3851
|
const offset = params?.offset ?? 0;
|
|
3852
|
+
const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
|
|
3685
3853
|
return driver.listenCollection({
|
|
3686
3854
|
path: slug,
|
|
3687
3855
|
limit: params?.limit,
|
|
@@ -3692,7 +3860,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3692
3860
|
searchString: params?.searchString,
|
|
3693
3861
|
onUpdate: (entities) => {
|
|
3694
3862
|
onUpdate({
|
|
3695
|
-
data: entities.map((row) => rowToEntity(row, slug, getPks())),
|
|
3863
|
+
data: entities.map((row) => rowToEntity(normalize(row), slug, getPks())),
|
|
3696
3864
|
meta: {
|
|
3697
3865
|
total: entities.length,
|
|
3698
3866
|
limit,
|
|
@@ -3705,10 +3873,11 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3705
3873
|
});
|
|
3706
3874
|
} : void 0,
|
|
3707
3875
|
listenById: driver.listenOne ? (id, onUpdate, onError) => {
|
|
3876
|
+
const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
|
|
3708
3877
|
return driver.listenOne({
|
|
3709
3878
|
path: slug,
|
|
3710
3879
|
id,
|
|
3711
|
-
onUpdate: (entity) => onUpdate(entity ? rowToEntity(entity, slug, getPks()) : void 0),
|
|
3880
|
+
onUpdate: (entity) => onUpdate(entity ? rowToEntity(normalize(entity), slug, getPks()) : void 0),
|
|
3712
3881
|
onError
|
|
3713
3882
|
});
|
|
3714
3883
|
} : void 0,
|
|
@@ -3839,7 +4008,7 @@ var SdkQueryBuilder = class {
|
|
|
3839
4008
|
* {@link SDKCollectionClient}. Every returned record is unwrapped to a flat row
|
|
3840
4009
|
* so the backend SDK is byte-for-byte the same shape as the frontend client.
|
|
3841
4010
|
*/
|
|
3842
|
-
function toSdkCollectionClient(snap) {
|
|
4011
|
+
function toSdkCollectionClient(snap, slug = "collection") {
|
|
3843
4012
|
const client = {
|
|
3844
4013
|
async find(params) {
|
|
3845
4014
|
const res = await snap.find(params);
|
|
@@ -3848,6 +4017,12 @@ function toSdkCollectionClient(snap) {
|
|
|
3848
4017
|
meta: res.meta
|
|
3849
4018
|
};
|
|
3850
4019
|
},
|
|
4020
|
+
iterate(params) {
|
|
4021
|
+
return paginateFind((p) => client.find(p), params, slug);
|
|
4022
|
+
},
|
|
4023
|
+
findAll(params) {
|
|
4024
|
+
return collectAllPages((p) => client.find(p), params, slug);
|
|
4025
|
+
},
|
|
3851
4026
|
async findById(id) {
|
|
3852
4027
|
const s = await snap.findById(id);
|
|
3853
4028
|
return s ? entityToRow(s) : void 0;
|
|
@@ -3899,7 +4074,7 @@ function wrapAsSdkData(entityData) {
|
|
|
3899
4074
|
function getAccessor(slug) {
|
|
3900
4075
|
let accessor = cache.get(slug);
|
|
3901
4076
|
if (!accessor) {
|
|
3902
|
-
accessor = toSdkCollectionClient(entityData.collection(slug));
|
|
4077
|
+
accessor = toSdkCollectionClient(entityData.collection(slug), slug);
|
|
3903
4078
|
cache.set(slug, accessor);
|
|
3904
4079
|
}
|
|
3905
4080
|
return accessor;
|
|
@@ -3916,8 +4091,12 @@ function wrapAsSdkData(entityData) {
|
|
|
3916
4091
|
*
|
|
3917
4092
|
* This is the developer-facing SDK data layer used by backend framework
|
|
3918
4093
|
* callbacks & scripts (`context.data` / `rebase.data`). It returns flat rows —
|
|
3919
|
-
* identical in shape to the frontend SDK client
|
|
3920
|
-
*
|
|
4094
|
+
* identical in shape to the frontend SDK client, down to how a relation is
|
|
4095
|
+
* served: a foreign key stays a foreign key, and a relation named in `include`
|
|
4096
|
+
* arrives as the target's own columns. The `{ __type: "relation" }` envelope is
|
|
4097
|
+
* the admin's view-model and never reaches here.
|
|
4098
|
+
*
|
|
4099
|
+
* The admin uses {@link buildRebaseData} (Entity) over its own driver.
|
|
3921
4100
|
*/
|
|
3922
4101
|
function buildSdkData(driver) {
|
|
3923
4102
|
return wrapAsSdkData(buildRebaseData(driver));
|
|
@@ -3989,6 +4168,6 @@ async function detectJunctionTables(executeSql) {
|
|
|
3989
4168
|
return junctionTables;
|
|
3990
4169
|
}
|
|
3991
4170
|
//#endregion
|
|
3992
|
-
export {
|
|
4171
|
+
export { toSnakeCase as A, createRelationRefWithData as C, getPolicyNamesForRule as D, generateForeignKeyName as E, DEFAULT_ONE_OF_VALUE as M, mergeDeep as O, createRelationRef as S, updateDateAutoValues as T, getTableVarName as _, getJunctionCollectionConfig as a, getDeclaredPrimaryKeys as b, getEffectiveSecurityRules as c, securityRuleToConditions as d, findAnonymousGrants as f, getTableName as g, getEnumVarName as h, CollectionRegistry as i, DEFAULT_ONE_OF_TYPE as j, camelCase as k, buildPropertyCallbacks as l, getColumnName as m, detectJunctionTables as n, getJunctionSecurityRules as o, findRelation as p, buildSdkData as r, resolveJunctionSpecs as s, classifyTable as t, policyToPostgres as u, resolveCollectionRelations as v, normalizeToEntityRelation as w, parseIdValues as x, buildCompositeId as y };
|
|
3993
4172
|
|
|
3994
|
-
//# sourceMappingURL=src-
|
|
4173
|
+
//# sourceMappingURL=src-BbFOPJ1S.js.map
|