@rebasepro/admin 0.7.0 → 0.8.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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{CollectionEditorDialog-iGgS4rLX.js → CollectionEditorDialog-BO_aQ-Z4.js} +7 -7
  3. package/dist/CollectionEditorDialog-BO_aQ-Z4.js.map +1 -0
  4. package/dist/{PropertyEditView-C9yhLyja.js → PropertyEditView-DKzOpMjR.js} +64 -38
  5. package/dist/PropertyEditView-DKzOpMjR.js.map +1 -0
  6. package/dist/{RouterCollectionsStudioView-Dqx27GD8.js → RouterCollectionsStudioView-BQTIExjA.js} +4 -4
  7. package/dist/{RouterCollectionsStudioView-Dqx27GD8.js.map → RouterCollectionsStudioView-BQTIExjA.js.map} +1 -1
  8. package/dist/collection_editor/_cms_internals.d.ts +1 -1
  9. package/dist/collection_editor/api/generateCollectionApi.d.ts +3 -2
  10. package/dist/collection_editor/serializable_types.d.ts +5 -9
  11. package/dist/collection_editor/serializable_utils.d.ts +2 -2
  12. package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +1 -2
  13. package/dist/collection_editor_ui.js +4 -4
  14. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  15. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  16. package/dist/components/RebaseCMS.d.ts +1 -1
  17. package/dist/components/SelectableTable/SelectionStore.d.ts +12 -21
  18. package/dist/components/field_configs.d.ts +1 -1
  19. package/dist/editor/editor.d.ts +0 -6
  20. package/dist/editor.js +1 -3
  21. package/dist/editor.js.map +1 -1
  22. package/dist/form/components/StorageUploadProgress.d.ts +6 -1
  23. package/dist/form/index.d.ts +0 -1
  24. package/dist/{history-ChHgyyvM.js → history-B3cqBzEV.js} +2 -2
  25. package/dist/{history-ChHgyyvM.js.map → history-B3cqBzEV.js.map} +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +2 -2
  28. package/dist/preview/components/StorageThumbnail.d.ts +3 -1
  29. package/dist/{src-DOX2nOyh.js → src-cxV1ODRG.js} +178 -460
  30. package/dist/src-cxV1ODRG.js.map +1 -0
  31. package/dist/types/components/PropertyPreviewProps.d.ts +2 -1
  32. package/dist/types/fields.d.ts +4 -6
  33. package/package.json +18 -18
  34. package/src/collection_editor/_cms_internals.ts +1 -1
  35. package/src/collection_editor/api/generateCollectionApi.ts +3 -2
  36. package/src/collection_editor/pgColumnToProperty.ts +2 -2
  37. package/src/collection_editor/serializable_types.ts +14 -27
  38. package/src/collection_editor/serializable_utils.ts +25 -37
  39. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +2 -2
  40. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +41 -24
  41. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +0 -9
  42. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +35 -1
  43. package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +1 -1
  44. package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -1
  45. package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +7 -29
  46. package/src/collection_editor/useJsonCollectionsConfigController.tsx +2 -2
  47. package/src/components/DefaultDrawer.tsx +1 -1
  48. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +11 -9
  49. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +2 -1
  50. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +2 -1
  51. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +23 -20
  52. package/src/components/EntityCollectionTable/index.tsx +1 -1
  53. package/src/components/EntityCollectionTable/table_bindings.tsx +24 -44
  54. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +1 -1
  55. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +12 -1
  56. package/src/components/EntityCollectionView/EntityCollectionView.tsx +8 -25
  57. package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -1
  58. package/src/components/EntityCollectionView/useBoardDataController.tsx +12 -40
  59. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +3 -3
  60. package/src/components/EntityDetailView.tsx +2 -2
  61. package/src/components/EntityEditView.tsx +2 -2
  62. package/src/components/EntityEditViewFormActions.tsx +3 -3
  63. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  64. package/src/components/RebaseCMS.tsx +2 -3
  65. package/src/components/RebaseNavigation.tsx +3 -2
  66. package/src/components/RelationSelector.tsx +2 -2
  67. package/src/components/SelectableTable/SelectableTable.tsx +11 -3
  68. package/src/components/SelectableTable/SelectionStore.ts +18 -48
  69. package/src/components/common/default_entity_actions.tsx +15 -4
  70. package/src/components/field_configs.tsx +0 -14
  71. package/src/editor/editor.tsx +4 -7
  72. package/src/form/EntityFormActions.tsx +2 -2
  73. package/src/form/EntityFormBinding.tsx +1 -1
  74. package/src/form/components/StorageUploadProgress.tsx +9 -2
  75. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +12 -1
  76. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +4 -4
  77. package/src/form/field_bindings/RelationFieldBinding.tsx +5 -7
  78. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +19 -15
  79. package/src/form/index.tsx +0 -1
  80. package/src/index.ts +1 -1
  81. package/src/preview/PropertyPreview.tsx +1 -16
  82. package/src/preview/components/StorageThumbnail.tsx +24 -7
  83. package/src/types/components/PropertyPreviewProps.tsx +1 -1
  84. package/src/types/fields.tsx +2 -7
  85. package/src/util/previews.ts +20 -0
  86. package/src/util/propertyConfigMapper.ts +3 -3
  87. package/src/util/property_utils.tsx +1 -2
  88. package/dist/CollectionEditorDialog-iGgS4rLX.js.map +0 -1
  89. package/dist/PropertyEditView-C9yhLyja.js.map +0 -1
  90. package/dist/components/EntityCollectionTable/fields/VirtualTableDateField.d.ts +0 -12
  91. package/dist/components/EntityCollectionTable/fields/VirtualTableInput.d.ts +0 -10
  92. package/dist/components/EntityCollectionTable/fields/VirtualTableNumberInput.d.ts +0 -9
  93. package/dist/components/EntityCollectionTable/fields/VirtualTableSwitch.d.ts +0 -8
  94. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +0 -11
  95. package/dist/src-DOX2nOyh.js.map +0 -1
  96. package/src/components/EntityCollectionTable/fields/VirtualTableDateField.tsx +0 -39
  97. package/src/components/EntityCollectionTable/fields/VirtualTableInput.tsx +0 -90
  98. package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +0 -83
  99. package/src/components/EntityCollectionTable/fields/VirtualTableSwitch.tsx +0 -32
  100. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +0 -141
