@rebasepro/types 0.17.3 → 0.18.1

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 (71) hide show
  1. package/README.md +4 -0
  2. package/dist/call_context.d.ts +20 -0
  3. package/dist/controllers/client.d.ts +36 -4
  4. package/dist/controllers/data.d.ts +120 -10
  5. package/dist/errors.d.ts +83 -4
  6. package/dist/index.es.js +522 -160
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/types/admin_block.d.ts +2 -2
  9. package/dist/types/auth_adapter.d.ts +41 -6
  10. package/dist/types/backend.d.ts +48 -0
  11. package/dist/types/collections.d.ts +25 -1
  12. package/dist/types/cron.d.ts +34 -0
  13. package/dist/types/database_adapter.d.ts +39 -0
  14. package/dist/types/entity_callbacks.d.ts +14 -1
  15. package/dist/types/filter-operators.d.ts +24 -1
  16. package/dist/types/policy.d.ts +29 -1
  17. package/dist/types/properties.d.ts +216 -3
  18. package/dist/types/relations.d.ts +65 -7
  19. package/dist/types/resource_kinds.d.ts +173 -17
  20. package/dist/types/resources.d.ts +108 -7
  21. package/dist/types/rls-functions.d.ts +11 -0
  22. package/dist/types/storage_source.d.ts +12 -23
  23. package/package.json +24 -23
  24. package/src/call_context.ts +0 -120
  25. package/src/controllers/auth_state.ts +0 -24
  26. package/src/controllers/client.ts +0 -494
  27. package/src/controllers/collection_registry.ts +0 -62
  28. package/src/controllers/data.ts +0 -1012
  29. package/src/controllers/data_driver.ts +0 -576
  30. package/src/controllers/effective_role.ts +0 -4
  31. package/src/controllers/email.ts +0 -91
  32. package/src/controllers/index.ts +0 -11
  33. package/src/controllers/storage.ts +0 -252
  34. package/src/errors.ts +0 -119
  35. package/src/index.ts +0 -5
  36. package/src/types/admin_block.ts +0 -209
  37. package/src/types/api_keys.ts +0 -108
  38. package/src/types/auth_adapter.ts +0 -580
  39. package/src/types/backend.ts +0 -987
  40. package/src/types/backup.ts +0 -26
  41. package/src/types/channel_bus.ts +0 -202
  42. package/src/types/chips.ts +0 -34
  43. package/src/types/collection_contract.ts +0 -278
  44. package/src/types/collections.ts +0 -763
  45. package/src/types/component_ref.ts +0 -92
  46. package/src/types/cron.ts +0 -213
  47. package/src/types/data_source.ts +0 -357
  48. package/src/types/database_adapter.ts +0 -267
  49. package/src/types/entities.ts +0 -226
  50. package/src/types/entity_callbacks.ts +0 -229
  51. package/src/types/filter-operators.ts +0 -444
  52. package/src/types/history.ts +0 -66
  53. package/src/types/index.ts +0 -36
  54. package/src/types/indexes.ts +0 -180
  55. package/src/types/policy.ts +0 -328
  56. package/src/types/postgres_introspection.ts +0 -101
  57. package/src/types/project_manifest.ts +0 -598
  58. package/src/types/properties.ts +0 -1368
  59. package/src/types/relations.ts +0 -417
  60. package/src/types/resource_kinds.ts +0 -390
  61. package/src/types/resources.ts +0 -368
  62. package/src/types/rls-functions.ts +0 -98
  63. package/src/types/schema_editing.ts +0 -157
  64. package/src/types/schema_version.ts +0 -112
  65. package/src/types/search.ts +0 -247
  66. package/src/types/security_rules.ts +0 -344
  67. package/src/types/storage_authorize.ts +0 -77
  68. package/src/types/storage_source.ts +0 -248
  69. package/src/types/websockets.ts +0 -117
  70. package/src/users/index.ts +0 -2
  71. package/src/users/user.ts +0 -69
package/dist/index.es.js CHANGED
@@ -30,12 +30,18 @@ var RebaseApiError = class extends Error {
30
30
  code;
31
31
  /** Structured error payload from the server, when present. */
32
32
  details;
33
+ /** See {@link RebaseErrorInit.requestId}. Quote it in a bug report. */
34
+ requestId;
35
+ /** See {@link RebaseErrorInit.retryAfterSeconds}. */
36
+ retryAfterSeconds;
33
37
  constructor(message, init = {}) {
34
38
  super(message);
35
39
  this.name = "RebaseApiError";
36
40
  this.status = init.status;
37
41
  this.code = init.code;
38
42
  this.details = init.details;
43
+ this.requestId = init.requestId;
44
+ this.retryAfterSeconds = init.retryAfterSeconds;
39
45
  if (init.cause !== void 0) this.cause = init.cause;
40
46
  }
41
47
  };
