@rebasepro/server 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.
Files changed (67) hide show
  1. package/dist/GCSStorageController-BEmDYFKc.js +216 -0
  2. package/dist/GCSStorageController-BEmDYFKc.js.map +1 -0
  3. package/dist/S3StorageController-B2EDXXMH.js +249 -0
  4. package/dist/S3StorageController-B2EDXXMH.js.map +1 -0
  5. package/dist/admin_block-CcSGdH7M.js +124 -0
  6. package/dist/admin_block-CcSGdH7M.js.map +1 -0
  7. package/dist/api/rest/write-validation.d.ts +22 -0
  8. package/dist/auth/bearer-token.d.ts +26 -0
  9. package/dist/auth/index.d.ts +1 -1
  10. package/dist/auth/middleware.d.ts +2 -0
  11. package/dist/auth/rate-limiter.d.ts +0 -11
  12. package/dist/auth/require-auth.d.ts +39 -0
  13. package/dist/auth-CuC9M2x6.js +8961 -0
  14. package/dist/auth-CuC9M2x6.js.map +1 -0
  15. package/dist/backend-CIxN4FVm.js +15 -0
  16. package/dist/backend-CIxN4FVm.js.map +1 -0
  17. package/dist/backup-CVggVhR2.js +163 -0
  18. package/dist/backup-CVggVhR2.js.map +1 -0
  19. package/dist/boot/boot.d.ts +53 -0
  20. package/dist/boot/driver.d.ts +35 -6
  21. package/dist/boot/fetch-bundle.d.ts +43 -0
  22. package/dist/boot/version-skew.d.ts +77 -0
  23. package/dist/contract-routes-Dj8i5AiM.js +264 -0
  24. package/dist/contract-routes-Dj8i5AiM.js.map +1 -0
  25. package/dist/cron/cron-scheduler.d.ts +34 -0
  26. package/dist/cron-loader-B1S2MCSl.js +63 -0
  27. package/dist/cron-loader-B1S2MCSl.js.map +1 -0
  28. package/dist/cron-routes-CrQ0tK-_.js +62 -0
  29. package/dist/cron-routes-CrQ0tK-_.js.map +1 -0
  30. package/dist/cron-scheduler-B3RFt0HS.js +647 -0
  31. package/dist/cron-scheduler-B3RFt0HS.js.map +1 -0
  32. package/dist/cron-store-BywZsyfZ.js +164 -0
  33. package/dist/cron-store-BywZsyfZ.js.map +1 -0
  34. package/dist/dynamic-import-Dvh-K5fl.js.map +1 -1
  35. package/dist/errors-CgkCzoj7.js +226 -0
  36. package/dist/errors-CgkCzoj7.js.map +1 -0
  37. package/dist/function-loader-B_1fYfUY.js +86 -0
  38. package/dist/function-loader-B_1fYfUY.js.map +1 -0
  39. package/dist/function-routes-C0cLIy3N.js +28 -0
  40. package/dist/function-routes-C0cLIy3N.js.map +1 -0
  41. package/dist/functions/define-function.d.ts +2 -2
  42. package/dist/index.d.ts +2 -1
  43. package/dist/index.es.js +8123 -17984
  44. package/dist/index.es.js.map +1 -1
  45. package/dist/init.d.ts +21 -5
  46. package/dist/{jwt-D-eI6TTu.js → jwt-DD6EtpGj.js} +32 -13
  47. package/dist/{jwt-D-eI6TTu.js.map → jwt-DD6EtpGj.js.map} +1 -1
  48. package/dist/logger-BYU66ENZ.js.map +1 -1
  49. package/dist/logs-routes-BYA72C_C.js +100 -0
  50. package/dist/logs-routes-BYA72C_C.js.map +1 -0
  51. package/dist/{openapi-generator-Bjzmb5cn.js → openapi-generator-BEwyiaAr.js} +9 -3
  52. package/dist/openapi-generator-BEwyiaAr.js.map +1 -0
  53. package/dist/{schema-editor-routes-DDxfOIid.js → schema-editor-routes-CbF20Mf1.js} +4 -3
  54. package/dist/{schema-editor-routes-DDxfOIid.js.map → schema-editor-routes-CbF20Mf1.js.map} +1 -1
  55. package/dist/singleton.d.ts +4 -2
  56. package/dist/{src-CoOAMnBh.js → src-Cum9kox5.js} +501 -86
  57. package/dist/src-Cum9kox5.js.map +1 -0
  58. package/dist/src-_qQ3RNCK.js +279 -0
  59. package/dist/src-_qQ3RNCK.js.map +1 -0
  60. package/dist/types-DSnOC4mF.js +38 -0
  61. package/dist/types-DSnOC4mF.js.map +1 -0
  62. package/package.json +10 -10
  63. package/dist/openapi-generator-Bjzmb5cn.js.map +0 -1
  64. package/dist/src-CoOAMnBh.js.map +0 -1
  65. package/dist/src-Ivjud8jD.js +0 -957
  66. package/dist/src-Ivjud8jD.js.map +0 -1
  67. /package/dist/{chunk-DSJWtz9O.js → rolldown-runtime-DSJWtz9O.js} +0 -0
