@rebasepro/types 0.16.0 → 0.16.1-canary.g041c925

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 (53) hide show
  1. package/dist/call_context.d.ts +5 -5
  2. package/dist/controllers/auth_state.d.ts +1 -1
  3. package/dist/controllers/client.d.ts +22 -9
  4. package/dist/controllers/collection_registry.d.ts +2 -2
  5. package/dist/controllers/data.d.ts +4 -12
  6. package/dist/controllers/data_driver.d.ts +7 -7
  7. package/dist/controllers/email.d.ts +54 -2
  8. package/dist/controllers/index.d.ts +8 -9
  9. package/dist/controllers/storage.d.ts +4 -4
  10. package/dist/index.d.ts +5 -5
  11. package/dist/index.es.js +429 -3
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/types/admin_block.d.ts +1 -1
  14. package/dist/types/auth_adapter.d.ts +18 -9
  15. package/dist/types/backend.d.ts +23 -10
  16. package/dist/types/collection_contract.d.ts +1 -1
  17. package/dist/types/collections.d.ts +16 -9
  18. package/dist/types/component_ref.d.ts +3 -2
  19. package/dist/types/cron.d.ts +1 -25
  20. package/dist/types/data_source.d.ts +1 -1
  21. package/dist/types/database_adapter.d.ts +5 -5
  22. package/dist/types/entities.d.ts +1 -1
  23. package/dist/types/entity_callbacks.d.ts +4 -4
  24. package/dist/types/index.d.ts +32 -29
  25. package/dist/types/project_manifest.d.ts +132 -27
  26. package/dist/types/properties.d.ts +58 -6
  27. package/dist/types/relations.d.ts +1 -1
  28. package/dist/types/resource_kinds.d.ts +174 -0
  29. package/dist/types/resources.d.ts +197 -0
  30. package/dist/types/schema_editing.d.ts +127 -0
  31. package/dist/types/schema_version.d.ts +1 -1
  32. package/dist/types/security_rules.d.ts +1 -1
  33. package/dist/users/index.d.ts +1 -1
  34. package/package.json +2 -2
  35. package/src/controllers/client.ts +14 -1
  36. package/src/controllers/data.ts +0 -9
  37. package/src/controllers/email.ts +55 -2
  38. package/src/controllers/index.ts +0 -1
  39. package/src/controllers/storage.ts +4 -4
  40. package/src/types/admin_block.ts +1 -2
  41. package/src/types/auth_adapter.ts +18 -10
  42. package/src/types/backend.ts +18 -1
  43. package/src/types/collections.ts +9 -2
  44. package/src/types/component_ref.ts +3 -2
  45. package/src/types/cron.ts +0 -24
  46. package/src/types/index.ts +3 -0
  47. package/src/types/project_manifest.ts +139 -26
  48. package/src/types/properties.ts +54 -0
  49. package/src/types/resource_kinds.ts +309 -0
  50. package/src/types/resources.ts +368 -0
  51. package/src/types/schema_editing.ts +154 -0
  52. package/dist/controllers/database_admin.d.ts +0 -11
  53. package/src/controllers/database_admin.ts +0 -22
package/dist/index.es.js CHANGED
@@ -400,8 +400,7 @@ var ADMIN_COLLECTION_KEYS = [
400
400
  "selectionController",
401
401
  "selectionEnabled",
402
402
  "sideDialogWidth",
403
- "sort",
404
- "titleProperty"
403
+ "sort"
405
404
  ];
