@rebasepro/server 0.11.1-canary.gfd39654 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -339,6 +339,161 @@ var ADMIN_COLLECTION_KEYS = [
339
339
  "sort",
340
340
  "titleProperty"
341
341
  ];
342
+ /**
343
+ * Every key that belongs inside a *property's* `admin` block, as data.
344
+ *
345
+ * The union of `AdminPropertyOptions` and its per-type extensions
346
+ * (`AdminStringOptions`, `AdminArrayOptions`, …) in `@rebasepro/admin-types`.
347
+ * It lives here for the same reason {@link ADMIN_COLLECTION_KEYS} does: the
348
+ * runtime consumers are core packages that the BaaS guard forbids from
349
+ * importing `@rebasepro/admin-types`. Here it is the boot-time collection
350
+ * validator in `@rebasepro/server`, which has to tell "you left `readOnly` at
351
+ * the top of the property, where nothing reads it" apart from "you invented a
352
+ * key we have never heard of".
353
+ *
354
+ * `@rebasepro/admin-types` re-exports this and asserts it names only real
355
+ * option keys.
356
+ *
357
+ * @group Models
358
+ */
359
+ var ADMIN_PROPERTY_KEYS = [
360
+ "canAddElements",
361
+ "clearable",
362
+ "columnWidth",
363
+ "customProps",
364
+ "disabled",
365
+ "expanded",
366
+ "Field",
367
+ "Filter",
368
+ "filterOperators",
369
+ "fixedFilter",
370
+ "hideFromCollection",
371
+ "includeEntityLink",
372
+ "includeId",
373
+ "markdown",
374
+ "minimalistView",
375
+ "multiline",
376
+ "Preview",
377
+ "previewAsTag",
378
+ "previewProperties",
379
+ "readOnly",
380
+ "sortable",
381
+ "spreadChildren",
382
+ "urlPreview",
383
+ "widget",
384
+ "widthPercentage"
385
+ ];
386
+ //#endregion
387
+ //#region ../types/src/types/data_source.ts
388
+ /**
389
+ * The default data-source key, used when a collection does not name a
390
+ * `dataSource`. Shared by the frontend router and the backend driver
391
+ * registry so both agree on "the default database".
392
+ * @group Models
393
+ */
394
+ var DEFAULT_DATA_SOURCE_KEY = "(default)";
395
+ /**
396
+ * Relation kinds assumed filterable when a driver does not say.
397
+ *
398
+ * `belongsTo` alone: its filter is a comparison on a column of the row being
399
+ * filtered, the one shape that needs no query construction a driver might not
400
+ * have. Everything else is a correlated subquery over another table.
401
+ *
402
+ * @group Models
403
+ */
404
+ var DEFAULT_FILTERABLE_RELATION_KINDS = ["belongsTo"];
405
+ /** @group Models */
406
+ var POSTGRES_CAPABILITIES = {
407
+ key: "postgres",
408
+ label: "PostgreSQL",
409
+ supportsRelations: true,
410
+ supportsSubcollections: false,
411
+ supportsRLS: true,
412
+ supportsReferences: false,
413
+ supportsColumnTypes: true,
414
+ supportsRealtime: true,
415
+ supportsVectors: true,
416
+ filterOperators: ALL_WHERE_FILTER_OPS,
417
+ filterableRelationKinds: [
418
+ "belongsTo",
419
+ "manyToMany",
420
+ "hasMany",
421
+ "hasOne"
422
+ ],
423
+ supportsSQLAdmin: true,
424
+ supportsDocumentAdmin: false,
425
+ supportsSchemaAdmin: true
426
+ };
427
+ /** @group Models */
428
+ var FIREBASE_CAPABILITIES = {
429
+ key: "firestore",
430
+ label: "Firebase / Firestore",
431
+ supportsRelations: false,
432
+ supportsSubcollections: true,
433
+ supportsRLS: false,
434
+ supportsReferences: true,
435
+ supportsColumnTypes: false,
436
+ supportsRealtime: true,
437
+ supportsVectors: false,
438
+ filterOperators: ALL_WHERE_FILTER_OPS.filter((op) => op !== "like" && op !== "ilike" && op !== "not-like" && op !== "not-ilike"),
439
+ filterableRelationKinds: [],
440
+ supportsSQLAdmin: false,
441
+ supportsDocumentAdmin: false,
442
+ supportsSchemaAdmin: false
443
+ };
444
+ /** @group Models */
445
+ var MONGODB_CAPABILITIES = {
446
+ key: "mongodb",
447
+ label: "MongoDB",
448
+ supportsRelations: false,
449
+ supportsSubcollections: true,
450
+ supportsRLS: false,
451
+ supportsReferences: true,
452
+ supportsColumnTypes: false,
453
+ supportsRealtime: false,
454
+ supportsVectors: false,
455
+ filterOperators: ALL_WHERE_FILTER_OPS,
456
+ filterableRelationKinds: [],
457
+ supportsSQLAdmin: false,
458
+ supportsDocumentAdmin: true,
459
+ supportsSchemaAdmin: true
460
+ };
461
+ /**
462
+ * Fallback capabilities when the driver is unknown.
463
+ * Enables everything so nothing is hidden unexpectedly.
464
+ * @group Models
465
+ */
466
+ var DEFAULT_CAPABILITIES = {
467
+ key: "(default)",
468
+ label: "Default",
469
+ supportsRelations: true,
470
+ supportsSubcollections: true,
471
+ supportsRLS: true,
472
+ supportsReferences: true,
473
+ supportsColumnTypes: true,
474
+ supportsRealtime: true,
475
+ supportsVectors: true,
476
+ filterOperators: ALL_WHERE_FILTER_OPS,
477
+ filterableRelationKinds: DEFAULT_FILTERABLE_RELATION_KINDS,
478
+ supportsSQLAdmin: true,
479
+ supportsDocumentAdmin: true,
480
+ supportsSchemaAdmin: true
481
+ };
482
+ var CAPABILITIES_REGISTRY = {
483
+ postgres: POSTGRES_CAPABILITIES,
484
+ firestore: FIREBASE_CAPABILITIES,
485
+ mongodb: MONGODB_CAPABILITIES,
486
+ "(default)": DEFAULT_CAPABILITIES
487
+ };
488
+ /**
489
+ * Look up capabilities for a given engine key.
490
+ * If `engine` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
491
+ * @group Models
492
+ */
493
+ function getDataSourceCapabilities(engine) {
494
+ if (!engine) return POSTGRES_CAPABILITIES;
495
+ return CAPABILITIES_REGISTRY[engine] ?? DEFAULT_CAPABILITIES;
496
+ }
342
497
  //#endregion