@@ -1,3 +1,4 @@
1
+ import { InferPropertyType } from "@rebasepro/types";
1
2
  import { Property } from "@rebasepro/types";
2
3
  /**
3
4
  * @group Preview components
@@ -11,7 +12,7 @@ export interface PropertyPreviewProps<P extends Property | Property, CustomProps
11
12
  * Name of the property
12
13
  */
13
14
  propertyKey?: string;
14
- value: any;
15
+ value: InferPropertyType<P> | any;
15
16
  /**
16
17
  * Property this display is related to, now strongly typed to P
17
18
  */
@@ -1,8 +1,9 @@
1
+ import { InferPropertyType } from "@rebasepro/types";
1
2
  import { Entity } from "@rebasepro/types";
2
3
  import { FormexController } from "./components/formex";
3
4
  import { EntityCollection } from "@rebasepro/types";
4
5
  import { Property } from "@rebasepro/types";
5
- export type DefaultFieldConfig = "text_field" | "multiline" | "markdown" | "url" | "email" | "switch" | "select" | "multi_select" | "user_select" | "number_input" | "number_select" | "multi_number_select" | "file_upload" | "multi_file_upload" | "reference_as_string" | "reference" | "multi_references" | "relation" | "date_time" | "group" | "key_value" | "repeat" | "custom_array" | "block" | "vector_input";
6
+ export type DefaultFieldConfig = "text_field" | "multiline" | "markdown" | "url" | "email" | "switch" | "select" | "multi_select" | "user_select" | "number_input" | "number_select" | "multi_number_select" | "file_upload" | "multi_file_upload" | "reference" | "multi_references" | "relation" | "date_time" | "group" | "key_value" | "repeat" | "custom_array" | "block" | "vector_input";
6
7
  /**
7
8
  * When building a custom field you need to create a React component that takes
8
9
  * this interface as props.
@@ -18,11 +19,8 @@ export interface FieldProps<P extends Property | Property = Property, CustomProp
18
19
  /**
19
20
  * Current value of this field, inferred from the property type P
20
21
  */