406
405
  /**
407
406
  * Every key that belongs inside a *property's* `admin` block, as data.
@@ -940,6 +939,20 @@ function usesLegacyRlsFunctions(sql) {
940
939
  //#endregion
941
940
  //#region src/types/backend.ts
942
941
  /**
942
+ * Type guard: can this admin plan a live schema change?
943
+ *
944
+ * Planning is engine-specific — it renders DDL, a Drizzle schema and the
945
+ * declarative SQL artifacts — so the implementation lives in the driver
946
+ * package. The server detects the capability structurally, exactly as it does
947
+ * for SQL, rather than importing an engine it is supposed to know nothing
948
+ * about.
949
+ *
950
+ * @group Admin
951
+ */
952
+ function isSchemaEditingAdmin(admin) {
953
+ return !!admin && typeof admin.planSchemaChange === "function";
954
+ }
955
+ /**
943
956
  * Type guard: does this admin support SQL operations?
944
957
  * @group Admin
945
958
  */
@@ -968,6 +981,14 @@ function isBranchAdmin(admin) {
968
981
  return !!admin && typeof admin.createBranch === "function";
969
982
  }
970
983
  //#endregion
984
+ //#region src/types/schema_editing.ts
985
+ var DEFAULT_COMMIT_PATHS = {
986
+ schemaFile: "backend/src/schema.generated.ts",
987
+ ddlFile: "drizzle/schema.sql",
988
+ policiesFile: "drizzle/policies.sql",
989
+ searchFile: "drizzle/search.sql"
990
+ };
991
+ //#endregion
971
992
  //#region src/types/channel_bus.ts
