@rebasepro/types 0.16.0 → 0.16.1-canary.g0d7af95

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 (57) 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 +433 -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 +34 -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 +33 -29
  25. package/dist/types/indexes.d.ts +179 -0
  26. package/dist/types/project_manifest.d.ts +132 -27
  27. package/dist/types/properties.d.ts +58 -6
  28. package/dist/types/relations.d.ts +1 -1
  29. package/dist/types/resource_kinds.d.ts +189 -0
  30. package/dist/types/resources.d.ts +197 -0
  31. package/dist/types/schema_editing.d.ts +127 -0
  32. package/dist/types/schema_version.d.ts +1 -1
  33. package/dist/types/security_rules.d.ts +1 -1
  34. package/dist/types/storage_source.d.ts +27 -0
  35. package/dist/users/index.d.ts +1 -1
  36. package/package.json +2 -2
  37. package/src/controllers/client.ts +14 -1
  38. package/src/controllers/data.ts +0 -9
  39. package/src/controllers/email.ts +55 -2
  40. package/src/controllers/index.ts +0 -1
  41. package/src/controllers/storage.ts +4 -4
  42. package/src/types/admin_block.ts +1 -2
  43. package/src/types/auth_adapter.ts +18 -10
  44. package/src/types/backend.ts +18 -1
  45. package/src/types/collections.ts +28 -2
  46. package/src/types/component_ref.ts +3 -2
  47. package/src/types/cron.ts +0 -24
  48. package/src/types/index.ts +4 -0
  49. package/src/types/indexes.ts +180 -0
  50. package/src/types/project_manifest.ts +139 -26
  51. package/src/types/properties.ts +54 -0
  52. package/src/types/resource_kinds.ts +324 -0
  53. package/src/types/resources.ts +368 -0
  54. package/src/types/schema_editing.ts +154 -0
  55. package/src/types/storage_source.ts +28 -0
  56. package/dist/controllers/database_admin.d.ts +0 -11
  57. 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,355 @@ 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: [
1242
+ "publicRead",
1243
+ "prefix",
1244
+ "account"
1245
+ ],
1246
+ implicitDefault: false
1247
+ });
1248
+ /**
1249
+ * Declare a bucket.
1250
+ *
1251
+ * ```ts
1252
+ * export const media = bucket("media", { transport: "direct" });
1253
+ * ```
1254
+ *
1255
+ * `transport: "direct"` means a provider SDK talks to the bucket and the
1256
+ * backend is not in the upload path.
1257
+ */
1258
+ function bucket(key = DEFAULT_RESOURCE_KEY, options = {}) {
1259
+ return declareResource("bucket", key, options);
1260
+ }
1261
+ registerResourceKind({
1262
+ kind: "topic",
1263
+ engines: ["jobs"],
1264
+ defaultEngine: "jobs",
1265
+ envBases: ["REBASE_TOPIC_URL"],
1266
+ optionKeys: ["delivery", "maxAttempts"],
1267
+ implicitDefault: false
1268
+ });
1269
+ var runtimeHolder = { current: null };
1270
+ /** Install the transport topics publish through. Called by the server at boot. */
1271
+ function setTopicRuntime(runtime) {
1272
+ runtimeHolder.current = runtime;
1273
+ }
1274
+ var subscriptions = [];
1275
+ /** Every declared subscription, for the worker to wire and the graph to record. */
1276
+ function declaredSubscriptions(topic) {
1277
+ return topic ? subscriptions.filter((s) => s.topic === topic) : subscriptions.slice();
1278
+ }
1279
+ /** Forget declared subscriptions. For tests, alongside `resetDeclaredResources`. */
1280
+ function resetDeclaredSubscriptions() {
1281
+ subscriptions.length = 0;
1282
+ }
1283
+ /**
1284
+ * Declare a topic.
1285
+ *
1286
+ * ```ts
1287
+ * export const signups = topic<{ userId: string }>("signups");
1288
+ * signups.subscription("send-welcome", async (event) => { … });
1289
+ * await signups.publish({ userId });
1290
+ * ```
1291
+ */
1292
+ function topic(key, options = {}) {
1293
+ 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.`);
1294
+ return {
1295
+ ...declareResource("topic", key, options),
1296
+ toString() {
1297
+ return key;
1298
+ },
1299
+ async publish(event) {
1300
+ const runtime = runtimeHolder.current;
1301
+ 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).`);
1302
+ await runtime.publish(key, event);
1303
+ },
1304
+ subscription(name, handler, subOptions = {}) {
1305
+ if (!name || name.trim() === "") throw new Error(`A subscription on topic "${key}" needs a non-empty name.`);
1306
+ 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.`);
1307
+ subscriptions.push({
1308
+ topic: key,
1309
+ name,
1310
+ handler,
1311
+ ...subOptions.maxAttempts !== void 0 ? { maxAttempts: subOptions.maxAttempts } : {}
1312
+ });
1313
+ }
1314
+ };
1315
+ }
1316
+ /**
1317
+ * The declared databases, in the shape `<Rebase dataSources>` takes.
1318
+ *
1319
+ * The frontend needs to know which sources exist and how they are reached — a
1320
+ * `direct`-transport source is one the browser talks to itself — and it imports
1321
+ * the same config package the backend does. Without these it would mean writing
1322
+ * the list a second time, by hand, next to the declarations, which is precisely
1323
+ * the two-homes problem this model removed everywhere else.
1324
+ *
1325
+ * ```tsx
1326
+ * import "../config/resources"; // registers them
1327
+ * import { declaredDataSources, declaredStorageSources } from "@rebasepro/types";
1328
+ *
1329
+ * <Rebase dataSources={declaredDataSources()} storageSources={declaredStorageSources()} />
1330
+ * ```
1331
+ *
1332
+ * The import is what registers them, so a bundler that drops an unused module
1333
+ * would leave this empty — hence the side-effect import above rather than a
1334
+ * bare re-export.
1335
+ */
1336
+ function declaredDataSources() {
1337
+ return declaredResources("database").map((r) => ({
1338
+ key: r.key,
1339
+ engine: r.engine,
1340
+ transport: r.transport,
1341
+ ...r.label !== void 0 ? { label: r.label } : {}
1342
+ }));
1343
+ }
1344
+ /** The declared buckets, in the shape `<Rebase storageSources>` takes. */
1345
+ function declaredStorageSources() {
1346
+ return declaredResources("bucket").map((r) => ({
1347
+ key: r.key,
1348
+ engine: r.engine,
1349
+ transport: r.transport,
1350
+ ...r.label !== void 0 ? { label: r.label } : {}
1351
+ }));
1352
+ }
1353
+ //#endregion
984
1354
  //#region src/types/storage_source.ts
985
1355
  /**
986
1356
  * Describes a named storage backend — a place files live.
@@ -1105,6 +1475,41 @@ function isLazyComponentRef(ref) {
1105
1475
  //#endregion
1106
1476
  //#region src/types/project_manifest.ts
1107
1477
  /**
1478
+ * Path prefixes the backend owns, which no static app may claim.
1479
+ *
1480
+ * One process — and, on the platform, one hostname — serves both the API and
1481
+ * however many static apps a project has. Mounting is longest-path-first, so an
1482
+ * app declaring `/api` would win against the API itself and every request to it
1483
+ * would be answered with that app's `index.html`: a 200 carrying HTML where the
1484
+ * caller expected JSON, from a project that looks deployed and healthy.
1485
+ *
1486
+ * Declared here rather than in either enforcer because both must agree. The CLI
1487
+ * checks it so a developer finds out while editing `rebase.json`; the control
1488
+ * plane checks it again at deploy intake, because the front door's correctness
1489
+ * cannot rest on a check that ran in somebody else's CLI — and a repository can
1490
+ * be deployed by a CLI older than this rule.
1491
+ */
1492
+ var RESERVED_BACKEND_PREFIXES = [
1493
+ "/api",
1494
+ "/health",
1495
+ "/healthz",
1496
+ "/livez",
1497
+ "/readyz",
1498
+ "/metrics"
1499
+ ];
1500
+ /**
1501
+ * Whether `path` collides with a prefix the backend owns.
1502
+ *
1503
+ * Compares at segment boundaries, so `/api` and `/api/v2` collide while
1504
+ * `/apidocs` does not — the same rule the router matches with, because a check
1505
+ * that is stricter than the router rejects paths that would have worked, and one
1506
+ * that is looser admits paths that will not.
1507
+ */
1508
+ function reservedPrefixFor(path) {
1509
+ const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
1510
+ return RESERVED_BACKEND_PREFIXES.find((reserved) => normalized === reserved || normalized.startsWith(`${reserved}/`));
1511
+ }
1512
+ /**
1108
1513
  * Version of the bundle *format* itself.
1109
1514
  *
1110
1515
  * Bumped only when the on-disk layout changes in a way an older runtime could
@@ -1128,6 +1533,31 @@ var BUNDLE_FORMAT_VERSION = 2;
1128
1533
  * any number of minors and patches while this stays put. It changes only when
1129
1534
  * the bundle/runtime contract breaks compatibility, and a project's
1130
1535
  * `manifest.runtime` range is matched against *this*.
1536
+ *
1537
+ * ## v2 — resources are declared, not configured
1538
+ *
1539
+ * `RebaseBackendConfig.dataSources` and `.storageSources` are gone. A project
1540
+ * declares its databases and buckets with `database()` / `bucket()` in its
1541
+ * config, and the runtime reads those declarations.
1542
+ *
1543
+ * This had to be a major, and the reason is the managed tier: it moves projects
1544
+ * onto new images WITHOUT rebuilding them. A bundle built against v1 exports
1545
+ * those keys, and a v2 runtime refuses them at boot — so without this bump, one
1546
+ * image rollout would crash-loop every tenant that had ever declared a second
1547
+ * database or bucket, in a wave, with the cause in a container log nobody is
1548
+ * watching.
1549
+ *
1550
+ * With the bump, a v1 bundle on a v2 runtime is refused by
1551
+ * `assertBundleCompatibility` with the remedy in the message, and the platform
1552
+ * keeps it on a v1 image until it is rebuilt. That is the whole purpose of this
1553
+ * number.
1554
+ *
1555
+ * **Release order matters and is not optional.** The control plane is the side
1556
+ * that rejects, so it ships FIRST: raise `SUPPORTED_RUNTIME_CONTRACT` in the
1557
+ * saas repo (it rejects only `contract >` its own, so it then accepts both),
1558
+ * deploy that, and only then release a runtime implementing v2. Shipping the
1559
+ * runtime first turns every deploy into a rejected intake blaming the tenant's
1560
+ * bundle.
1131
1561
  */
1132
1562
  var RUNTIME_CONTRACT_VERSION = 1;
1133
1563
  /** Header carrying the schema version an SDK was generated from. */
@@ -1445,6 +1875,6 @@ function isPublicStoragePath(path) {
1445
1875
  return p.startsWith("public/") || p.startsWith(`default/public/`);
1446
1876
  }
1447
1877
  //#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 };
1878
+ 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
1879
 
1450
1880
  //# sourceMappingURL=index.es.js.map