@rebasepro/server-postgres 0.11.1-canary.gfd39654 → 0.12.1-canary.gdfba2a1
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/auth/services.d.ts +16 -0
- package/dist/backup-service-DH9kPg-E.js +8866 -0
- package/dist/backup-service-DH9kPg-E.js.map +1 -0
- package/dist/collections/buildRegistry.d.ts +1 -1
- package/dist/connection-B5Wndbr1.js +196 -0
- package/dist/connection-B5Wndbr1.js.map +1 -0
- package/dist/{ensure-collection-tables-DGMYK0fr.js → ensure-collection-tables-CIHSH962.js} +5 -5
- package/dist/ensure-collection-tables-CIHSH962.js.map +1 -0
- package/dist/history/HistoryService.d.ts +9 -29
- package/dist/index.es.js +698 -9604
- package/dist/index.es.js.map +1 -1
- package/dist/schema/auth-schema.d.ts +83 -144
- 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-DihrDFuP.js} +354 -165
- package/dist/src-DihrDFuP.js.map +1 -0
- package/dist/{src-D5xBTl32.js → src-DoU9yPqq.js} +79 -189
- package/dist/src-DoU9yPqq.js.map +1 -0
- package/dist/utils/drizzle-conditions.d.ts +157 -3
- package/dist/utils/pg-error-utils.d.ts +6 -3
- package/dist/websocket-BKcGvILX.js +528 -0
- package/dist/websocket-BKcGvILX.js.map +1 -0
- package/package.json +14 -14
- package/src/PostgresBootstrapper.ts +23 -6
- package/src/auth/ensure-tables.ts +164 -9
- package/src/auth/services.ts +21 -2
- package/src/collections/buildRegistry.ts +1 -1
- package/src/history/HistoryService.ts +13 -31
- package/src/schema/auth-schema.ts +30 -19
- package/src/schema/dynamic-tables.ts +1 -1
- package/src/schema/generate-drizzle-schema-logic.ts +17 -5
- package/src/schema/generate-postgres-ddl-logic.ts +7 -3
- 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/chunk-DSJWtz9O.js +0 -40
- package/dist/ensure-collection-tables-DGMYK0fr.js.map +0 -1
- package/dist/src-3VmUJ8Xn.js.map +0 -1
- package/dist/src-D5xBTl32.js.map +0 -1
|
@@ -1,8 +1,135 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
import "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { c as __require, o as __commonJSMin } from "./connection-B5Wndbr1.js";
|
|
5
|
+
import { a as getDataSourceCapabilities, c as toCanonicalOp, n as isPostgresCollectionConfig, o as NULL_OPS, r as isRelationalCollectionConfig, s as REST_TO_CANONICAL, t as getDeclaredSubcollections } from "./src-DoU9yPqq.js";
|
|
6
|
+
//#region ../types/src/types/entities.ts
|
|
7
|
+
/**
|
|
8
|
+
* Class used to create a reference to a entity in a different path
|
|
9
|
+
*/
|
|
10
|
+
var EntityRelation = class {
|
|
11
|
+
__type = "relation";
|
|
12
|
+
/**
|
|
13
|
+
* ID of the entity
|
|
14
|
+
*/
|
|
15
|
+
id;
|
|
16
|
+
/**
|
|
17
|
+
* A string representing the path of the referenced document (relative
|
|
18
|
+
* to the root of the database).
|
|
19
|
+
*/
|
|
20
|
+
path;
|
|
21
|
+
/**
|
|
22
|
+
* Pre-fetched data payload to eliminate N+1 queries.
|
|
23
|
+
* When present, clients can use this directly instead of fetching.
|
|
24
|
+
*/
|
|
25
|
+
data;
|
|
26
|
+
constructor(id, path, data) {
|
|
27
|
+
this.id = id;
|
|
28
|
+
this.path = path;
|
|
29
|
+
this.data = data;
|
|
30
|
+
}
|
|
31
|
+
get pathWithId() {
|
|
32
|
+
return `${this.path}/${this.id}`;
|
|
33
|
+
}
|
|
34
|
+
isEntityReference() {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
isEntityRelation() {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var Vector = class {
|
|
42
|
+
value;
|
|
43
|
+
constructor(value) {
|
|
44
|
+
this.value = value;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region ../types/src/types/relations.ts
|
|
49
|
+
/** @group Models */
|
|
50
|
+
function hasForeignKeyOnTarget(relation) {
|
|
51
|
+
return relation.kind === "hasOne" || relation.kind === "hasMany";
|
|
52
|
+
}
|
|
53
|
+
/** @group Models */
|
|
54
|
+
function isManyToMany(relation) {
|
|
55
|
+
return relation.kind === "manyToMany";
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region ../types/src/types/policy.ts
|
|
59
|
+
/**
|
|
60
|
+
* The id a request without a logged-in user reports as `auth.uid()`.
|
|
61
|
+
*
|
|
62
|
+
* A user-context request always sets `app.uid`: blank would read back as
|
|
63
|
+
* `NULL`, and `NULL` is how the trusted server context is recognised, so an
|
|
64
|
+
* anonymous visitor would be promoted to server privileges. The driver
|
|
65
|
+
* therefore substitutes this sentinel at the single chokepoint where the GUC
|
|
66
|
+
* is set.
|
|
67
|
+
*
|
|
68
|
+
* The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
|
|
69
|
+
* tautology on the user path** — it is true for anonymous visitors too. Use
|
|
70
|
+
* {@link policy.authenticated} (or `auth.uid() <> 'anonymous'`) to mean "signed
|
|
71
|
+
* in", and {@link policy.serverContext} to mean "the trusted server context".
|
|
72
|
+
*
|
|
73
|
+
* @group Models
|
|
74
|
+
*/
|
|
75
|
+
var ANONYMOUS_USER_ID = "anonymous";
|
|
76
|
+
/** @group Models */
|
|
77
|
+
var policy = {
|
|
78
|
+
true: () => ({ kind: "true" }),
|
|
79
|
+
false: () => ({ kind: "false" }),
|
|
80
|
+
and: (...operands) => ({
|
|
81
|
+
kind: "and",
|
|
82
|
+
operands
|
|
83
|
+
}),
|
|
84
|
+
or: (...operands) => ({
|
|
85
|
+
kind: "or",
|
|
86
|
+
operands
|
|
87
|
+
}),
|
|
88
|
+
not: (operand) => ({
|
|
89
|
+
kind: "not",
|
|
90
|
+
operand
|
|
91
|
+
}),
|
|
92
|
+
compare: (left, op, right) => ({
|
|
93
|
+
kind: "compare",
|
|
94
|
+
op,
|
|
95
|
+
left,
|
|
96
|
+
right
|
|
97
|
+
}),
|
|
98
|
+
rolesOverlap: (roles) => ({
|
|
99
|
+
kind: "rolesOverlap",
|
|
100
|
+
roles
|
|
101
|
+
}),
|
|
102
|
+
rolesContain: (roles) => ({
|
|
103
|
+
kind: "rolesContain",
|
|
104
|
+
roles
|
|
105
|
+
}),
|
|
106
|
+
authenticated: () => ({ kind: "authenticated" }),
|
|
107
|
+
serverContext: () => ({ kind: "serverContext" }),
|
|
108
|
+
existsIn: (args) => ({
|
|
109
|
+
kind: "existsIn",
|
|
110
|
+
collection: args.collection,
|
|
111
|
+
where: args.where
|
|
112
|
+
}),
|
|
113
|
+
raw: (sql) => ({
|
|
114
|
+
kind: "raw",
|
|
115
|
+
sql
|
|
116
|
+
}),
|
|
117
|
+
field: (name) => ({
|
|
118
|
+
kind: "field",
|
|
119
|
+
name
|
|
120
|
+
}),
|
|
121
|
+
outerField: (name) => ({
|
|
122
|
+
kind: "outerField",
|
|
123
|
+
name
|
|
124
|
+
}),
|
|
125
|
+
literal: (value) => ({
|
|
126
|
+
kind: "literal",
|
|
127
|
+
value
|
|
128
|
+
}),
|
|
129
|
+
authUid: () => ({ kind: "authUid" }),
|
|
130
|
+
authRoles: () => ({ kind: "authRoles" })
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
6
133
|
//#region ../common/src/util/common.ts
|
|
7
134
|
var DEFAULT_ONE_OF_TYPE = "type";
|
|
8
135
|
var DEFAULT_ONE_OF_VALUE = "value";
|
|
@@ -1264,7 +1391,7 @@ function traverseValueProperty(inputValue, property, operation) {
|
|
|
1264
1391
|
return value;
|
|
1265
1392
|
}
|
|
1266
1393
|
/**
|
|
1267
|
-
* Create a lightweight relation stub for
|
|
1394
|
+
* Create a lightweight relation stub for admin views.
|
|
1268
1395
|
* Replaces inline `{ id, path, __type: "relation" }` object literals.
|
|
1269
1396
|
*/
|
|
1270
1397
|
function createRelationRef(id, path) {
|
|
@@ -1527,7 +1654,7 @@ var _resolvedRelationsCache = /* @__PURE__ */ new WeakMap();
|
|
|
1527
1654
|
function resolveCollectionRelations(collection) {
|
|
1528
1655
|
const cached = _resolvedRelationsCache.get(collection);
|
|
1529
1656
|
if (cached) return cached;
|
|
1530
|
-
if (!
|
|
1657
|
+
if (!isRelationalCollectionConfig(collection)) return {};
|
|
1531
1658
|
const relations = {};
|
|
1532
1659
|
for (const relation of collection.relations ?? []) {
|
|
1533
1660
|
const resolved = resolveRelation(relation, collection);
|
|
@@ -1543,7 +1670,7 @@ function resolveCollectionRelations(collection) {
|
|
|
1543
1670
|
return relations;
|
|
1544
1671
|
}
|
|
1545
1672
|
function getTableName(collection) {
|
|
1546
|
-
if (
|
|
1673
|
+
if (isRelationalCollectionConfig(collection)) return collection.table ?? toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
1547
1674
|
return toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
1548
1675
|
}
|
|
1549
1676
|
function getTableVarName(tableName) {
|
|
@@ -2016,75 +2143,6 @@ function rolesArraySql(roles) {
|
|
|
2016
2143
|
return `ARRAY[${[...roles].sort().map((r) => `'${r}'`).join(",")}]`;
|
|
2017
2144
|
}
|
|
2018
2145
|
//#endregion
|
|
2019
|
-
//#region ../common/src/util/callbacks.ts
|
|
2020
|
-
/**
|
|
2021
|
-
* Helper function to recursively check if there are any callbacks in the properties.
|
|
2022
|
-
*/
|
|
2023
|
-
function hasPropertyCallbacks(properties, callbackName) {
|
|
2024
|
-
if (!properties) return false;
|
|
2025
|
-
for (const property of Object.values(properties)) {
|
|
2026
|
-
if (property.callbacks?.[callbackName]) return true;
|
|
2027
|
-
if (property.type === "map" && property.properties) {
|
|
2028
|
-
if (hasPropertyCallbacks(property.properties, callbackName)) return true;
|
|
2029
|
-
} else if (property.type === "array" && property.of) {
|
|
2030
|
-
const ofs = Array.isArray(property.of) ? property.of : [property.of];
|
|
2031
|
-
for (const of of ofs) {
|
|
2032
|
-
if (of.callbacks?.[callbackName]) return true;
|
|
2033
|
-
if (of.type === "map" && of.properties && hasPropertyCallbacks(of.properties, callbackName)) return true;
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
}
|
|
2037
|
-
return false;
|
|
2038
|
-
}
|
|
2039
|
-
/**
|
|
2040
|
-
* Recursively process properties to apply field-level hooks.
|
|
2041
|
-
*/
|
|
2042
|
-
async function processProperties(properties, values, previousValues, propsContext, callbackName) {
|
|
2043
|
-
if (!values || typeof values !== "object") return values;
|
|
2044
|
-
const result = { ...values };
|
|
2045
|
-
for (const [key, property] of Object.entries(properties)) {
|
|
2046
|
-
if (result[key] === void 0) continue;
|
|
2047
|
-
let currentValue = result[key];
|
|
2048
|
-
const previousValue = previousValues?.[key];
|
|
2049
|
-
if (property.type === "array" && Array.isArray(currentValue)) {
|
|
2050
|
-
if (property.of && !Array.isArray(property.of)) currentValue = await Promise.all(currentValue.map(async (item, index) => {
|
|
2051
|
-
const prevItem = Array.isArray(previousValue) ? previousValue[index] : void 0;
|
|
2052
|
-
return (await processProperties({ "_tmp": property.of }, { "_tmp": item }, { "_tmp": prevItem }, propsContext, callbackName))["_tmp"];
|
|
2053
|
-
}));
|
|
2054
|
-
} else if (property.type === "map" && property.properties && typeof currentValue === "object") currentValue = await processProperties(property.properties, currentValue, previousValue ?? {}, propsContext, callbackName);
|
|
2055
|
-
if (property.callbacks?.[callbackName]) {
|
|
2056
|
-
const cbRes = await Promise.resolve(property.callbacks[callbackName]({
|
|
2057
|
-
...propsContext,
|
|
2058
|
-
value: currentValue,
|
|
2059
|
-
previousValue
|
|
2060
|
-
}));
|
|
2061
|
-
if (cbRes !== void 0) currentValue = cbRes;
|
|
2062
|
-
}
|
|
2063
|
-
result[key] = currentValue;
|
|
2064
|
-
}
|
|
2065
|
-
return result;
|
|
2066
|
-
}
|
|
2067
|
-
/**
|
|
2068
|
-
* Helper function to extract field-level PropertyCallbacks from a properties schema
|
|
2069
|
-
* and wrap them into an CollectionCallbacks object recursively.
|
|
2070
|
-
*/
|
|
2071
|
-
var buildPropertyCallbacks = (properties) => {
|
|
2072
|
-
if (!properties) return void 0;
|
|
2073
|
-
const propertyCallbacks = {};
|
|
2074
|
-
if (hasPropertyCallbacks(properties, "afterRead")) propertyCallbacks.afterRead = async (props) => {
|
|
2075
|
-
const row = props.row;
|
|
2076
|
-
const processedValues = await processProperties(properties, row, row, props, "afterRead");
|
|
2077
|
-
return {
|
|
2078
|
-
...props.row,
|
|
2079
|
-
...processedValues
|
|
2080
|
-
};
|
|
2081
|
-
};
|
|
2082
|
-
if (hasPropertyCallbacks(properties, "beforeSave")) propertyCallbacks.beforeSave = async (props) => {
|
|
2083
|
-
return await processProperties(properties, props.values, props.previousValues ?? {}, props, "beforeSave");
|
|
2084
|
-
};
|
|
2085
|
-
return Object.keys(propertyCallbacks).length > 0 ? propertyCallbacks : void 0;
|
|
2086
|
-
};
|
|
2087
|
-
//#endregion
|
|
2088
2146
|
//#region ../common/src/util/auth-default-policies.ts
|
|
2089
2147
|
/**
|
|
2090
2148
|
* Default RLS policies injected by the schema generator.
|
|
@@ -2152,8 +2210,8 @@ function getIdPropertyName$1(collection) {
|
|
|
2152
2210
|
* Collections that opt out via `disableDefaultPolicies` are returned unchanged.
|
|
2153
2211
|
*/
|
|
2154
2212
|
function getEffectiveSecurityRules(collection) {
|
|
2155
|
-
const explicit = [...
|
|
2156
|
-
if (collection.disableDefaultPolicies) return explicit;
|
|
2213
|
+
const explicit = [...collection.securityRules ?? []];
|
|
2214
|
+
if (isPostgresCollectionConfig(collection) && collection.disableDefaultPolicies) return explicit;
|
|
2157
2215
|
const tableName = getTableName(collection);
|
|
2158
2216
|
const injected = [];
|
|
2159
2217
|
injected.push({
|
|
@@ -2324,7 +2382,7 @@ function coversUpdate(rule) {
|
|
|
2324
2382
|
* stays locked (RLS is still enabled) until they write policies for it.
|
|
2325
2383
|
*/
|
|
2326
2384
|
function getJunctionSecurityRules(spec) {
|
|
2327
|
-
if (spec.declaringSides.every((side) => side.collection.disableDefaultPolicies)) return [];
|
|
2385
|
+
if (spec.declaringSides.every((side) => isPostgresCollectionConfig(side.collection) && side.collection.disableDefaultPolicies)) return [];
|
|
2328
2386
|
const rules = [];
|
|
2329
2387
|
rules.push({
|
|
2330
2388
|
name: `${spec.table}_default_admin_read`,
|
|
@@ -2659,10 +2717,27 @@ function getJunctionSecurityRules(spec) {
|
|
|
2659
2717
|
});
|
|
2660
2718
|
})))();
|
|
2661
2719
|
/**
|
|
2662
|
-
*
|
|
2720
|
+
* How wide a `varchar`/`char` column should be for a given property.
|
|
2721
|
+
*
|
|
2722
|
+
* One definition, three call sites, because they used to disagree. For the same
|
|
2723
|
+
* `columnType: "varchar"` property the DDL generator emitted `VARCHAR(255)`
|
|
2724
|
+
* while the Drizzle generator emitted a bare `varchar("col")` — which Postgres
|
|
2725
|
+
* reads as *unbounded* — so which of the two you ran decided whether the column
|
|
2726
|
+
* had a limit at all. Introspection then dropped the length entirely, so reading
|
|
2727
|
+
* an existing `character varying(500)` column back and regenerating it produced
|
|
2728
|
+
* a `VARCHAR(255)`: a silent narrowing of a column with data already in it.
|
|
2729
|
+
*
|
|
2730
|
+
* `validation.max` is the property's own statement about how long the value may
|
|
2731
|
+
* be, so it is the only sensible source for the column's width — and it keeps
|
|
2732
|
+
* the constraint the database enforces in step with the one the app enforces,
|
|
2733
|
+
* rather than inventing a second, different limit underneath it.
|
|
2663
2734
|
*/
|
|
2735
|
+
function resolveStringColumnLength(prop) {
|
|
2736
|
+
const max = prop.validation?.max;
|
|
2737
|
+
return typeof max === "number" && Number.isInteger(max) && max > 0 ? max : 255;
|
|
2738
|
+
}
|
|
2664
2739
|
//#endregion
|
|
2665
|
-
//#region ../../node_modules/.pnpm/fast-equals@6.0.
|
|
2740
|
+
//#region ../../node_modules/.pnpm/fast-equals@6.0.2/node_modules/fast-equals/dist/es/index.mjs
|
|
2666
2741
|
var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
2667
2742
|
var { hasOwnProperty } = Object.prototype;
|
|
2668
2743
|
/**
|
|
@@ -2698,7 +2773,8 @@ function createIsCircular(areItemsEqual) {
|
|
|
2698
2773
|
* not enumerable and symbol properties.
|
|
2699
2774
|
*/
|
|
2700
2775
|
function getStrictProperties(object) {
|
|
2701
|
-
|
|
2776
|
+
const symbols = getOwnPropertySymbols(object);
|
|
2777
|
+
return symbols.length ? getOwnPropertyNames(object).concat(symbols) : getOwnPropertyNames(object);
|
|
2702
2778
|
}
|
|
2703
2779
|
/**
|
|
2704
2780
|
* Whether the object contains the property passed as an own property.
|
|
@@ -2771,7 +2847,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2771
2847
|
const size = a.size;
|
|
2772
2848
|
if (size !== b.size) return false;
|
|
2773
2849
|
if (!size) return true;
|
|
2774
|
-
const matchedIndices = new
|
|
2850
|
+
const matchedIndices = new Uint8Array(size);
|
|
2775
2851
|
const aIterable = a.entries();
|
|
2776
2852
|
let aResult;
|
|
2777
2853
|
let bResult;
|
|
@@ -2779,7 +2855,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2779
2855
|
while (aResult = aIterable.next()) {
|
|
2780
2856
|
if (aResult.done) break;
|
|
2781
2857
|
const bIterable = b.entries();
|
|
2782
|
-
let hasMatch =
|
|
2858
|
+
let hasMatch = 0;
|
|
2783
2859
|
let matchIndex = 0;
|
|
2784
2860
|
while (bResult = bIterable.next()) {
|
|
2785
2861
|
if (bResult.done) break;
|
|
@@ -2790,7 +2866,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2790
2866
|
const aEntry = aResult.value;
|
|
2791
2867
|
const bEntry = bResult.value;
|
|
2792
2868
|
if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state) && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
|
|
2793
|
-
hasMatch = matchedIndices[matchIndex] =
|
|
2869
|
+
hasMatch = matchedIndices[matchIndex] = 1;
|
|
2794
2870
|
break;
|
|
2795
2871
|
}
|
|
2796
2872
|
matchIndex++;
|
|
@@ -2848,19 +2924,19 @@ function areSetsEqual(a, b, state) {
|
|
|
2848
2924
|
const size = a.size;
|
|
2849
2925
|
if (size !== b.size) return false;
|
|
2850
2926
|
if (!size) return true;
|
|
2851
|
-
const matchedIndices = new
|
|
2927
|
+
const matchedIndices = new Uint8Array(size);
|
|
2852
2928
|
const aIterable = a.values();
|
|
2853
2929
|
let aResult;
|
|
2854
2930
|
let bResult;
|
|
2855
2931
|
while (aResult = aIterable.next()) {
|
|
2856
2932
|
if (aResult.done) break;
|
|
2857
2933
|
const bIterable = b.values();
|
|
2858
|
-
let hasMatch =
|
|
2934
|
+
let hasMatch = 0;
|
|
2859
2935
|
let matchIndex = 0;
|
|
2860
2936
|
while (bResult = bIterable.next()) {
|
|
2861
2937
|
if (bResult.done) break;
|
|
2862
2938
|
if (!matchedIndices[matchIndex] && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
|
|
2863
|
-
hasMatch = matchedIndices[matchIndex] =
|
|
2939
|
+
hasMatch = matchedIndices[matchIndex] = 1;
|
|
2864
2940
|
break;
|
|
2865
2941
|
}
|
|
2866
2942
|
matchIndex++;
|
|
@@ -2873,8 +2949,8 @@ function areSetsEqual(a, b, state) {
|
|
|
2873
2949
|
* Whether the TypedArray instances are equal in value.
|
|
2874
2950
|
*/
|
|
2875
2951
|
function areTypedArraysEqual(a, b) {
|
|
2876
|
-
let index = a.
|
|
2877
|
-
if (b.
|
|
2952
|
+
let index = a.length;
|
|
2953
|
+
if (b.length !== index || a.byteOffset !== b.byteOffset) return false;
|
|
2878
2954
|
while (index-- > 0) if (a[index] !== b[index]) return false;
|
|
2879
2955
|
return true;
|
|
2880
2956
|
}
|
|
@@ -3444,6 +3520,136 @@ var QueryBuilder = class {
|
|
|
3444
3520
|
return this.collection.listen(this.params, onUpdate, onError);
|
|
3445
3521
|
}
|
|
3446
3522
|
};
|
|
3523
|
+
/** Rows `findAll()` will materialise before it refuses to continue. */
|
|
3524
|
+
var DEFAULT_FIND_ALL_MAX_ROWS = 1e4;
|
|
3525
|
+
/**
|
|
3526
|
+
* Requests one walk may make before it gives up on the server ever saying
|
|
3527
|
+
* `hasMore: false`. At the default page size that is two million rows — far
|
|
3528
|
+
* past any legitimate walk, and short of running forever.
|
|
3529
|
+
*/
|
|
3530
|
+
var DEFAULT_MAX_PAGES = 1e4;
|
|
3531
|
+
/**
|
|
3532
|
+
* Thrown when a walk stops for a reason the caller needs to know about.
|
|
3533
|
+
*
|
|
3534
|
+
* Every one of these is a case where the alternative would be silent: a
|
|
3535
|
+
* truncated array that looks complete, or a loop that never returns. Check
|
|
3536
|
+
* {@link code} to tell them apart.
|
|
3537
|
+
*/
|
|
3538
|
+
var RebasePaginationError = class RebasePaginationError extends Error {
|
|
3539
|
+
code;
|
|
3540
|
+
constructor(code, message) {
|
|
3541
|
+
super(message);
|
|
3542
|
+
this.name = "RebasePaginationError";
|
|
3543
|
+
this.code = code;
|
|
3544
|
+
Object.setPrototypeOf(this, RebasePaginationError.prototype);
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
function normalizePageSize(raw) {
|
|
3548
|
+
if (raw === void 0 || !Number.isFinite(raw)) return 200;
|
|
3549
|
+
return Math.max(1, Math.floor(raw));
|
|
3550
|
+
}
|
|
3551
|
+
function normalizeMaxPages(raw) {
|
|
3552
|
+
if (raw === void 0) return DEFAULT_MAX_PAGES;
|
|
3553
|
+
if (raw === Number.POSITIVE_INFINITY) return raw;
|
|
3554
|
+
if (!Number.isFinite(raw)) return DEFAULT_MAX_PAGES;
|
|
3555
|
+
return Math.max(1, Math.floor(raw));
|
|
3556
|
+
}
|
|
3557
|
+
function normalizeMaxRows(raw) {
|
|
3558
|
+
if (raw === void 0) return DEFAULT_FIND_ALL_MAX_ROWS;
|
|
3559
|
+
if (raw === Number.POSITIVE_INFINITY) return raw;
|
|
3560
|
+
if (!Number.isFinite(raw)) return DEFAULT_FIND_ALL_MAX_ROWS;
|
|
3561
|
+
return Math.max(0, Math.floor(raw));
|
|
3562
|
+
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Add one condition to a `where` map without disturbing what is already there.
|
|
3565
|
+
*
|
|
3566
|
+
* The caller's own filter on the cursor column has to survive — dropping it
|
|
3567
|
+
* would widen the query, which is the silent-filter-loss failure mode — so a
|
|
3568
|
+
* second condition on the same column becomes the array-of-tuples form that
|
|
3569
|
+
* `FindParams.where` already accepts, and both are AND-ed.
|
|
3570
|
+
*/
|
|
3571
|
+
function appendCondition(where, column, condition) {
|
|
3572
|
+
const next = { ...where ?? {} };
|
|
3573
|
+
const existing = next[column];
|
|
3574
|
+
if (existing === void 0) next[column] = condition;
|
|
3575
|
+
else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) next[column] = [...existing, condition];
|
|
3576
|
+
else next[column] = [existing, condition];
|
|
3577
|
+
return next;
|
|
3578
|
+
}
|
|
3579
|
+
function cursorEquals(a, b) {
|
|
3580
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
3581
|
+
return Object.is(a, b);
|
|
3582
|
+
}
|
|
3583
|
+
/**
|
|
3584
|
+
* Walk every row a query matches, yielding one row at a time and fetching the
|
|
3585
|
+
* next page only when the consumer asks for it.
|
|
3586
|
+
*
|
|
3587
|
+
* See {@link SDKCollectionClient.iterate} for the caller-facing contract,
|
|
3588
|
+
* including the offset-drift caveat and the `cursor` alternative.
|
|
3589
|
+
*
|
|
3590
|
+
* @param find the transport's single-page read
|
|
3591
|
+
* @param params `find()` parameters minus the window, plus the walk options
|
|
3592
|
+
* @param label the collection name, so an error says which walk failed
|
|
3593
|
+
*/
|
|
3594
|
+
async function* paginateFind(find, params, label = "collection") {
|
|
3595
|
+
const { pageSize, cursor, maxPages, ...rest } = params ?? {};
|
|
3596
|
+
const findParams = { ...rest };
|
|
3597
|
+
const size = normalizePageSize(pageSize);
|
|
3598
|
+
const pageCap = normalizeMaxPages(maxPages);
|
|
3599
|
+
const cursorField = typeof cursor === "string" ? cursor : cursor?.field;
|
|
3600
|
+
const requestedDirection = typeof cursor === "object" && cursor !== null ? cursor.direction : void 0;
|
|
3601
|
+
let direction = "asc";
|
|
3602
|
+
if (cursorField) {
|
|
3603
|
+
const orderBy = findParams.orderBy;
|
|
3604
|
+
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.`);
|
|
3605
|
+
direction = requestedDirection ?? orderBy?.[1] ?? "asc";
|
|
3606
|
+
findParams.orderBy = [cursorField, direction];
|
|
3607
|
+
}
|
|
3608
|
+
const seekOp = direction === "desc" ? "<" : ">";
|
|
3609
|
+
const baseWhere = findParams.where;
|
|
3610
|
+
let offset = 0;
|
|
3611
|
+
let pages = 0;
|
|
3612
|
+
let cursorValue;
|
|
3613
|
+
let seeking = false;
|
|
3614
|
+
for (;;) {
|
|
3615
|
+
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\`.`);
|
|
3616
|
+
const pageParams = {
|
|
3617
|
+
...findParams,
|
|
3618
|
+
limit: size
|
|
3619
|
+
};
|
|
3620
|
+
if (cursorField) {
|
|
3621
|
+
if (seeking) pageParams.where = appendCondition(baseWhere, cursorField, [seekOp, cursorValue]);
|
|
3622
|
+
} else pageParams.offset = offset;
|
|
3623
|
+
const page = await find(pageParams);
|
|
3624
|
+
pages += 1;
|
|
3625
|
+
const rows = page?.data ?? [];
|
|
3626
|
+
if (rows.length === 0) return;
|
|
3627
|
+
for (const row of rows) yield row;
|
|
3628
|
+
if (page?.meta?.hasMore !== true) return;
|
|
3629
|
+
if (cursorField) {
|
|
3630
|
+
const nextValue = rows[rows.length - 1]?.[cursorField];
|
|
3631
|
+
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.`);
|
|
3632
|
+
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.`);
|
|
3633
|
+
cursorValue = nextValue;
|
|
3634
|
+
seeking = true;
|
|
3635
|
+
} else offset += rows.length;
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
/**
|
|
3639
|
+
* {@link paginateFind}, collected into an array under a ceiling.
|
|
3640
|
+
*
|
|
3641
|
+
* See {@link SDKCollectionClient.findAll}.
|
|
3642
|
+
*/
|
|
3643
|
+
async function collectAllPages(find, params, label = "collection") {
|
|
3644
|
+
const { maxRows, ...rest } = params ?? {};
|
|
3645
|
+
const cap = normalizeMaxRows(maxRows);
|
|
3646
|
+
const out = [];
|
|
3647
|
+
for await (const row of paginateFind(find, rest, label)) {
|
|
3648
|
+
out.push(row);
|
|
3649
|
+
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()\`.`);
|
|
3650
|
+
}
|
|
3651
|
+
return out;
|
|
3652
|
+
}
|
|
3447
3653
|
//#endregion
|
|
3448
3654
|
//#region ../common/src/data/filter-dialect.ts
|
|
3449
3655
|
/**
|
|
@@ -3593,6 +3799,42 @@ function rowToEntity(row, slug, primaryKeys = []) {
|
|
|
3593
3799
|
values: row
|
|
3594
3800
|
};
|
|
3595
3801
|
}
|
|
3802
|
+
/**
|
|
3803
|
+
* The relation envelope `toCmsRow` writes where a relation was:
|
|
3804
|
+
* `{ id, path, __type: "relation", data: { id, path, values } }`. It is the
|
|
3805
|
+
* admin's view-model, and the only pipeline that produces one is postgres'.
|
|
3806
|
+
*/
|
|
3807
|
+
function isRelationEnvelope(value) {
|
|
3808
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && value.__type === "relation";
|
|
3809
|
+
}
|
|
3810
|
+
/** The target's own columns, as `toRestRow` would have inlined them. */
|
|
3811
|
+
function inlineEnvelope(envelope) {
|
|
3812
|
+
return envelope.data?.values ?? {};
|
|
3813
|
+
}
|
|
3814
|
+
/**
|
|
3815
|
+
* Replace every relation envelope on a row with the target's flat columns.
|
|
3816
|
+
*
|
|
3817
|
+
* The SDK serves one relation shape — the inlined one (see
|
|
3818
|
+
* {@link RestFetchService}) — and reads that come back through a *driver*
|
|
3819
|
+
* method rather than the REST pipeline still carry envelopes. Realtime is the
|
|
3820
|
+
* one such read left: there is no `listenForRest`, so the rows arrive shaped
|
|
3821
|
+
* for the admin and are flattened here instead.
|
|
3822
|
+
*
|
|
3823
|
+
* Only applied where the REST pipeline is the contract (see `find`); a driver
|
|
3824
|
+
* without a `restFetchService` keeps whatever it returns, so the admin's own
|
|
3825
|
+
* path through {@link buildRebaseData} is untouched.
|
|
3826
|
+
*/
|
|
3827
|
+
function inlineRelationRefs(row) {
|
|
3828
|
+
let out;
|
|
3829
|
+
for (const [key, value] of Object.entries(row)) if (isRelationEnvelope(value)) {
|
|
3830
|
+
out = out ?? { ...row };
|
|
3831
|
+
out[key] = inlineEnvelope(value);
|
|
3832
|
+
} else if (Array.isArray(value) && value.some(isRelationEnvelope)) {
|
|
3833
|
+
out = out ?? { ...row };
|
|
3834
|
+
out[key] = value.map((item) => isRelationEnvelope(item) ? inlineEnvelope(item) : item);
|
|
3835
|
+
}
|
|
3836
|
+
return out ?? row;
|
|
3837
|
+
}
|
|
3596
3838
|
function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
3597
3839
|
const accessor = {
|
|
3598
3840
|
async find(params) {
|
|
@@ -3600,14 +3842,14 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3600
3842
|
const limit = params?.limit ?? 20;
|
|
3601
3843
|
const offset = params?.offset ?? 0;
|
|
3602
3844
|
const fetchService = driver.restFetchService;
|
|
3603
|
-
const rows = fetchService
|
|
3845
|
+
const rows = fetchService ? await fetchService.fetchCollectionForRest(slug, {
|
|
3604
3846
|
filter,
|
|
3605
3847
|
limit: params?.limit,
|
|
3606
3848
|
offset: params?.offset,
|
|
3607
3849
|
orderBy: params?.orderBy?.[0],
|
|
3608
3850
|
order: params?.orderBy?.[1],
|
|
3609
3851
|
searchString: params?.searchString
|
|
3610
|
-
}, params
|
|
3852
|
+
}, params?.include) : await driver.fetchCollection({
|
|
3611
3853
|
path: slug,
|
|
3612
3854
|
limit: params?.limit,
|
|
3613
3855
|
offset: params?.offset,
|
|
@@ -3636,7 +3878,8 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3636
3878
|
};
|
|
3637
3879
|
},
|
|
3638
3880
|
async findById(id) {
|
|
3639
|
-
const
|
|
3881
|
+
const fetchService = driver.restFetchService;
|
|
3882
|
+
const row = fetchService ? await fetchService.fetchOneForRest(slug, id) : await driver.fetchOne({
|
|
3640
3883
|
path: slug,
|
|
3641
3884
|
id
|
|
3642
3885
|
});
|
|
@@ -3682,6 +3925,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3682
3925
|
listen: driver.listenCollection ? (params, onUpdate, onError) => {
|
|
3683
3926
|
const limit = params?.limit ?? 20;
|
|
3684
3927
|
const offset = params?.offset ?? 0;
|
|
3928
|
+
const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
|
|
3685
3929
|
return driver.listenCollection({
|
|
3686
3930
|
path: slug,
|
|
3687
3931
|
limit: params?.limit,
|
|
@@ -3692,7 +3936,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3692
3936
|
searchString: params?.searchString,
|
|
3693
3937
|
onUpdate: (entities) => {
|
|
3694
3938
|
onUpdate({
|
|
3695
|
-
data: entities.map((row) => rowToEntity(row, slug, getPks())),
|
|
3939
|
+
data: entities.map((row) => rowToEntity(normalize(row), slug, getPks())),
|
|
3696
3940
|
meta: {
|
|
3697
3941
|
total: entities.length,
|
|
3698
3942
|
limit,
|
|
@@ -3705,10 +3949,11 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3705
3949
|
});
|
|
3706
3950
|
} : void 0,
|
|
3707
3951
|
listenById: driver.listenOne ? (id, onUpdate, onError) => {
|
|
3952
|
+
const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
|
|
3708
3953
|
return driver.listenOne({
|
|
3709
3954
|
path: slug,
|
|
3710
3955
|
id,
|
|
3711
|
-
onUpdate: (entity) => onUpdate(entity ? rowToEntity(entity, slug, getPks()) : void 0),
|
|
3956
|
+
onUpdate: (entity) => onUpdate(entity ? rowToEntity(normalize(entity), slug, getPks()) : void 0),
|
|
3712
3957
|
onError
|
|
3713
3958
|
});
|
|
3714
3959
|
} : void 0,
|
|
@@ -3839,7 +4084,7 @@ var SdkQueryBuilder = class {
|
|
|
3839
4084
|
* {@link SDKCollectionClient}. Every returned record is unwrapped to a flat row
|
|
3840
4085
|
* so the backend SDK is byte-for-byte the same shape as the frontend client.
|
|
3841
4086
|
*/
|
|
3842
|
-
function toSdkCollectionClient(snap) {
|
|
4087
|
+
function toSdkCollectionClient(snap, slug = "collection") {
|
|
3843
4088
|
const client = {
|
|
3844
4089
|
async find(params) {
|
|
3845
4090
|
const res = await snap.find(params);
|
|
@@ -3848,6 +4093,12 @@ function toSdkCollectionClient(snap) {
|
|
|
3848
4093
|
meta: res.meta
|
|
3849
4094
|
};
|
|
3850
4095
|
},
|
|
4096
|
+
iterate(params) {
|
|
4097
|
+
return paginateFind((p) => client.find(p), params, slug);
|
|
4098
|
+
},
|
|
4099
|
+
findAll(params) {
|
|
4100
|
+
return collectAllPages((p) => client.find(p), params, slug);
|
|
4101
|
+
},
|
|
3851
4102
|
async findById(id) {
|
|
3852
4103
|
const s = await snap.findById(id);
|
|
3853
4104
|
return s ? entityToRow(s) : void 0;
|
|
@@ -3899,7 +4150,7 @@ function wrapAsSdkData(entityData) {
|
|
|
3899
4150
|
function getAccessor(slug) {
|
|
3900
4151
|
let accessor = cache.get(slug);
|
|
3901
4152
|
if (!accessor) {
|
|
3902
|
-
accessor = toSdkCollectionClient(entityData.collection(slug));
|
|
4153
|
+
accessor = toSdkCollectionClient(entityData.collection(slug), slug);
|
|
3903
4154
|
cache.set(slug, accessor);
|
|
3904
4155
|
}
|
|
3905
4156
|
return accessor;
|
|
@@ -3916,79 +4167,17 @@ function wrapAsSdkData(entityData) {
|
|
|
3916
4167
|
*
|
|
3917
4168
|
* This is the developer-facing SDK data layer used by backend framework
|
|
3918
4169
|
* callbacks & scripts (`context.data` / `rebase.data`). It returns flat rows —
|
|
3919
|
-
* identical in shape to the frontend SDK client
|
|
3920
|
-
*
|
|
4170
|
+
* identical in shape to the frontend SDK client, down to how a relation is
|
|
4171
|
+
* served: a foreign key stays a foreign key, and a relation named in `include`
|
|
4172
|
+
* arrives as the target's own columns. The `{ __type: "relation" }` envelope is
|
|
4173
|
+
* the admin's view-model and never reaches here.
|
|
4174
|
+
*
|
|
4175
|
+
* The admin uses {@link buildRebaseData} (Entity) over its own driver.
|
|
3921
4176
|
*/
|
|
3922
4177
|
function buildSdkData(driver) {
|
|
3923
4178
|
return wrapAsSdkData(buildRebaseData(driver));
|
|
3924
4179
|
}
|
|
3925
4180
|
//#endregion
|
|
3926
|
-
|
|
3927
|
-
/** Schemas that are always considered Rebase-internal. */
|
|
3928
|
-
var REBASE_INTERNAL_SCHEMAS = ["rebase", "auth"];
|
|
3929
|
-
/** Table-name prefixes that mark a table as Rebase-internal regardless of schema. */
|
|
3930
|
-
var REBASE_INTERNAL_PREFIXES = [
|
|
3931
|
-
"_rebase_",
|
|
3932
|
-
"_auth_",
|
|
3933
|
-
"drizzle_"
|
|
3934
|
-
];
|
|
3935
|
-
/**
|
|
3936
|
-
* Synchronously classify a table based on naming conventions.
|
|
3937
|
-
*
|
|
3938
|
-
* @param tableName - The unqualified name of the table.
|
|
3939
|
-
* @param schemaName - The schema the table belongs to (e.g. `"public"`, `"rebase"`).
|
|
3940
|
-
* @returns `"rebase-internal"` when the table belongs to a reserved schema or
|
|
3941
|
-
* carries a reserved prefix; `"user"` otherwise.
|
|
3942
|
-
*
|
|
3943
|
-
* @remarks
|
|
3944
|
-
* Junction-table detection requires an async database query and is therefore
|
|
3945
|
-
* **not** handled by this function. Use {@link detectJunctionTables} to obtain
|
|
3946
|
-
* the set of junction tables, then reclassify as needed.
|
|
3947
|
-
*/
|
|
3948
|
-
function classifyTable(tableName, schemaName) {
|
|
3949
|
-
if (REBASE_INTERNAL_SCHEMAS.includes(schemaName) || REBASE_INTERNAL_PREFIXES.some((prefix) => tableName.startsWith(prefix))) return "rebase-internal";
|
|
3950
|
-
return "user";
|
|
3951
|
-
}
|
|
3952
|
-
/** SQL query that detects junction tables in the `public` schema. */
|
|
3953
|
-
var JUNCTION_TABLES_SQL = `
|
|
3954
|
-
SELECT t.table_name
|
|
3955
|
-
FROM information_schema.tables t
|
|
3956
|
-
WHERE t.table_schema = 'public'
|
|
3957
|
-
AND t.table_type = 'BASE TABLE'
|
|
3958
|
-
AND NOT EXISTS (
|
|
3959
|
-
SELECT 1
|
|
3960
|
-
FROM information_schema.columns c
|
|
3961
|
-
WHERE c.table_schema = t.table_schema
|
|
3962
|
-
AND c.table_name = t.table_name
|
|
3963
|
-
AND c.column_name NOT IN (
|
|
3964
|
-
SELECT kcu.column_name
|
|
3965
|
-
FROM information_schema.key_column_usage kcu
|
|
3966
|
-
JOIN information_schema.table_constraints tc
|
|
3967
|
-
ON tc.constraint_name = kcu.constraint_name
|
|
3968
|
-
AND tc.table_schema = kcu.table_schema
|
|
3969
|
-
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
3970
|
-
AND kcu.table_schema = t.table_schema
|
|
3971
|
-
AND kcu.table_name = t.table_name
|
|
3972
|
-
)
|
|
3973
|
-
)
|
|
3974
|
-
`;
|
|
3975
|
-
/**
|
|
3976
|
-
* Asynchronously detect junction (link) tables in the `public` schema.
|
|
3977
|
-
*
|
|
3978
|
-
* A junction table is defined as a table where **every** column participates in
|
|
3979
|
-
* at least one foreign-key constraint.
|
|
3980
|
-
*
|
|
3981
|
-
* @param executeSql - A callback that executes a raw SQL string and returns the
|
|
3982
|
-
* resulting rows.
|
|
3983
|
-
* @returns A `Set` containing the names of all detected junction tables.
|
|
3984
|
-
*/
|
|
3985
|
-
async function detectJunctionTables(executeSql) {
|
|
3986
|
-
const rows = await executeSql(JUNCTION_TABLES_SQL);
|
|
3987
|
-
const junctionTables = /* @__PURE__ */ new Set();
|
|
3988
|
-
for (const row of rows) if (typeof row.table_name === "string") junctionTables.add(row.table_name);
|
|
3989
|
-
return junctionTables;
|
|
3990
|
-
}
|
|
3991
|
-
//#endregion
|
|
3992
|
-
export { DEFAULT_ONE_OF_TYPE as A, createRelationRefWithData as C, mergeDeep as D, getPolicyNamesForRule as E, camelCase 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_VALUE as j, toSnakeCase 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 };
|
|
4181
|
+
export { DEFAULT_ONE_OF_VALUE as A, updateDateAutoValues as C, camelCase as D, mergeDeep as E, hasForeignKeyOnTarget as M, isManyToMany as N, toSnakeCase as O, Vector as P, normalizeToEntityRelation as S, getPolicyNamesForRule as T, buildCompositeId as _, getJunctionSecurityRules as a, createRelationRef as b, policyToPostgres as c, findRelation as d, getColumnName as f, resolveCollectionRelations as g, getTableVarName as h, getJunctionCollectionConfig as i, ANONYMOUS_USER_ID as j, DEFAULT_ONE_OF_TYPE as k, securityRuleToConditions as l, getTableName as m, CollectionRegistry as n, resolveJunctionSpecs as o, getEnumVarName as p, resolveStringColumnLength as r, getEffectiveSecurityRules as s, buildSdkData as t, findAnonymousGrants as u, getDeclaredPrimaryKeys as v, generateForeignKeyName as w, createRelationRefWithData as x, parseIdValues as y };
|
|
3993
4182
|
|
|
3994
|
-
//# sourceMappingURL=src-
|
|
4183
|
+
//# sourceMappingURL=src-DihrDFuP.js.map
|