343
498
  //#region ../types/src/types/collections.ts
344
499
  /**
@@ -357,6 +512,29 @@ function isPostgresCollectionConfig(collection) {
357
512
  return !collection.engine || collection.engine === "postgres";
358
513
  }
359
514
  /**
515
+ * Narrows to the SQL collection fields — `table`, `relations`,
516
+ * `disableDefaultPolicies` — by asking the engine's declared capabilities
517
+ * rather than by naming Postgres.
518
+ *
519
+ * The two halves of this already existed and were never joined. The engine
520
+ * split (`PostgresCollectionConfig` / `FirebaseCollectionConfig` /
521
+ * `MongoDBCollectionConfig`) said which fields belong to which engine at the
522
+ * type level; {@link DataSourceCapabilities} said the same thing at runtime,
523
+ * down to a `supportsRelations` flag. So call sites guarded on the capability
524
+ * and then read a field the base type had to declare for them — which is why
525
+ * those fields were on the base, and why a MongoDB collection could be written
526
+ * with a `table`.
527
+ *
528
+ * Prefer this over {@link isPostgresCollectionConfig} wherever the question is
529
+ * "does this collection live in a SQL table", so a custom SQL engine
530
+ * registered through `registerDataSourceCapabilities` is included.
531
+ *
532
+ * @group Models
533
+ */
534
+ function isRelationalCollectionConfig(collection) {
535
+ return getDataSourceCapabilities(collection.engine).supportsRelations;
536
+ }
537
+ /**
360
538
  * Type guard for Firebase / Firestore collections.
361
539
  * @group Models
362
540
  */
@@ -467,94 +645,6 @@ function isSQLAdmin(admin) {
467
645
  return !!admin && typeof admin.executeSql === "function";
468
646
  }
469
647
  //#endregion