@@ -49,11 +55,76 @@ var RebaseApiError = class extends Error {
49
55
  * @group Errors
50
56
  */
51
57
  var RebaseClientError = class extends RebaseApiError {
52
- constructor(message) {
53
- super(message);
58
+ /**
59
+ * `init` is the same one {@link RebaseApiError} takes, and it is what makes
60
+ * `code` reachable at all.
61
+ *
62
+ * The constructor used to accept a message and nothing else, so every
63
+ * client-side failure — an undefined filter value, an unknown accessor,
64
+ * `listen()` on a client built with `realtime: false`, a function name with
65
+ * a `/` in it, `refreshSession()` while signed out — arrived with `code ===
66
+ * undefined`. The documented `switch (e.code)` in this file's own example
67
+ * fell to `default: throw e` for all of them, and the only client-side error
68
+ * that *did* carry a code was `OFFLINE`, because that one path minted a
69
+ * `RebaseApiError` instead.
70
+ */
71
+ constructor(message, init = {}) {
72
+ super(message, init);
54
73
  this.name = "RebaseClientError";
55
74
  }
56
75
  };
76
+ /**
77
+ * Brand for a contract method a particular client cannot serve.
78
+ *
79
+ * `Symbol.for` rather than a fresh symbol: two copies of `@rebasepro/types` in
80
+ * one tree — which happens, see `docs/dependency-duplication-traps.md` — must
81
+ * agree about it, and a module-local symbol would not.
82
+ */
83
+ var UNSUPPORTED_METHOD = Symbol.for("rebase.unsupportedMethod");
84
+ /**
85
+ * Build the stub a client installs for a contract method it cannot serve.
86
+ *
87
+ * `listen`, `listenById` and `count` are part of `SDKCollectionClient`, not
88
+ * optional extras — a caller should be able to write
89
+ * `client.data.posts.count()` without asking first, and a transport that cannot
90
+ * serve it should answer with a sentence naming the configuration that would,
91
+ * rather than with `undefined is not a function` at the call site. Where the
92
+ * transport genuinely cannot (a client built with `realtime: false`, a driver
93
+ * with no `listenCollection`), it installs one of these instead of omitting the
94
+ * method.
95
+ *
96
+ * @param message What to tell the caller, naming the fix.
97
+ * @group Errors
98
+ */
99
+ function unsupportedMethod(message) {
100
+ const stub = () => {
101
+ throw new RebaseClientError(message, { code: "REALTIME_DISABLED" });
102
+ };
103
+ stub[UNSUPPORTED_METHOD] = true;
104
+ return stub;
105
+ }
106
+ /**
107
+ * Can this method actually do anything?
108
+ *
109
+ * `true` for a stub from {@link unsupportedMethod} **and** for a method that is
110
+ * simply not there — a partial client, a hand-built test double, an
111
+ * implementation written against an older shape of the interface. Both mean the
112
+ * same thing to a caller, so both answer the same way, and an adapter that
113
+ * checks this cannot be caught out by either.
114
+ *
115
+ * Ordinary code does not need it: calling the method and letting it throw is
116
+ * the normal path. Adapters do — the admin panel chooses between subscribing
117
+ * and a one-shot `find()` by asking whether the client can listen, and a UI
118
+ * that subscribes into a throw is worse than one that polls. This is the
119
+ * question `if (accessor.listen)` used to be asking, made explicit now that the
120
+ * method is always there to call.
121
+ *
122
+ * @group Errors
123
+ */
124
+ function isUnsupported(method) {
125
+ if (typeof method !== "function") return true;
126
+ return method[UNSUPPORTED_METHOD] === true;
127
+ }
57
128
  //#endregion
58
129
  //#region src/types/entities.ts
59
130
  /**
@@ -363,6 +434,7 @@ var ADMIN_COLLECTION_KEYS = [
363
434
  "Actions",
364
435
  "additionalFields",
365
436
  "alwaysApplyDefaultValues",
437
+ "browserCallbacks",
366
438
  "components",
367
439
  "customViews",
368
440
  "defaultEntityAction",
@@ -430,6 +502,7 @@ var ADMIN_PROPERTY_KEYS = [
430
502
  "Filter",
431
503
  "filterOperators",
432
504
  "fixedFilter",
505
+ "format",
433
506
  "hideFromCollection",
434
507
  "includeEntityLink",
435
508
  "includeId",
@@ -440,6 +513,7 @@ var ADMIN_PROPERTY_KEYS = [
440
513
  "previewAsTag",
441
514
  "previewProperties",
442
515
  "readOnly",
516
+ "renderInForm",
443
517
  "sortable",
444
518
  "span",
445
519
  "spreadChildren",
@@ -821,6 +895,7 @@ var policy = {
821
895
  roles
822
896
  }),
823
897
  authenticated: () => ({ kind: "authenticated" }),
898
+ registered: () => ({ kind: "registered" }),
824
899
  serverContext: () => ({ kind: "serverContext" }),
825
900
  existsIn: (args) => ({
826
901
  kind: "existsIn",
@@ -906,6 +981,17 @@ var REBASE_SCHEMA = "rebase";
906
981
  var RLS_UID_SQL = `${REBASE_SCHEMA}.uid()`;
907
982
  /** The request's roles as a comma-separated string, for `string_to_array`. */
908
983
  var RLS_ROLES_SQL = `${REBASE_SCHEMA}.roles()`;
984
+ /**
985
+ * Whether the caller is a GUEST — signed in through anonymous sign-in rather
986
+ * than with an account.
987
+ *
988
+ * A different question from {@link ANONYMOUS_USER_ID}, and the two are easy to
989
+ * confuse: that sentinel means "no session at all", while this means "a session
990
+ * with nobody behind it". Anonymous sign-in mints a real user row with a real
991
+ * uid, so before this reached the database the two kinds of caller were one
992
+ * principal inside every policy.
993
+ */
994
+ var RLS_IS_ANONYMOUS_SQL = `${REBASE_SCHEMA}.is_anonymous()`;
909
995
  /** The request's JWT claims as `jsonb`, or `{}`. */
910
996
  var RLS_JWT_SQL = `${REBASE_SCHEMA}.jwt()`;
911
997
  /**
@@ -1015,36 +1101,170 @@ function isResourceHandle(value) {
1015
1101
  function resourceKeyOf(ref) {
1016
1102
  return isResourceHandle(ref) ? ref.key : ref;
1017
1103
  }
1104
+ /**
1105
+ * Replace every resource handle inside a value with its key, deeply.
1106
+ *
1107
+ * Applied where authored config becomes data: `defineCollection`, the
1108
+ * collection loaders, the derive step. Past that point a collection is plain
1109
+ * data that serialises, compares with `===` and reaches the admin UI over the
1110
+ * wire, so a handle must not survive into it. Plain objects and arrays are
1111
+ * walked; anything else — a function, a Date, a class instance — is a leaf and
1112
+ * is returned as it is, which is what keeps callbacks and validators intact.
1113
+ */
1114
+ function resolveResourceRefs(value) {
1115
+ if (isResourceHandle(value)) return value.key;
1116
+ if (Array.isArray(value)) {
1117
+ let changed = false;
1118
+ const out = value.map((item) => {
1119
+ const next = resolveResourceRefs(item);
1120
+ if (next !== item) changed = true;
1121
+ return next;
1122
+ });
1123
+ return changed ? out : value;
1124
+ }
1125
+ if (value !== null && typeof value === "object") {
1126
+ const proto = Object.getPrototypeOf(value);
1127
+ if (proto === Object.prototype || proto === null) {
1128
+ let changed = false;
1129
+ const out = {};
1130
+ for (const [k, v] of Object.entries(value)) {
1131
+ const next = resolveResourceRefs(v);
1132
+ if (next !== v) changed = true;
1133
+ out[k] = next;
1134
+ }
1135
+ return changed ? out : value;
1136
+ }
1137
+ }
1138
+ return value;
1139
+ }
1018
1140
  var GLOBAL_KEY = Symbol.for("@rebasepro/types.resourceRegistry");
1141
+ /**
1142
+ * Where kinds live, versioned — and why the version is in the symbol.
1143
+ *
1144
+ * Sharing one kinds map across copies means the copy that registers SECOND is
1145
+ * the one that runs the comparison. That copy is whatever the bundle happens to
1146
+ * carry, which for a driver is a build of this package frozen at its release —
1147
+ * so the rule enforced is the rule that shipped THEN, not the one written here.
1148
+ *
1149
+ * `revision` (390bb03cd, applied to `database` in 346df48e2) was supposed to
1150
+ * settle a disagreement between two copies, and it settles it only when the
1151
+ * copy doing the arithmetic knows what `revision` is. 0.17.0–0.17.3 do not:
1152
+ * they deep-equal the spec and throw. The runtime registers at import and a
1153
+ * driver is imported after it, so the old copy is always second, always the
1154
+ * judge, and always throws — verified by the bundle corpus on 2026-09-07,
1155
+ * which reported v0.17.3's message verbatim ("Two packages cannot define the
1156
+ * same kind.", no revision clause) while the runtime it ran on was 0.18.
1157
+ *
1158
+ * So copies that understand `revision` keep their kinds here, under a symbol
1159
+ * no released copy looks at, and the legacy map is left to whoever still wants
1160
+ * it. An old copy then registers into a map nobody contests, finds no existing
1161
+ * entry, and cannot throw — in any load order, which is what the previous fix
1162
+ * only claimed. Bumping this suffix again is how a future change to the
1163
+ * REGISTRATION PROTOCOL is made; a change to a kind's own definition is still
1164
+ * `revision`, among peers that share this map.
1165
+ */
1166
+ var KINDS_KEY = Symbol.for("@rebasepro/types.resourceKinds.v2");
1019
1167
  function registry() {
1020
1168
  const g = globalThis;
1021
- let existing = g[GLOBAL_KEY];
1022
- if (!existing) {
1023
- existing = {
1169
+ let shared = g[GLOBAL_KEY];
1170
+ if (!shared) {
1171
+ shared = {
1024
1172
  kinds: /* @__PURE__ */ new Map(),
1025
1173
  declarations: /* @__PURE__ */ new Map()
1026
1174
  };
1027
- g[GLOBAL_KEY] = existing;
1175
+ g[GLOBAL_KEY] = shared;
1028
1176
  }
1029
- return existing;
1177
+ let kinds = g[KINDS_KEY];
1178
+ if (!kinds) {
1179
+ kinds = /* @__PURE__ */ new Map();
1180
+ g[KINDS_KEY] = kinds;
1181
+ }
1182
+ return {
1183
+ kinds,
1184
+ legacyKinds: shared.kinds,
1185
+ declarations: shared.declarations
1186
+ };
1187
+ }
1188
+ /**
1189
+ * Every kind visible to this copy: the versioned map, plus anything only a
1190
+ * legacy copy registered.
1191
+ *
1192
+ * The fallback is not for Rebase's own kinds — this copy defines all of those —
1193
+ * but for a third-party driver built against an older `@rebasepro/types` that
1194
+ * registers a kind of its own. Dropping it would make that kind invisible and
1195
+ * turn `declareResource` into "unknown resource kind" for something genuinely
1196
+ * registered.
1197
+ */
1198
+ function visibleKinds() {
1199
+ const { kinds, legacyKinds } = registry();
1200
+ if (legacyKinds.size === 0) return kinds;
1201
+ const merged = new Map(legacyKinds);
1202
+ for (const [k, v] of kinds) merged.set(k, v);
1203
+ return merged;
1204
+ }
1205
+ var amendments = /* @__PURE__ */ new Map();
1206
+ /**
1207
+ * Correct a registered kind without touching its registered literal.
1208
+ *
1209
+ * Use this, never an edit to the literal, for a kind that has shipped in a
1210
+ * published package. The amendment applies to reads through this copy only.
1211
+ */
1212
+ function amendResourceKind(kind, amendment) {
1213
+ amendments.set(kind, {
1214
+ ...amendments.get(kind),
1215
+ ...amendment
1216
+ });
1217
+ }
1218
+ /** A registered kind as this copy sees it: the shared literal plus this copy's amendments. */
1219
+ function effectiveKind(spec) {
1220
+ const amendment = amendments.get(spec.kind);
1221
+ return amendment ? {
1222
+ ...spec,
1223
+ ...amendment
1224
+ } : spec;
1030
1225
  }
1031
1226
  /** `kind:key`, the graph's primary key. */
1032
1227
  function declarationId(kind, key) {
1033
1228
  return `${kind}:${key}`;
1034
1229
  }
1035
- /** Register a resource kind. Idempotent for an identical spec; throws on a conflicting one. */
1230
+ /**
1231
+ * Register a resource kind.
1232
+ *
1233
+ * Idempotent for an identical spec. When a spec for the same kind is already
1234
+ * registered and differs, the `revision` decides: the higher one is kept and
1235
+ * the other copy is warned about, in either load order. Two different specs at
1236
+ * the SAME revision are a genuine conflict — two packages defining one kind, or
1237
+ * a change that forgot to bump — and still throw.
1238
+ *
1239
+ * Both copies in that comparison are peers on `KINDS_KEY`, which is what makes
1240
+ * the rule enforceable: a copy old enough not to know `revision` writes to the
1241
+ * legacy map instead and never reaches this function's arithmetic. Registering
1242
+ * a kind an older copy already put in the legacy map is therefore not a
1243
+ * conflict — it is the ordinary case, and `visibleKinds` prefers this one.
1244
+ */
1036
1245
  function registerResourceKind(spec) {
1037
- const existing = registry().kinds.get(spec.kind);
1038
- if (existing && JSON.stringify(existing) !== JSON.stringify(spec)) throw new Error(`Resource kind "${spec.kind}" is already registered with a different definition. Two packages cannot define the same kind.`);
1039
- registry().kinds.set(spec.kind, spec);
1246
+ const kinds = registry().kinds;
1247
+ const existing = kinds.get(spec.kind);
1248
+ if (!existing) {
1249
+ kinds.set(spec.kind, spec);
1250
+ return;
1251
+ }
1252
+ if (JSON.stringify(existing) === JSON.stringify(spec)) return;
1253
+ const have = existing.revision ?? 0;
1254
+ const incoming = spec.revision ?? 0;
1255
+ if (have === incoming) throw new Error(`Resource kind "${spec.kind}" is already registered with a different definition at revision ${have}. Two packages cannot define the same kind; a newer definition of the same kind must carry a higher \`revision\`.`);
1256
+ const [kept, dropped] = incoming > have ? [spec, existing] : [existing, spec];
1257
+ if (kept === spec) kinds.set(spec.kind, spec);
1258
+ console.warn(`[resources] Resource kind "${spec.kind}" is registered twice, at revisions ${dropped.revision ?? 0} and ${kept.revision ?? 0}; keeping revision ${kept.revision ?? 0}. The older copy is usually @rebasepro/types inlined in a driver built before the kind changed — rebuild the project with a current driver to remove it.`);
1040
1259
  }
1041
1260
  /** Every registered kind, for validators and for `rebase doctor`. */
1042
1261
  function resourceKinds() {
1043
- return [...registry().kinds.values()];
1262
+ return [...visibleKinds().values()].map(effectiveKind);
1044
1263
  }
1045
1264
  /** One registered kind, or undefined. */
1046
1265
  function resourceKind(kind) {
1047
- return registry().kinds.get(kind);
1266
+ const spec = visibleKinds().get(kind);
1267
+ return spec && effectiveKind(spec);
1048
1268
  }
1049
1269
  var COMMON_OPTION_KEYS = [
1050
1270
  "engine",
@@ -1065,9 +1285,9 @@ function isValidEngine(spec, engine) {
1065
1285
  * fine: a config module evaluated twice must not be an error.
1066
1286
  */
1067
1287
  function declareResource(kind, key = DEFAULT_RESOURCE_KEY, options = {}) {
1068
- const spec = registry().kinds.get(kind);
1288
+ const spec = resourceKind(kind);
1069
1289
  if (!spec) {
1070
- const known = [...registry().kinds.keys()].sort().join(", ") || "none";
1290
+ const known = [...visibleKinds().keys()].sort().join(", ") || "none";
1071
1291
  throw new Error(`Unknown resource kind "${kind}". Registered kinds: ${known}. Call registerResourceKind() before declaring one.`);
1072
1292
  }
1073
1293
  if (!key || typeof key !== "string" || key.trim() === "") throw new Error(`A ${kind} needs a non-empty key.`);
@@ -1149,13 +1369,29 @@ function findEnvSuffixCollision(keys) {
1149
1369
  }
1150
1370
  /** The current graph format version. */
1151
1371
  var RESOURCE_GRAPH_VERSION = 1;
1152
- /** Build a graph from the current declarations, sorted for a stable diff. */
1153
- function buildResourceGraph() {
1372
+ /**
1373
+ * Build a graph from the current declarations, sorted for a stable diff.
1374
+ *
1375
+ * `usedBy` maps a `kind:key` id to the things that reach it. The derive step
1376
+ * supplies it after evaluating collections; a runtime building the graph at
1377
+ * boot passes nothing and gets declarations alone, which is all it binds from.
1378
+ */
1379
+ function buildResourceGraph(usedBy) {
1154
1380
  return {
1155
1381
  version: 1,
1156
- resources: declaredResources().slice().sort((a, b) => a.kind.localeCompare(b.kind) || a.key.localeCompare(b.key))
1382
+ resources: declaredResources().slice().sort((a, b) => a.kind.localeCompare(b.kind) || a.key.localeCompare(b.key)).map((r) => {
1383
+ const users = usedBy?.get(declarationId(r.kind, r.key));
1384
+ return users && users.length > 0 ? {
1385
+ ...r,
1386
+ usedBy: [...users].sort()
1387
+ } : r;
1388
+ })
1157
1389
  };
1158
1390
  }
1391
+ /** `kind:key`, the id `usedBy` maps are keyed by. Exported for the derive step. */
1392
+ function resourceId(kind, key) {
1393
+ return declarationId(kind, key);
1394
+ }
1159
1395
  /**
1160
1396
  * The environment variables worth writing for a resource, given its engine.
1161
1397
  *
@@ -1169,6 +1405,78 @@ function envBasesForResource(declaration) {
1169
1405
  return spec.envBasesByEngine?.[declaration.engine] ?? spec.envBases;
1170
1406
  }
1171
1407
  //#endregion
1408
+ //#region src/types/storage_source.ts
1409
+ /**
1410
+ * Describes a named storage backend — a place files live.
1411
+ *
1412
+ * Declared once and shared front + back: the frontend uses it to decide
1413
+ * transport (HTTP proxy vs direct SDK), the backend uses the same `key`
1414
+ * to resolve a StorageController, and collection properties reference
1415
+ * a definition by its `key` via `StorageConfig.storageSource`.
1416
+ *
1417
+ * This mirrors the {@link DataSourceDefinition} pattern used for databases.
1418
+ *
1419
+ * @group Models
1420
+ */
1421
+ /**
1422
+ * The default storage source key, used when a property does not specify
1423
+ * a `storageSource`. Shared by the frontend and backend registries so
1424
+ * both agree on "the default storage backend".
1425
+ * @group Models
1426
+ */
1427
+ var DEFAULT_STORAGE_SOURCE_KEY = "(default)";
1428
+ /**
1429
+ * The environment-variable suffix for a storage or data source key.
1430
+ *
1431
+ * `""` for the default source — so a single-bucket project keeps configuring
1432
+ * plain `S3_BUCKET` — and `__<KEY>` for every named one, uppercased with
1433
+ * non-alphanumerics collapsed to underscores: `media-cdn` → `S3_BUCKET__MEDIA_CDN`.
1434
+ *
1435
+ * The rule derives the variable name from the declared key rather than
1436
+ * discovering keys by scanning the environment. Scanning would have to guess how
1437
+ * `S3_BUCKET__MEDIA_CDN` splits into a key; deriving cannot be ambiguous, and a
1438
+ * typo surfaces as a missing source at boot instead of a silently ignored
1439
+ * variable.
1440
+ *
1441
+ * It lives in this package, with no dependencies, because four things must agree
1442
+ * on it exactly: the CLI (validating a build), the runtime (reading its own
1443
+ * environment), the control plane (writing a tenant's Secret), and the docs. A
1444
+ * second implementation of a naming convention is a second chance to disagree.
1445
+ *
1446
+ * @group Models
1447
+ */
1448
+ function storageEnvSuffix(key, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
1449
+ if (!key || key === defaultKey) return "";
1450
+ const normalized = key.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1451
+ if (!normalized) throw new Error(`Source key "${key}" cannot be turned into an environment variable name. Use a key containing at least one letter or digit.`);
1452
+ return `__${normalized}`;
1453
+ }
1454
+ /**
1455
+ * Two distinct keys that collapse onto the same variable name, or `null`.
1456
+ *
1457
+ * `media-cdn` and `media_cdn` are different source keys but the same suffix, so
1458
+ * without this one of them silently reads the other's configuration. Returns the
1459
+ * offending pair rather than throwing, so each caller can raise it in its own
1460
+ * idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy
1461
+ * in a control plane.
1462
+ *
1463
+ * @group Models
1464
+ */
1465
+ function findStorageSuffixCollision(keys, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
1466
+ const seen = /* @__PURE__ */ new Map();
1467
+ for (const key of keys) {
1468
+ const suffix = storageEnvSuffix(key, defaultKey);
1469
+ const existing = seen.get(suffix);
1470
+ if (existing !== void 0 && existing !== key) return {
1471
+ a: existing,
1472
+ b: key,
1473
+ suffix
1474
+ };
1475
+ seen.set(suffix, key);
1476
+ }
1477
+ return null;
1478
+ }
1479
+ //#endregion
1172
1480
  //#region src/types/resource_kinds.ts
1173
1481
  /**
1174
1482
  * The kinds Rebase ships, and the constructors a project declares them with.
@@ -1184,6 +1492,7 @@ function envBasesForResource(declaration) {
1184
1492
  * instead of looking like a typo of one that exists.
1185
1493
  */
1186
1494
  registerResourceKind({
1495
+ revision: 1,
1187
1496
  kind: "database",
1188
1497
  engines: [
1189
1498
  "postgres",
@@ -1204,6 +1513,15 @@ registerResourceKind({
1204
1513
  ],
1205
1514
  implicitDefault: true
1206
1515
  });
1516
+ amendResourceKind("database", { envBases: [
1517
+ "DATABASE_URL",
1518
+ "DATABASE_READ_URL",
1519
+ "ADMIN_CONNECTION_STRING",
1520
+ "REBASE_DRIVER",
1521
+ "DB_POOL_MAX",
1522
+ "DB_POOL_IDLE_TIMEOUT",
1523
+ "DB_POOL_CONNECT_TIMEOUT"
1524
+ ] });
1207
1525
  function database(keyOrOptions = DEFAULT_RESOURCE_KEY, options = {}) {
1208
1526
  return typeof keyOrOptions === "string" ? declareResource("database", keyOrOptions, options) : declareResource("database", DEFAULT_RESOURCE_KEY, keyOrOptions);
1209
1527
  }
@@ -1263,18 +1581,49 @@ registerResourceKind({
1263
1581
  ],
1264
1582
  implicitDefault: false
1265
1583
  });
1266
- /**
1267
- * Declare a bucket.
1268
- *
1269
- * ```ts
1270
- * export const media = bucket("media", { transport: "direct" });
1271
- * ```
1272
- *
1273
- * `transport: "direct"` means a provider SDK talks to the bucket and the
1274
- * backend is not in the upload path.
1275
- */
1276
- function bucket(key = DEFAULT_RESOURCE_KEY, options = {}) {
1277
- return declareResource("bucket", key, options);
1584
+ amendResourceKind("bucket", {
1585
+ optionKeys: [
1586
+ "publicRead",
1587
+ "prefix",
1588
+ "account",
1589
+ "default"
1590
+ ],
1591
+ envBases: [
1592
+ "STORAGE_TYPE",
1593
+ "STORAGE_PATH",
1594
+ "S3_BUCKET",
1595
+ "S3_REGION",
1596
+ "S3_ACCESS_KEY_ID",
1597
+ "S3_SECRET_ACCESS_KEY",
1598
+ "S3_ENDPOINT",
1599
+ "S3_FORCE_PATH_STYLE",
1600
+ "GCS_BUCKET",
1601
+ "GCS_PROJECT_ID",
1602
+ "GCS_KEY_FILENAME"
1603
+ ],
1604
+ envBasesByEngine: {
1605
+ local: ["STORAGE_TYPE", "STORAGE_PATH"],
1606
+ s3: [
1607
+ "STORAGE_TYPE",
1608
+ "S3_BUCKET",
1609
+ "S3_REGION",
1610
+ "S3_ACCESS_KEY_ID",
1611
+ "S3_SECRET_ACCESS_KEY",
1612
+ "S3_ENDPOINT",
1613
+ "S3_FORCE_PATH_STYLE"
1614
+ ],
1615
+ gcs: [
1616
+ "STORAGE_TYPE",
1617
+ "GCS_BUCKET",
1618
+ "GCS_PROJECT_ID",
1619
+ "GCS_KEY_FILENAME"
1620
+ ],
1621
+ azure: [],
1622
+ firebase: []
1623
+ }
1624
+ });
1625
+ function bucket(keyOrOptions = DEFAULT_RESOURCE_KEY, options = {}) {
1626
+ return typeof keyOrOptions === "string" ? declareResource("bucket", keyOrOptions, options) : declareResource("bucket", DEFAULT_RESOURCE_KEY, keyOrOptions);
1278
1627
  }
1279
1628
  registerResourceKind({
1280
1629
  kind: "topic",
@@ -1284,6 +1633,7 @@ registerResourceKind({
1284
1633
  optionKeys: ["delivery", "maxAttempts"],
1285
1634
  implicitDefault: false
1286
1635
  });
1636
+ amendResourceKind("topic", { envBases: [] });
1287
1637
  var runtimeHolder = { current: null };
1288
1638
  /** Install the transport topics publish through. Called by the server at boot. */
1289
1639
  function setTopicRuntime(runtime) {
@@ -1331,10 +1681,145 @@ function topic(key, options = {}) {
1331
1681
  }
1332
1682
  };
1333
1683
  }
1684
+ registerResourceKind({
1685
+ kind: "cron",
1686
+ engines: ["scheduler"],
1687
+ defaultEngine: "scheduler",
1688
+ envBases: [],
1689
+ optionKeys: [
1690
+ "schedule",
1691
+ "timezone",
1692
+ "description",
1693
+ "enabled",
1694
+ "timeoutSeconds",
1695
+ "catchUpWindowSeconds"
1696
+ ],
1697
+ implicitDefault: false
1698
+ });
1699
+ /**
1700
+ * Declare a cron, as the scheduler's `defineCron` does on its way through.
1701
+ *
1702
+ * Projects do not call this: `defineCron` in `@rebasepro/server` does, so a
1703
+ * cron file is both the handler and the declaration — one file, one name, and
1704
+ * the graph derived from it says what a host needs to know without evaluating
1705
+ * the handler. Exported so the derive step and the scheduler spell the
1706
+ * declaration identically.
1707
+ */
1708
+ function declareCron(name, options) {
1709
+ if (typeof options.schedule !== "string" || options.schedule.trim() === "") throw new Error(`Cron "${name}" needs a schedule — a five-field cron expression such as "0 3 * * *".`);
1710
+ return declareResource("cron", name, options);
1711
+ }
1712
+ registerResourceKind({
1713
+ kind: "function",
1714
+ engines: ["http"],
1715
+ defaultEngine: "http",
1716
+ envBases: [],
1717
+ optionKeys: [
1718
+ "portable",
1719
+ "requires",
1720
+ "file"
1721
+ ],
1722
+ implicitDefault: false
1723
+ });
1724
+ /** Declare a function. Called by the derive step, not by projects. */
1725
+ function declareFunction(name, options = {}) {
1726
+ return declareResource("function", name, options);
1727
+ }
1728
+ registerResourceKind({
1729
+ kind: "queue",
1730
+ engines: ["jobs"],
1731
+ defaultEngine: "jobs",
1732
+ envBases: [],
1733
+ optionKeys: ["maxAttempts"],
1734
+ implicitDefault: false
1735
+ });
1736
+ var queueRuntimeHolder = { current: null };
1737
+ /** Install the transport queues enqueue through. Called by the server at boot. */
1738
+ function setQueueRuntime(runtime) {
1739
+ queueRuntimeHolder.current = runtime;
1740
+ }
1741
+ var queueConsumers = /* @__PURE__ */ new Map();
1742
+ /** Every declared queue handler, for the worker to wire. */
1743
+ function declaredQueueConsumers() {
1744
+ return [...queueConsumers.values()];
1745
+ }
1746
+ /** Forget declared queue handlers. For tests, alongside `resetDeclaredResources`. */
1747
+ function resetDeclaredQueueConsumers() {
1748
+ queueConsumers.clear();
1749
+ }
1750
+ /**
1751
+ * Declare a queue.
1752
+ *
1753
+ * ```ts
1754
+ * export const thumbnails = queue<{ key: string }>("thumbnails");
1755
+ * thumbnails.handler(async ({ key }) => { … });
1756
+ * await thumbnails.enqueue({ key }, { runAt: new Date(Date.now() + 60_000) });
1757
+ * ```
1758
+ *
1759
+ * The difference from a topic is the number of consumers: a queue has one, a
1760
+ * topic fans out to every subscription. Both ride on the durable job queue, so
1761
+ * declaring either turns it on.
1762
+ */
1763
+ function queue(key, options = {}) {
1764
+ return {
1765
+ ...declareResource("queue", key, options),
1766
+ toString() {
1767
+ return key;
1768
+ },
1769
+ async enqueue(payload, enqueueOptions) {
1770
+ const runtime = queueRuntimeHolder.current;
1771
+ if (!runtime) throw new Error(`Cannot enqueue on queue "${key}": no queue runtime is installed. Enqueueing works inside a running Rebase backend; this looks like config being evaluated outside one (a build, a script, or a test without a harness).`);
1772
+ return runtime.enqueue(key, payload, enqueueOptions);
1773
+ },
1774
+ handler(fn) {
1775
+ if (queueConsumers.has(key)) throw new Error(`Queue "${key}" already has a handler. A queue has exactly one consumer; work that several things react to is a topic with several subscriptions.`);
1776
+ queueConsumers.set(key, {
1777
+ queue: key,
1778
+ handler: fn
1779
+ });
1780
+ }
1781
+ };
1782
+ }
1783
+ /**
1784
+ * One declaration, as the data layer's definition.
1785
+ *
1786
+ * There is exactly one of these per kind, and everything that needs a
1787
+ * definition goes through it — the frontend, the managed runtime's boot path,
1788
+ * and an ejected project's own entrypoint. That is not tidiness: the mapping
1789
+ * used to exist twice, once here and once in `@rebasepro/server`'s
1790
+ * `graphToStorageSources`, and the two disagreed. The server's copy carried a
1791
+ * bucket's `account`; this one dropped it, so a bucket declared with shared
1792
+ * credentials resolved them on the managed runtime and resolved *nothing* in an
1793
+ * ejected backend — the source was skipped and every upload to it answered 501.
1794
+ *
1795
+ * A field-by-field map is one line away from that failure at all times, so
1796
+ * there is now one line to keep right instead of two to keep equal.
1797
+ */
1798
+ function resourceToDataSource(declaration) {
1799
+ return {
1800
+ key: declaration.key === "(default)" ? DEFAULT_DATA_SOURCE_KEY : declaration.key,
1801
+ engine: declaration.engine,
1802
+ transport: declaration.transport,
1803
+ ...typeof declaration.options.databaseId === "string" ? { databaseId: declaration.options.databaseId } : {},
1804
+ ...declaration.label !== void 0 ? { label: declaration.label } : {}
1805
+ };
1806
+ }
1807
+ /** One declaration, as the storage layer's definition. See {@link resourceToDataSource}. */
1808
+ function resourceToStorageSource(declaration) {
1809
+ return {
1810
+ key: declaration.key === "(default)" ? DEFAULT_STORAGE_SOURCE_KEY : declaration.key,
1811
+ engine: declaration.engine,
1812
+ transport: declaration.transport,
1813
+ ...typeof declaration.options.account === "string" ? { account: declaration.options.account } : {},
1814
+ ...declaration.options.default === true ? { default: true } : {},
1815
+ ...declaration.label !== void 0 ? { label: declaration.label } : {}
1816
+ };
1817
+ }
1334
1818
  /**
1335
- * The declared databases, in the shape `<Rebase dataSources>` takes.
1819
+ * The declared databases, as definitions.
1336
1820
  *
1337
- * The frontend needs to know which sources exist and how they are reached — a
1821
+ * Both the frontend and a project's own backend entrypoint read this. The
1822
+ * frontend needs to know which sources exist and how they are reached — a
1338
1823
  * `direct`-transport source is one the browser talks to itself — and it imports
1339
1824
  * the same config package the backend does. Without these it would mean writing
1340
1825
  * the list a second time, by hand, next to the declarations, which is precisely
@@ -1352,134 +1837,11 @@ function topic(key, options = {}) {
1352
1837
  * bare re-export.
1353
1838
  */
1354
1839
  function declaredDataSources() {
1355
- return declaredResources("database").map((r) => ({
1356
- key: r.key,
1357
- engine: r.engine,
1358
- transport: r.transport,
1359
- ...r.label !== void 0 ? { label: r.label } : {}
1360
- }));
1361
- }
1362
- /** The declared buckets, in the shape `<Rebase storageSources>` takes. */
1363
- function declaredStorageSources() {
1364
- return declaredResources("bucket").map((r) => ({
1365
- key: r.key,
1366
- engine: r.engine,
1367
- transport: r.transport,
1368
- ...r.label !== void 0 ? { label: r.label } : {}
1369
- }));
1840
+ return declaredResources("database").map(resourceToDataSource);
1370
1841
  }
1371
- //#endregion
1372
- //#region src/types/storage_source.ts
1373
- /**
1374
- * Describes a named storage backend — a place files live.
1375
- *
1376
- * Declared once and shared front + back: the frontend uses it to decide
1377
- * transport (HTTP proxy vs direct SDK), the backend uses the same `key`
1378
- * to resolve a StorageController, and collection properties reference
1379
- * a definition by its `key` via `StorageConfig.storageSource`.
1380
- *
1381
- * This mirrors the {@link DataSourceDefinition} pattern used for databases.
1382
- *
1383
- * @group Models
1384
- */
1385
- /**
1386
- * The default storage source key, used when a property does not specify
1387
- * a `storageSource`. Shared by the frontend and backend registries so
1388
- * both agree on "the default storage backend".
1389
- * @group Models
1390
- */
1391
- var DEFAULT_STORAGE_SOURCE_KEY = "(default)";
1392
- /**
1393
- * The environment-variable suffix for a storage or data source key.
1394
- *
1395
- * `""` for the default source — so a single-bucket project keeps configuring
1396
- * plain `S3_BUCKET` — and `__<KEY>` for every named one, uppercased with
1397
- * non-alphanumerics collapsed to underscores: `media-cdn` → `S3_BUCKET__MEDIA_CDN`.
1398
- *
1399
- * The rule derives the variable name from the declared key rather than
1400
- * discovering keys by scanning the environment. Scanning would have to guess how
1401
- * `S3_BUCKET__MEDIA_CDN` splits into a key; deriving cannot be ambiguous, and a
1402
- * typo surfaces as a missing source at boot instead of a silently ignored
1403
- * variable.
1404
- *
1405
- * It lives in this package, with no dependencies, because four things must agree
1406
- * on it exactly: the CLI (validating a build), the runtime (reading its own
1407
- * environment), the control plane (writing a tenant's Secret), and the docs. A
1408
- * second implementation of a naming convention is a second chance to disagree.
1409
- *
1410
- * @group Models
1411
- */
1412
- function storageEnvSuffix(key, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
1413
- if (!key || key === defaultKey) return "";
1414
- const normalized = key.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
1415
- if (!normalized) throw new Error(`Source key "${key}" cannot be turned into an environment variable name. Use a key containing at least one letter or digit.`);
1416
- return `__${normalized}`;
1417
- }
1418
- /**
1419
- * Two distinct keys that collapse onto the same variable name, or `null`.
1420
- *
1421
- * `media-cdn` and `media_cdn` are different source keys but the same suffix, so
1422
- * without this one of them silently reads the other's configuration. Returns the
1423
- * offending pair rather than throwing, so each caller can raise it in its own
1424
- * idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy
1425
- * in a control plane.
1426
- *
1427
- * @group Models
1428
- */
1429
- function findStorageSuffixCollision(keys, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
1430
- const seen = /* @__PURE__ */ new Map();
1431
- for (const key of keys) {
1432
- const suffix = storageEnvSuffix(key, defaultKey);
1433
- const existing = seen.get(suffix);
1434
- if (existing !== void 0 && existing !== key) return {
1435
- a: existing,
1436
- b: key,
1437
- suffix
1438
- };
1439
- seen.set(suffix, key);
1440
- }
1441
- return null;
1442
- }
1443
- /**
1444
- * Merge the two places a project may declare storage sources into one list.
1445
- *
1446
- * `rebase.json` is authoritative for every field it states. Config code may add
1447
- * sources it does not mention and fill in fields it left out, but may not
1448
- * contradict it: the manifest is what a host reads to decide which buckets need
1449
- * configuring, and a runtime that quietly disagreed with it would put the
1450
- * console back to describing a topology the tenant does not have — the exact
1451
- * failure this whole mechanism exists to end.
1452
- *
1453
- * Note what is *not* here: no default source is invented when both inputs are
1454
- * empty. That decision belongs to the resolver, which knows whether declaring
1455
- * nothing means "one plain bucket" (it does) or "no storage at all".
1456
- *
1457
- * @group Models
1458
- */
1459
- function normalizeStorageSources(declared, exported) {
1460
- const merged = /* @__PURE__ */ new Map();
1461
- const declaredEntries = Array.isArray(declared) ? declared.filter((d) => d?.key).map((d) => [d.key, d]) : Object.entries(declared ?? {});
1462
- for (const [key, config] of declaredEntries) merged.set(key, {
1463
- key,
1464
- engine: config.engine,
1465
- transport: config.transport ?? "server",
1466
- ...config.label !== void 0 ? { label: config.label } : {}
1467
- });
1468
- for (const definition of exported ?? []) {
1469
- if (!definition?.key) continue;
1470
- const existing = merged.get(definition.key);
1471
- if (!existing) {
1472
- merged.set(definition.key, {
1473
- key: definition.key,
1474
- engine: definition.engine,
1475
- transport: definition.transport ?? "server",
1476
- ...definition.label !== void 0 ? { label: definition.label } : {}
1477
- });
1478
- continue;
1479
- }
1480
- if (existing.label === void 0 && definition.label !== void 0) existing.label = definition.label;
1481
- }
1482
- return Array.from(merged.values());
1842
+ /** The declared buckets, as definitions. */
1843
+ function declaredStorageSources() {
1844
+ return declaredResources("bucket").map(resourceToStorageSource);
1483
1845
  }
1484
1846
  //#endregion
1485
1847
  //#region src/types/component_ref.ts
@@ -1893,6 +2255,6 @@ function isPublicStoragePath(path) {
1893
2255
  return p.startsWith("public/") || p.startsWith(`default/public/`);
1894
2256
  }
1895
2257
  //#endregion
1896
- export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_COMMIT_PATHS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, DEFAULT_RESOURCE_KEY, DEFAULT_SEARCH_COLUMN, DEFAULT_SEARCH_LANGUAGE, DEFAULT_SEARCH_WEIGHT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, LEGACY_RLS_JWT_SQL, LEGACY_RLS_ROLES_SQL, LEGACY_RLS_SCHEMA, LEGACY_RLS_UID_SQL, ListLimitError, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REBASE_SCHEMA, RELEVANCE_SORT_FIELD, RESERVED_BACKEND_PREFIXES, RESOURCE_GRAPH_VERSION, REST_TO_CANONICAL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, bucket, buildResourceGraph, canonicalSchemaPayload, computeSchemaVersion, database, declareResource, declaredDataSources, declaredDatabaseExtensions, declaredResources, declaredStorageSources, declaredSubscriptions, deserializeCollections, encodeRelationAggregateSort, envBasesForResource, findEnvSuffixCollision, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationAggregateSort, isRelationalCollectionConfig, isResourceHandle, isSQLAdmin, isSchemaAdmin, isSchemaEditingAdmin, isSerializedCollectionRef, isToMany, isValidEngine, nestAdminCollectionKeys, nestAdminKeysOf, nestAdminPropertyKeys, normalizeStorageSources, parseRelationAggregateSort, policy, registerDataSourceCapabilities, registerResourceKind, reservedPrefixFor, resetDeclaredResources, resetDeclaredSubscriptions, resolveClientListLimit, resourceEnvSuffix, resourceKeyOf, resourceKind, resourceKinds, rewriteLegacyRlsFunctions, serializeCollections, setTopicRuntime, sortKeyToString, storageEnvSuffix, toCanonicalOp, topic, usesLegacyRlsFunctions };
2258
+ export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_COMMIT_PATHS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, DEFAULT_RESOURCE_KEY, DEFAULT_SEARCH_COLUMN, DEFAULT_SEARCH_LANGUAGE, DEFAULT_SEARCH_WEIGHT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, LEGACY_RLS_JWT_SQL, LEGACY_RLS_ROLES_SQL, LEGACY_RLS_SCHEMA, LEGACY_RLS_UID_SQL, ListLimitError, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REBASE_SCHEMA, RELEVANCE_SORT_FIELD, RESERVED_BACKEND_PREFIXES, RESOURCE_GRAPH_VERSION, REST_TO_CANONICAL, RLS_IS_ANONYMOUS_SQL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, amendResourceKind, bucket, buildResourceGraph, canonicalSchemaPayload, computeSchemaVersion, database, declareCron, declareFunction, declareResource, declaredDataSources, declaredDatabaseExtensions, declaredQueueConsumers, declaredResources, declaredStorageSources, declaredSubscriptions, deserializeCollections, encodeRelationAggregateSort, envBasesForResource, findEnvSuffixCollision, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationAggregateSort, isRelationalCollectionConfig, isResourceHandle, isSQLAdmin, isSchemaAdmin, isSchemaEditingAdmin, isSerializedCollectionRef, isToMany, isUnsupported, isValidEngine, nestAdminCollectionKeys, nestAdminKeysOf, nestAdminPropertyKeys, parseRelationAggregateSort, policy, queue, registerDataSourceCapabilities, registerResourceKind, reservedPrefixFor, resetDeclaredQueueConsumers, resetDeclaredResources, resetDeclaredSubscriptions, resolveClientListLimit, resolveResourceRefs, resourceEnvSuffix, resourceId, resourceKeyOf, resourceKind, resourceKinds, resourceToDataSource, resourceToStorageSource, rewriteLegacyRlsFunctions, serializeCollections, setQueueRuntime, setTopicRuntime, sortKeyToString, storageEnvSuffix, toCanonicalOp, topic, unsupportedMethod, usesLegacyRlsFunctions };
1897
2259
 
1898
2260
  //# sourceMappingURL=index.es.js.map