@rebasepro/cms-types 0.17.3-canary.gdd23447 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +49 -0
  2. package/dist/admin_collection.d.ts +49 -53
  3. package/dist/collections.d.ts +1 -1
  4. package/dist/controllers/customization_controller.d.ts +2 -2
  5. package/dist/controllers/navigation.d.ts +0 -1
  6. package/dist/controllers/registry.d.ts +20 -0
  7. package/dist/define_collection.d.ts +132 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.es.js +12 -8
  10. package/dist/index.es.js.map +1 -1
  11. package/dist/types/plugins.d.ts +2 -2
  12. package/dist/types/property_options.d.ts +132 -1
  13. package/dist/types/slots.d.ts +30 -4
  14. package/dist/types/translations.d.ts +96 -4
  15. package/package.json +27 -23
  16. package/src/admin_collection.ts +0 -775
  17. package/src/augment.ts +0 -79
  18. package/src/collections.ts +0 -312
  19. package/src/controllers/analytics_controller.tsx +0 -57
  20. package/src/controllers/auth.ts +0 -122
  21. package/src/controllers/customization_controller.tsx +0 -81
  22. package/src/controllers/dialogs_controller.tsx +0 -37
  23. package/src/controllers/index.ts +0 -10
  24. package/src/controllers/local_config_persistence.tsx +0 -22
  25. package/src/controllers/navigation.ts +0 -288
  26. package/src/controllers/registry.ts +0 -114
  27. package/src/controllers/side_dialogs_controller.tsx +0 -82
  28. package/src/controllers/side_panel_controller.tsx +0 -112
  29. package/src/controllers/snackbar.ts +0 -51
  30. package/src/index.ts +0 -20
  31. package/src/react_component_ref.ts +0 -52
  32. package/src/rebase_context.ts +0 -81
  33. package/src/types/breadcrumbs.ts +0 -16
  34. package/src/types/builders.ts +0 -18
  35. package/src/types/collection_views.tsx +0 -125
  36. package/src/types/component_overrides.ts +0 -244
  37. package/src/types/entity_actions.tsx +0 -134
  38. package/src/types/entity_display.ts +0 -182
  39. package/src/types/entity_link_builder.ts +0 -8
  40. package/src/types/entity_views.tsx +0 -135
  41. package/src/types/export_import.ts +0 -26
  42. package/src/types/form_layout.ts +0 -137
  43. package/src/types/formex.ts +0 -45
  44. package/src/types/index.ts +0 -18
  45. package/src/types/locales.ts +0 -81
  46. package/src/types/modify_collections.tsx +0 -6
  47. package/src/types/plugins.tsx +0 -346
  48. package/src/types/property_config.tsx +0 -97
  49. package/src/types/property_options.ts +0 -300
  50. package/src/types/slots.tsx +0 -334
  51. package/src/types/translations.ts +0 -1104
  52. package/src/types/user_management_delegate.ts +0 -23
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # @rebasepro/cms-types
2
+
3
+ Type definitions for the Rebase CMS: collection and property shapes, the entity
4
+ and navigation models, and the translation keys the admin panel renders.
5
+
6
+ This package contains **types only**. Nothing here executes — it is the
7
+ vocabulary that the runtime, the generated SDK and the admin panel all agree on,
8
+ kept in one package so a change to a collection's shape cannot mean one thing to
9
+ the server and another to the panel.
10
+
11
+ The runtime that consumes these types is
12
+ [`@rebasepro/cms`](https://www.npmjs.com/package/@rebasepro/cms). If you are
13
+ building an app, that is the package you want; you will normally get this one as
14
+ a transitive dependency rather than installing it yourself.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @rebasepro/cms-types
20
+ ```
21
+
22
+ ESM-only: `"type": "module"` with no CommonJS build, so it is loaded with
23
+ `import`. `require()` of it resolves only on Node 22.12+, which supports
24
+ `require(esm)`.
25
+
26
+ ## Usage
27
+
28
+ ```ts
29
+ import type { CollectionConfig } from "@rebasepro/cms-types";
30
+
31
+ export const posts: CollectionConfig = {
32
+ name: "Posts",
33
+ slug: "posts",
34
+ table: "posts",
35
+ properties: {
36
+ title: { name: "Title", type: "string", validation: { required: true } },
37
+ body: { name: "Body", type: "string", admin: { multiline: true } }
38
+ }
39
+ };
40
+ ```
41
+
42
+ ## Documentation
43
+
44
+ - [Collections](https://rebase.pro/docs/backend/collections)
45
+ - [Full documentation](https://rebase.pro/docs)
46
+
47
+ ## License
48
+
49
+ MIT
@@ -15,7 +15,7 @@
15
15
  * `WhereFilterOp` mistake, and this block is far bigger than one union.
16
16
  */
17
17
  import type React from "react";
18
- import type { CollectionConfig, ComponentRef, FilterPreset, FilterValues, FirebaseCollectionConfig, FirebaseProperties, InferEntityType, MongoDBCollectionConfig, MongoProperties, OrderBySpec, PostgresCollectionConfig, PostgresProperties, User } from "@rebasepro/types";
18
+ import type { CollectionCallbacks, CollectionConfig, ComponentRef, FilterPreset, FilterValues, OrderBySpec, PostgresCollectionConfig, User } from "@rebasepro/types";
19
19
  import type { AdditionalFieldDelegate, CollectionActionsProps, CollectionSize, DefaultSelectedViewBuilder, KanbanConfig, SelectionController, ViewMode } from "./collections.js";
20
20
  import type { EntityCustomView, FormViewConfig } from "./types/entity_views.js";
21
21
  import type { CollectionCustomView } from "./types/collection_views.js";
@@ -122,6 +122,48 @@ export type AdminCollectionOptions<M extends Record<string, unknown> = Record<st
122
122
  * If not specified, the list view uses a smart default (Title, Status, Date).
123
123
  */
124
124
  listProperties?: ColumnKey<M>[];
125
+ /**
126
+ * Lifecycle callbacks that run **in the browser**, in the admin panel.
127
+ *
128
+ * The twin of the collection's top-level `callbacks`, and the distinction is
129
+ * only where the code runs — the shape is identical:
130
+ *
131
+ * - `callbacks` runs on the server, on every path that reaches it (REST,
132
+ * realtime, `dataAsAdmin`). Its bodies are stripped from the admin bundle,
133
+ * so a secret read there never leaves the server.
134
+ * - `browserCallbacks` runs in the panel, and nowhere else. It ships to
135
+ * every visitor.
136
+ *
137
+ * This exists for collections on a `direct` or `custom` transport — a
138
+ * Firestore collection the panel talks to itself, with no Rebase server in
139
+ * the request path. Nothing server-side sees those writes, so `callbacks`
140
+ * can never fire for them; this block is the only place their lifecycle
141
+ * logic can live.
142
+ *
143
+ * Two rules follow from "ships to every visitor", and neither is a style
144
+ * preference:
145
+ *
146
+ * 1. **No secrets.** No API keys, no `process.env`, no logic you would mind
147
+ * a reader of the bundle seeing. Put that in `callbacks`.
148
+ * 2. **Not a security boundary.** A `browserCallbacks.afterRead` that
149
+ * redacts a field redacts it *after* the browser already holds the row —
150
+ * for a direct transport the raw document came straight from the store.
151
+ * It is presentation. Redaction that has to hold belongs in `callbacks`,
152
+ * or in the store's own rules.
153
+ *
154
+ * On a server-transport collection (the default) the server has already run
155
+ * `callbacks` before the row arrives, so a `browserCallbacks.afterRead`
156
+ * here runs *in addition* — write it to be idempotent, or don't write it.
157
+ *
158
+ * ```ts
159
+ * admin: {
160
+ * browserCallbacks: {
161
+ * afterRead: ({ row }) => ({ ...row, label: `${row.city} (${row.code})` })
162
+ * }
163
+ * }
164
+ * ```
165
+ */
166
+ browserCallbacks?: CollectionCallbacks<M, USER>;
125
167
  /**
126
168
  * How a record of this collection shows up — its title, subtitle, image,
127
169
  * status, date and tags.
@@ -509,55 +551,13 @@ export type AdminCollectionOptions<M extends Record<string, unknown> = Record<st
509
551
  * writing one is an error — which is the guarantee a BaaS install depends on.
510
552
  */
511
553
  /**
512
- * Define a collection with the admin block type-checked.
513
- *
514
- * The same identity function as `defineCollection` in `@rebasepro/common` — which
515
- * is what a BaaS or headless project uses, and where `admin` does not exist at all
516
- * — with one difference: importing this one brings the augmentation with it, so
517
- * `admin: { icon, listProperties, kanban }` gets completion and a typo is an
518
- * error. See {@link AdminCollectionOptions}.
519
- *
520
- * Import it from the layer you are in. A project with an admin panel wants this
521
- * one; a project without one has no `admin` block to check.
522
- *
523
- * `const P` captures the literal property types, which is what gives
524
- * `admin.display`, `admin.sort` and `admin.propertiesOrder` completion over
525
- * the collection's own property keys rather than plain `string`.
554
+ * `defineCollection` lives in `./define_collection`, and this is why.
526
555
  *
527
- * @example
528
- * export default defineCollection({
529
- * slug: "posts",
530
- * table: "posts",
531
- * properties: {
532
- * title: { name: "Title", type: "string" },
533
- * status: { name: "Status", type: "string" }
534
- * },
535
- * admin: {
536
- * icon: "FileText",
537
- * display: { title: "title" }, // completion: "title" | "status"
538
- * listProperties: ["title", "status"]
539
- * }
540
- * });
541
- *
542
- * @group Builder
556
+ * A collection file is loaded by the backend as well as by the panel, so the
557
+ * builder it imports has to be reachable without React. This module names
558
+ * `React` throughout — it describes the panel's option types — so the builder
559
+ * sits apart from it and the barrel exports both.
543
560
  */
544
- export declare function defineCollection<const P extends PostgresProperties, USER extends User = User>(collection: Omit<PostgresCollectionConfig<InferEntityType<P>, USER>, "properties"> & {
545
- properties: P;
546
- }): PostgresCollectionConfig<InferEntityType<P>, USER> & {
547
- properties: P;
548
- };
549
- /** Define a Firestore-backed collection with the admin block checked. @group Builder */
550
- export declare function defineCollection<const P extends FirebaseProperties, USER extends User = User>(collection: Omit<FirebaseCollectionConfig<InferEntityType<P>, USER>, "properties"> & {
551
- properties: P;
552
- }): FirebaseCollectionConfig<InferEntityType<P>, USER> & {
553
- properties: P;
554
- };
555
- /** Define a MongoDB-backed collection with the admin block checked. @group Builder */
556
- export declare function defineCollection<const P extends MongoProperties, USER extends User = User>(collection: Omit<MongoDBCollectionConfig<InferEntityType<P>, USER>, "properties"> & {
557
- properties: P;
558
- }): MongoDBCollectionConfig<InferEntityType<P>, USER> & {
559
- properties: P;
560
- };
561
561
  /**
562
562
  * Re-exported from `@rebasepro/types`, where the list has to live: the ts-morph
563
563
  * schema editor in `@rebasepro/server` needs it to know which keys go inside the
@@ -573,12 +573,8 @@ export type { AdminCollectionKey } from "@rebasepro/types";
573
573
  * Core's list, re-exported through a `satisfies` clause that is the agreement
574
574
  * check: a key core names that is not an option here fails to compile, and
575
575
  * `satisfies` keeps the literal tuple type rather than widening it to `string[]`.
576
- *
577
- * The reverse direction — an option missing from core's list — has no type-level
578
- * expression, since there is no exhaustiveness check over an optional-property
579
- * keyof. `test/admin_collection.test.ts` counts them instead.
580
576
  */
581
- export declare const ADMIN_COLLECTION_KEYS: readonly ["Actions", "additionalFields", "alwaysApplyDefaultValues", "components", "customViews", "defaultEntityAction", "defaultFilter", "defaultSelectedView", "defaultSize", "defaultViewMode", "disableDefaultActions", "display", "enabledViews", "entityActions", "entityViews", "exportable", "filterPresets", "fixedFilter", "form", "formAutoSave", "formView", "group", "hideFromEntityViews", "hideFromNavigation", "hideIdFromCollection", "hideIdFromForm", "icon", "includeJsonView", "inlineEditing", "kanban", "listProperties", "localChangesBackup", "openEntityMode", "orderProperty", "pagination", "previewProperties", "propertiesOrder", "selectionController", "selectionEnabled", "sideDialogWidth", "sort"];
577
+ export declare const ADMIN_COLLECTION_KEYS: readonly ["Actions", "additionalFields", "alwaysApplyDefaultValues", "browserCallbacks", "components", "customViews", "defaultEntityAction", "defaultFilter", "defaultSelectedView", "defaultSize", "defaultViewMode", "disableDefaultActions", "display", "enabledViews", "entityActions", "entityViews", "exportable", "filterPresets", "fixedFilter", "form", "formAutoSave", "formView", "group", "hideFromEntityViews", "hideFromNavigation", "hideIdFromCollection", "hideIdFromForm", "icon", "includeJsonView", "inlineEditing", "kanban", "listProperties", "localChangesBackup", "openEntityMode", "orderProperty", "pagination", "previewProperties", "propertiesOrder", "selectionController", "selectionEnabled", "sideDialogWidth", "sort"];
582
578
  /**
583
579
  * A collection as the admin panel works with it: the contract with the `admin`
584
580
  * block flattened onto the top level.
@@ -12,7 +12,7 @@
12
12
  * That is what made them safe to lift: they were never part of the BaaS surface,
13
13
  * only stored next to it.
14
14
  */
15
- import React from "react";
15
+ import type React from "react";
16
16
  import type { Entity, EntityStatus, FilterValues, OrderByTuple, User } from "@rebasepro/types";
17
17
  import type { RebaseContext } from "./rebase_context.js";
18
18
  import type { AdminCollection, PropertyPath } from "@rebasepro/cms-types";
@@ -5,7 +5,7 @@ import type { EntityCustomView } from "../types/entity_views.js";
5
5
  import type { CollectionCustomView } from "../types/collection_views.js";
6
6
  import type { RebasePlugin } from "../types/plugins.js";
7
7
  import type { PropertyConfig } from "../types/property_config.js";
8
- import type { SlotContribution } from "../types/slots.js";
8
+ import type { AnySlotContribution } from "../types/slots.js";
9
9
  import type { ComponentOverrideMap } from "../types/component_overrides.js";
10
10
  export type CustomizationController = {
11
11
  /**
@@ -19,7 +19,7 @@ export type CustomizationController = {
19
19
  /**
20
20
  * Pre-merged slots from plugins + direct slot contributions.
21
21
  */
22
- resolvedSlots: SlotContribution[];
22
+ resolvedSlots: AnySlotContribution[];
23
23
  /**
24
24
  * List of additional custom views for entities.
25
25
  * You can use the key to reference the custom view in
@@ -125,7 +125,6 @@ export interface AppView {
125
125
  * You can use any of the icons in the Lucide specs:
126
126
  * https://lucide.dev/icons/
127
127
  * e.g. 'ShoppingCart' or 'User'
128
- * Find all the icons in https://rebase.pro/docs/icons
129
128
  */
130
129
  icon?: string | React.ReactNode;
131
130
  /**
@@ -67,8 +67,28 @@ export interface RebaseCMSConfig<EC extends AdminCollection = AdminCollection> {
67
67
  basePath?: string;
68
68
  }
69
69
  export interface RebaseStudioConfig {
70
+ /**
71
+ * Which built-in tools to register. Omit for all of them; pass a shorter
72
+ * list to hide the rest.
73
+ */
70
74
  tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "backups" | "api" | "logs" | "api-keys")[];
75
+ /** Replaces the Studio landing page. */
71
76
  homePage?: ReactNode;
77
+ /**
78
+ * Your own tools, added beside the built-in ones.
79
+ *
80
+ * These are ordinary {@link AppView}s — the only thing that makes a view a
81
+ * Studio tool rather than a CMS view is being registered here rather than
82
+ * on `<RebaseCMS views>`: the drawer shows CMS views in content mode and
83
+ * these in Studio mode.
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <RebaseStudio devViews={[
88
+ * { slug: "queues", name: "Queues", group: "Compute", view: <QueuesView/> }
89
+ * ]}/>
90
+ * ```
91
+ */
72
92
  devViews?: AppView[];
73
93
  }