470
- //#region ../types/src/types/data_source.ts
471
- /**
472
- * The default data-source key, used when a collection does not name a
473
- * `dataSource`. Shared by the frontend router and the backend driver
474
- * registry so both agree on "the default database".
475
- * @group Models
476
- */
477
- var DEFAULT_DATA_SOURCE_KEY = "(default)";
478
- /** @group Models */
479
- var POSTGRES_CAPABILITIES = {
480
- key: "postgres",
481
- label: "PostgreSQL",
482
- supportsRelations: true,
483
- supportsSubcollections: false,
484
- supportsRLS: true,
485
- supportsReferences: false,
486
- supportsColumnTypes: true,
487
- supportsRealtime: true,
488
- filterOperators: ALL_WHERE_FILTER_OPS,
489
- supportsSQLAdmin: true,
490
- supportsDocumentAdmin: false,
491
- supportsSchemaAdmin: true
492
- };
493
- /** @group Models */
494
- var FIREBASE_CAPABILITIES = {
495
- key: "firestore",
496
- label: "Firebase / Firestore",
497
- supportsRelations: false,
498
- supportsSubcollections: true,
499
- supportsRLS: false,
500
- supportsReferences: true,
501
- supportsColumnTypes: false,
502
- supportsRealtime: true,
503
- filterOperators: ALL_WHERE_FILTER_OPS.filter((op) => op !== "like" && op !== "ilike" && op !== "not-like" && op !== "not-ilike"),
504
- supportsSQLAdmin: false,
505
- supportsDocumentAdmin: false,
506
- supportsSchemaAdmin: false
507
- };
508
- /** @group Models */
509
- var MONGODB_CAPABILITIES = {
510
- key: "mongodb",
511
- label: "MongoDB",
512
- supportsRelations: false,
513
- supportsSubcollections: true,
514
- supportsRLS: false,
515
- supportsReferences: true,
516
- supportsColumnTypes: false,
517
- supportsRealtime: false,
518
- filterOperators: ALL_WHERE_FILTER_OPS,
519
- supportsSQLAdmin: false,
520
- supportsDocumentAdmin: true,
521
- supportsSchemaAdmin: true
522
- };
523
- /**
524
- * Fallback capabilities when the driver is unknown.
525
- * Enables everything so nothing is hidden unexpectedly.
526
- * @group Models
527
- */
528
- var DEFAULT_CAPABILITIES = {
529
- key: "(default)",
530
- label: "Default",
531
- supportsRelations: true,
532
- supportsSubcollections: true,
533
- supportsRLS: true,
534
- supportsReferences: true,
535
- supportsColumnTypes: true,
536
- supportsRealtime: true,
537
- filterOperators: ALL_WHERE_FILTER_OPS,
538
- supportsSQLAdmin: true,
539
- supportsDocumentAdmin: true,
540
- supportsSchemaAdmin: true
541
- };
542
- var CAPABILITIES_REGISTRY = {
543
- postgres: POSTGRES_CAPABILITIES,
544
- firestore: FIREBASE_CAPABILITIES,
545
- mongodb: MONGODB_CAPABILITIES,
546
- "(default)": DEFAULT_CAPABILITIES
547
- };
548
- /**
549
- * Look up capabilities for a given engine key.
550
- * If `engine` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
551
- * @group Models
552
- */
553
- function getDataSourceCapabilities(engine) {
554
- if (!engine) return POSTGRES_CAPABILITIES;
555
- return CAPABILITIES_REGISTRY[engine] ?? DEFAULT_CAPABILITIES;
556
- }
557
- //#endregion
558
648
  //#region ../types/src/types/storage_source.ts
559
649
  /**
560
650
  * Describes a named storage backend — a place files live.
@@ -575,6 +665,98 @@ function getDataSourceCapabilities(engine) {
575
665
  * @group Models
576
666
  */
577
667
  var DEFAULT_STORAGE_SOURCE_KEY = "(default)";