21
- value: any;
22
- /**
23
- * Set value of field directly
24
- */
25
- setValue: (value: any | null, shouldValidate?: boolean) => void;
22
+ value: InferPropertyType<P> | any;
23
+ setValue: (value: InferPropertyType<P> | null | any, shouldValidate?: boolean) => void;
26
24
  /**
27
25
  * Set value of a different field directly
28
26
  * @param propertyKey
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/admin",
3
3
  "type": "module",
4
- "version": "0.7.0",
4
+ "version": "0.8.0",
5
5
  "description": "Rebase CMS — content management views, forms, and routing",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -31,14 +31,6 @@
31
31
  "headless cms",
32
32
  "content manager"
33
33
  ],
34
- "scripts": {
35
- "watch": "vite build --watch",
36
- "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
37
- "test:lint": "eslint \"src/**\" --quiet",
38
- "test": "jest --passWithNoTests",
39
- "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f",
40
- "generateIcons": "ts-node --esm src/icons/generateIcons.ts"
41
- },
42
34
  "exports": {
43
35
  ".": {
44
36
  "types": "./dist/index.d.ts",
@@ -63,13 +55,6 @@
63
55
  "@dnd-kit/sortable": "^10.0.0",
64
56
  "@dnd-kit/utilities": "^3.2.2",
65
57
  "@floating-ui/dom": "^1.7.6",
66
- "@rebasepro/common": "workspace:*",
67
- "@rebasepro/core": "workspace:*",
68
- "@rebasepro/formex": "workspace:*",
69
- "@rebasepro/schema-inference": "workspace:*",
70
- "@rebasepro/types": "workspace:*",
71
- "@rebasepro/ui": "workspace:*",
72
- "@rebasepro/utils": "workspace:*",
73
58
  "cmdk": "^1.1.1",
74
59
  "date-fns": "^4.4.0",
75
60
  "exceljs": "^4.4.0",
@@ -97,7 +82,14 @@
97
82
  "prosemirror-view": "^1.41.9",
98
83
  "react-dropzone": "^15.0.0",
99
84
  "react-use-measure": "^2.1.7",
100
- "zod": "^4.4.3"
85
+ "zod": "^4.4.3",
86
+ "@rebasepro/common": "0.8.0",
87
+ "@rebasepro/core": "0.8.0",
88
+ "@rebasepro/formex": "0.8.0",
89
+ "@rebasepro/schema-inference": "0.8.0",
90
+ "@rebasepro/types": "0.8.0",
91
+ "@rebasepro/ui": "0.8.0",
92
+ "@rebasepro/utils": "0.8.0"
101
93
  },
102
94
  "peerDependencies": {
103
95
  "react": ">=19.0.0",
@@ -168,5 +160,13 @@
168
160
  "^@rebasepro/formex$": "<rootDir>/../formex/src/index.ts",
169
161
  "^@rebasepro/utils$": "<rootDir>/../utils/src/index.ts"
170
162
  }
163
+ },
164
+ "scripts": {
165
+ "watch": "vite build --watch",
166
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
167
+ "test:lint": "eslint \"src/**\" --quiet",
168
+ "test": "jest --passWithNoTests",
169
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f",
170
+ "generateIcons": "ts-node --esm src/icons/generateIcons.ts"
171
171
  }
172
- }
172
+ }
@@ -16,7 +16,7 @@ export { FieldCaption } from "../components/FieldCaption";
16
16
  export { SearchIconsView } from "../components/SearchIconsView";
17
17
  export { PropertyConfigBadge } from "../components/PropertyConfigBadge";
18
18
  export { EntityCollectionTable } from "../components/EntityCollectionTable";
19
- export { VirtualTableInput } from "../components/EntityCollectionTable/fields/VirtualTableInput";
19
+ export { VirtualTableInput } from "@rebasepro/ui";
20
20
  export { ArrayContainer } from "../components/ArrayContainer";
21
21
  export type { ArrayEntryParams } from "../components/ArrayContainer";
22
22
  export { useSelectionController } from "../components/EntityCollectionView/useSelectionController";
@@ -55,8 +55,9 @@ export const DEFAULT_COLLECTION_GENERATION_ENDPOINT = "https://api.rebase.pro/co
55
55
  */