74
94
  /**
@@ -0,0 +1,132 @@
1
+ /**
2
+ * `defineCollection` — the admin-aware builder, in a module a backend can load.
3
+ *
4
+ * This is the function every scaffolded collection file imports, and it must be
5
+ * reachable from a Node process that has no React and no DOM. So it lives here,
6
+ * apart from `admin_collection.ts` (which describes the panel's option types and
7
+ * names `React` throughout) and well away from `collections.ts` (the panel's
8
+ * view models, which import React as a value).
9
+ *
10
+ * The side-effect import below is the other half of what the import buys you:
11
+ * `augment.ts` is what declares `admin` on `BaseCollectionConfig` and on every
12
+ * property type, so importing this builder brings the block's type-checking with
13
+ * it. It is types only, and compiles to nothing.
14
+ */
15
+ import "./augment.js";
16
+ import type { FirebaseCollectionConfig, FirebaseProperties, FirebaseProperty, InferEntityType, MongoDBCollectionConfig, MongoProperties, MongoProperty, PostgresCollectionConfig, PostgresProperties, PostgresProperty, Properties, Property, StrictProperties, User } from "@rebasepro/types";
17
+ import { type ResourceRef } from "@rebasepro/types";
18
+ /**
19
+ * The engines a collection can name. Absent means Postgres.
20
+ *
21
+ * The discriminant that replaced three overloads of `defineCollection`. See
22
+ * {@link CollectionConfigForEngine} for why that mattered.
23
+ */
24
+ type CollectionEngine = "postgres" | "firestore" | "mongodb";
25
+ /**
26
+ * The concrete collection type an `engine` selects.
27
+ *
28
+ * `defineCollection` used to be three overloads — one per engine — and overload
29
+ * resolution is what made its errors unreadable. When no overload matches,
30
+ * TypeScript emits **one** diagnostic at the call site listing each overload's
31
+ * *first* failure, so:
32
+ *
33
+ * - a bad `defaultValue` **and** a misspelled `admin.display.title` in the same
34
+ * collection reported only the first. Fixing it revealed the second on the
35
+ * next run, one per edit-compile cycle;
36
+ * - the error landed on `defineCollection(`, not on the key that was wrong;
37
+ * - and every Postgres collection's error dragged `FirebaseCollectionConfig`
38
+ * and `MongoDBCollectionConfig` through the message, naming two engines the
39
+ * author had not mentioned and does not use.
40
+ *
41
+ * With one signature there is no resolution to fail: each error is reported
42
+ * where it is, all of them at once, against the one config type the `engine`
43
+ * selects.
44
+ */
45
+ type CollectionConfigForEngine<E, P, USER extends User> = E extends "firestore" ? FirebaseCollectionConfig<EntityShapeOf<P>, USER> : E extends "mongodb" ? MongoDBCollectionConfig<EntityShapeOf<P>, USER> : PostgresCollectionConfig<EntityShapeOf<P>, USER>;
46
+ /**
47
+ * `InferEntityType`, tolerant of a property map that has an error in it.
48
+ *
49
+ * `P` is deliberately **unconstrained** on the builder, and this is why. A
50
+ * constraint TypeScript cannot satisfy is a constraint it silently falls back
51
+ * from: one property with a bad `defaultValue` made `P extends PostgresProperties`
52
+ * fail, `P` became `PostgresProperties`, `M` became `Record<string, unknown>`,
53
+ * and every `admin` key — `display.title`, `listProperties`, `propertiesOrder` —
54
+ * widened to `string` and stopped being checked. So a collection with two
55
+ * mistakes reported one, and reported the second only after the first was fixed.
56
+ *
57
+ * With no constraint, `keyof P` survives a bad property and the `admin` block is
58
+ * still checked against the real key set. Exactness and the engine gate move
59
+ * into `StrictProperties`, which reports them on the property itself.
60
+ */
61
+ type EntityShapeOf<P> = InferEntityType<{
62
+ [K in keyof P]: P[K] extends Property ? P[K] : Property;
63
+ }>;
64
+ /** The property union an engine admits — the engine gate, as a type. */
65
+ type PropertyForEngine<E> = E extends "firestore" ? FirebaseProperty : E extends "mongodb" ? MongoProperty : PostgresProperty;
66
+ /** {@link PropertyForEngine} as a property map, for the `P` constraint. */
67
+ type PropertiesForEngine<E> = E extends "firestore" ? FirebaseProperties : E extends "mongodb" ? MongoProperties : PostgresProperties;
68
+ /**
69
+ * Define a collection with the admin block type-checked.
70
+ *
71
+ * The same identity function as `defineCollection` in `@rebasepro/common` — which
72
+ * is what a BaaS or headless project uses, and where `admin` does not exist at all
73
+ * — with one difference: importing this one brings the augmentation with it, so
74
+ * `admin: { icon, listProperties, kanban }` gets completion and a typo is an
75
+ * error. See {@link AdminCollectionOptions}.
76
+ *
77
+ * Import it from the layer you are in. A project with an admin panel wants this
78
+ * one; a project without one has no `admin` block to check.
79
+ *
80
+ * `const P` captures the literal property types, which is what gives
81
+ * `admin.display`, `admin.sort` and `admin.propertiesOrder` completion over
82
+ * the collection's own property keys rather than plain `string`.
83
+ *
84
+ * @example
85
+ * export default defineCollection({
86
+ * slug: "posts",
87
+ * table: "posts",
88
+ * properties: {
89
+ * title: { name: "Title", type: "string" },
90
+ * status: { name: "Status", type: "string" }
91
+ * },
92
+ * admin: {
93
+ * icon: "FileText",
94
+ * display: { title: "title" }, // completion: "title" | "status"
95
+ * listProperties: ["title", "status"]
96
+ * }
97
+ * });
98
+ *
99
+ * @group Builder
100
+ */
101
+ export declare function defineCollection<const E extends CollectionEngine = "postgres",
102
+ /**
103
+ * The properties, **constrained**. This is what checks them, and — just as
104
+ * importantly — what supplies the contextual type inside them: without a
105
+ * constraint the parameter of an inline
106
+ * `callbacks: { beforeSave: ({ value }) => … }` has nothing to be typed
107
+ * from, and TypeScript reports an implicit `any` on a callback the author
108
+ * wrote correctly.
109
+ */
110
+ const P extends PropertiesForEngine<E> & Properties = PropertiesForEngine<E> & Properties,
111
+ /**
112
+ * The properties again, **unconstrained**, and this is why there are two.
113
+ *
114
+ * A constraint TypeScript cannot satisfy is one it silently falls back
115
+ * from: one property with a bad `defaultValue` made `P` become
116
+ * `PostgresProperties`, the entity shape become `Record<string, unknown>`,
117
+ * and every `admin` key — `display.title`, `listProperties`,
118
+ * `propertiesOrder` — widen to `string` and stop being checked. A
119
+ * collection with two mistakes reported one, and revealed the second only
120
+ * after the first was fixed.
121
+ *
122
+ * `KEYS` has no constraint to fall back from, so `keyof KEYS` survives a bad
123
+ * property and the `admin` block is still checked against the real key set.
124
+ */
125
+ const KEYS = Properties, USER extends User = User>(collection: Omit<CollectionConfigForEngine<E, KEYS, USER>, "properties" | "engine" | "dataSource"> & {
126
+ engine?: E;
127
+ properties: StrictProperties<P, PropertyForEngine<E>> & KEYS;
128
+ dataSource?: ResourceRef;
129
+ }): CollectionConfigForEngine<E, KEYS, USER> & {
130
+ properties: KEYS;
131
+ };
132
+ export {};
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@
11
11
  import "./augment.js";