@@ -1,8 +1,240 @@
1
1
  import { createRequire as __createRequire } from "module";
2
2
  import "process";
3
3
  __createRequire(import.meta.url);
4
- import { r as __require, t as __commonJSMin } from "./chunk-DSJWtz9O.js";
5
- import { S as toCanonicalOp, b as NULL_OPS, f as getDeclaredSubcollections, g as getDataSourceCapabilities, l as policy, m as isRelationalCollectionConfig, w as EntityRelation, x as REST_TO_CANONICAL, y as CANONICAL_TO_REST } from "./src-Ivjud8jD.js";
4
+ import { r as __require, t as __commonJSMin } from "./rolldown-runtime-DSJWtz9O.js";
5
+ import { c as NULL_OPS, i as isRelationalCollectionConfig, l as REST_TO_CANONICAL, n as getDeclaredSubcollections, o as getDataSourceCapabilities, r as isPostgresCollectionConfig, s as CANONICAL_TO_REST, u as toCanonicalOp } from "./src-_qQ3RNCK.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
+ * @example
11
+ * // Simple reference (most common case - single driver, single db)
12
+ * new EntityReference({ id: "123", path: "users" })
13
+ *
14
+ * // Reference to a different driver (e.g., Firestore)
15
+ * new EntityReference({ id: "123", path: "analytics", driver: "firestore" })
16
+ *
17
+ * // Reference to a specific database within a driver
18
+ * new EntityReference({ id: "123", path: "orders", driver: "postgres", databaseId: "orders_db" })
19
+ */
20
+ var EntityReference = class {
21
+ __type = "reference";
22
+ /**
23
+ * ID of the entity
24
+ */
25
+ id;
26
+ /**
27
+ * A string representing the path of the referenced document (relative
28
+ * to the root of the database).
29
+ */
30
+ path;
31
+ /**
32
+ * Which driver (e.g., 'postgres', 'firestore').
33
+ * Defaults to "(default)" if not specified.
34
+ */
35
+ driver;
36
+ /**
37
+ * Which database within the driver.
38
+ * Defaults to "(default)" if not specified.
39
+ */
40
+ databaseId;
41
+ /**
42
+ * Create a reference to a entity.
43
+ *
44
+ * @example
45
+ * // Simple reference (most common case)
46
+ * new EntityReference({ id: "123", path: "users" })
47
+ *
48
+ * // With driver
49
+ * new EntityReference({ id: "123", path: "analytics", driver: "firestore" })
50
+ */
51
+ constructor(props) {
52
+ this.id = props.id;
53
+ this.path = props.path;
54
+ this.driver = props.driver;
55
+ this.databaseId = props.databaseId;
56
+ }
57
+ get pathWithId() {
58
+ return `${this.path}/${this.id}`;
59
+ }
60
+ /**
61
+ * Get the full path including driver and database prefixes if specified.
62
+ * For the common case (single driver, single db), this just returns pathWithId.
63
+ */
64
+ get fullPath() {
65
+ const parts = [];
66
+ if (this.driver && this.driver !== "(default)") parts.push(this.driver);
67
+ if (this.databaseId && this.databaseId !== "(default)") parts.push(this.databaseId);
68
+ if (parts.length > 0) return `${parts.join(":")}:::${this.path}/${this.id}`;
69
+ return this.pathWithId;
70
+ }
71
+ isEntityReference() {
72
+ return true;
73
+ }
74
+ };
75
+ /**
76
+ * Class used to create a reference to a entity in a different path
77
+ */
78
+ var EntityRelation = class {
79
+ __type = "relation";
80
+ /**
81
+ * ID of the entity
82
+ */
83
+ id;
84
+ /**
85
+ * A string representing the path of the referenced document (relative
86
+ * to the root of the database).
87
+ */
88
+ path;
89
+ /**
90
+ * Pre-fetched data payload to eliminate N+1 queries.
91
+ * When present, clients can use this directly instead of fetching.
92
+ */
93
+ data;
94
+ constructor(id, path, data) {
95
+ this.id = id;
96
+ this.path = path;
97
+ this.data = data;
98
+ }
99
+ get pathWithId() {
100
+ return `${this.path}/${this.id}`;
101
+ }
102
+ isEntityReference() {
103
+ return false;
104
+ }
105
+ isEntityRelation() {
106
+ return true;
107
+ }
108
+ };
109
+ var GeoPoint = class {
110
+ /**
111
+ * The latitude of this GeoPoint instance.
112
+ */
113
+ latitude;
114
+ /**
115
+ * The longitude of this GeoPoint instance.
116
+ */
117
+ longitude;
118
+ constructor(latitude, longitude) {
119
+ this.latitude = latitude;
120
+ this.longitude = longitude;
121
+ }
122
+ };
123
+ var Vector = class {
124
+ value;
125
+ constructor(value) {
126
+ this.value = value;
127
+ }
128
+ };
129
+ //#endregion
130
+ //#region ../types/src/types/policy.ts
131
+ /**
132
+ * The id a request without a logged-in user reports as `auth.uid()`.
133
+ *
134
+ * A user-context request always sets `app.uid`: blank would read back as
135
+ * `NULL`, and `NULL` is how the trusted server context is recognised, so an
136
+ * anonymous visitor would be promoted to server privileges. The driver
137
+ * therefore substitutes this sentinel at the single chokepoint where the GUC
138
+ * is set.
139
+ *
140
+ * The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
141
+ * tautology on the user path** — it is true for anonymous visitors too. Use
142
+ * {@link policy.authenticated} to mean "signed in", and
143
+ * {@link policy.serverContext} to mean "the trusted server context". Do not
144
+ * hand-write the comparison: see {@link ANONYMOUS_USER_IDS} for why one
145
+ * literal is not enough.
146
+ *
147
+ * @group Models
148
+ */
149
+ var ANONYMOUS_USER_ID = "anonymous";
150
+ /**
151
+ * Every uid that has ever meant "nobody is signed in" — newest first.
152
+ *
153
+ * There are two because there were two. The types, the policy compiler, the
154
+ * JavaScript evaluator and the linter were all built on
155
+ * {@link ANONYMOUS_USER_ID}, while the request path scoped unauthenticated
156
+ * callers as `'anon'` — so `policy.authenticated()`, which compiled to
157
+ * `auth.uid() <> 'anonymous'`, was *true* for an anonymous visitor. The
158
+ * sanctioned way to write "signed in" granted to everyone, and the linter
159
+ * flagged the spelling that actually worked as a foreign convention.
160
+ *
161
+ * The request path now reports {@link ANONYMOUS_USER_ID}. `'anon'` stays here
162
+ * because policies outlive the server that generated them: a database still
163
+ * holding policies from before the fix, or a project whose server has not been
164
+ * upgraded yet, must not become a grant in either direction. Compile against
165
+ * this list, not against a single literal.
166
+ *
167
+ * No real user id is ever one of these, so a match is always "not signed in".
168
+ *
169
+ * @group Models
170
+ */
171
+ var ANONYMOUS_USER_IDS = [ANONYMOUS_USER_ID, "anon"];
172
+ /**
173
+ * Whether a uid stands for "no one is signed in", in any spelling rebase has
174
+ * used. `null`/`undefined` is the trusted server context, not an anonymous
175
+ * caller, and is therefore **not** anonymous — see {@link ANONYMOUS_USER_ID}.
176
+ *
177
+ * @group Models
178
+ */
179
+ function isAnonymousUid(uid) {
180
+ return typeof uid === "string" && ANONYMOUS_USER_IDS.includes(uid);
181
+ }
182
+ /** @group Models */
183
+ var policy = {
184
+ true: () => ({ kind: "true" }),
185
+ false: () => ({ kind: "false" }),
186
+ and: (...operands) => ({
187
+ kind: "and",
188
+ operands
189
+ }),
190
+ or: (...operands) => ({
191
+ kind: "or",
192
+ operands
193
+ }),
194
+ not: (operand) => ({
195
+ kind: "not",
196
+ operand
197
+ }),
198
+ compare: (left, op, right) => ({
199
+ kind: "compare",
200
+ op,
201
+ left,
202
+ right
203
+ }),
204
+ rolesOverlap: (roles) => ({
205
+ kind: "rolesOverlap",
206
+ roles
207
+ }),
208
+ rolesContain: (roles) => ({
209
+ kind: "rolesContain",
210
+ roles
211
+ }),
212
+ authenticated: () => ({ kind: "authenticated" }),
213
+ serverContext: () => ({ kind: "serverContext" }),
214
+ existsIn: (args) => ({
215
+ kind: "existsIn",
216
+ collection: args.collection,
217
+ where: args.where
218
+ }),
219
+ raw: (sql) => ({
220
+ kind: "raw",
221
+ sql
222
+ }),
223
+ field: (name) => ({
224
+ kind: "field",
225
+ name
226
+ }),
227
+ outerField: (name) => ({
228
+ kind: "outerField",
229
+ name
230
+ }),
231
+ literal: (value) => ({
232
+ kind: "literal",
233
+ value
234
+ }),
235
+ authUid: () => ({ kind: "authUid" }),
236
+ authRoles: () => ({ kind: "authRoles" })
237
+ };
6
238
  (/* @__PURE__ */ __commonJSMin(((exports, module) => {
7
239
  (function(e) {
8
240
  var t;
@@ -1004,23 +1236,107 @@ function removeFunctions(o) {
1004
1236
  if (o === void 0) return void 0;
1005
1237
  if (o === null) return null;
1006
1238
  if (typeof o === "object") {
1007
- if (Array.isArray(o)) return o.map((v) => removeFunctions(v));
1239
+ if (Array.isArray(o)) return o.filter((v) => typeof v !== "function").map((v) => removeFunctions(v));
1008
1240
  if (!isPlainObject(o)) return o;
1009
- return Object.entries(o).filter(([_, value]) => typeof value !== "function").map(([key, value]) => {
1010
- if (Array.isArray(value)) return { [key]: value.map((v) => removeFunctions(v)) };
1011
- else if (typeof value === "object") return { [key]: removeFunctions(value) };
1012
- else return { [key]: value };
1013
- }).reduce((a, b) => ({
1014
- ...a,
1015
- ...b
1016
- }), {});
1241
+ return Object.entries(o).filter(([_, value]) => typeof value !== "function").reduce((acc, [key, value]) => {
1242
+ acc[key] = removeFunctions(value);
1243
+ return acc;
1244
+ }, {});
1017
1245
  }
1018
1246
  return o;
1019
1247
  }
1020
1248
  /**
1249
+ * Returns the singular of an English word.
1250
+ *
1251
+ * @param {string} word
1252
+ * @param {number} [amount]
1253
+ * @returns {string}
1254
+ */
1255
+ function singular(word, amount) {
1256
+ if (amount !== void 0 && amount !== 1) return word;
1257
+ const singulars = {
1258
+ "(quiz)zes$": "$1",
1259
+ "(matr)ices$": "$1ix",
1260
+ "(vert|ind)ices$": "$1ex",
1261
+ "^(ox)en$": "$1",
1262
+ "(alias)es$": "$1",
1263
+ "(octop|vir)i$": "$1us",
1264
+ "(cris|ax|test)es$": "$1is",
1265
+ "(shoe)s$": "$1",
1266
+ "(o)es$": "$1",
1267
+ "(bus)es$": "$1",
1268
+ "([m|l])ice$": "$1ouse",
1269
+ "(x|ch|ss|sh)es$": "$1",
1270
+ "(m)ovies$": "$1ovie",
1271
+ "(s)eries$": "$1eries",
1272
+ "([^aeiouy]|qu)ies$": "$1y",
1273
+ "([lr])ves$": "$1f",
1274
+ "(tive)s$": "$1",
1275
+ "(hive)s$": "$1",
1276
+ "(li|wi|kni)ves$": "$1fe",
1277
+ "(shea|loa|lea|thie)ves$": "$1f",
1278
+ "(^analy)ses$": "$1sis",
1279
+ "((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$": "$1$2sis",
1280
+ "([ti])a$": "$1um",
1281
+ "(n)ews$": "$1ews",
1282
+ "(h|bl)ouses$": "$1ouse",
1283
+ "(corpse)s$": "$1",
1284
+ "(us)es$": "$1",
1285
+ s$: ""
1286
+ };
1287
+ const irregular = {
1288
+ move: "moves",
1289
+ foot: "feet",
1290
+ goose: "geese",
1291
+ sex: "sexes",
1292
+ child: "children",
1293
+ man: "men",
1294
+ tooth: "teeth",
1295
+ person: "people"
1296
+ };
1297
+ if ([
1298
+ "sheep",
1299
+ "fish",
1300
+ "deer",
1301
+ "moose",
1302
+ "series",
1303
+ "species",
1304
+ "money",
1305
+ "rice",
1306
+ "information",
1307
+ "equipment",
1308
+ "bison",
1309
+ "cod",
1310
+ "offspring",
1311
+ "pike",
1312
+ "salmon",
1313
+ "shrimp",
1314
+ "swine",
1315
+ "trout",
1316
+ "aircraft",
1317
+ "hovercraft",
1318
+ "spacecraft",
1319
+ "sugar",
1320
+ "tuna",
1321
+ "you",
1322
+ "wood"
1323
+ ].indexOf(word.toLowerCase()) >= 0) return word;
1324
+ for (const w in irregular) {
1325
+ const pattern = new RegExp(`${irregular[w]}$`, "i");
1326
+ if (pattern.test(word)) return word.replace(pattern, w);
1327
+ }
1328
+ for (const reg in singulars) {
1329
+ const pattern = new RegExp(reg, "i");
1330
+ if (pattern.test(word)) return word.replace(pattern, singulars[reg]);
1331
+ }
1332
+ return word;
1333
+ }
1334
+ /**
1021
1335
  * Generates a foreign key column name from a given string, typically a collection slug or name.
1022
- * It converts the name to snake_case, attempts to singularize it by removing a trailing 's'
1023
- * (a common convention for collection names), and appends '_id'.
1336
+ * It singularizes the name, converts it to snake_case and appends '_id'.
1337
+ *
1338
+ * Singularization runs *before* snake-casing so that acronyms survive: `toSnakeCase`
1339
+ * splits on every capital, which turned "URLs" into "ur_ls" and then "ur_l_id".
1024
1340
  *
1025
1341
  * @param name The base name to convert to a foreign key.
1026
1342
  * @returns A foreign key name in the format 'singular_name_id'.
@@ -1030,8 +1346,8 @@ function removeFunctions(o) {
1030
1346
  * generateForeignKeyName("users")
1031
1347
  *
1032
1348
  * @example
1033
- * // returns "post_id"
1034
- * generateForeignKeyName("posts")
1349
+ * // returns "category_id"
1350
+ * generateForeignKeyName("categories")
1035
1351
  *
1036
1352
  * @example
1037
1353
  * // returns "product_id"
@@ -1039,8 +1355,21 @@ function removeFunctions(o) {
1039
1355
  *
1040
1356
  */
1041
1357
  function generateForeignKeyName(name) {
1042
- const snakeCaseName = toSnakeCase(name);
1043
- return `${snakeCaseName.endsWith("s") ? snakeCaseName.slice(0, -1) : snakeCaseName}_id`;
1358
+ return `${toSnakeCase(singularizeForKey(name))}_id`;
1359
+ }
1360
+ /**
1361
+ * `singular()` handles real English plurals, but its final catch-all rule strips
1362
+ * any trailing "s", which mangles words that only look plural. Guard the two
1363
+ * cases that produce a column name nobody would recognise:
1364
+ *
1365
+ * - a double "s" ending is never a plural marker ("address", "class", "process"),
1366
+ * so stripping it yields "addres";
1367
+ * - a name that singularizes to nothing (the literal "s") would yield "_id".
1368
+ */
1369
+ function singularizeForKey(name) {
1370
+ if (/ss$/i.test(name)) return name;
1371
+ const result = singular(name);
1372
+ return result.length > 0 ? result : name;
1044
1373
  }
1045
1374
  //#endregion
1046
1375
  //#region ../common/src/util/entities.ts
@@ -1169,8 +1498,7 @@ function enumToObjectEntries(enumValues) {
1169
1498
  function resolveRelation(relation, sourceCollection, propertyKey) {
1170
1499
  const target = relation.target;
1171
1500
  if (typeof target !== "function") throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has no \`target\`. Give it a thunk: \`target: () => otherCollection\`.`);
1172
- const targetCollection = target();
1173
- if (!targetCollection?.slug) throw new Error(`Relation${relation.relationName ? ` '${relation.relationName}'` : ""} on '${sourceCollection.slug}' has a \`target\` that did not resolve to a collection.`);
1501
+ const targetCollection = callTarget(relation, sourceCollection, propertyKey, target);
1174
1502
  const relationName = relation.relationName ?? propertyKey ?? toSnakeCase(targetCollection.slug);
1175
1503
  const shared = {
1176
1504
  relationName,
@@ -1197,7 +1525,8 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
1197
1525
  cardinality: "one",
1198
1526
  writable: true,
1199
1527
  shared: false,
1200
- foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
1528
+ foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName),
1529
+ sourceKey: relation.sourceKey
1201
1530
  };
1202
1531
  case "hasMany": return {
1203
1532
  ...shared,
@@ -1205,7 +1534,8 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
1205
1534
  cardinality: "many",
1206
1535
  writable: true,
1207
1536
  shared: false,
1208
- foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName)
1537
+ foreignKeyOnTarget: relation.foreignKeyOnTarget ?? generateForeignKeyName(sourceName),
1538
+ sourceKey: relation.sourceKey
1209
1539
  };
1210
1540
  case "manyToMany": {
1211
1541
  const sourceTable = getTableName(sourceCollection);
@@ -1234,6 +1564,43 @@ function resolveRelation(relation, sourceCollection, propertyKey) {
1234
1564
  default: throw new Error(`Unknown relation kind: ${JSON.stringify(relation)}`);
1235
1565
  }
1236
1566
  }
1567
+ /** How this relation is addressed in an error message, before it has a resolved name. */
1568
+ function describe(relation, sourceCollection, propertyKey) {
1569
+ const name = relation.relationName ?? propertyKey;
1570
+ return `Relation${name ? ` '${name}'` : ""} on '${sourceCollection.slug}'`;
1571
+ }
1572
+ /**
1573
+ * Call the `target` thunk, and translate the two ways an import cycle breaks it
1574
+ * into an error that names the cause.
1575
+ *
1576
+ * The thunk exists to defer the reference until every module has finished
1577
+ * evaluating, and for a cycle that closes at import time it does. What it cannot
1578
+ * defer is a cycle that leaves the binding permanently unusable, and there are
1579
+ * two shapes of that:
1580
+ *
1581
+ * - **ESM/TDZ.** `const` and `class` bindings in a not-yet-evaluated module are
1582
+ * in the temporal dead zone, so reading one throws `ReferenceError: x is not
1583
+ * defined`. The stack points at the thunk — a one-line arrow function that is
1584
+ * obviously fine — and says nothing about the cycle that made it throw.
1585
+ * - **CJS interop.** The half-initialised module object has no `default` yet,
1586
+ * the import resolves to `undefined`, and the thunk returns it without
1587
+ * complaint. That one used to surface here as "did not resolve to a
1588
+ * collection", which is true and unhelpful.
1589
+ *
1590
+ * Both mean the same thing, and the fix for both is the same: break the cycle,
1591
+ * or move the relation into the collection that does not close it.
1592
+ */
1593
+ function callTarget(relation, sourceCollection, propertyKey, target) {
1594
+ let targetCollection;
1595
+ try {
1596
+ targetCollection = target();
1597
+ } catch (error) {
1598
+ 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 });
1599
+ throw error;
1600
+ }
1601
+ 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`."));
1602
+ return targetCollection;
1603
+ }
1237
1604
  //#endregion
1238
1605
  //#region ../common/src/util/relations.ts
1239
1606
  /**
@@ -1381,7 +1748,105 @@ function getEntityChildViews(collection) {
1381
1748
  function getSubcollections(collection) {
1382
1749
  return getEntityChildViews(collection).map((view) => view.collection);
1383
1750
  }
1384
- policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
1751
+ //#endregion
1752
+ //#region ../common/src/util/auth-default-policies.ts
1753
+ /**
1754
+ * Default RLS policies injected by the schema generator.
1755
+ *
1756
+ * Rebase's enforcement model is unified: authenticated (user-context) requests
1757
+ * run under the restricted `rebase_user` role, so Postgres RLS binds *every*
1758
+ * statement — reads and writes. A collection's `securityRules` are the whole
1759
+ * authorization model. The server context (auth flows, migrations,
1760
+ * `dataAsAdmin`) runs as the owner and bypasses RLS.
1761
+ *
1762
+ * Because RLS default-denies, every collection is **locked by default**: with
1763
+ * no rules, only the server context and admins can touch it. The generator
1764
+ * injects that safe baseline:
1765
+ *
1766
+ * **For every collection**
1767
+ * 1. A permissive **server-or-admin SELECT** grant.
1768
+ * 2. A permissive **server-or-admin write** grant (insert/update/delete).
1769
+ *
1770
+ * Author `securityRules` are permissive and OR together, so explicit rules only
1771
+ * *broaden* access from this locked baseline (e.g. "users read/write their own
1772
+ * rows").
1773
+ *
1774
+ * **For auth collections additionally**
1775
+ * 3. A permissive **self SELECT** grant (`id = auth.uid()`), so users can read
1776
+ * their own row (profile, session bootstrap) without every app re-declaring
1777
+ * it.
1778
+ * 4. A **restrictive** admin write gate. Restrictive policies are AND'd with
1779
+ * every other policy, so a write is rejected unless the caller is an admin
1780
+ * (or the server context) — even if the author also wrote a permissive rule
1781
+ * such as "a user may edit their own row". Without this, a permissive owner
1782
+ * rule would let a user change their own `roles`.
1783
+ *
1784
+ * The server context is recognised as `auth.uid() IS NULL` (`policy.serverContext()`)
1785
+ * — the built-in flows that run without a user (signup, migrations) set no user
1786
+ * GUC — which also lets the owner connection satisfy these policies even under
1787
+ * FORCE RLS. A *user* request never reaches that state: an anonymous one carries
1788
+ * `ANONYMOUS_USER_ID`, precisely so it cannot pass for the server here.
1789
+ *
1790
+ * Opt out with `disableDefaultPolicies: true` to take full responsibility for
1791
+ * the collection's RLS.
1792
+ */
1793
+ var SERVER_OR_ADMIN_EXPR$1 = policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
1794
+ /** Write operations that must be admin-gated by default on auth collections. */
1795
+ var DEFAULT_GUARDED_OPS = [
1796
+ "insert",
1797
+ "update",
1798
+ "delete"
1799
+ ];
1800
+ /** Whether a collection is flagged as an authentication collection. */
1801
+ function isAuthCollection(collection) {
1802
+ const auth = collection.auth;
1803
+ return auth === true || typeof auth === "object" && auth?.enabled === true;
1804
+ }
1805
+ /** The property marked as the row id (falls back to `id`). */
1806
+ function getIdPropertyName(collection) {
1807
+ for (const [name, prop] of Object.entries(collection.properties ?? {})) if (prop && typeof prop === "object" && "isId" in prop && prop.isId) return name;
1808
+ return "id";
1809
+ }
1810
+ /**
1811
+ * Returns the security rules that should be applied to a collection: the
1812
+ * author's explicit `securityRules` plus the framework defaults described in
1813
+ * the module doc (baseline server/admin read for all collections; self-read
1814
+ * and the admin write gate for auth collections).
1815
+ *
1816
+ * Collections that opt out via `disableDefaultPolicies` are returned unchanged.
1817
+ */
1818
+ function getEffectiveSecurityRules(collection) {
1819
+ const explicit = [...collection.securityRules ?? []];
1820
+ if (isPostgresCollectionConfig(collection) && collection.disableDefaultPolicies) return explicit;
1821
+ const tableName = getTableName(collection);
1822
+ const injected = [];
1823
+ injected.push({
1824
+ name: `${tableName}_default_admin_read`,
1825
+ operations: ["select"],
1826
+ condition: SERVER_OR_ADMIN_EXPR$1
1827
+ });
1828
+ injected.push({
1829
+ name: `${tableName}_default_admin_write`,
1830
+ operations: [...DEFAULT_GUARDED_OPS],
1831
+ condition: SERVER_OR_ADMIN_EXPR$1,
1832
+ check: SERVER_OR_ADMIN_EXPR$1
1833
+ });
1834
+ if (isAuthCollection(collection)) {
1835
+ injected.push({
1836
+ name: `${tableName}_default_self_read`,
1837
+ operations: ["select"],
1838
+ condition: policy.compare(policy.field(getIdPropertyName(collection)), "eq", policy.authUid())
1839
+ });
1840
+ injected.push({
1841
+ name: `${tableName}_require_admin_write`,
1842
+ mode: "restrictive",
1843
+ operations: [...DEFAULT_GUARDED_OPS],
1844
+ condition: SERVER_OR_ADMIN_EXPR$1,
1845
+ check: SERVER_OR_ADMIN_EXPR$1
1846
+ });
1847
+ }
1848
+ return [...explicit, ...injected];
1849
+ }
1385
1850
  policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
1386
1851
  (/* @__PURE__ */ __commonJSMin(((exports, module) => {
1387
1852
  (function(root, factory) {
@@ -1660,7 +2125,7 @@ policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
1660
2125
  * Apply PropertyConditions to a resolved property, evaluating all JSON Logic rules.
1661
2126
  */
1662
2127
  //#endregion
1663
- //#region ../../node_modules/.pnpm/fast-equals@6.0.0/node_modules/fast-equals/dist/es/index.mjs
2128
+ //#region ../../node_modules/.pnpm/fast-equals@6.0.2/node_modules/fast-equals/dist/es/index.mjs
1664
2129
  var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
1665
2130
  var { hasOwnProperty } = Object.prototype;
1666
2131
  /**
@@ -1696,7 +2161,8 @@ function createIsCircular(areItemsEqual) {
1696
2161
  * not enumerable and symbol properties.
1697
2162
  */
1698
2163
  function getStrictProperties(object) {
1699
- return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
2164
+ const symbols = getOwnPropertySymbols(object);
2165
+ return symbols.length ? getOwnPropertyNames(object).concat(symbols) : getOwnPropertyNames(object);
1700
2166
  }
1701
2167
  /**
1702
2168
  * Whether the object contains the property passed as an own property.
@@ -1769,7 +2235,7 @@ function areMapsEqual(a, b, state) {
1769
2235
  const size = a.size;
1770
2236
  if (size !== b.size) return false;
1771
2237
  if (!size) return true;
1772
- const matchedIndices = new Array(size);
2238
+ const matchedIndices = new Uint8Array(size);
1773
2239
  const aIterable = a.entries();
1774
2240
  let aResult;
1775
2241
  let bResult;
@@ -1777,7 +2243,7 @@ function areMapsEqual(a, b, state) {
1777
2243
  while (aResult = aIterable.next()) {
1778
2244
  if (aResult.done) break;
1779
2245
  const bIterable = b.entries();
1780
- let hasMatch = false;
2246
+ let hasMatch = 0;
1781
2247
  let matchIndex = 0;
1782
2248
  while (bResult = bIterable.next()) {
1783
2249
  if (bResult.done) break;
@@ -1788,7 +2254,7 @@ function areMapsEqual(a, b, state) {
1788
2254
  const aEntry = aResult.value;
1789
2255
  const bEntry = bResult.value;
1790
2256
  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)) {
1791
- hasMatch = matchedIndices[matchIndex] = true;
2257
+ hasMatch = matchedIndices[matchIndex] = 1;
1792
2258
  break;
1793
2259
  }
1794
2260
  matchIndex++;
@@ -1846,19 +2312,19 @@ function areSetsEqual(a, b, state) {
1846
2312
  const size = a.size;
1847
2313
  if (size !== b.size) return false;
1848
2314
  if (!size) return true;
1849
- const matchedIndices = new Array(size);
2315
+ const matchedIndices = new Uint8Array(size);
1850
2316
  const aIterable = a.values();
1851
2317
  let aResult;
1852
2318
  let bResult;
1853
2319
  while (aResult = aIterable.next()) {
1854
2320
  if (aResult.done) break;
1855
2321
  const bIterable = b.values();
1856
- let hasMatch = false;
2322
+ let hasMatch = 0;
1857
2323
  let matchIndex = 0;
1858
2324
  while (bResult = bIterable.next()) {
1859
2325
  if (bResult.done) break;
1860
2326
  if (!matchedIndices[matchIndex] && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
1861
- hasMatch = matchedIndices[matchIndex] = true;
2327
+ hasMatch = matchedIndices[matchIndex] = 1;
1862
2328
  break;
1863
2329
  }
1864
2330
  matchIndex++;
@@ -1871,8 +2337,8 @@ function areSetsEqual(a, b, state) {
1871
2337
  * Whether the TypedArray instances are equal in value.
1872
2338
  */
1873
2339
  function areTypedArraysEqual(a, b) {
1874
- let index = a.byteLength;
1875
- if (b.byteLength !== index || a.byteOffset !== b.byteOffset) return false;
2340
+ let index = a.length;
2341
+ if (b.length !== index || a.byteOffset !== b.byteOffset) return false;
1876
2342
  while (index-- > 0) if (a[index] !== b[index]) return false;
1877
2343
  return true;
1878
2344
  }
@@ -2885,7 +3351,7 @@ function rowToEntity(row, slug, primaryKeys = []) {
2885
3351
  };
2886
3352
  }
2887
3353
  /**
2888
- * The relation envelope `toCmsRow` writes where a relation was:
3354
+ * The relation envelope `toFlatRow` writes where a relation was:
2889
3355
  * `{ id, path, __type: "relation", data: { id, path, values } }`. It is the
2890
3356
  * admin's view-model, and the only pipeline that produces one is postgres'.
2891
3357
  */
@@ -3306,57 +3772,6 @@ function buildRoutedRebaseData({ defaultData, sources, resolveKey }) {
3306
3772
  } });
3307
3773
  }
3308
3774
  //#endregion
3309
- //#region ../common/src/data/sort-dialect.ts
3310
- /**
3311
- * Sort-order wire codec.
3312
- *
3313
- * This is the ONLY module that knows about the colon-delimited wire format
3314
- * (`"field:direction"`) used in HTTP query parameters.
3315
- * Everything else speaks {@link OrderByTuple} exclusively.
3316
- *
3317
- * Mirrors the filter architecture in `filter-dialect.ts`.
3318
- *
3319
- * @module
3320
- */
3321
- /**
3322
- * Serialize an {@link OrderByTuple} to the wire format `"field:direction"`.
3323
- *
3324
- * **Runtime tolerance:** if the input is already a well-formed wire string
3325
- * (from an untyped JS caller), it is returned unchanged.
3326
- * This is undocumented tolerance, not public API — don't rely on it.
3327
- *
3328
- * @param orderBy - A canonical `[field, direction]` tuple, or at runtime
3329
- * possibly a pre-serialized string (undocumented tolerance).
3330
- * @returns The wire-format string, or `undefined` if the input is falsy.
3331
- *
3332
- * @remarks
3333
- * Field names containing `:` are representable in the tuple form but
3334
- * **not** on the wire — this is an inherent limitation of the colon-delimited
3335
- * encoding and is not resolved here.
3336
- */
3337
- function serializeOrderBy(orderBy) {
3338
- if (!orderBy) return void 0;
3339
- if (typeof orderBy === "string") return orderBy;
3340
- return `${orderBy[0]}:${orderBy[1]}`;
3341
- }
3342
- /**
3343
- * Deserialize a wire-format `"field:direction"` string into an {@link OrderByTuple}.
3344
- *
3345
- * Lenient parsing (matches existing server behaviour):
3346
- * - Bare field name (no colon): `"name"` → `["name", "asc"]`
3347
- * - Unknown direction: `"name:foo"` → `["name", "asc"]`
3348
- * - Empty / falsy input: → `undefined`
3349
- *
3350
- * @param raw - The wire-format string from an HTTP query parameter.
3351
- * @returns The canonical tuple, or `undefined` if the input is empty/falsy.
3352
- */
3353
- function deserializeOrderBy(raw) {
3354
- if (!raw) return void 0;
3355
- const idx = raw.indexOf(":");
3356
- if (idx === -1) return [raw, "asc"];
3357
- return [raw.slice(0, idx), raw.slice(idx + 1) === "desc" ? "desc" : "asc"];
3358
- }
3359
- //#endregion
3360
- export { toSnakeCase as _, deserializeFilter as a, serializeLogicalCondition as c, CollectionRegistry as d, createDataSourceRegistry as f, buildCompositeId as g, resolveCollectionRelations as h, buildSdkData as i, collectAllPages as l, findRelation as m, serializeOrderBy as n, deserializeLogicalCondition as o, resolveDataSource as p, buildRoutedRebaseData as r, serializeFilter as s, deserializeOrderBy as t, paginateFind as u };
3775
+ export { Vector as S, ANONYMOUS_USER_ID as _, serializeFilter as a, EntityRelation as b, paginateFind as c, resolveDataSource as d, getEffectiveSecurityRules as f, toSnakeCase as g, buildCompositeId as h, deserializeLogicalCondition as i, CollectionRegistry as l, resolveCollectionRelations as m, buildSdkData as n, serializeLogicalCondition as o, findRelation as p, deserializeFilter as r, collectAllPages as s, buildRoutedRebaseData as t, createDataSourceRegistry as u, isAnonymousUid as v, GeoPoint as x, EntityReference as y };
3361
3776
 
3362
- //# sourceMappingURL=src-CoOAMnBh.js.map
3777
+ //# sourceMappingURL=src-Cum9kox5.js.map