56
56
  export interface BuildCollectionGenerationCallbackProps {
57
57
  /**
58
- * Function to get the auth token (e.g., from Firebase Auth)
59
- * This is typically `authController.getAuthToken` from `@rebasepro/client-firebase`
58
+ * Function to get the auth token.
59
+ * This is typically `authController.getAuthToken` from `@rebasepro/client`
60
+ * (or `@rebasepro/client-firebase` if using Firebase).
60
61
  */
61
62
  getAuthToken: () => Promise<string>;
62
63
 
@@ -1,4 +1,4 @@
1
- import { EntityCollection, Property, StringProperty, NumberProperty, ArrayProperty, TableColumnInfo, TableMetadata } from "@rebasepro/types";
1
+ import { EntityCollection, Property, StringProperty, NumberProperty, ArrayProperty, TableColumnInfo, TableMetadata, PostgresProperties } from "@rebasepro/types";
2
2
  import { prettifyIdentifier } from "@rebasepro/utils";
3
3
 
4
4
  /**
@@ -282,7 +282,7 @@ export function buildCollectionFromTableMetadata(
282
282
  name: prettifiedName,
283
283
  slug: tableName,
284
284
  table: tableName,
285
- properties,
285
+ properties: properties as PostgresProperties,
286
286
  propertiesOrder,
287
287
  ...(relations.length > 0 ? { relations } : {}),
288
288
  ...(securityRules.length > 0 ? { securityRules } : {})
@@ -12,33 +12,22 @@
12
12
  */
13
13
 
14
14
  import type {
15
- DataType,
16
- EnumValues,
17
- PropertyValidationSchema,
18
- NumberPropertyValidationSchema,
19
15
  ArrayPropertyValidationSchema,
20
- PropertyConditions,
21
- ImageResize,
22
- FileType,
23
- ColorKey,
24
- ColorScheme,
25
- } from "@rebasepro/types";
26
-
27
- import type {
28
- ViewMode,
29
16
  CollectionSize,
30
- SecurityRule,
31
- FilterValues,
17
+ EnumValues,
18
+ FileType,
32
19
  FilterPreset,
33
- WhereFilterOp,
20
+ FilterValues,
21
+ ImageResize,
22
+ JoinStep,
34
23
  KanbanConfig,
35
- SecurityOperation,
36
24
  NavigationGroupMapping,
37
- } from "@rebasepro/types";
38
-
39
- import type {
25
+ NumberPropertyValidationSchema,
40
26
  OnAction,
41
- JoinStep,
27
+ PropertyConditions,
28
+ PropertyValidationSchema,
29
+ SecurityRule,
30
+ ViewMode,
42
31
  } from "@rebasepro/types";
43
32
 
44
33
  // ═══════════════════════════════════════════════════════════════════════
@@ -109,6 +98,8 @@ export interface SerializableStorageConfig {
109
98
  includeBucketUrl?: boolean;
110
99
  storeUrl?: boolean;
111
100
  maxSize?: number;
101
+ /** Key of the named storage backend to use (see `StorageConfig.storageSource`). */
102
+ storageSource?: string;
112
103
  // processFile, postProcess, previewUrl are dropped (functions)
113
104
  }
114
105
 
@@ -200,13 +191,9 @@ export interface SerializableStringProperty extends SerializableBaseProperty {
200
191
  validation?: SerializableStringValidation;
201
192
  isId?: boolean | "manual" | "uuid" | "cuid" | string;
202
193
  enum?: EnumValues;
203
- multiline?: boolean;
204
- markdown?: boolean;
205
194
  storage?: SerializableStorageConfig;
206
195
  userSelect?: boolean;
207
- url?: boolean | "image" | "video" | "audio" | "file";
208
196
  email?: boolean;
209
- previewAsTag?: boolean;
210
197
  reference?: SerializableReferenceProperty;
211
198
  }
212
199
 
@@ -236,7 +223,6 @@ export interface SerializableDateProperty extends SerializableBaseProperty {
236
223
  mode?: "date" | "date_time";
237
224
  timezone?: string;
238
225
  autoValue?: "on_create" | "on_update";
239
- clearable?: boolean;
240
226
  }
241
227
 
242
228
  /** JSON-serializable `GeopointProperty`. */
@@ -391,7 +377,8 @@ export interface SerializableCollection {
391
377
  icon?: string;
392
378
 
393
379
  group?: string;
394
- driver?: string;
380
+ engine?: string;
381
+ dataSource?: string;
395
382
  databaseId?: string;
396
383
 
397
384
  properties: SerializableProperties;
@@ -9,44 +9,44 @@
9
9
  */
10
10
 
11
11
  import type {
12
- EntityCollection,
13
- Property,
14
- StringProperty,
15
- NumberProperty,
12
+ ArrayProperty,
13
+ BaseUIConfig,
14
+ BinaryProperty,
16
15
  BooleanProperty,
17
16
  DateProperty,
17
+ EntityCollection,
18
18
  GeopointProperty,
19
- ReferenceProperty,
20
- RelationProperty,
21
- ArrayProperty,
22
19
  MapProperty,
23
- VectorProperty,
24
- BinaryProperty,
20
+ NumberProperty,
25
21
  Properties,
22
+ Property,
23
+ ReferenceProperty,
24
+ RelationProperty,
26
25
  StorageConfig,
27
- BaseUIConfig,
26
+ StringProperty,
27
+ VectorProperty,
28
28
  } from "@rebasepro/types";
29
29
 
30
30
  import type {
31
- SerializableCollection,
32
- SerializableProperty,
33
- SerializableProperties,
34
- SerializableStorageConfig,
35
- SerializableBaseUIConfig,
31
+ SerializableArrayProperty,
36
32
  SerializableBaseProperty,
37
- SerializableStringProperty,
38
- SerializableNumberProperty,
33
+ SerializableBaseUIConfig,
34
+ SerializableBinaryProperty,
39
35
  SerializableBooleanProperty,
36
+ SerializableCollection,
40
37
  SerializableDateProperty,
38
+ SerializableDateValidation,
41
39
  SerializableGeopointProperty,
40
+ SerializableMapProperty,
41
+ SerializableNumberProperty,
42
+ SerializableProperties,
43
+ SerializableProperty,
42
44
  SerializableReferenceProperty,
43
45
  SerializableRelationProperty,
44
- SerializableArrayProperty,
45
- SerializableMapProperty,
46
- SerializableVectorProperty,
47
- SerializableBinaryProperty,
46
+ SerializableStorageConfig,
47
+ SerializableStringProperty,
48
48
  SerializableStringValidation,
49
- SerializableDateValidation,
49
+ SerializableVectorProperty,
50
50
  } from "./serializable_types";
51
51
 
52
52
  // ═══════════════════════════════════════════════════════════════════════
@@ -90,6 +90,7 @@ function toSerializableStorageConfig(storage: StorageConfig | undefined): Serial
90
90
  if (storage.includeBucketUrl !== undefined) result.includeBucketUrl = storage.includeBucketUrl;
91
91
  if (storage.storeUrl !== undefined) result.storeUrl = storage.storeUrl;
92
92
  if (storage.maxSize !== undefined) result.maxSize = storage.maxSize;
93
+ if (storage.storageSource !== undefined) result.storageSource = storage.storageSource;
93
94
  // processFile, postProcess, previewUrl are intentionally dropped (functions)
94
95
 
95
96
  return result;
@@ -167,12 +168,8 @@ export function toSerializableProperty(property: Property): SerializableProperty
167
168
  if (sp.columnType) result.columnType = sp.columnType;
168
169
  if (sp.isId !== undefined) result.isId = sp.isId;
169
170
  if (sp.enum) result.enum = sp.enum;
170
- if (sp.multiline) result.multiline = sp.multiline;
171
- if (sp.markdown) result.markdown = sp.markdown;
172
171
  if (sp.userSelect) result.userSelect = sp.userSelect;
173
- if (sp.url) result.url = sp.url;
174
172
  if (sp.email) result.email = sp.email;
175
- if (sp.previewAsTag) result.previewAsTag = sp.previewAsTag;
176
173
 
177
174
  // Convert validation.matches from RegExp to string
178
175
  if (sp.validation) {
@@ -187,11 +184,6 @@ export function toSerializableProperty(property: Property): SerializableProperty
187
184
  const storage = toSerializableStorageConfig(sp.storage);
188
185
  if (storage) result.storage = storage;
189
186
 
190
- // Reference sub-property
191
- if (sp.reference) {
192
- result.reference = toSerializableProperty(sp.reference) as SerializableReferenceProperty;
193
- }
194
-
195
187
  return result;
196
188
  }
197
189
 
@@ -228,7 +220,6 @@ export function toSerializableProperty(property: Property): SerializableProperty
228
220
  if (dp.mode) result.mode = dp.mode;
229
221
  if (dp.timezone) result.timezone = dp.timezone;
230
222
  if (dp.autoValue) result.autoValue = dp.autoValue;
231
- if (dp.clearable) result.clearable = dp.clearable;
232
223
 
233
224
  // Convert Date validation min/max to ISO strings
234
225
  if (dp.validation) {
@@ -416,7 +407,8 @@ export function toSerializableCollection(collection: EntityCollection): Serializ
416
407
  if (collection.singularName) result.singularName = collection.singularName;
417
408
  if (collection.description) result.description = collection.description;
418
409
  if (collection.group) result.group = collection.group;
419
- if (collection.driver) result.driver = collection.driver;
410
+ if (collection.engine) result.engine = collection.engine;
411
+ if (collection.dataSource) result.dataSource = collection.dataSource;
420
412
  if (collection.databaseId) result.databaseId = collection.databaseId;
421
413
  if (collection.titleProperty) result.titleProperty = collection.titleProperty as string;
422
414
  if (collection.ownerId) result.ownerId = collection.ownerId;
@@ -543,10 +535,6 @@ export function fromSerializableProperty(serialized: SerializableProperty): Prop
543
535
  case "string": {
544
536
  const sp = serialized as SerializableStringProperty;
545
537
  const result = { ...sp } as unknown as StringProperty;
546
- // Convert reference sub-property
547
- if (sp.reference) {
548
- result.reference = fromSerializableProperty(sp.reference) as ReferenceProperty;
549
- }
550
538
  return result;
551
539
  }
552
540
 
@@ -95,7 +95,7 @@ export function AICollectionGeneratorPopover({
95
95
  name: c.name,
96
96
  properties: c.properties,
97
97
  propertiesOrder: c.propertiesOrder
98
- }));
98
+ } as Partial<EntityCollection>));
99
99
 