12
12
  export * from "./types/property_options.js";
13
13
  export * from "./react_component_ref.js";
14
+ export * from "./define_collection.js";
14
15
  export * from "./collections.js";
15
16
  export * from "./admin_collection.js";
16
17
  export * from "./rebase_context.js";
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ADMIN_COLLECTION_KEYS as ADMIN_COLLECTION_KEYS$1, ADMIN_PROPERTY_KEYS as ADMIN_PROPERTY_KEYS$1, nestAdminCollectionKeys } from "@rebasepro/types";
1
+ import { ADMIN_COLLECTION_KEYS as ADMIN_COLLECTION_KEYS$1, ADMIN_PROPERTY_KEYS as ADMIN_PROPERTY_KEYS$1, nestAdminCollectionKeys, resolveResourceRefs } from "@rebasepro/types";
2
2
  //#region src/types/property_options.ts
3
3
  /**
4
4
  * Core's list, re-exported through the same `satisfies` agreement check that
@@ -39,19 +39,23 @@ function asReactComponent(component) {
39
39
  return component;
40
40
  }
41
41
  //#endregion
42
- //#region src/admin_collection.ts
43
- /** Identity at runtime; the overloads above are the whole point. @group Builder */
42
+ //#region src/define_collection.ts
43
+ /**
44
+ * At runtime this records the collection as data: a resource handle written
45
+ * where a key belongs — `dataSource: analytics`, `storageSource: media` — is
46
+ * replaced by its key, so what leaves here serialises and compares like the
47
+ * string it always was. The signature above is the rest of the point.
48
+ * @group Builder
49
+ */
44
50
  function defineCollection(collection) {
45
- return collection;
51
+ return resolveResourceRefs(collection);
46
52
  }
53
+ //#endregion
54
+ //#region src/admin_collection.ts
47
55
  /**
48
56
  * Core's list, re-exported through a `satisfies` clause that is the agreement
49
57
  * check: a key core names that is not an option here fails to compile, and
50
58
  * `satisfies` keeps the literal tuple type rather than widening it to `string[]`.
51
- *
52
- * The reverse direction — an option missing from core's list — has no type-level
53
- * expression, since there is no exhaustiveness check over an optional-property
54
- * keyof. `test/admin_collection.test.ts` counts them instead.
55
59
  */
56
60
  var ADMIN_COLLECTION_KEYS = ADMIN_COLLECTION_KEYS$1;
57
61
  /**