@rebasepro/server-postgres 0.12.1-canary.gf5f1d39 → 0.13.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/PostgresBackendDriver.d.ts +1 -1
- package/dist/PostgresBootstrapper.d.ts +25 -1
- package/dist/auth/services.d.ts +21 -0
- package/dist/backup/backup-service.d.ts +10 -1
- package/dist/backup/pg-tools.d.ts +47 -0
- package/dist/backup-service-CD8o_1Sl.js +8999 -0
- package/dist/backup-service-CD8o_1Sl.js.map +1 -0
- package/dist/cli-helpers.d.ts +39 -0
- package/dist/connection-BuZ97wsr.js +250 -0
- package/dist/connection-BuZ97wsr.js.map +1 -0
- package/dist/connection.d.ts +42 -0
- package/dist/ensure-collection-policies-ViG8XiPn.js +57 -0
- package/dist/ensure-collection-policies-ViG8XiPn.js.map +1 -0
- package/dist/ensure-collection-tables-CBQdOETu.js +650 -0
- package/dist/ensure-collection-tables-CBQdOETu.js.map +1 -0
- package/dist/index.es.js +1231 -10031
- package/dist/index.es.js.map +1 -1
- package/dist/policy-CeA1JcxP.js +105 -0
- package/dist/policy-CeA1JcxP.js.map +1 -0
- package/dist/schema/auth-schema.d.ts +83 -144
- package/dist/schema/ensure-collection-policies.d.ts +60 -0
- package/dist/schema/ensure-collection-tables.d.ts +44 -2
- package/dist/schema/generate-postgres-ddl-logic.d.ts +135 -1
- package/dist/schema/introspect-db-constraints.d.ts +57 -0
- package/dist/schema/introspect-db-logic.d.ts +94 -5
- package/dist/schema/introspect-db-queries.d.ts +119 -0
- package/dist/schema/introspect-db-structure.d.ts +263 -0
- package/dist/schema/introspect-db-types.d.ts +11 -0
- package/dist/services/FetchService.d.ts +4 -1
- package/dist/services/RelationService.d.ts +24 -1
- package/dist/services/channel-bus/index.d.ts +1 -7
- package/dist/services/collection-helpers.d.ts +36 -2
- package/dist/services/dataService.d.ts +3 -1
- package/dist/services/row-pipeline.d.ts +1 -1
- package/dist/{src-BbFOPJ1S.js → src-DlPBctw_.js} +299 -173
- package/dist/src-DlPBctw_.js.map +1 -0
- package/dist/{src-Zqwaw3P5.js → src-DoU9yPqq.js} +3 -159
- package/dist/src-DoU9yPqq.js.map +1 -0
- package/dist/utils/connection-string.d.ts +29 -0
- package/dist/utils/drizzle-conditions.d.ts +5 -4
- package/dist/utils/pg-error-utils.d.ts +35 -0
- package/dist/websocket-B2LsrINK.js +530 -0
- package/dist/websocket-B2LsrINK.js.map +1 -0
- package/package.json +14 -14
- package/src/PostgresAdapter.ts +21 -2
- package/src/PostgresBackendDriver.ts +4 -0
- package/src/PostgresBootstrapper.ts +192 -33
- package/src/auth/ensure-tables.ts +164 -9
- package/src/auth/services.ts +24 -2
- package/src/backup/backup-cli.ts +41 -2
- package/src/backup/backup-service.ts +38 -5
- package/src/backup/pg-tools.ts +96 -3
- package/src/cli-helpers.ts +70 -0
- package/src/cli.ts +44 -26
- package/src/collections/validate-relations.ts +15 -0
- package/src/connection.ts +73 -0
- package/src/data-transformer.ts +9 -3
- package/src/databasePoolManager.ts +5 -2
- package/src/schema/auth-schema.ts +30 -19
- package/src/schema/ensure-collection-policies.ts +105 -0
- package/src/schema/ensure-collection-tables.test.ts +105 -9
- package/src/schema/ensure-collection-tables.ts +220 -32
- package/src/schema/generate-drizzle-schema-logic.ts +42 -6
- package/src/schema/generate-postgres-ddl-logic.ts +382 -19
- package/src/schema/introspect-db-constraints.ts +385 -0
- package/src/schema/introspect-db-inference.ts +18 -8
- package/src/schema/introspect-db-logic.ts +385 -71
- package/src/schema/introspect-db-queries.ts +326 -0
- package/src/schema/introspect-db-structure.ts +670 -0
- package/src/schema/introspect-db-types.ts +56 -0
- package/src/schema/introspect-db.ts +37 -80
- package/src/schema/introspect-runtime.test.ts +56 -8
- package/src/schema/introspect-runtime.ts +31 -9
- package/src/security/policy-drift.test.ts +11 -3
- package/src/services/BranchService.ts +66 -28
- package/src/services/FetchService.ts +90 -14
- package/src/services/PersistService.ts +20 -6
- package/src/services/RelationService.ts +249 -48
- package/src/services/channel-bus/index.ts +0 -9
- package/src/services/collection-helpers.ts +69 -3
- package/src/services/dataService.ts +3 -1
- package/src/services/realtimeService.ts +3 -3
- package/src/services/row-pipeline.ts +1 -1
- package/src/utils/connection-string.ts +58 -0
- package/src/utils/drizzle-conditions.ts +31 -6
- package/src/utils/pg-error-utils.ts +65 -0
- package/src/websocket.ts +18 -9
- package/dist/chunk-DSJWtz9O.js +0 -40
- package/dist/ensure-collection-tables-CNTcZGvn.js +0 -304
- package/dist/ensure-collection-tables-CNTcZGvn.js.map +0 -1
- package/dist/src-BbFOPJ1S.js.map +0 -1
- package/dist/src-Zqwaw3P5.js.map +0 -1
|
@@ -1,8 +1,61 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
import "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
4
|
+
import { l as __require, s as __commonJSMin } from "./connection-BuZ97wsr.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
|
+
import { n as ANONYMOUS_USER_IDS, r as policy, t as ANONYMOUS_USER_ID } from "./policy-CeA1JcxP.js";
|
|
7
|
+
//#region ../types/src/types/entities.ts
|
|
8
|
+
/**
|
|
9
|
+
* Class used to create a reference to a entity in a different path
|
|
10
|
+
*/
|
|
11
|
+
var EntityRelation = class {
|
|
12
|
+
__type = "relation";
|
|
13
|
+
/**
|
|
14
|
+
* ID of the entity
|
|
15
|
+
*/
|
|
16
|
+
id;
|
|
17
|
+
/**
|
|
18
|
+
* A string representing the path of the referenced document (relative
|
|
19
|
+
* to the root of the database).
|
|
20
|
+
*/
|
|
21
|
+
path;
|
|
22
|
+
/**
|
|
23
|
+
* Pre-fetched data payload to eliminate N+1 queries.
|
|
24
|
+
* When present, clients can use this directly instead of fetching.
|
|
25
|
+
*/
|
|
26
|
+
data;
|
|
27
|
+
constructor(id, path, data) {
|
|
28
|
+
this.id = id;
|
|
29
|
+
this.path = path;
|
|
30
|
+
this.data = data;
|
|
31
|
+
}
|
|
32
|
+
get pathWithId() {
|
|
33
|
+
return `${this.path}/${this.id}`;
|
|
34
|
+
}
|
|
35
|
+
isEntityReference() {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
isEntityRelation() {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var Vector = class {
|
|
43
|
+
value;
|
|
44
|
+
constructor(value) {
|
|
45
|
+
this.value = value;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region ../types/src/types/relations.ts
|
|
50
|
+
/** @group Models */
|
|
51
|
+
function hasForeignKeyOnTarget(relation) {
|
|
52
|
+
return relation.kind === "hasOne" || relation.kind === "hasMany";
|
|
53
|
+
}
|
|
54
|
+
/** @group Models */
|
|
55
|
+
function isManyToMany(relation) {
|
|
56
|
+
return relation.kind === "manyToMany";
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
6
59
|
//#region ../common/src/util/common.ts
|
|
7
60
|
var DEFAULT_ONE_OF_TYPE = "type";
|
|
8
61
|
var DEFAULT_ONE_OF_VALUE = "value";
|
|
@@ -1014,16 +1067,12 @@ function removeFunctions(o) {
|
|
|
1014
1067
|
if (o === void 0) return void 0;
|
|
1015
1068
|
if (o === null) return null;
|
|
1016
1069
|
if (typeof o === "object") {
|
|
1017
|
-
if (Array.isArray(o)) return o.map((v) => removeFunctions(v));
|
|
1070
|
+
if (Array.isArray(o)) return o.filter((v) => typeof v !== "function").map((v) => removeFunctions(v));
|
|
1018
1071
|
if (!isPlainObject(o)) return o;
|
|
1019
|
-
return Object.entries(o).filter(([_, value]) => typeof value !== "function").
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
}).reduce((a, b) => ({
|
|
1024
|
-
...a,
|
|
1025
|
-
...b
|
|
1026
|
-
}), {});
|
|
1072
|
+
return Object.entries(o).filter(([_, value]) => typeof value !== "function").reduce((acc, [key, value]) => {
|
|
1073
|
+
acc[key] = removeFunctions(value);
|
|
1074
|
+
return acc;
|
|
1075
|
+
}, {});
|
|
1027
1076
|
}
|
|
1028
1077
|
return o;
|
|
1029
1078
|
}
|
|
@@ -1162,11 +1211,101 @@ function getPolicyNamesForRule(rule, tableName) {
|
|
|
1162
1211
|
return ops.map((op, opIdx) => rule.name ? ops.length > 1 ? `${rule.name}_${op}` : rule.name : `${tableName}_${op}_${ruleHash}${ops.length > 1 ? `_${opIdx}` : ""}`);
|
|
1163
1212
|
}
|
|
1164
1213
|
//#endregion
|
|
1214
|
+
//#region ../utils/src/plurals.ts
|
|
1215
|
+
/**
|
|
1216
|
+
* Returns the singular of an English word.
|
|
1217
|
+
*
|
|
1218
|
+
* @param {string} word
|
|
1219
|
+
* @param {number} [amount]
|
|
1220
|
+
* @returns {string}
|
|
1221
|
+
*/
|
|
1222
|
+
function singular(word, amount) {
|
|
1223
|
+
if (amount !== void 0 && amount !== 1) return word;
|
|
1224
|
+
const singulars = {
|
|
1225
|
+
"(quiz)zes$": "$1",
|
|
1226
|
+
"(matr)ices$": "$1ix",
|
|
1227
|
+
"(vert|ind)ices$": "$1ex",
|
|
1228
|
+
"^(ox)en$": "$1",
|
|
1229
|
+
"(alias)es$": "$1",
|
|
1230
|
+
"(octop|vir)i$": "$1us",
|
|
1231
|
+
"(cris|ax|test)es$": "$1is",
|
|
1232
|
+
"(shoe)s$": "$1",
|
|
1233
|
+
"(o)es$": "$1",
|
|
1234
|
+
"(bus)es$": "$1",
|
|
1235
|
+
"([m|l])ice$": "$1ouse",
|
|
1236
|
+
"(x|ch|ss|sh)es$": "$1",
|
|
1237
|
+
"(m)ovies$": "$1ovie",
|
|
1238
|
+
"(s)eries$": "$1eries",
|
|
1239
|
+
"([^aeiouy]|qu)ies$": "$1y",
|
|
1240
|
+
"([lr])ves$": "$1f",
|
|
1241
|
+
"(tive)s$": "$1",
|
|
1242
|
+
"(hive)s$": "$1",
|
|
1243
|
+
"(li|wi|kni)ves$": "$1fe",
|
|
1244
|
+
"(shea|loa|lea|thie)ves$": "$1f",
|
|
1245
|
+
"(^analy)ses$": "$1sis",
|
|
1246
|
+
"((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$": "$1$2sis",
|
|
1247
|
+
"([ti])a$": "$1um",
|
|
1248
|
+
"(n)ews$": "$1ews",
|
|
1249
|
+
"(h|bl)ouses$": "$1ouse",
|
|
1250
|
+
"(corpse)s$": "$1",
|
|
1251
|
+
"(us)es$": "$1",
|
|
1252
|
+
s$: ""
|
|
1253
|
+
};
|
|
1254
|
+
const irregular = {
|
|
1255
|
+
move: "moves",
|
|
1256
|
+
foot: "feet",
|
|
1257
|
+
goose: "geese",
|
|
1258
|
+
sex: "sexes",
|
|
1259
|
+
child: "children",
|
|
1260
|
+
man: "men",
|
|
1261
|
+
tooth: "teeth",
|
|
1262
|
+
person: "people"
|
|
1263
|
+
};
|
|
1264
|
+
if ([
|
|
1265
|
+
"sheep",
|
|
1266
|
+
"fish",
|
|
1267
|
+
"deer",
|
|
1268
|
+
"moose",
|
|
1269
|
+
"series",
|
|
1270
|
+
"species",
|
|
1271
|
+
"money",
|
|
1272
|
+
"rice",
|
|
1273
|
+
"information",
|
|
1274
|
+
"equipment",
|
|
1275
|
+
"bison",
|
|
1276
|
+
"cod",
|
|
1277
|
+
"offspring",
|
|
1278
|
+
"pike",
|
|
1279
|
+
"salmon",
|
|
1280
|
+
"shrimp",
|
|
1281
|
+
"swine",
|
|
1282
|
+
"trout",
|
|
1283
|
+
"aircraft",
|
|
1284
|
+
"hovercraft",
|
|
1285
|
+
"spacecraft",
|
|
1286
|
+
"sugar",
|
|
1287
|
+
"tuna",
|
|
1288
|
+
"you",
|
|
1289
|
+
"wood"
|
|
1290
|
+
].indexOf(word.toLowerCase()) >= 0) return word;
|
|
1291
|
+
for (const w in irregular) {
|
|
1292
|
+
const pattern = new RegExp(`${irregular[w]}$`, "i");
|
|
1293
|
+
if (pattern.test(word)) return word.replace(pattern, w);
|
|
1294
|
+
}
|
|
1295
|
+
for (const reg in singulars) {
|
|
1296
|
+
const pattern = new RegExp(reg, "i");
|
|
1297
|
+
if (pattern.test(word)) return word.replace(pattern, singulars[reg]);
|
|
1298
|
+
}
|
|
1299
|
+
return word;
|
|
1300
|
+
}
|
|
1301
|
+
//#endregion
|
|
1165
1302
|
//#region ../utils/src/names.ts
|
|
1166
1303
|
/**
|
|
1167
1304
|
* Generates a foreign key column name from a given string, typically a collection slug or name.
|
|
1168
|
-
* It
|
|
1169
|
-
*
|
|
1305
|
+
* It singularizes the name, converts it to snake_case and appends '_id'.
|
|
1306
|
+
*
|
|
1307
|
+
* Singularization runs *before* snake-casing so that acronyms survive: `toSnakeCase`
|
|
1308
|
+
* splits on every capital, which turned "URLs" into "ur_ls" and then "ur_l_id".
|
|
1170
1309
|
*
|
|
1171
1310
|
* @param name The base name to convert to a foreign key.
|
|
1172
1311
|
* @returns A foreign key name in the format 'singular_name_id'.
|
|
@@ -1176,8 +1315,8 @@ function getPolicyNamesForRule(rule, tableName) {
|
|
|
1176
1315
|
* generateForeignKeyName("users")
|
|
1177
1316
|
*
|
|
1178
1317
|
* @example
|
|
1179
|
-
* // returns "
|
|
1180
|
-
* generateForeignKeyName("
|
|
1318
|
+
* // returns "category_id"
|
|
1319
|
+
* generateForeignKeyName("categories")
|
|
1181
1320
|
*
|
|
1182
1321
|
* @example
|
|
1183
1322
|
* // returns "product_id"
|
|
@@ -1185,8 +1324,41 @@ function getPolicyNamesForRule(rule, tableName) {
|
|
|
1185
1324
|
*
|
|
1186
1325
|
*/
|
|
1187
1326
|
function generateForeignKeyName(name) {
|
|
1188
|
-
|
|
1189
|
-
|
|
1327
|
+
return `${toSnakeCase(singularizeForKey(name))}_id`;
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* `singular()` handles real English plurals, but its final catch-all rule strips
|
|
1331
|
+
* any trailing "s", which mangles words that only look plural. Guard the two
|
|
1332
|
+
* cases that produce a column name nobody would recognise:
|
|
1333
|
+
*
|
|
1334
|
+
* - a double "s" ending is never a plural marker ("address", "class", "process"),
|
|
1335
|
+
* so stripping it yields "addres";
|
|
1336
|
+
* - a name that singularizes to nothing (the literal "s") would yield "_id".
|
|
1337
|
+
*/
|
|
1338
|
+
function singularizeForKey(name) {
|
|
1339
|
+
if (/ss$/i.test(name)) return name;
|
|
1340
|
+
const result = singular(name);
|
|
1341
|
+
return result.length > 0 ? result : name;
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* What `generateForeignKeyName` returned before it learned to singularize:
|
|
1345
|
+
* snake-case the name, then chop one trailing "s".
|
|
1346
|
+
*
|
|
1347
|
+
* This is here to be *detected*, never to be generated. A database provisioned
|
|
1348
|
+
* under the old rule carries `categorie_id`, `addresse_id`, `children_id` or
|
|
1349
|
+
* `ur_l_id` where the current rule expects `category_id`, `address_id`,
|
|
1350
|
+
* `child_id` and `url_id` — and the boot-time schema ensure is additive, so it
|
|
1351
|
+
* would create the new column empty beside the populated old one and leave the
|
|
1352
|
+
* relation reading nothing. No error, no missing table: the failure is silent,
|
|
1353
|
+
* which is the only reason this function still exists.
|
|
1354
|
+
*
|
|
1355
|
+
* `ensureCollectionSchema` calls it to recognise that shape and say so.
|
|
1356
|
+
* Returns the same string as `generateForeignKeyName` for every regular plural,
|
|
1357
|
+
* so a caller can compare the two and act only when they differ.
|
|
1358
|
+
*/
|
|
1359
|
+
function legacyForeignKeyName(name) {
|
|
1360
|
+
const snake = toSnakeCase(name);
|
|
1361
|
+
return `${snake.endsWith("s") ? snake.slice(0, -1) : snake}_id`;
|
|
1190
1362
|
}
|
|
1191
1363
|
//#endregion
|
|
1192
1364
|
//#region ../common/src/util/entities.ts
|
|
@@ -1286,6 +1458,34 @@ function createRelationRefWithData(id, path, data) {
|
|
|
1286
1458
|
data
|
|
1287
1459
|
};
|
|
1288
1460
|
}
|
|
1461
|
+
/** The eight-four-four-four-twelve shape of a UUID, any version. */
|
|
1462
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1463
|
+
/** Whether one address part can be a value of the column it addresses. */
|
|
1464
|
+
function partIsAddressable(part, pk) {
|
|
1465
|
+
if (pk.isUUID) return UUID_PATTERN.test(String(part));
|
|
1466
|
+
if (pk.type === "number") return typeof part === "number" ? Number.isFinite(part) : !isNaN(parseInt(String(part), 10));
|
|
1467
|
+
return true;
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Whether an address could name a row at all, before asking the database.
|
|
1471
|
+
*
|
|
1472
|
+
* A `uuid` column cannot hold `"new"`, and an `integer` column cannot hold
|
|
1473
|
+
* `"abc"` — so the answer to "which row is this" is "none", and that is a 404,
|
|
1474
|
+
* not a failure. Postgres cannot say so politely: the comparison never runs, it
|
|
1475
|
+
* raises `22P02` and aborts the enclosing transaction, after which every
|
|
1476
|
+
* further statement returns the far less helpful `25P02`.
|
|
1477
|
+
*
|
|
1478
|
+
* `isUUID` must come from the column, not from `isId: "uuid"` in a config: the
|
|
1479
|
+
* config is a claim about a key, and a `text` column that holds ids of some
|
|
1480
|
+
* other shape is a working app this must not start rejecting.
|
|
1481
|
+
*/
|
|
1482
|
+
function isAddressableId(idValue, primaryKeys) {
|
|
1483
|
+
if (primaryKeys.length === 0) return false;
|
|
1484
|
+
if (primaryKeys.length === 1) return partIsAddressable(idValue, primaryKeys[0]);
|
|
1485
|
+
const parts = String(idValue).split(":::");
|
|
1486
|
+
if (parts.length !== primaryKeys.length) return false;
|
|
1487
|
+
return parts.every((part, i) => partIsAddressable(part, primaryKeys[i]));
|
|
1488
|
+
}
|
|
1289
1489
|
/**
|
|
1290
1490
|
* Derive a row's address from its key columns.
|
|
1291
1491
|
*
|
|
@@ -1426,8 +1626,7 @@ function enumToObjectEntries(enumValues) {
|
|
|
1426
1626
|
function resolveRelation(relation, sourceCollection, propertyKey) {
|
|
1427
1627
|
const target = relation.target;
|
|
1428
1628
|
if (typeof target !== "function") throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has no \`target\`. Give it a thunk: \`target: () => otherCollection\`.`);
|
|
1429
|
-
const targetCollection = target
|
|
1430
|
-
if (!targetCollection?.slug) throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has a \`target\` that did not resolve to a collection.`);
|
|
1629
|
+
const targetCollection = callTarget(relation, sourceCollection, propertyKey, target);
|
|
1431
1630
|
const relationName = relation.relationName ?? propertyKey ?? toSnakeCase(targetCollection.slug);
|
|
1432
1631
|
const shared = {
|
|
1433
1632
|
relationName,
|
|
@@ -1454,7 +1653,8 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
|
|
|
1454
1653
|
cardinality: "one",
|
|
1455
1654
|
writable: true,
|
|
1456
1655
|
shared: false,
|
|
1457
|
-
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
|
|
1656
|
+
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName),
|
|
1657
|
+
sourceKey: relation.sourceKey
|
|
1458
1658
|
};
|
|
1459
1659
|
case "hasMany": return {
|
|
1460
1660
|
...shared,
|
|
@@ -1462,7 +1662,8 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
|
|
|
1462
1662
|
cardinality: "many",
|
|
1463
1663
|
writable: true,
|
|
1464
1664
|
shared: false,
|
|
1465
|
-
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
|
|
1665
|
+
foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName),
|
|
1666
|
+
sourceKey: relation.sourceKey
|
|
1466
1667
|
};
|
|
1467
1668
|
case "manyToMany": {
|
|
1468
1669
|
const sourceTable = getTableName(sourceCollection);
|
|
@@ -1491,6 +1692,43 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
|
|
|
1491
1692
|
default: throw new Error(`Unknown relation kind: ${JSON.stringify(relation)}`);
|
|
1492
1693
|
}
|
|
1493
1694
|
}
|
|
1695
|
+
/** How this relation is addressed in an error message, before it has a resolved name. */
|
|
1696
|
+
function describe(relation, sourceCollection, propertyKey) {
|
|
1697
|
+
const name = relation.relationName ?? propertyKey;
|
|
1698
|
+
return `Relation${name ? ` '${name}'` : ""} on '${sourceCollection.slug}'`;
|
|
1699
|
+
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Call the `target` thunk, and translate the two ways an import cycle breaks it
|
|
1702
|
+
* into an error that names the cause.
|
|
1703
|
+
*
|
|
1704
|
+
* The thunk exists to defer the reference until every module has finished
|
|
1705
|
+
* evaluating, and for a cycle that closes at import time it does. What it cannot
|
|
1706
|
+
* defer is a cycle that leaves the binding permanently unusable, and there are
|
|
1707
|
+
* two shapes of that:
|
|
1708
|
+
*
|
|
1709
|
+
* - **ESM/TDZ.** `const` and `class` bindings in a not-yet-evaluated module are
|
|
1710
|
+
* in the temporal dead zone, so reading one throws `ReferenceError: x is not
|
|
1711
|
+
* defined`. The stack points at the thunk — a one-line arrow function that is
|
|
1712
|
+
* obviously fine — and says nothing about the cycle that made it throw.
|
|
1713
|
+
* - **CJS interop.** The half-initialised module object has no `default` yet,
|
|
1714
|
+
* the import resolves to `undefined`, and the thunk returns it without
|
|
1715
|
+
* complaint. That one used to surface here as "did not resolve to a
|
|
1716
|
+
* collection", which is true and unhelpful.
|
|
1717
|
+
*
|
|
1718
|
+
* Both mean the same thing, and the fix for both is the same: break the cycle,
|
|
1719
|
+
* or move the relation into the collection that does not close it.
|
|
1720
|
+
*/
|
|
1721
|
+
function callTarget(relation, sourceCollection, propertyKey, target) {
|
|
1722
|
+
let targetCollection;
|
|
1723
|
+
try {
|
|
1724
|
+
targetCollection = target();
|
|
1725
|
+
} catch (error) {
|
|
1726
|
+
if (error instanceof ReferenceError) throw new Error(`${describe(relation, sourceCollection, propertyKey)} targets a collection that is not initialized yet — almost always an import cycle between the two collection files. Break the cycle (move the shared piece into a third module, or import the target lazily) so the target's module finishes evaluating before the registry is built.`, { cause: error });
|
|
1727
|
+
throw error;
|
|
1728
|
+
}
|
|
1729
|
+
if (!targetCollection?.slug) throw new Error(`${describe(relation, sourceCollection, propertyKey)} has a \`target\` that resolved to ${targetCollection === void 0 ? "`undefined`" : "something that is not a collection"}. ` + (targetCollection === void 0 ? "Under CommonJS interop an import cycle resolves the default import to `undefined`, so check whether this collection and its target import each other. Otherwise the thunk is returning the wrong value — it must return the collection itself, not a promise or a module." : "The thunk must return a collection config with a `slug`."));
|
|
1730
|
+
return targetCollection;
|
|
1731
|
+
}
|
|
1494
1732
|
//#endregion
|
|
1495
1733
|
//#region ../common/src/util/relations.ts
|
|
1496
1734
|
/**
|
|
@@ -1811,7 +2049,12 @@ var UID_NOT_NULL = /auth\.uid\(\)\s+IS\s+NOT\s+NULL/i;
|
|
|
1811
2049
|
* is how the trusted *server* context is recognised), so:
|
|
1812
2050
|
*
|
|
1813
2051
|
* - `auth.uid() IS NOT NULL` is a tautology on the user path, and
|
|
1814
|
-
* - `auth.uid() != 'anon'`
|
|
2052
|
+
* - `auth.uid() != 'anon'` excludes one spelling of anonymous and admits the
|
|
2053
|
+
* other. This one is not hypothetical and was not only a foreign habit:
|
|
2054
|
+
* rebase's own request path reported `'anon'` while everything that compiled
|
|
2055
|
+
* or checked a policy used `'anonymous'`, so whichever literal an author
|
|
2056
|
+
* picked, half the anonymous callers walked through. See
|
|
2057
|
+
* {@link ANONYMOUS_USER_IDS}.
|
|
1815
2058
|
*
|
|
1816
2059
|
* Either one turns a lockdown into a full grant, and neither looks wrong. No
|
|
1817
2060
|
* real user id is ever one of these literals, and a user-context request is
|
|
@@ -1849,7 +2092,7 @@ function findAnonymousGrants(expr) {
|
|
|
1849
2092
|
found.push({
|
|
1850
2093
|
pattern: "foreign-uid-literal",
|
|
1851
2094
|
detail: literal.value,
|
|
1852
|
-
explanation: `'${literal.value}' is a ${platform} convention. Rebase reports an anonymous request as '${ANONYMOUS_USER_ID}', so comparing against '${literal.value}' passes for every caller. Use \`condition: policy.authenticated()\` to mean "signed in".`
|
|
2095
|
+
explanation: `'${literal.value}' is a ${platform} convention. Rebase reports an anonymous request as '${ANONYMOUS_USER_ID}', so comparing against '${literal.value}' passes for every caller. Use \`condition: policy.authenticated()\` to mean "signed in" — it compiles to NOT IN (${ANONYMOUS_USER_IDS.map((v) => `'${v}'`).join(", ")}), covering every spelling rebase has reported rather than whichever one you remember.`
|
|
1853
2096
|
});
|
|
1854
2097
|
return;
|
|
1855
2098
|
}
|
|
@@ -1944,7 +2187,7 @@ function compile(expr, scope) {
|
|
|
1944
2187
|
}
|
|
1945
2188
|
case "rolesOverlap": return `string_to_array(auth.roles(), ',') && ${rolesArraySql(expr.roles)}`;
|
|
1946
2189
|
case "rolesContain": return `string_to_array(auth.roles(), ',') @> ${rolesArraySql(expr.roles)}`;
|
|
1947
|
-
case "authenticated": return `auth.uid() IS NOT NULL AND auth.uid()
|
|
2190
|
+
case "authenticated": return `auth.uid() IS NOT NULL AND auth.uid() NOT IN (${ANONYMOUS_USER_IDS.map(quoteLiteral).join(", ")})`;
|
|
1948
2191
|
case "serverContext": return "auth.uid() IS NULL";
|
|
1949
2192
|
case "existsIn": return compileExistsIn(expr, scope);
|
|
1950
2193
|
case "raw": return expr.sql.replace(/\{(\w+)\}/g, (_, col) => `${outerQualifier(scope)}${resolveColumnName(col, scope.outerCollection)}`);
|
|
@@ -2016,75 +2259,6 @@ function rolesArraySql(roles) {
|
|
|
2016
2259
|
return `ARRAY[${[...roles].sort().map((r) => `'${r}'`).join(",")}]`;
|
|
2017
2260
|
}
|
|
2018
2261
|
//#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
2262
|
//#region ../common/src/util/auth-default-policies.ts
|
|
2089
2263
|
/**
|
|
2090
2264
|
* Default RLS policies injected by the schema generator.
|
|
@@ -2659,10 +2833,27 @@ function getJunctionSecurityRules(spec) {
|
|
|
2659
2833
|
});
|
|
2660
2834
|
})))();
|
|
2661
2835
|
/**
|
|
2662
|
-
*
|
|
2836
|
+
* How wide a `varchar`/`char` column should be for a given property.
|
|
2837
|
+
*
|
|
2838
|
+
* One definition, three call sites, because they used to disagree. For the same
|
|
2839
|
+
* `columnType: "varchar"` property the DDL generator emitted `VARCHAR(255)`
|
|
2840
|
+
* while the Drizzle generator emitted a bare `varchar("col")` — which Postgres
|
|
2841
|
+
* reads as *unbounded* — so which of the two you ran decided whether the column
|
|
2842
|
+
* had a limit at all. Introspection then dropped the length entirely, so reading
|
|
2843
|
+
* an existing `character varying(500)` column back and regenerating it produced
|
|
2844
|
+
* a `VARCHAR(255)`: a silent narrowing of a column with data already in it.
|
|
2845
|
+
*
|
|
2846
|
+
* `validation.max` is the property's own statement about how long the value may
|
|
2847
|
+
* be, so it is the only sensible source for the column's width — and it keeps
|
|
2848
|
+
* the constraint the database enforces in step with the one the app enforces,
|
|
2849
|
+
* rather than inventing a second, different limit underneath it.
|
|
2663
2850
|
*/
|
|
2851
|
+
function resolveStringColumnLength(prop) {
|
|
2852
|
+
const max = prop.validation?.max;
|
|
2853
|
+
return typeof max === "number" && Number.isInteger(max) && max > 0 ? max : 255;
|
|
2854
|
+
}
|
|
2664
2855
|
//#endregion
|
|
2665
|
-
//#region ../../node_modules/.pnpm/fast-equals@6.0.
|
|
2856
|
+
//#region ../../node_modules/.pnpm/fast-equals@6.0.2/node_modules/fast-equals/dist/es/index.mjs
|
|
2666
2857
|
var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
2667
2858
|
var { hasOwnProperty } = Object.prototype;
|
|
2668
2859
|
/**
|
|
@@ -2698,7 +2889,8 @@ function createIsCircular(areItemsEqual) {
|
|
|
2698
2889
|
* not enumerable and symbol properties.
|
|
2699
2890
|
*/
|
|
2700
2891
|
function getStrictProperties(object) {
|
|
2701
|
-
|
|
2892
|
+
const symbols = getOwnPropertySymbols(object);
|
|
2893
|
+
return symbols.length ? getOwnPropertyNames(object).concat(symbols) : getOwnPropertyNames(object);
|
|
2702
2894
|
}
|
|
2703
2895
|
/**
|
|
2704
2896
|
* Whether the object contains the property passed as an own property.
|
|
@@ -2771,7 +2963,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2771
2963
|
const size = a.size;
|
|
2772
2964
|
if (size !== b.size) return false;
|
|
2773
2965
|
if (!size) return true;
|
|
2774
|
-
const matchedIndices = new
|
|
2966
|
+
const matchedIndices = new Uint8Array(size);
|
|
2775
2967
|
const aIterable = a.entries();
|
|
2776
2968
|
let aResult;
|
|
2777
2969
|
let bResult;
|
|
@@ -2779,7 +2971,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2779
2971
|
while (aResult = aIterable.next()) {
|
|
2780
2972
|
if (aResult.done) break;
|
|
2781
2973
|
const bIterable = b.entries();
|
|
2782
|
-
let hasMatch =
|
|
2974
|
+
let hasMatch = 0;
|
|
2783
2975
|
let matchIndex = 0;
|
|
2784
2976
|
while (bResult = bIterable.next()) {
|
|
2785
2977
|
if (bResult.done) break;
|
|
@@ -2790,7 +2982,7 @@ function areMapsEqual(a, b, state) {
|
|
|
2790
2982
|
const aEntry = aResult.value;
|
|
2791
2983
|
const bEntry = bResult.value;
|
|
2792
2984
|
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] =
|
|
2985
|
+
hasMatch = matchedIndices[matchIndex] = 1;
|
|
2794
2986
|
break;
|
|
2795
2987
|
}
|
|
2796
2988
|
matchIndex++;
|
|
@@ -2848,19 +3040,19 @@ function areSetsEqual(a, b, state) {
|
|
|
2848
3040
|
const size = a.size;
|
|
2849
3041
|
if (size !== b.size) return false;
|
|
2850
3042
|
if (!size) return true;
|
|
2851
|
-
const matchedIndices = new
|
|
3043
|
+
const matchedIndices = new Uint8Array(size);
|
|
2852
3044
|
const aIterable = a.values();
|
|
2853
3045
|
let aResult;
|
|
2854
3046
|
let bResult;
|
|
2855
3047
|
while (aResult = aIterable.next()) {
|
|
2856
3048
|
if (aResult.done) break;
|
|
2857
3049
|
const bIterable = b.values();
|
|
2858
|
-
let hasMatch =
|
|
3050
|
+
let hasMatch = 0;
|
|
2859
3051
|
let matchIndex = 0;
|
|
2860
3052
|
while (bResult = bIterable.next()) {
|
|
2861
3053
|
if (bResult.done) break;
|
|
2862
3054
|
if (!matchedIndices[matchIndex] && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
|
|
2863
|
-
hasMatch = matchedIndices[matchIndex] =
|
|
3055
|
+
hasMatch = matchedIndices[matchIndex] = 1;
|
|
2864
3056
|
break;
|
|
2865
3057
|
}
|
|
2866
3058
|
matchIndex++;
|
|
@@ -2873,8 +3065,8 @@ function areSetsEqual(a, b, state) {
|
|
|
2873
3065
|
* Whether the TypedArray instances are equal in value.
|
|
2874
3066
|
*/
|
|
2875
3067
|
function areTypedArraysEqual(a, b) {
|
|
2876
|
-
let index = a.
|
|
2877
|
-
if (b.
|
|
3068
|
+
let index = a.length;
|
|
3069
|
+
if (b.length !== index || a.byteOffset !== b.byteOffset) return false;
|
|
2878
3070
|
while (index-- > 0) if (a[index] !== b[index]) return false;
|
|
2879
3071
|
return true;
|
|
2880
3072
|
}
|
|
@@ -3724,7 +3916,7 @@ function rowToEntity(row, slug, primaryKeys = []) {
|
|
|
3724
3916
|
};
|
|
3725
3917
|
}
|
|
3726
3918
|
/**
|
|
3727
|
-
* The relation envelope `
|
|
3919
|
+
* The relation envelope `toFlatRow` writes where a relation was:
|
|
3728
3920
|
* `{ id, path, __type: "relation", data: { id, path, values } }`. It is the
|
|
3729
3921
|
* admin's view-model, and the only pipeline that produces one is postgres'.
|
|
3730
3922
|
*/
|
|
@@ -4102,72 +4294,6 @@ function buildSdkData(driver) {
|
|
|
4102
4294
|
return wrapAsSdkData(buildRebaseData(driver));
|
|
4103
4295
|
}
|
|
4104
4296
|
//#endregion
|
|
4105
|
-
|
|
4106
|
-
/** Schemas that are always considered Rebase-internal. */
|
|
4107
|
-
var REBASE_INTERNAL_SCHEMAS = ["rebase", "auth"];
|
|
4108
|
-
/** Table-name prefixes that mark a table as Rebase-internal regardless of schema. */
|
|
4109
|
-
var REBASE_INTERNAL_PREFIXES = [
|
|
4110
|
-
"_rebase_",
|
|
4111
|
-
"_auth_",
|
|
4112
|
-
"drizzle_"
|
|
4113
|
-
];
|
|
4114
|
-
/**
|
|
4115
|
-
* Synchronously classify a table based on naming conventions.
|
|
4116
|
-
*
|
|
4117
|
-
* @param tableName - The unqualified name of the table.
|
|
4118
|
-
* @param schemaName - The schema the table belongs to (e.g. `"public"`, `"rebase"`).
|
|
4119
|
-
* @returns `"rebase-internal"` when the table belongs to a reserved schema or
|
|
4120
|
-
* carries a reserved prefix; `"user"` otherwise.
|
|
4121
|
-
*
|
|
4122
|
-
* @remarks
|
|
4123
|
-
* Junction-table detection requires an async database query and is therefore
|
|
4124
|
-
* **not** handled by this function. Use {@link detectJunctionTables} to obtain
|
|
4125
|
-
* the set of junction tables, then reclassify as needed.
|
|
4126
|
-
*/
|
|
4127
|
-
function classifyTable(tableName, schemaName) {
|
|
4128
|
-
if (REBASE_INTERNAL_SCHEMAS.includes(schemaName) || REBASE_INTERNAL_PREFIXES.some((prefix) => tableName.startsWith(prefix))) return "rebase-internal";
|
|
4129
|
-
return "user";
|
|
4130
|
-
}
|
|
4131
|
-
/** SQL query that detects junction tables in the `public` schema. */
|
|
4132
|
-
var JUNCTION_TABLES_SQL = `
|
|
4133
|
-
SELECT t.table_name
|
|
4134
|
-
FROM information_schema.tables t
|
|
4135
|
-
WHERE t.table_schema = 'public'
|
|
4136
|
-
AND t.table_type = 'BASE TABLE'
|
|
4137
|
-
AND NOT EXISTS (
|
|
4138
|
-
SELECT 1
|
|
4139
|
-
FROM information_schema.columns c
|
|
4140
|
-
WHERE c.table_schema = t.table_schema
|
|
4141
|
-
AND c.table_name = t.table_name
|
|
4142
|
-
AND c.column_name NOT IN (
|
|
4143
|
-
SELECT kcu.column_name
|
|
4144
|
-
FROM information_schema.key_column_usage kcu
|
|
4145
|
-
JOIN information_schema.table_constraints tc
|
|
4146
|
-
ON tc.constraint_name = kcu.constraint_name
|
|
4147
|
-
AND tc.table_schema = kcu.table_schema
|
|
4148
|
-
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
4149
|
-
AND kcu.table_schema = t.table_schema
|
|
4150
|
-
AND kcu.table_name = t.table_name
|
|
4151
|
-
)
|
|
4152
|
-
)
|
|
4153
|
-
`;
|
|
4154
|
-
/**
|
|
4155
|
-
* Asynchronously detect junction (link) tables in the `public` schema.
|
|
4156
|
-
*
|
|
4157
|
-
* A junction table is defined as a table where **every** column participates in
|
|
4158
|
-
* at least one foreign-key constraint.
|
|
4159
|
-
*
|
|
4160
|
-
* @param executeSql - A callback that executes a raw SQL string and returns the
|
|
4161
|
-
* resulting rows.
|
|
4162
|
-
* @returns A `Set` containing the names of all detected junction tables.
|
|
4163
|
-
*/
|
|
4164
|
-
async function detectJunctionTables(executeSql) {
|
|
4165
|
-
const rows = await executeSql(JUNCTION_TABLES_SQL);
|
|
4166
|
-
const junctionTables = /* @__PURE__ */ new Set();
|
|
4167
|
-
for (const row of rows) if (typeof row.table_name === "string") junctionTables.add(row.table_name);
|
|
4168
|
-
return junctionTables;
|
|
4169
|
-
}
|
|
4170
|
-
//#endregion
|
|
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 };
|
|
4297
|
+
export { toSnakeCase as A, normalizeToEntityRelation as C, getPolicyNamesForRule as D, legacyForeignKeyName as E, Vector as F, DEFAULT_ONE_OF_VALUE as M, hasForeignKeyOnTarget as N, mergeDeep as O, isManyToMany as P, createRelationRefWithData as S, generateForeignKeyName as T, buildCompositeId as _, getJunctionSecurityRules as a, parseIdValues as b, policyToPostgres as c, findRelation as d, getColumnName as f, resolveCollectionRelations as g, getTableVarName as h, getJunctionCollectionConfig as i, DEFAULT_ONE_OF_TYPE as j, camelCase 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, updateDateAutoValues as w, createRelationRef as x, isAddressableId as y };
|
|
4172
4298
|
|
|
4173
|
-
//# sourceMappingURL=src-
|
|
4299
|
+
//# sourceMappingURL=src-DlPBctw_.js.map
|