100
100
  const result = await generateCollection({
101
101
  prompt: prompt.trim(),
@@ -106,7 +106,7 @@ export function AICollectionGeneratorPopover({
106
106
  name: existingCollection.name,
107
107
  properties: existingCollection.properties,
108
108
  propertiesOrder: existingCollection.propertiesOrder
109
- }
109
+ } as Partial<EntityCollection>
110
110
  })
111
111
  });
112
112
 
@@ -1,31 +1,50 @@
1
-
2
- import { useUnsavedChangesDialog, UnsavedChangesDialog } from "@rebasepro/core";
3
- import { useNavigationStateController, useCollectionRegistryController, useUrlController } from "../../_cms_internals";
4
1
  import * as React from "react";
5
2
  import { useEffect, useRef, useState } from "react";
6
- import { ConfirmationDialog, ErrorView, useAuthController, useCustomizationController, useSnackbarController } from "@rebasepro/core";
3
+ import {
4
+ ConfirmationDialog,
5
+ ErrorView,
6
+ UnsavedChangesDialog,
7
+ useAuthController,
8
+ useCustomizationController,
9
+ useUnsavedChangesDialog
10
+ } from "@rebasepro/core";
11
+ import {
12
+ getInferenceType,
13
+ ImportSaveInProgress,
14
+ useCollectionRegistryController,
15
+ useImportConfig,
16
+ useNavigationStateController,
17
+ useUrlController
18
+ } from "../../_cms_internals";
7
19
  import { useSafeSnackbarController } from "../../useSafeSnackbarController";