668
+ /**
669
+ * The environment-variable suffix for a storage or data source key.
670
+ *
671
+ * `""` for the default source — so a single-bucket project keeps configuring
672
+ * plain `S3_BUCKET` — and `__<KEY>` for every named one, uppercased with
673
+ * non-alphanumerics collapsed to underscores: `media-cdn` → `S3_BUCKET__MEDIA_CDN`.
674
+ *
675
+ * The rule derives the variable name from the declared key rather than
676
+ * discovering keys by scanning the environment. Scanning would have to guess how
677
+ * `S3_BUCKET__MEDIA_CDN` splits into a key; deriving cannot be ambiguous, and a
678
+ * typo surfaces as a missing source at boot instead of a silently ignored
679
+ * variable.
680
+ *
681
+ * It lives in this package, with no dependencies, because four things must agree
682
+ * on it exactly: the CLI (validating a build), the runtime (reading its own
683
+ * environment), the control plane (writing a tenant's Secret), and the docs. A
684
+ * second implementation of a naming convention is a second chance to disagree.
685
+ *
686
+ * @group Models
687
+ */
688
+ function storageEnvSuffix(key, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
689
+ if (!key || key === defaultKey) return "";
690
+ const normalized = key.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
691
+ 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.`);
692
+ return `__${normalized}`;
693
+ }
694
+ /**
695
+ * Two distinct keys that collapse onto the same variable name, or `null`.
696
+ *
697
+ * `media-cdn` and `media_cdn` are different source keys but the same suffix, so
698
+ * without this one of them silently reads the other's configuration. Returns the
699
+ * offending pair rather than throwing, so each caller can raise it in its own
700
+ * idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy
701
+ * in a control plane.
702
+ *
703
+ * @group Models
704
+ */
705
+ function findStorageSuffixCollision(keys, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
706
+ const seen = /* @__PURE__ */ new Map();
707
+ for (const key of keys) {
708
+ const suffix = storageEnvSuffix(key, defaultKey);
709
+ const existing = seen.get(suffix);
710
+ if (existing !== void 0 && existing !== key) return {
711
+ a: existing,
712
+ b: key,
713
+ suffix
714
+ };
715
+ seen.set(suffix, key);
716
+ }
717
+ return null;
718
+ }
719
+ /**
720
+ * Merge the two places a project may declare storage sources into one list.
721
+ *
722
+ * `rebase.json` is authoritative for every field it states. Config code may add
723
+ * sources it does not mention and fill in fields it left out, but may not
724
+ * contradict it: the manifest is what a host reads to decide which buckets need
725
+ * configuring, and a runtime that quietly disagreed with it would put the
726
+ * console back to describing a topology the tenant does not have — the exact
727
+ * failure this whole mechanism exists to end.
728
+ *
729
+ * Note what is *not* here: no default source is invented when both inputs are
730
+ * empty. That decision belongs to the resolver, which knows whether declaring
731
+ * nothing means "one plain bucket" (it does) or "no storage at all".
732
+ *
733
+ * @group Models
734
+ */
735
+ function normalizeStorageSources(declared, exported) {
736
+ const merged = /* @__PURE__ */ new Map();
737
+ const declaredEntries = Array.isArray(declared) ? declared.filter((d) => d?.key).map((d) => [d.key, d]) : Object.entries(declared ?? {});
738
+ for (const [key, config] of declaredEntries) merged.set(key, {
739
+ key,
740
+ engine: config.engine,
741
+ transport: config.transport ?? "server",
742
+ ...config.label !== void 0 ? { label: config.label } : {}
743
+ });
744
+ for (const definition of exported ?? []) {
745
+ if (!definition?.key) continue;
746
+ const existing = merged.get(definition.key);
747
+ if (!existing) {
748
+ merged.set(definition.key, {
749
+ key: definition.key,
750
+ engine: definition.engine,
751
+ transport: definition.transport ?? "server",
752
+ ...definition.label !== void 0 ? { label: definition.label } : {}
753
+ });
754
+ continue;
755
+ }
756
+ if (existing.label === void 0 && definition.label !== void 0) existing.label = definition.label;
757
+ }
758
+ return Array.from(merged.values());
759
+ }
578
760
  //#endregion
579
761
  //#region ../types/src/types/project_manifest.ts
580
762
  /** Header carrying the schema version an SDK was generated from. */
@@ -770,6 +952,6 @@ function computeSchemaVersion(collections) {
770
952
  return `v1:${hex(h1)}${hex(h2)}`;
771
953
  }
772
954
  //#endregion
773
- export { RebaseClientError as C, RebaseApiError as S, toCanonicalOp as _, DEFAULT_DATA_SOURCE_KEY as a, GeoPoint as b, policy as c, getDeclaredSubcollections as d, isPostgresCollectionConfig as f, REST_TO_CANONICAL as g, NULL_OPS as h, DEFAULT_STORAGE_SOURCE_KEY as i, isToMany as l, CANONICAL_TO_REST as m, serializeCollections as n, getDataSourceCapabilities as o, ADMIN_COLLECTION_KEYS as p, SCHEMA_VERSION_HEADER as r, isSQLAdmin as s, computeSchemaVersion as t, getCollectionDataPath as u, EntityReference as v, Vector as x, EntityRelation as y };
955
+ export { EntityReference as C, RebaseApiError as D, Vector as E, RebaseClientError as O, toCanonicalOp as S, GeoPoint as T, ADMIN_COLLECTION_KEYS as _, findStorageSuffixCollision as a, NULL_OPS as b, isSQLAdmin as c, getCollectionDataPath as d, getDeclaredSubcollections as f, getDataSourceCapabilities as g, DEFAULT_DATA_SOURCE_KEY as h, DEFAULT_STORAGE_SOURCE_KEY as i, policy as l, isRelationalCollectionConfig as m, serializeCollections as n, normalizeStorageSources as o, isPostgresCollectionConfig as p, SCHEMA_VERSION_HEADER as r, storageEnvSuffix as s, computeSchemaVersion as t, isToMany as u, ADMIN_PROPERTY_KEYS as v, EntityRelation as w, REST_TO_CANONICAL as x, CANONICAL_TO_REST as y };
774
956
 
775
- //# sourceMappingURL=src-BYbxB4PR.js.map
957
+ //# sourceMappingURL=src-Ivjud8jD.js.map