972
993
  /**
973
994
  * Whether `setting` is an already-constructed transport rather than a request
@@ -981,6 +1002,351 @@ function isChannelBusInstance(setting) {
981
1002
  return typeof setting?.publish === "function";
982
1003
  }
983
1004
  //#endregion
1005
+ //#region src/types/resources.ts
1006
+ /** The key a resource takes when a project declares only one of its kind. */
1007
+ var DEFAULT_RESOURCE_KEY = "(default)";
1008
+ var BRAND = Symbol.for("@rebasepro/types.resource");
1009
+ /** Whether a value is a resource handle rather than a plain string key. */
1010
+ function isResourceHandle(value) {
1011
+ return typeof value === "object" && value !== null && BRAND in value;
1012
+ }
1013
+ /** The key a resource reference names, whether it is a handle or already a key. */
1014
+ function resourceKeyOf(ref) {
1015
+ return isResourceHandle(ref) ? ref.key : ref;
1016
+ }
1017
+ var GLOBAL_KEY = Symbol.for("@rebasepro/types.resourceRegistry");
1018
+ function registry() {
1019
+ const g = globalThis;
1020
+ let existing = g[GLOBAL_KEY];
1021
+ if (!existing) {
1022
+ existing = {
1023
+ kinds: /* @__PURE__ */ new Map(),
1024
+ declarations: /* @__PURE__ */ new Map()
1025
+ };
1026
+ g[GLOBAL_KEY] = existing;
1027
+ }
1028
+ return existing;
1029
+ }
1030
+ /** `kind:key`, the graph's primary key. */
1031
+ function declarationId(kind, key) {
1032
+ return `${kind}:${key}`;
1033
+ }
1034
+ /** Register a resource kind. Idempotent for an identical spec; throws on a conflicting one. */
1035
+ function registerResourceKind(spec) {
1036
+ const existing = registry().kinds.get(spec.kind);
1037
+ 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.`);
1038
+ registry().kinds.set(spec.kind, spec);
1039
+ }
1040
+ /** Every registered kind, for validators and for `rebase doctor`. */
1041
+ function resourceKinds() {
1042
+ return [...registry().kinds.values()];
1043
+ }
1044
+ /** One registered kind, or undefined. */
1045
+ function resourceKind(kind) {
1046
+ return registry().kinds.get(kind);
1047
+ }
1048
+ var COMMON_OPTION_KEYS = [
1049
+ "engine",
1050
+ "transport",
1051
+ "label"
1052
+ ];
1053
+ /** Whether an engine is one the kind knows, or an explicit `custom:` opt-out. */
1054
+ function isValidEngine(spec, engine) {
1055
+ return engine.startsWith("custom:") || spec.engines.includes(engine);
1056
+ }
1057
+ /**
1058
+ * Declare a resource. The primitive every kind's constructor is built from.
1059
+ *
1060
+ * Redeclaring the same `kind:key` with a *different* shape throws rather than
1061
+ * merging. Merging is what the old storage path did, and it silently discarded
1062
+ * one of the two engines — a declaration accepted and then ignored, which is
1063
+ * the failure this whole model exists to remove. Redeclaring it identically is
1064
+ * fine: a config module evaluated twice must not be an error.
1065
+ */
1066
+ function declareResource(kind, key = DEFAULT_RESOURCE_KEY, options = {}) {
1067
+ const spec = registry().kinds.get(kind);
1068
+ if (!spec) {
1069
+ const known = [...registry().kinds.keys()].sort().join(", ") || "none";
1070
+ throw new Error(`Unknown resource kind "${kind}". Registered kinds: ${known}. Call registerResourceKind() before declaring one.`);
1071
+ }
1072
+ if (!key || typeof key !== "string" || key.trim() === "") throw new Error(`A ${kind} needs a non-empty key.`);
1073
+ const engine = options.engine ?? spec.defaultEngine;
1074
+ if (!isValidEngine(spec, engine)) throw new Error(`Unknown ${kind} engine "${engine}" for "${key}". Known engines: ${spec.engines.join(", ")}. An engine this build does not ship is spelled "custom:${engine}", which says so at the call site rather than failing later.`);
1075
+ const allowed = /* @__PURE__ */ new Set([...COMMON_OPTION_KEYS, ...spec.optionKeys ?? []]);
1076
+ const unknown = Object.keys(options).filter((k) => !allowed.has(k));
1077
+ if (unknown.length > 0) throw new Error(`Unknown option(s) on ${kind} "${key}": ${unknown.join(", ")}. A ${kind} accepts: ${[...allowed].sort().join(", ")}.`);
1078
+ const extra = {};
1079
+ for (const k of spec.optionKeys ?? []) if (options[k] !== void 0) extra[k] = options[k];
1080
+ const declaration = {
1081
+ kind,
1082
+ key,
1083
+ engine,
1084
+ transport: options.transport ?? "server",
1085
+ ...options.label !== void 0 ? { label: options.label } : {},
1086
+ options: Object.freeze(extra)
1087
+ };
1088
+ const id = declarationId(kind, key);
1089
+ const previous = registry().declarations.get(id);
1090
+ if (previous) {
1091
+ if (JSON.stringify(previous) !== JSON.stringify(declaration)) throw new Error(`${kind} "${key}" is declared twice with different configuration. Declare it once and export it — two declarations of one resource is the ambiguity this model exists to remove, so it is refused rather than merged.`);
1092
+ } else registry().declarations.set(id, declaration);
1093
+ return {
1094
+ ...declaration,
1095
+ toString() {
1096
+ return key;
1097
+ },
1098
+ [BRAND]: true
1099
+ };
1100
+ }
1101
+ /** Every declared resource, in declaration order, optionally filtered by kind. */
1102
+ function declaredResources(kind) {
1103
+ const all = [...registry().declarations.values()];
1104
+ return kind ? all.filter((r) => r.kind === kind) : all;
1105
+ }
1106
+ /**
1107
+ * Forget every declaration, keeping registered kinds.
1108
+ *
1109
+ * For tests and for a CLI that evaluates more than one project in a process.
1110
+ * Kinds survive because they are registered by module import, which will not
1111
+ * happen a second time.
1112
+ */
1113
+ function resetDeclaredResources() {
1114
+ registry().declarations.clear();
1115
+ }
1116
+ /**
1117
+ * The env-var suffix a resource's bindings use: `__ANALYTICS` for `analytics`,
1118
+ * and nothing at all for the default-keyed one.
1119
+ *
1120
+ * The default takes no suffix so that a project with one database configured
1121
+ * through plain `DATABASE_URL` keeps working having declared nothing — the
1122
+ * overwhelmingly common project must not have to say so.
1123
+ */
1124
+ function resourceEnvSuffix(key) {
1125
+ if (key === "(default)") return "";
1126
+ return `__${key.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
1127
+ }
1128
+ /**
1129
+ * Two resources of a kind whose keys differ but whose env suffixes do not.
1130
+ *
1131
+ * `media-files` and `media_files` both become `__MEDIA_FILES`, so one would
1132
+ * silently read the other's configuration. Returned rather than thrown so the
1133
+ * caller can report it with the rest of a validation pass.
1134
+ */
1135
+ function findEnvSuffixCollision(keys) {
1136
+ const seen = /* @__PURE__ */ new Map();
1137
+ for (const key of keys) {
1138
+ const suffix = resourceEnvSuffix(key);
1139
+ const previous = seen.get(suffix);
1140
+ if (previous !== void 0 && previous !== key) return {
1141
+ a: previous,
1142
+ b: key,
1143
+ suffix
1144
+ };
1145
+ seen.set(suffix, key);
1146
+ }
1147
+ return null;
1148
+ }
1149
+ /** The current graph format version. */
1150
+ var RESOURCE_GRAPH_VERSION = 1;
1151
+ /** Build a graph from the current declarations, sorted for a stable diff. */
1152
+ function buildResourceGraph() {
1153
+ return {
1154
+ version: 1,
1155
+ resources: declaredResources().slice().sort((a, b) => a.kind.localeCompare(b.kind) || a.key.localeCompare(b.key))
1156
+ };
1157
+ }
1158
+ /**
1159
+ * The environment variables worth writing for a resource, given its engine.
1160
+ *
1161
+ * Falls back to every base the kind reads when the engine is unknown — a
1162
+ * `custom:` engine gets the full list rather than an empty one, because
1163
+ * guessing narrow would silently omit the variable it actually needs.
1164
+ */
1165
+ function envBasesForResource(declaration) {
1166
+ const spec = resourceKind(declaration.kind);
1167
+ if (!spec) return [];
1168
+ return spec.envBasesByEngine?.[declaration.engine] ?? spec.envBases;
1169
+ }
1170
+ //#endregion
1171
+ //#region src/types/resource_kinds.ts
1172
+ /**
1173
+ * The kinds Rebase ships, and the constructors a project declares them with.
1174
+ *
1175
+ * Each kind is registered rather than hardcoded, so a fourth one arrives
1176
+ * without editing a manifest schema, a validator and a switch statement. That
1177
+ * cost is precisely why databases and buckets ended up declared in different
1178
+ * files with different rules — the cheapest thing to do was always to bolt the
1179
+ * new kind onto whichever home was nearest.
1180
+ *
1181
+ * A kind owns its engine list. `custom:<id>` is always accepted, so a build
1182
+ * that ships an engine this package has never heard of says so at the call site
1183
+ * instead of looking like a typo of one that exists.
1184
+ */
1185
+ registerResourceKind({
1186
+ kind: "database",
1187
+ engines: [
1188
+ "postgres",
1189
+ "mongodb",
1190
+ "firestore",
1191
+ "sqlite"
1192
+ ],
1193
+ defaultEngine: "postgres",
1194
+ envBases: [
1195
+ "DATABASE_URL",
1196
+ "REBASE_DRIVER",
1197
+ "REBASE_DB_POOL_MAX"
1198
+ ],
1199
+ optionKeys: ["databaseId", "migrations"],
1200
+ implicitDefault: true
1201
+ });
1202
+ /**
1203
+ * Declare a database.
1204
+ *
1205
+ * ```ts
1206
+ * export const main = database(); // the default one
1207
+ * export const analytics = database("analytics"); // reads DATABASE_URL__ANALYTICS
1208
+ * ```
1209
+ */
1210
+ function database(key = DEFAULT_RESOURCE_KEY, options = {}) {
1211
+ return declareResource("database", key, options);
1212
+ }
1213
+ registerResourceKind({
1214
+ kind: "bucket",
1215
+ engines: [
1216
+ "local",
1217
+ "s3",
1218
+ "gcs",
1219
+ "azure",
1220
+ "firebase"
1221
+ ],
1222
+ defaultEngine: "local",
1223
+ envBases: [
1224
+ "S3_BUCKET",
1225
+ "GCS_BUCKET",
1226
+ "STORAGE_BUCKET",
1227
+ "STORAGE_PUBLIC_URL"
1228
+ ],
1229
+ envBasesByEngine: {
1230
+ local: ["STORAGE_BUCKET"],
1231
+ s3: [
1232
+ "S3_BUCKET",
1233
+ "STORAGE_ENDPOINT",
1234
+ "STORAGE_REGION",
1235
+ "STORAGE_PUBLIC_URL"
1236
+ ],
1237
+ gcs: ["GCS_BUCKET", "STORAGE_PUBLIC_URL"],
1238
+ azure: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"],
1239
+ firebase: ["STORAGE_BUCKET", "STORAGE_PUBLIC_URL"]
1240
+ },
1241
+ optionKeys: ["publicRead", "prefix"],
1242
+ implicitDefault: false
1243
+ });
1244
+ /**
1245
+ * Declare a bucket.
1246
+ *
1247
+ * ```ts
1248
+ * export const media = bucket("media", { transport: "direct" });
1249
+ * ```
1250
+ *
1251
+ * `transport: "direct"` means a provider SDK talks to the bucket and the
1252
+ * backend is not in the upload path.
1253
+ */
1254
+ function bucket(key = DEFAULT_RESOURCE_KEY, options = {}) {
1255
+ return declareResource("bucket", key, options);
1256
+ }
1257
+ registerResourceKind({
1258
+ kind: "topic",
1259
+ engines: ["jobs"],
1260
+ defaultEngine: "jobs",
1261
+ envBases: ["REBASE_TOPIC_URL"],
1262
+ optionKeys: ["delivery", "maxAttempts"],
1263
+ implicitDefault: false
1264
+ });
1265
+ var runtimeHolder = { current: null };
1266
+ /** Install the transport topics publish through. Called by the server at boot. */
1267
+ function setTopicRuntime(runtime) {
1268
+ runtimeHolder.current = runtime;
1269
+ }
1270
+ var subscriptions = [];
1271
+ /** Every declared subscription, for the worker to wire and the graph to record. */
1272
+ function declaredSubscriptions(topic) {
1273
+ return topic ? subscriptions.filter((s) => s.topic === topic) : subscriptions.slice();
1274
+ }
1275
+ /** Forget declared subscriptions. For tests, alongside `resetDeclaredResources`. */
1276
+ function resetDeclaredSubscriptions() {
1277
+ subscriptions.length = 0;
1278
+ }
1279
+ /**
1280
+ * Declare a topic.
1281
+ *
1282
+ * ```ts
1283
+ * export const signups = topic<{ userId: string }>("signups");
1284
+ * signups.subscription("send-welcome", async (event) => { … });
1285
+ * await signups.publish({ userId });
1286
+ * ```
1287
+ */
1288
+ function topic(key, options = {}) {
1289
+ if (options.delivery === "at-most-once") throw new Error(`Topic "${key}" asks for at-most-once delivery, which no shipped transport implements. The durable queue behind topics retries, so it is at-least-once and a handler must tolerate seeing an event twice. Refused rather than quietly given the other guarantee.`);
1290
+ return {
1291
+ ...declareResource("topic", key, options),
1292
+ toString() {
1293
+ return key;
1294
+ },
1295
+ async publish(event) {
1296
+ const runtime = runtimeHolder.current;
1297
+ if (!runtime) throw new Error(`Cannot publish to topic "${key}": no topic runtime is installed. Publishing works inside a running Rebase backend; this looks like config being evaluated outside one (a build, a script, or a test without a harness).`);
1298
+ await runtime.publish(key, event);
1299
+ },
1300
+ subscription(name, handler, subOptions = {}) {
1301
+ if (!name || name.trim() === "") throw new Error(`A subscription on topic "${key}" needs a non-empty name.`);
1302
+ if (subscriptions.some((s) => s.topic === key && s.name === name)) throw new Error(`Topic "${key}" already has a subscription named "${name}". The name is what a job row records and what a retry counts against, so two cannot share one.`);
1303
+ subscriptions.push({
1304
+ topic: key,
1305
+ name,
1306
+ handler,
1307
+ ...subOptions.maxAttempts !== void 0 ? { maxAttempts: subOptions.maxAttempts } : {}
1308
+ });
1309
+ }
1310
+ };
1311
+ }
1312
+ /**
1313
+ * The declared databases, in the shape `<Rebase dataSources>` takes.
1314
+ *
1315
+ * The frontend needs to know which sources exist and how they are reached — a
1316
+ * `direct`-transport source is one the browser talks to itself — and it imports
1317
+ * the same config package the backend does. Without these it would mean writing
1318
+ * the list a second time, by hand, next to the declarations, which is precisely
1319
+ * the two-homes problem this model removed everywhere else.
1320
+ *
1321
+ * ```tsx
1322
+ * import "../config/resources"; // registers them
1323
+ * import { declaredDataSources, declaredStorageSources } from "@rebasepro/types";
1324
+ *
1325
+ * <Rebase dataSources={declaredDataSources()} storageSources={declaredStorageSources()} />
1326
+ * ```
1327
+ *
1328
+ * The import is what registers them, so a bundler that drops an unused module
1329
+ * would leave this empty — hence the side-effect import above rather than a
1330
+ * bare re-export.
1331
+ */
1332
+ function declaredDataSources() {
1333
+ return declaredResources("database").map((r) => ({
1334
+ key: r.key,
1335
+ engine: r.engine,
1336
+ transport: r.transport,
1337
+ ...r.label !== void 0 ? { label: r.label } : {}
1338
+ }));
1339
+ }
1340
+ /** The declared buckets, in the shape `<Rebase storageSources>` takes. */
1341
+ function declaredStorageSources() {
1342
+ return declaredResources("bucket").map((r) => ({
1343
+ key: r.key,
1344
+ engine: r.engine,
1345
+ transport: r.transport,
1346
+ ...r.label !== void 0 ? { label: r.label } : {}
1347
+ }));
1348
+ }
1349
+ //#endregion
984
1350
  //#region src/types/storage_source.ts
985
1351
  /**
986
1352
  * Describes a named storage backend — a place files live.
@@ -1105,6 +1471,41 @@ function isLazyComponentRef(ref) {
1105
1471
  //#endregion
1106
1472
  //#region src/types/project_manifest.ts
1107
1473
  /**
1474
+ * Path prefixes the backend owns, which no static app may claim.
1475
+ *
1476
+ * One process — and, on the platform, one hostname — serves both the API and
1477
+ * however many static apps a project has. Mounting is longest-path-first, so an
1478
+ * app declaring `/api` would win against the API itself and every request to it
1479
+ * would be answered with that app's `index.html`: a 200 carrying HTML where the
1480
+ * caller expected JSON, from a project that looks deployed and healthy.
1481
+ *
1482
+ * Declared here rather than in either enforcer because both must agree. The CLI
1483
+ * checks it so a developer finds out while editing `rebase.json`; the control
1484
+ * plane checks it again at deploy intake, because the front door's correctness
1485
+ * cannot rest on a check that ran in somebody else's CLI — and a repository can
1486
+ * be deployed by a CLI older than this rule.
1487
+ */
1488
+ var RESERVED_BACKEND_PREFIXES = [
1489
+ "/api",
1490
+ "/health",
1491
+ "/healthz",
1492
+ "/livez",
1493
+ "/readyz",
1494
+ "/metrics"
1495
+ ];
1496
+ /**
1497
+ * Whether `path` collides with a prefix the backend owns.
1498
+ *
1499
+ * Compares at segment boundaries, so `/api` and `/api/v2` collide while
1500
+ * `/apidocs` does not — the same rule the router matches with, because a check
1501
+ * that is stricter than the router rejects paths that would have worked, and one
1502
+ * that is looser admits paths that will not.
1503
+ */
1504
+ function reservedPrefixFor(path) {
1505
+ const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
1506
+ return RESERVED_BACKEND_PREFIXES.find((reserved) => normalized === reserved || normalized.startsWith(`${reserved}/`));
1507
+ }
1508
+ /**
1108
1509
  * Version of the bundle *format* itself.
1109
1510
  *
1110
1511
  * Bumped only when the on-disk layout changes in a way an older runtime could
@@ -1128,6 +1529,31 @@ var BUNDLE_FORMAT_VERSION = 2;
1128
1529
  * any number of minors and patches while this stays put. It changes only when
1129
1530
  * the bundle/runtime contract breaks compatibility, and a project's
1130
1531
  * `manifest.runtime` range is matched against *this*.
1532
+ *
1533
+ * ## v2 — resources are declared, not configured
1534
+ *
1535
+ * `RebaseBackendConfig.dataSources` and `.storageSources` are gone. A project
1536
+ * declares its databases and buckets with `database()` / `bucket()` in its
1537
+ * config, and the runtime reads those declarations.
1538
+ *
1539
+ * This had to be a major, and the reason is the managed tier: it moves projects
1540
+ * onto new images WITHOUT rebuilding them. A bundle built against v1 exports
1541
+ * those keys, and a v2 runtime refuses them at boot — so without this bump, one
1542
+ * image rollout would crash-loop every tenant that had ever declared a second
1543
+ * database or bucket, in a wave, with the cause in a container log nobody is
1544
+ * watching.
1545
+ *
1546
+ * With the bump, a v1 bundle on a v2 runtime is refused by
1547
+ * `assertBundleCompatibility` with the remedy in the message, and the platform
1548
+ * keeps it on a v1 image until it is rebuilt. That is the whole purpose of this
1549
+ * number.
1550
+ *
1551
+ * **Release order matters and is not optional.** The control plane is the side
1552
+ * that rejects, so it ships FIRST: raise `SUPPORTED_RUNTIME_CONTRACT` in the
1553
+ * saas repo (it rejects only `contract >` its own, so it then accepts both),
1554
+ * deploy that, and only then release a runtime implementing v2. Shipping the
1555
+ * runtime first turns every deploy into a rejected intake blaming the tenant's
1556
+ * bundle.
1131
1557
  */
1132
1558
  var RUNTIME_CONTRACT_VERSION = 1;
1133
1559
  /** Header carrying the schema version an SDK was generated from. */
@@ -1445,6 +1871,6 @@ function isPublicStoragePath(path) {
1445
1871
  return p.startsWith("public/") || p.startsWith(`default/public/`);
1446
1872
  }
1447
1873
  //#endregion
1448
- 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_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, 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, REST_TO_CANONICAL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, canonicalSchemaPayload, computeSchemaVersion, deserializeCollections, encodeRelationAggregateSort, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationAggregateSort, isRelationalCollectionConfig, isSQLAdmin, isSchemaAdmin, isSerializedCollectionRef, isToMany, nestAdminCollectionKeys, nestAdminKeysOf, nestAdminPropertyKeys, normalizeStorageSources, parseRelationAggregateSort, policy, registerDataSourceCapabilities, resolveClientListLimit, rewriteLegacyRlsFunctions, serializeCollections, sortKeyToString, storageEnvSuffix, toCanonicalOp, usesLegacyRlsFunctions };
1874
+ 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, 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 };
1449
1875
 
1450
1876
  //# sourceMappingURL=index.es.js.map