8
- import { CircularProgressCenter } from "@rebasepro/ui";
9
20
  import {
10
21
  ArrowLeftIcon,
11
22
  Button,
12
23
  CheckIcon,
24
+ CircularProgressCenter,
13
25
  cls,
14
26
  coolIconKeys,
15
27
  defaultBorderMixin,
16
28
  Dialog,
17
- DialogActions,
18
- DialogContent,
19
29
  DialogTitle,
20
30
  IconButton,
21
31
  LoadingButton,
22
32
  Tab,
23
- Tabs,
24
- Typography
33
+ Tabs
25
34
  } from "@rebasepro/ui";
26
- import { Entity, EntityCollection, MapProperty, Properties, Property, PropertyConfig, User, getDataSourceCapabilities } from "@rebasepro/types";
27
- import type { PostgresCollection } from "@rebasepro/types";
28
- import { getSubcollections, isPropertyBuilder, removeInitialAndTrailingSlashes, getTableName } from "@rebasepro/common";
35
+ import {
36
+ EngineProperties,
37
+ Entity,
38
+ EntityCollection,
39
+ getDataSourceCapabilities,
40
+ MapProperty,
41
+ Properties,
42
+ Property,
43
+ PropertyConfig,
44
+ TableMetadata,
45
+ User
46
+ } from "@rebasepro/types";
47
+ import { getSubcollections, getTableName, isPropertyBuilder, removeInitialAndTrailingSlashes } from "@rebasepro/common";
29
48
  import { CollectionEditorSchema } from "./CollectionYupValidation";
30
49
  import { GeneralSettingsForm } from "./GeneralSettingsForm";
31
50
  import { DisplaySettingsForm } from "./DisplaySettingsForm";
@@ -33,7 +52,6 @@ import { CollectionPropertiesEditorForm } from "./CollectionPropertiesEditorForm
33
52
  import { CollectionsConfigController } from "../../types/config_controller";
34
53
  import { CollectionEditorWelcomeView } from "./CollectionEditorWelcomeView";
35
54
  import { CollectionInference } from "../../types/collection_inference";
36
- import { getInferenceType, ImportSaveInProgress, useImportConfig } from "../../_cms_internals";
37
55
  import { buildEntityPropertiesFromData } from "@rebasepro/schema-inference";
38
56
  import { CollectionEditorImportMapping } from "./import/CollectionEditorImportMapping";
39
57
  import { CollectionEditorImportDataPreview } from "./import/CollectionEditorImportDataPreview";
@@ -42,10 +60,9 @@ import { Formex, FormexController, useCreateFormex } from "@rebasepro/formex";
42
60
  import { getFullIdPath } from "./util";
43
61
  import { AICollectionGeneratorPopover } from "./AICollectionGeneratorPopover";
44
62
  import { AIModifiedPathsProvider, useAIModifiedPaths } from "./AIModifiedPathsContext";
45
- import { CollectionOperation, CollectionGenerationCallback } from "../../api/generateCollectionApi";
63
+ import { CollectionGenerationCallback, CollectionOperation } from "../../api/generateCollectionApi";
46
64
  import { CollectionRLSTab } from "./CollectionRLSTab";
47
65
  import { buildCollectionFromTableMetadata } from "../../pgColumnToProperty";
48
- import { TableMetadata } from "@rebasepro/types";
49
66
  import { mergeDeep, randomString, removeUndefined } from "@rebasepro/utils";
50
67
  import type { CollectionEditorExtensionProps, CollectionEditorTab } from "../../extensibility_types";
51
68
 
@@ -242,8 +259,8 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
242
259
  }, [collection, fallbackSlug]);
243
260
 
244
261
  // Build initial values - handle copyFrom for duplication
245
- const initialValues: EntityCollection<any> = React.useMemo(() => {
246
- return initialCollection
262
+ const initialValues = React.useMemo((): EntityCollection<any> => {
263
+ return (initialCollection
247
264
  ? applyPropertyConfigs(initialCollection, propertyConfigs)
248
265
  : copyFromProp
249
266
  ? (() => {
@@ -259,11 +276,11 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
259
276
  slug: initialValuesProp?.slug ?? fallbackSlug,
260
277
  table: initialValuesProp?.slug ?? "",
261
278
  name: initialValuesProp?.name ?? "",
262
- properties: {} as Properties,
279
+ properties: {} as EngineProperties,
263
280
  propertiesOrder: [],
264
281
  icon: initialIcon,
265
282
  ownerId: authController.user?.uid ?? ""
266
- };
283
+ }) as EntityCollection<any>;
267
284
  }, [initialCollection, propertyConfigs, copyFromProp, initialValuesProp, fallbackSlug, initialIcon, authController.user?.uid]);
268
285
 
269
286
  if (!initialLoadingCompleted) {
@@ -455,7 +472,7 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
455
472
  };
456
473
 
457
474
  if (Object.keys(inferredCollection.properties ?? {}).length > 0) {
458
- values.properties = inferredCollection.properties as Properties;
475
+ values.properties = inferredCollection.properties as EngineProperties;
459
476
  values.propertiesOrder = inferredCollection.propertiesOrder as Extract<keyof M, string>[];
460
477
  }
461
478
 
@@ -697,7 +714,7 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
697
714
  {(!visibleTabs || visibleTabs.includes("properties")) && <Tab value={"properties"}>
698
715
  Properties
699
716
  </Tab>}
700
- {(!visibleTabs || visibleTabs.includes("rls")) && getDataSourceCapabilities(values.driver).supportsRLS && <Tab value={"rls"}>
717
+ {(!visibleTabs || visibleTabs.includes("rls")) && getDataSourceCapabilities(values.engine).supportsRLS && <Tab value={"rls"}>
701
718
  RLS
702
719
  </Tab>}
703
720
  </Tabs>
@@ -807,7 +824,7 @@ function CollectionEditorInternal<M extends Record<string, unknown>>({
807
824
  <DisplaySettingsForm expandKanban={expandKanban} standalone={standalone}/>
808
825
  }
809
826
 
810
- {currentView === "rls" && getDataSourceCapabilities(values.driver).supportsRLS &&
827
+ {currentView === "rls" && getDataSourceCapabilities(values.engine).supportsRLS &&
811
828
  <CollectionRLSTab/>
812
829
  }
813
830
 
@@ -974,8 +991,8 @@ function applyPropertyConfigs<M extends Record<string, unknown> = Record<string,
974
991
 
975
992
  return {
976
993
  ...rest,
977
- properties: propertiesResult
978
- };
994
+ properties: propertiesResult as EngineProperties
995
+ } as EntityCollection<M>;
979
996
  }
980
997
 
981
998
  function applyPropertiesConfig(property: Property, propertyConfigs: Record<string, PropertyConfig>) {
@@ -505,13 +505,6 @@ function PropertyEditFormFields({
505
505
  existing={existing}
506
506
  multiple={false}
507
507
  disabled={disabled}/>;
508
- } else if (selectedFieldConfigId === "reference_as_string") {
509
- childComponent =
510
- <ReferencePropertyField showErrors={showErrors}
511
- existing={existing}
512
- asString={true}
513
- multiple={false}
514
- disabled={disabled}/>;
515
508
  } else if (selectedFieldConfigId === "date_time") {
516
509
  childComponent = <DateTimePropertyField disabled={disabled}/>;
517
510
  } else if (selectedFieldConfigId === "multi_references") {
@@ -686,7 +679,6 @@ const WIDGET_TYPE_MAP: Record<PropertyConfigId, string> = {
686
679
  multi_file_upload: "File",
687
680
  relation: "Relation",
688
681
  reference: "Reference",
689
- reference_as_string: "Text",
690
682
  multi_references: "Reference",
691
683
  date_time: "Date",
692
684
  group: "Group",
@@ -707,7 +699,6 @@ const WIDGET_BASE_TYPE_MAP: Record<string, PropertyType> = {
707
699
  multi_select: "string",
708
700
  file_upload: "string",
709
701
  multi_file_upload: "string",
710
- reference_as_string: "string",
711
702
  user_select: "string",
712
703
  number_input: "number",
713
704
  number_select: "number",
@@ -13,7 +13,8 @@ import {
13
13
  } from "@rebasepro/ui";
14
14
 
15
15
  import { Field, FormexFieldProps, getIn, useFormex } from "@rebasepro/formex";
16
- import { useTranslation } from "@rebasepro/core";
16
+ import { useStorageSources, useTranslation } from "@rebasepro/core";
17
+ import { DEFAULT_STORAGE_SOURCE_KEY } from "@rebasepro/types";
17
18
  import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
18
19
  import { ArrayPropertyValidation } from "./validation/ArrayPropertyValidation";
19
20
  import { ValidationPanel } from "./validation/ValidationPanel";
@@ -42,9 +43,11 @@ export function StoragePropertyField({
42
43
  setFieldValue
43
44
  } = useFormex();
44
45
  const { t } = useTranslation();
46
+ const storageSources = useStorageSources();
45
47
 
46
48
  const baseStoragePath = multiple ? "of.storage" : "storage";
47
49
  const acceptedFiles = `${baseStoragePath}.acceptedFiles`;
50
+ const storageSource = `${baseStoragePath}.storageSource`;
48
51
 
49
52
  const metadata = `${baseStoragePath}.metadata`;
50
53
  const fileName = `${baseStoragePath}.fileName`;
@@ -76,6 +79,11 @@ export function StoragePropertyField({
76
79
  const fileTypesValue: string[] | undefined = Array.isArray(storedValue) ? storedValue : undefined;
77
80
  const allFileTypesSelected = !fileTypesValue || fileTypesValue.length === 0;
78
81
 
82
+ // Available storage backends (from `<Rebase storageSources={...}>`).
83
+ const sourceKeys = Object.keys(storageSources.sources)
84
+ .filter((key) => key !== DEFAULT_STORAGE_SOURCE_KEY);
85
+ const storageSourceValue = (getIn(values, storageSource) as string | undefined) ?? DEFAULT_STORAGE_SOURCE_KEY;
86
+
79
87
  const handleTypesChange = (value: string[]) => {
80
88
  if (!value) setFieldValue(acceptedFiles, undefined);
81
89
  else setFieldValue(acceptedFiles, value);
@@ -102,6 +110,32 @@ export function StoragePropertyField({
102
110
 
103
111
  <div className={"grid grid-cols-12 gap-2 p-4"}>
104
112
 
113
+ {sourceKeys.length > 0 && (
114
+ <div className={"col-span-12"}>
115
+ <Select
116
+ className={"w-full"}
117
+ disabled={disabled}
118
+ name={storageSource}
119
+ value={storageSourceValue}
120
+ onValueChange={(value) =>
121
+ setFieldValue(storageSource, !value || value === DEFAULT_STORAGE_SOURCE_KEY ? undefined : value)}
122
+ label={"Storage backend"}
123
+ renderValue={(key) => {
124
+ const label = storageSources.registry[key]?.label;
125
+ return label ?? (key === DEFAULT_STORAGE_SOURCE_KEY ? "Default" : key);
126
+ }}>
127
+ <SelectItem value={DEFAULT_STORAGE_SOURCE_KEY}>
128
+ Default
129
+ </SelectItem>
130
+ {sourceKeys.map((key) => (
131
+ <SelectItem key={key} value={key}>
132
+ {storageSources.registry[key]?.label ?? key}
133
+ </SelectItem>
134
+ ))}
135
+ </Select>
136
+ </div>
137
+ )}
138
+
105
139
  <div className={"col-span-12"}>
106
140
 
107
141
  <MultiSelect
@@ -93,7 +93,7 @@ export const blogCollectionTemplate = {
93
93
  publish_date: {
94
94
  name: "Publish date",
95
95
  type: "date",
96
- clearable: true
96
+ ui: { clearable: true }
97
97
  },
98
98
  reviewed: {
99
99
  name: "Reviewed",
@@ -16,7 +16,6 @@ export const supportedFieldsIds: PropertyConfigId[] = [
16
16
  "file_upload",
17
17
  "multi_file_upload",
18
18
  "reference",
19
- "reference_as_string",
20
19
  "multi_references",
21
20
  "relation",
22
21
  "switch",