@rebasepro/cms 0.17.3 → 0.18.1
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.
- package/README.md +4 -0
- package/dist/{CollectionEditorDialog-B-akreOU.js → CollectionEditorDialog-BeX4b92r.js} +13 -7
- package/dist/{CollectionEditorDialog-B-akreOU.js.map → CollectionEditorDialog-BeX4b92r.js.map} +1 -1
- package/dist/{PropertyEditView-CiY84wkR.js → PropertyEditView-C7thfj4L.js} +3 -3
- package/dist/{PropertyEditView-CiY84wkR.js.map → PropertyEditView-C7thfj4L.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js → RouterCollectionsStudioView-BtjzvB6E.js} +4 -4
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js.map → RouterCollectionsStudioView-BtjzvB6E.js.map} +1 -1
- package/dist/{SchemaChangeDialog-DceT8QFX.js → SchemaChangeDialog-CkqK6KOC.js} +4 -2
- package/dist/{SchemaChangeDialog-DceT8QFX.js.map → SchemaChangeDialog-CkqK6KOC.js.map} +1 -1
- package/dist/collection_editor/api/generateCollectionApi.d.ts +1 -2
- package/dist/collection_editor_ui.d.ts +2 -0
- package/dist/collection_editor_ui.js +6 -5
- package/dist/collection_editor_ui.js.map +1 -1
- package/dist/components/DeleteEntityDialog.d.ts +2 -3
- package/dist/components/RebaseLayout.d.ts +11 -4
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/editor/sanitize-html.d.ts +15 -0
- package/dist/editor.js +195 -10
- package/dist/editor.js.map +1 -1
- package/dist/{export-Ben8E355.js → export--arni_VY.js} +2 -2
- package/dist/{export-Ben8E355.js.map → export--arni_VY.js.map} +1 -1
- package/dist/form/components/LabelWithIcon.d.ts +10 -0
- package/dist/{history-DIEVd26f.js → history-C2TpoQwi.js} +2 -2
- package/dist/{history-DIEVd26f.js.map → history-C2TpoQwi.js.map} +1 -1
- package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +1 -1
- package/dist/hooks/navigation/useResolvedViews.d.ts +1 -1
- package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
- package/dist/{import-D25x7ko-.js → import-DTkXNoBg.js} +2 -2
- package/dist/{import-D25x7ko-.js.map → import-DTkXNoBg.js.map} +1 -1
- package/dist/index.js +78 -33
- package/dist/index.js.map +1 -1
- package/dist/util/propertyConfigMapper.d.ts +1 -1
- package/dist/util-CfLFggP7.js +57 -0
- package/dist/util-CfLFggP7.js.map +1 -0
- package/dist/{util-DVqnqlLn.js → util-DE1WQW6h.js} +134 -112
- package/dist/util-DE1WQW6h.js.map +1 -0
- package/package.json +42 -34
- package/dist/util-DVqnqlLn.js.map +0 -1
- package/src/collection_editor/CollectionEditorDialogsContext.tsx +0 -25
- package/src/collection_editor/ConfigControllerProvider.tsx +0 -395
- package/src/collection_editor/_cms_internals.ts +0 -41
- package/src/collection_editor/api/generateCollectionApi.ts +0 -126
- package/src/collection_editor/api/index.ts +0 -1
- package/src/collection_editor/extensibility_types.ts +0 -168
- package/src/collection_editor/index.ts +0 -108
- package/src/collection_editor/liveSchemaClient.ts +0 -285
- package/src/collection_editor/relation_kinds.ts +0 -44
- package/src/collection_editor/serializable_types.ts +0 -535
- package/src/collection_editor/serializable_utils.ts +0 -729
- package/src/collection_editor/types/collection_editor_controller.tsx +0 -62
- package/src/collection_editor/types/collection_inference.ts +0 -18
- package/src/collection_editor/types/config_controller.tsx +0 -121
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +0 -199
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +0 -51
- package/src/collection_editor/ui/EditorCollectionAction.tsx +0 -54
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +0 -90
- package/src/collection_editor/ui/EditorEntityAction.tsx +0 -50
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +0 -114
- package/src/collection_editor/ui/KanbanSetupAction.tsx +0 -43
- package/src/collection_editor/ui/MissingReferenceWidget.tsx +0 -35
- package/src/collection_editor/ui/NewCollectionButton.tsx +0 -27
- package/src/collection_editor/ui/NewCollectionCard.tsx +0 -48
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +0 -260
- package/src/collection_editor/ui/collection_editor/AIModifiedPathsContext.tsx +0 -90
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +0 -388
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +0 -1098
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +0 -301
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +0 -172
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +0 -620
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +0 -530
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +0 -462
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +0 -104
- package/src/collection_editor/ui/collection_editor/CollectionYupValidation.tsx +0 -9
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +0 -199
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +0 -315
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/EntityActionsSelectDialog.tsx +0 -40
- package/src/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +0 -373
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +0 -288
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +0 -141
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +0 -194
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +0 -53
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +0 -980
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +0 -364
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +0 -44
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +0 -470
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +0 -256
- package/src/collection_editor/ui/collection_editor/SwitchControl.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +0 -68
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +0 -67
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +0 -296
- package/src/collection_editor/ui/collection_editor/import/clean_import_data.ts +0 -57
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +0 -147
- package/src/collection_editor/ui/collection_editor/properties/BooleanPropertyField.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +0 -113
- package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +0 -250
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +0 -126
- package/src/collection_editor/ui/collection_editor/properties/KeyValuePropertyField.tsx +0 -20
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +0 -153
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +0 -217
- package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +0 -117
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +0 -129
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +0 -335
- package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -107
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +0 -403
- package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +0 -148
- package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +0 -91
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +0 -34
- package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +0 -925
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +0 -626
- package/src/collection_editor/ui/collection_editor/properties/conditions/index.ts +0 -6
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +0 -93
- package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +0 -52
- package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +0 -63
- package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +0 -114
- package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +0 -154
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +0 -112
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +0 -183
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +0 -88
- package/src/collection_editor/ui/collection_editor/templates/users_template.ts +0 -42
- package/src/collection_editor/ui/collection_editor/util.ts +0 -28
- package/src/collection_editor/ui/collection_editor/utils/strings.ts +0 -1
- package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +0 -276
- package/src/collection_editor/useCollectionEditorController.tsx +0 -9
- package/src/collection_editor/useCollectionsConfigController.tsx +0 -9
- package/src/collection_editor/useJsonCollectionsConfigController.tsx +0 -297
- package/src/collection_editor/useLiveSchemaEditing.tsx +0 -315
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -341
- package/src/collection_editor/useSafeSnackbarController.ts +0 -9
- package/src/collection_editor/validateCollectionJson.ts +0 -440
- package/src/collection_editor_ui.ts +0 -21
- package/src/components/AdditionalFieldValue.tsx +0 -68
- package/src/components/AdminModeSyncer.tsx +0 -56
- package/src/components/ArrayContainer.tsx +0 -542
- package/src/components/ClearFilterSortButton.tsx +0 -56
- package/src/components/CollectionEditorDialogs.tsx +0 -69
- package/src/components/CollectionPanel.tsx +0 -179
- package/src/components/CollectionTableBinding/CollectionRowActions.tsx +0 -244
- package/src/components/CollectionTableBinding/CollectionTableBinding.tsx +0 -394
- package/src/components/CollectionTableBinding/CollectionTableBindingProps.tsx +0 -172
- package/src/components/CollectionTableBinding/PropertyTableCell.tsx +0 -350
- package/src/components/CollectionTableBinding/column_utils.tsx +0 -155
- package/src/components/CollectionTableBinding/fields/TableMultipleRelationField.tsx +0 -131
- package/src/components/CollectionTableBinding/fields/TableReferenceField.tsx +0 -193
- package/src/components/CollectionTableBinding/fields/TableRelationField.tsx +0 -192
- package/src/components/CollectionTableBinding/fields/TableRelationSelectorField.tsx +0 -42
- package/src/components/CollectionTableBinding/fields/TableStorageUpload.tsx +0 -324
- package/src/components/CollectionTableBinding/fields/VirtualTableSelect.tsx +0 -132
- package/src/components/CollectionTableBinding/fields/VirtualTableUserSelect.tsx +0 -41
- package/src/components/CollectionTableBinding/index.tsx +0 -14
- package/src/components/CollectionTableBinding/internal/CollectionTableToolbar.tsx +0 -96
- package/src/components/CollectionTableBinding/internal/EntityTableCell.tsx +0 -309
- package/src/components/CollectionTableBinding/internal/EntityTableCellActions.tsx +0 -80
- package/src/components/CollectionTableBinding/internal/common.tsx +0 -74
- package/src/components/CollectionTableBinding/internal/popup_field/PopupFormField.tsx +0 -422
- package/src/components/CollectionTableBinding/internal/popup_field/useDraggable.tsx +0 -99
- package/src/components/CollectionTableBinding/internal/popup_field/useWindowSize.tsx +0 -22
- package/src/components/CollectionTableBinding/table_bindings.tsx +0 -350
- package/src/components/CollectionViewBinding/BoardCardBinding.tsx +0 -263
- package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +0 -662
- package/src/components/CollectionViewBinding/CollectionCardViewBinding.tsx +0 -159
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +0 -1430
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +0 -227
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +0 -1603
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +0 -240
- package/src/components/CollectionViewBinding/EntityCardBinding.tsx +0 -239
- package/src/components/CollectionViewBinding/FilterPresetsButton.tsx +0 -298
- package/src/components/CollectionViewBinding/FiltersDialog.tsx +0 -218
- package/src/components/CollectionViewBinding/SearchExplanation.tsx +0 -106
- package/src/components/CollectionViewBinding/SearchHighlight.tsx +0 -311
- package/src/components/CollectionViewBinding/SlotValue.tsx +0 -156
- package/src/components/CollectionViewBinding/SortButton.tsx +0 -354
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +0 -49
- package/src/components/CollectionViewBinding/SplitListShowButton.tsx +0 -28
- package/src/components/CollectionViewBinding/SplitListView.tsx +0 -488
- package/src/components/CollectionViewBinding/SplitViewContext.tsx +0 -34
- package/src/components/CollectionViewBinding/ViewModeToggle.tsx +0 -250
- package/src/components/CollectionViewBinding/hooks/useCollectionInlineEditor.ts +0 -81
- package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +0 -181
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +0 -802
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +0 -703
- package/src/components/CollectionViewBinding/useSelectionController.tsx +0 -40
- package/src/components/CollectionViewBinding/utils.ts +0 -22
- package/src/components/DefaultAppBar.tsx +0 -264
- package/src/components/DefaultDrawer.tsx +0 -593
- package/src/components/DeleteEntityDialog.tsx +0 -205
- package/src/components/DetailViewBinding.tsx +0 -731
- package/src/components/DrawerNavigationGroup.tsx +0 -141
- package/src/components/DrawerNavigationItem.tsx +0 -115
- package/src/components/EditFormActions.tsx +0 -303
- package/src/components/EditViewBinding.tsx +0 -1069
- package/src/components/EntityDisplayHeader.tsx +0 -170
- package/src/components/EntityIdentityBar.tsx +0 -428
- package/src/components/EntityInspector.tsx +0 -156
- package/src/components/EntityPreviewBinding.tsx +0 -432
- package/src/components/EntityPreviewNesting.tsx +0 -50
- package/src/components/EntityViewBinding.tsx +0 -374
- package/src/components/FieldCaption.tsx +0 -14
- package/src/components/HomePage/ContentHomePage.tsx +0 -586
- package/src/components/HomePage/FavouritesView.tsx +0 -60
- package/src/components/HomePage/HomePageDnD.tsx +0 -704
- package/src/components/HomePage/NavigationCard.tsx +0 -81
- package/src/components/HomePage/NavigationCardBinding.tsx +0 -107
- package/src/components/HomePage/NavigationGroup.tsx +0 -156
- package/src/components/HomePage/RenameGroupDialog.tsx +0 -123
- package/src/components/HomePage/SmallNavigationCard.tsx +0 -41
- package/src/components/HomePage/index.tsx +0 -5
- package/src/components/InlineEntityPreview.tsx +0 -149
- package/src/components/JsonPreviewBinding.tsx +0 -66
- package/src/components/PropertyCollectionView.tsx +0 -336
- package/src/components/PropertyConfigBadge.tsx +0 -28
- package/src/components/PropertyIdCopyTooltip.tsx +0 -47
- package/src/components/RebaseAuthGate.tsx +0 -44
- package/src/components/RebaseCMS.tsx +0 -30
- package/src/components/RebaseLayout.tsx +0 -80
- package/src/components/RebaseNavigation.tsx +0 -369
- package/src/components/RebaseRouteDefs.tsx +0 -127
- package/src/components/RebaseShell.tsx +0 -83
- package/src/components/ReferenceTable/SelectionTableBinding.tsx +0 -389
- package/src/components/ReferenceWidget.tsx +0 -156
- package/src/components/RelationSelector.tsx +0 -926
- package/src/components/SearchIconsView.tsx +0 -78
- package/src/components/SelectableTable/SelectableTable.tsx +0 -309
- package/src/components/SelectableTable/SelectableTableContext.tsx +0 -7
- package/src/components/SelectableTable/SelectionStore.ts +0 -43
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +0 -59
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +0 -146
- package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +0 -190
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +0 -250
- package/src/components/SelectableTable/filters/RelationFilterField.tsx +0 -238
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +0 -282
- package/src/components/SelectableTable/filters/null_filter.ts +0 -63
- package/src/components/SideDialogs.tsx +0 -238
- package/src/components/SidePanelBinding.tsx +0 -361
- package/src/components/SidePanelProvider.tsx +0 -80
- package/src/components/UserSelector.tsx +0 -513
- package/src/components/admin/CreationResultDialog.tsx +0 -138
- package/src/components/admin/index.ts +0 -1
- package/src/components/app/AppBar.tsx +0 -17
- package/src/components/app/Drawer.tsx +0 -38
- package/src/components/app/Scaffold.tsx +0 -366
- package/src/components/app/index.ts +0 -4
- package/src/components/app/useApp.tsx +0 -36
- package/src/components/common/default_entity_actions.tsx +0 -440
- package/src/components/common/index.ts +0 -1
- package/src/components/field_configs.tsx +0 -506
- package/src/components/history/EntityHistoryEntry.tsx +0 -203
- package/src/components/history/EntityHistoryView.tsx +0 -206
- package/src/components/history/LastEditedByFormAction.tsx +0 -24
- package/src/components/history/LastEditedByIndicator.tsx +0 -95
- package/src/components/history/UserChip.tsx +0 -15
- package/src/components/history/index.tsx +0 -5
- package/src/components/index.ts +0 -63
- package/src/contexts/BreacrumbsContext.tsx +0 -45
- package/src/contexts/SideDialogsControllerContext.tsx +0 -5
- package/src/contexts/SidePanelControllerContext.tsx +0 -5
- package/src/data_export/export/BasicExportAction.tsx +0 -142
- package/src/data_export/export/ExportCollectionAction.tsx +0 -321
- package/src/data_export/export/export.ts +0 -295
- package/src/data_export/export/fetch_export_data.ts +0 -90
- package/src/data_export/export/index.ts +0 -4
- package/src/data_export/index.ts +0 -1
- package/src/data_import/components/DataNewPropertiesMapping.tsx +0 -261
- package/src/data_import/components/ImportFileUpload.tsx +0 -42
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +0 -58
- package/src/data_import/components/ImportSaveInProgress.tsx +0 -121
- package/src/data_import/components/index.ts +0 -4
- package/src/data_import/hooks/index.ts +0 -1
- package/src/data_import/hooks/useImportConfig.tsx +0 -34
- package/src/data_import/import/ImportCollectionAction.tsx +0 -461
- package/src/data_import/import/index.ts +0 -1
- package/src/data_import/index.ts +0 -5
- package/src/data_import/types/column_mapping.ts +0 -32
- package/src/data_import/types/index.ts +0 -1
- package/src/data_import/utils/csv.ts +0 -153
- package/src/data_import/utils/data.ts +0 -181
- package/src/data_import/utils/file_headers.ts +0 -14
- package/src/data_import/utils/file_to_json.ts +0 -149
- package/src/data_import/utils/get_import_inference_type.ts +0 -33
- package/src/data_import/utils/get_properties_mapping.ts +0 -67
- package/src/data_import/utils/index.ts +0 -5
- package/src/data_import/utils/save_entities.ts +0 -138
- package/src/data_import/utils/transforms.ts +0 -70
- package/src/editor/components/SlashCommandMenu.tsx +0 -532
- package/src/editor/components/editor-bubble-item.tsx +0 -32
- package/src/editor/components/editor-bubble.tsx +0 -143
- package/src/editor/components/image-bubble.tsx +0 -183
- package/src/editor/components/index.ts +0 -14
- package/src/editor/components/table-bubble.tsx +0 -233
- package/src/editor/editor.tsx +0 -529
- package/src/editor/extensions/HighlightDecorationExtension.ts +0 -115
- package/src/editor/extensions/Image.ts +0 -159
- package/src/editor/extensions/TextLoadingDecorationExtension.tsx +0 -107
- package/src/editor/extensions/clipboard.ts +0 -72
- package/src/editor/extensions/custom-keymap.ts +0 -25
- package/src/editor/extensions/drag-and-drop.tsx +0 -508
- package/src/editor/hooks/useProseMirror.ts +0 -126
- package/src/editor/hooks/useProseMirrorContext.ts +0 -15
- package/src/editor/index.ts +0 -2
- package/src/editor/markdown-it-plugins.d.ts +0 -24
- package/src/editor/markdown.ts +0 -204
- package/src/editor/nodeViews/ImageComponent.tsx +0 -20
- package/src/editor/nodeViews/ReactNodeView.tsx +0 -89
- package/src/editor/nodeViews/TaskItemComponent.tsx +0 -30
- package/src/editor/nodeViews/index.ts +0 -35
- package/src/editor/plugins/index.ts +0 -58
- package/src/editor/plugins/inputrules.ts +0 -82
- package/src/editor/plugins/placeholderPlugin.ts +0 -55
- package/src/editor/plugins/slashCommandPlugin.ts +0 -65
- package/src/editor/schema.ts +0 -339
- package/src/editor/selectors/ai-selector.tsx +0 -110
- package/src/editor/selectors/color-selector.tsx +0 -199
- package/src/editor/selectors/link-selector.tsx +0 -122
- package/src/editor/selectors/node-selector.tsx +0 -159
- package/src/editor/selectors/text-buttons.tsx +0 -79
- package/src/editor/types.ts +0 -6
- package/src/editor/useProseMirror.ts +0 -125
- package/src/editor/utils/prosemirror-utils.ts +0 -113
- package/src/editor/utils/remove_classes.ts +0 -18
- package/src/editor/utils/useDebouncedCallback.ts +0 -25
- package/src/form/EntityForm.tsx +0 -761
- package/src/form/EntityFormActions.tsx +0 -160
- package/src/form/EntityFormBinding.tsx +0 -342
- package/src/form/PropertyFieldBinding.tsx +0 -348
- package/src/form/components/ErrorFocus.tsx +0 -44
- package/src/form/components/FieldBlock.tsx +0 -189
- package/src/form/components/FieldHelperText.tsx +0 -84
- package/src/form/components/FormRail.tsx +0 -153
- package/src/form/components/FormSections.tsx +0 -145
- package/src/form/components/LabelWithIcon.tsx +0 -43
- package/src/form/components/LabelWithIconAndTooltip.tsx +0 -28
- package/src/form/components/LocalChangesMenu.tsx +0 -147
- package/src/form/components/StorageItemPreview.tsx +0 -81
- package/src/form/components/StorageUploadProgress.tsx +0 -118
- package/src/form/components/index.tsx +0 -6
- package/src/form/components/useRailVisible.tsx +0 -47
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +0 -109
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -172
- package/src/form/field_bindings/BinaryFieldBinding.tsx +0 -177
- package/src/form/field_bindings/BlockFieldBinding.tsx +0 -282
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +0 -78
- package/src/form/field_bindings/GeopointFieldBinding.tsx +0 -200
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -574
- package/src/form/field_bindings/MapFieldBinding.tsx +0 -120
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +0 -259
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +0 -130
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +0 -168
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -94
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +0 -146
- package/src/form/field_bindings/RelationFieldBinding.tsx +0 -202
- package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -143
- package/src/form/field_bindings/SelectFieldBinding.tsx +0 -111
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +0 -521
- package/src/form/field_bindings/SwitchFieldBinding.tsx +0 -70
- package/src/form/field_bindings/TextFieldBinding.tsx +0 -189
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +0 -71
- package/src/form/field_bindings/VectorFieldBinding.tsx +0 -209
- package/src/form/form_utils.ts +0 -243
- package/src/form/index.tsx +0 -36
- package/src/form/useClearRestoreValue.tsx +0 -36
- package/src/form/useUndoableDiscard.ts +0 -39
- package/src/form/validation.ts +0 -583
- package/src/hooks/index.ts +0 -16
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +0 -22
- package/src/hooks/navigation/contexts/NavigationStateContext.tsx +0 -16
- package/src/hooks/navigation/contexts/UrlContext.tsx +0 -24
- package/src/hooks/navigation/contexts/index.ts +0 -14
- package/src/hooks/navigation/useAsyncResolver.ts +0 -100
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +0 -218
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +0 -134
- package/src/hooks/navigation/useBuildUrlController.tsx +0 -66
- package/src/hooks/navigation/useNavigationResolution.ts +0 -271
- package/src/hooks/navigation/useResolvedCollections.ts +0 -102
- package/src/hooks/navigation/useResolvedViews.tsx +0 -139
- package/src/hooks/navigation/useTopLevelNavigation.ts +0 -273
- package/src/hooks/navigation/utils.ts +0 -200
- package/src/hooks/useAdminContext.tsx +0 -83
- package/src/hooks/useBreadcrumbsController.tsx +0 -17
- package/src/hooks/useBuildSideDialogsController.tsx +0 -145
- package/src/hooks/useBuildSidePanel.tsx +0 -315
- package/src/hooks/useChildViewSource.ts +0 -46
- package/src/hooks/useEntityDisplay.tsx +0 -262
- package/src/hooks/useEntityDisplayTitle.tsx +0 -49
- package/src/hooks/useHistory.ts +0 -178
- package/src/hooks/useRecordActions.tsx +0 -69
- package/src/hooks/useResolvedNavigationFrom.tsx +0 -167
- package/src/hooks/useResolvedUsers.ts +0 -148
- package/src/hooks/useSelectionDialog.tsx +0 -58
- package/src/hooks/useSideDialogsController.tsx +0 -25
- package/src/hooks/useSidePanel.tsx +0 -13
- package/src/index.ts +0 -124
- package/src/preview/PropertyPreview.tsx +0 -331
- package/src/preview/compact_text.ts +0 -68
- package/src/preview/components/ArrayEnumPreview.tsx +0 -39
- package/src/preview/components/BooleanPreview.tsx +0 -28
- package/src/preview/components/DatePreview.tsx +0 -106
- package/src/preview/components/EmptyValue.tsx +0 -10
- package/src/preview/components/EnumValuesChip.tsx +0 -39
- package/src/preview/components/ImagePreview.tsx +0 -144
- package/src/preview/components/InlineEntityListPreview.tsx +0 -42
- package/src/preview/components/ReferencePreview.tsx +0 -235
- package/src/preview/components/RelationPreview.tsx +0 -271
- package/src/preview/components/StorageThumbnail.tsx +0 -147
- package/src/preview/components/UrlComponentPreview.tsx +0 -116
- package/src/preview/components/UserPreview.tsx +0 -30
- package/src/preview/components/date_fns_locales.ts +0 -125
- package/src/preview/index.ts +0 -26
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -73
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -67
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +0 -77
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -49
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -70
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -79
- package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +0 -35
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -79
- package/src/preview/property_previews/MapPropertyPreview.tsx +0 -198
- package/src/preview/property_previews/NumberPropertyPreview.tsx +0 -39
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +0 -276
- package/src/preview/property_previews/StringPropertyPreview.tsx +0 -70
- package/src/preview/util.ts +0 -39
- package/src/routes/CustomViewRoute.tsx +0 -33
- package/src/routes/RebaseRoute.tsx +0 -467
- package/src/routes/index.ts +0 -2
- package/src/types/components/EntityFormActionsProps.tsx +0 -20
- package/src/types/components/EntityFormProps.tsx +0 -119
- package/src/types/components/PropertyPreviewProps.tsx +0 -85
- package/src/types/components/formex.tsx +0 -2
- package/src/types/components/index.ts +0 -3
- package/src/types/fields.tsx +0 -340
- package/src/types/index.ts +0 -4
- package/src/util/dataControllerAdapter.ts +0 -88
- package/src/util/entity_actions.ts +0 -28
- package/src/util/index.ts +0 -5
- package/src/util/navigation_utils.ts +0 -89
- package/src/util/number_format.ts +0 -46
- package/src/util/previews.ts +0 -131
- package/src/util/propertyConfigMapper.ts +0 -134
- package/src/util/property_utils.tsx +0 -236
- package/src/util/resolutions.ts +0 -96
- package/src/util/view_constants.ts +0 -33
- package/src/util/view_mode.ts +0 -176
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { getPropertyInPath } from "../../util";
|
|
2
|
-
import { Entity, EntityReference, CollectionRegistryController, Properties, Property, Vector } from "@rebasepro/types";
|
|
3
|
-
import { AuthController, AdminCollection } from "@rebasepro/cms-types";
|
|
4
|
-
import { isPropertyBuilder } from "@rebasepro/common";
|
|
5
|
-
import { unflattenObject } from "./transforms";
|
|
6
|
-
import { getIn } from "@rebasepro/forms";
|
|
7
|
-
import { inferTypeFromValue } from "@rebasepro/inference";
|
|
8
|
-
import { isPrototypePollutingKey, mergeDeep } from "@rebasepro/utils";
|
|
9
|
-
|
|
10
|
-
export function convertDataToEntity(authController: AuthController,
|
|
11
|
-
navigation: CollectionRegistryController,
|
|
12
|
-
data: Record<any, any>,
|
|
13
|
-
idColumn: string | undefined,
|
|
14
|
-
headersMapping: Record<string, string | null>,
|
|
15
|
-
properties: Properties,
|
|
16
|
-
path: string,
|
|
17
|
-
defaultValues: Record<string, any>): Entity<any> {
|
|
18
|
-
const flatObject = flattenEntry(data);
|
|
19
|
-
if (idColumn)
|
|
20
|
-
delete flatObject[idColumn];
|
|
21
|
-
const mappedKeysObject = Object.entries(flatObject)
|
|
22
|
-
.map(([key, value]) => {
|
|
23
|
-
const mappedKey = (getIn(headersMapping, key) as string | undefined) ?? key;
|
|
24
|
-
|
|
25
|
-
const mappedProperty = getPropertyInPath(properties, mappedKey);
|
|
26
|
-
if (!mappedProperty) {
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
const processedValue = processValueMapping(authController, value, navigation, mappedProperty);
|
|
30
|
-
return ({
|
|
31
|
-
[mappedKey]: processedValue
|
|
32
|
-
});
|
|
33
|
-
})
|
|
34
|
-
.reduce((acc, curr) => ({ ...acc,
|
|
35
|
-
...curr }), {});
|
|
36
|
-
|
|
37
|
-
const values = mergeDeep(defaultValues ?? {}, unflattenObject(mappedKeysObject));
|
|
38
|
-
let id = idColumn ? data[idColumn] : undefined;
|
|
39
|
-
if (typeof id === "string") {
|
|
40
|
-
id = id.trim();
|
|
41
|
-
} else if (typeof id === "number") {
|
|
42
|
-
id = id.toString();
|
|
43
|
-
} else if (typeof id === "boolean") {
|
|
44
|
-
id = id.toString();
|
|
45
|
-
} else if (id instanceof Date) {
|
|
46
|
-
id = id.toISOString();
|
|
47
|
-
} else if (id && "toString" in id) {
|
|
48
|
-
id = id.toString();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
id,
|
|
53
|
-
values,
|
|
54
|
-
path: path
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function flattenEntry(obj: Record<string, unknown>, parent = ""): Record<string, unknown> {
|
|
59
|
-
return Object.keys(obj).reduce<Record<string, unknown>>((acc, key) => {
|
|
60
|
-
// Keys come from the uploaded file, so `acc[key] = …` is the class-22
|
|
61
|
-
// primitive when the key is `__proto__`; refuse the column instead.
|
|
62
|
-
if (isPrototypePollutingKey(key)) {
|
|
63
|
-
console.warn(`Skipping column "${key}": a header may not reach the prototype chain`);
|
|
64
|
-
return acc;
|
|
65
|
-
}
|
|
66
|
-
const prefixedKey = parent ? `${parent}.${key}` : key;
|
|
67
|
-
|
|
68
|
-
if (typeof obj[key] === "object" && !(obj[key] instanceof Date) && obj[key] !== null && !Array.isArray(obj[key])) {
|
|
69
|
-
Object.assign(acc, flattenEntry(obj[key] as Record<string, unknown>, prefixedKey));
|
|
70
|
-
} else {
|
|
71
|
-
acc[prefixedKey] = obj[key];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return acc;
|
|
75
|
-
}, {});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function processValueMapping(authController: AuthController, value: any, navigation: CollectionRegistryController, property?: Property): any {
|
|
79
|
-
if (value === null) return null;
|
|
80
|
-
|
|
81
|
-
if (property === undefined) return value;
|
|
82
|
-
const usedProperty: Property | null = property;
|
|
83
|
-
if (usedProperty === null) return value;
|
|
84
|
-
const from = inferTypeFromValue(value);
|
|
85
|
-
const to = usedProperty.type;
|
|
86
|
-
|
|
87
|
-
if (to === "vector") {
|
|
88
|
-
if (value && typeof value === "object" && "value" in value && Array.isArray(value.value)) {
|
|
89
|
-
return new Vector(value.value);
|
|
90
|
-
} else if (Array.isArray(value)) {
|
|
91
|
-
return new Vector(value.map(Number));
|
|
92
|
-
} else if (typeof value === "string") {
|
|
93
|
-
let cleaned = value.trim();
|
|
94
|
-
if (cleaned.startsWith("[") && cleaned.endsWith("]")) {
|
|
95
|
-
cleaned = cleaned.slice(1, -1);
|
|
96
|
-
}
|
|
97
|
-
if (cleaned === "") return null;
|
|
98
|
-
return new Vector(cleaned.split(",").map(v => {
|
|
99
|
-
const num = Number(v.trim());
|
|
100
|
-
return isNaN(num) ? 0 : num;
|
|
101
|
-
}));
|
|
102
|
-
}
|
|
103
|
-
return value;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (from === "array" && to === "array" && Array.isArray(value) && usedProperty.of && !Array.isArray(usedProperty.of) && !isPropertyBuilder(usedProperty.of)) {
|
|
107
|
-
return value.map(v => processValueMapping(authController, v, navigation, usedProperty.of as Property));
|
|
108
|
-
} else if (from === "string" && to === "number" && typeof value === "string") {
|
|
109
|
-
// `Number("")` is 0, so a blank cell used to import as a real zero — a
|
|
110
|
-
// price of nothing rather than a price nobody filled in — and `Number`
|
|
111
|
-
// of anything unreadable imported as NaN. Both are absent values, and
|
|
112
|
-
// saying so lets the importer's own validation see them. The `vector`
|
|
113
|
-
// branch above already draws the same distinction.
|
|
114
|
-
const trimmed = value.trim();
|
|
115
|
-
if (trimmed === "") return null;
|
|
116
|
-
const num = Number(trimmed);
|
|
117
|
-
return Number.isNaN(num) ? null : num;
|
|
118
|
-
} else if (from === "string" && to === "array" && typeof value === "string" && usedProperty.of && !Array.isArray(usedProperty.of) && !isPropertyBuilder(usedProperty.of)) {
|
|
119
|
-
return value.split(",").map((v: string) => processValueMapping(authController, v, navigation, usedProperty.of as Property));
|
|
120
|
-
} else if (from === "string" && to === "boolean") {
|
|
121
|
-
return value === "true";
|
|
122
|
-
} else if (from === "number" && to === "boolean") {
|
|
123
|
-
return value === 1;
|
|
124
|
-
} else if (from === "boolean" && to === "number") {
|
|
125
|
-
return value ? 1 : 0;
|
|
126
|
-
} else if (from === "boolean" && to === "string") {
|
|
127
|
-
return value ? "true" : "false";
|
|
128
|
-
} else if (from === "number" && to === "string" && typeof value === "number") {
|
|
129
|
-
return value.toString();
|
|
130
|
-
} else if (from === "string" && to === "array" && typeof value === "string") {
|
|
131
|
-
return value.split(",").map((v: string) => v.trim());
|
|
132
|
-
} else if (from === "string" && to === "date" && typeof value === "string") {
|
|
133
|
-
try {
|
|
134
|
-
return new Date(value);
|
|
135
|
-
} catch (e) {
|
|
136
|
-
return value;
|
|
137
|
-
}
|
|
138
|
-
} else if (value instanceof Date && to === "string") {
|
|
139
|
-
return value.toISOString();
|
|
140
|
-
} else if (from === "number" && to === "date" && typeof value === "number") {
|
|
141
|
-
try {
|
|
142
|
-
return new Date(value);
|
|
143
|
-
} catch (e) {
|
|
144
|
-
return value;
|
|
145
|
-
}
|
|
146
|
-
} else if (from === "string" && to === "reference" && typeof value === "string") {
|
|
147
|
-
// Parse optional database name in format: database_name:::path/to/entity
|
|
148
|
-
// or simple format: path/to/entity
|
|
149
|
-
let databaseId: string | undefined = undefined;
|
|
150
|
-
let referencePath = value;
|
|
151
|
-
|
|
152
|
-
if (value.includes(":::")) {
|
|
153
|
-
const [dbName, pathPart] = value.split(":::");
|
|
154
|
-
if (dbName && dbName !== "(default)") {
|
|
155
|
-
databaseId = dbName;
|
|
156
|
-
}
|
|
157
|
-
referencePath = pathPart;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// split value into path and entityId (entityId is the last part of the path, after the last /)
|
|
161
|
-
const path = referencePath.split("/").slice(0, -1).join("/");
|
|
162
|
-
const entityId = referencePath.split("/").slice(-1)[0];
|
|
163
|
-
|
|
164
|
-
// If no explicit database was provided in the string, try to get it from the collection
|
|
165
|
-
if (databaseId === undefined) {
|
|
166
|
-
const targetCollection: AdminCollection<any> | undefined = navigation.getCollection(path);
|
|
167
|
-
databaseId = targetCollection?.databaseId;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return new EntityReference({ id: entityId,
|
|
171
|
-
path,
|
|
172
|
-
databaseId });
|
|
173
|
-
|
|
174
|
-
} else if (from === to) {
|
|
175
|
-
return value;
|
|
176
|
-
} else if (from === "array" && to === "string" && Array.isArray(value)) {
|
|
177
|
-
return value.join(",");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return value;
|
|
181
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Worksheet } from "exceljs";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Extract column headers from the first row of an ExcelJS worksheet.
|
|
5
|
-
* Returns an array of header strings in column order.
|
|
6
|
-
*/
|
|
7
|
-
export function getWorksheetHeaders(worksheet: Worksheet): string[] {
|
|
8
|
-
const headers: string[] = [];
|
|
9
|
-
const headerRow = worksheet.getRow(1);
|
|
10
|
-
headerRow.eachCell({ includeEmpty: false }, (cell, colNumber) => {
|
|
11
|
-
headers[colNumber - 1] = cell.text ?? `Column${colNumber}`;
|
|
12
|
-
});
|
|
13
|
-
return headers.filter(Boolean);
|
|
14
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { getWorksheetHeaders } from "./file_headers";
|
|
2
|
-
import { mapJsonParse, unflattenObject } from "./transforms";
|
|
3
|
-
import { parseCsvToObjects } from "./csv";
|
|
4
|
-
import { isPrototypePollutingKey } from "@rebasepro/utils";
|
|
5
|
-
|
|
6
|
-
type ConversionResult = {
|
|
7
|
-
data: object[];
|
|
8
|
-
propertiesOrder: string[]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* ExcelJS, fetched the first time somebody actually opens a workbook.
|
|
13
|
-
*
|
|
14
|
-
* It was a top-level `import ExcelJS from "exceljs"`, and that one line put
|
|
15
|
-
* 940 kB of spreadsheet reader into the admin's entry chunk — preloaded on the
|
|
16
|
-
* login screen, before anyone has authenticated, let alone clicked Import.
|
|
17
|
-
* `CollectionViewActions` lazy-loads the import and export actions and says so
|
|
18
|
-
* in a comment, but the package's own barrel (`src/index.ts` re-exports
|
|
19
|
-
* `./data_import`) puts this module back in the entry's static graph, so the
|
|
20
|
-
* `lazy()` bought nothing. A static import inside a module the barrel reaches
|
|
21
|
-
* is eager no matter what the component above it does; the only thing that
|
|
22
|
-
* makes a dependency lazy is importing it lazily, here.
|
|
23
|
-
*/
|
|
24
|
-
type ExcelJsModule = typeof import("exceljs");
|
|
25
|
-
|
|
26
|
-
let excelJsModule: Promise<ExcelJsModule> | undefined;
|
|
27
|
-
|
|
28
|
-
function loadExcelJs(): Promise<ExcelJsModule> {
|
|
29
|
-
// exceljs is CommonJS, so the namespace a bundler hands back wraps the real
|
|
30
|
-
// module under `default`. Native ESM (and the type declarations) put the
|
|
31
|
-
// members at the top level. Accept either.
|
|
32
|
-
excelJsModule ??= import("exceljs").then(mod => (mod as { default?: ExcelJsModule }).default ?? mod);
|
|
33
|
-
return excelJsModule;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Whether this file is delimited text rather than a workbook.
|
|
38
|
-
*
|
|
39
|
-
* Browsers report `text/csv`, `application/csv` or nothing at all for the same
|
|
40
|
-
* `.csv`, so the extension is the reliable half of the test.
|
|
41
|
-
*/
|
|
42
|
-
function isCsvFile(file: File): boolean {
|
|
43
|
-
const name = (file.name ?? "").toLowerCase();
|
|
44
|
-
if (name.endsWith(".csv") || name.endsWith(".tsv")) return true;
|
|
45
|
-
return file.type === "text/csv" || file.type === "application/csv";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Turn the parsed cells of one sheet/file into the entity-shaped rows the import maps. */
|
|
49
|
-
function toImportRows(rows: Array<Record<string, unknown>>): object[] {
|
|
50
|
-
return rows.map(mapJsonParse).map(unflattenObject);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function convertFileToJson(file: File): Promise<ConversionResult> {
|
|
54
|
-
return new Promise((resolve, reject) => {
|
|
55
|
-
if (isCsvFile(file)) {
|
|
56
|
-
// Not the ExcelJS branch: `workbook.xlsx.load` is a zip reader, and
|
|
57
|
-
// every CSV — the format this admin exports by default — died on it
|
|
58
|
-
// with "Can't find end of central directory : is this a zip file ?".
|
|
59
|
-
console.debug("Converting CSV file to JSON", file.name);
|
|
60
|
-
const reader = new FileReader();
|
|
61
|
-
reader.onload = function (e) {
|
|
62
|
-
try {
|
|
63
|
-
const { headers, data } = parseCsvToObjects(e.target?.result as string);
|
|
64
|
-
if (headers.length === 0) {
|
|
65
|
-
reject(new Error("The CSV file is empty"));
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
resolve({
|
|
69
|
-
data: toImportRows(data),
|
|
70
|
-
propertiesOrder: headers
|
|
71
|
-
});
|
|
72
|
-
} catch (err) {
|
|
73
|
-
console.error("Error parsing CSV file", err);
|
|
74
|
-
reject(err);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
reader.onerror = () => reject(reader.error ?? new Error("Could not read the file"));
|
|
78
|
-
// Explicit UTF-8: the pre-ExcelJS implementation passed
|
|
79
|
-
// `codepage: 65001` for the same reason, and the browser's default
|
|
80
|
-
// guess mangles accented and CJK text.
|
|
81
|
-
reader.readAsText(file, "utf-8");
|
|
82
|
-
} else if (file.type === "application/json") {
|
|
83
|
-
console.debug("Converting JSON file to JSON", file.name);
|
|
84
|
-
const reader = new FileReader();
|
|
85
|
-
reader.onload = function (e) {
|
|
86
|
-
try {
|
|
87
|
-
const data = e.target?.result as string;
|
|
88
|
-
const jsonData = JSON.parse(data);
|
|
89
|
-
if (!Array.isArray(jsonData)) {
|
|
90
|
-
reject(new Error("JSON file should contain an array of objects"));
|
|
91
|
-
} else {
|
|
92
|
-
const propertiesOrder = jsonData.length > 0 ? Object.keys(jsonData[0]) : [];
|
|
93
|
-
resolve({
|
|
94
|
-
data: jsonData,
|
|
95
|
-
propertiesOrder
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
} catch (e) {
|
|
99
|
-
console.error("Error parsing JSON file", e);
|
|
100
|
-
reject(e);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
reader.readAsText(file);
|
|
104
|
-
} else {
|
|
105
|
-
console.debug("Converting Excel file to JSON", file.name);
|
|
106
|
-
const reader = new FileReader();
|
|
107
|
-
reader.onload = async function (e) {
|
|
108
|
-
try {
|
|
109
|
-
const buffer = e.target?.result as ArrayBuffer;
|
|
110
|
-
const ExcelJS = await loadExcelJs();
|
|
111
|
-
const workbook = new ExcelJS.Workbook();
|
|
112
|
-
await workbook.xlsx.load(buffer);
|
|
113
|
-
const worksheet = workbook.worksheets[0];
|
|
114
|
-
if (!worksheet) {
|
|
115
|
-
reject(new Error("No worksheets found in file"));
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const headers = getWorksheetHeaders(worksheet);
|
|
120
|
-
|
|
121
|
-
// Convert rows to JSON objects (skip header row)
|
|
122
|
-
const parsedData: Array<Record<string, any>> = [];
|
|
123
|
-
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
|
|
124
|
-
if (rowNumber === 1) return;
|
|
125
|
-
const obj: Record<string, any> = {};
|
|
126
|
-
row.eachCell({ includeEmpty: false }, (cell, colNumber) => {
|
|
127
|
-
const header = headers[colNumber - 1];
|
|
128
|
-
// A `__proto__` header would be the prototype setter
|
|
129
|
-
// here rather than a column; refused, as in `csv.ts`.
|
|
130
|
-
if (header && !isPrototypePollutingKey(header)) {
|
|
131
|
-
obj[header] = cell.value;
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
parsedData.push(obj);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
resolve({
|
|
138
|
-
data: toImportRows(parsedData),
|
|
139
|
-
propertiesOrder: headers
|
|
140
|
-
});
|
|
141
|
-
} catch (err) {
|
|
142
|
-
console.error("Error parsing Excel file", err);
|
|
143
|
-
reject(err);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
reader.readAsArrayBuffer(file);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { DataType } from "@rebasepro/types";
|
|
2
|
-
|
|
3
|
-
export function getInferenceType(value: any): DataType {
|
|
4
|
-
// `typeof null === "object"`, so a null or empty CSV cell used to fall past
|
|
5
|
-
// every check and land on "map" — an empty cell described as a nested object.
|
|
6
|
-
// `inferTypeFromValue` in @rebasepro/inference already answers "string" here;
|
|
7
|
-
// the two entry points into inference have to agree.
|
|
8
|
-
if (value === null || value === undefined)
|
|
9
|
-
return "string";
|
|
10
|
-
if (typeof value === "number")
|
|
11
|
-
return "number";
|
|
12
|
-
else if (typeof value === "string")
|
|
13
|
-
return "string";
|
|
14
|
-
else if (typeof value === "boolean")
|
|
15
|
-
return "boolean";
|
|
16
|
-
else if (value instanceof Date)
|
|
17
|
-
return "date";
|
|
18
|
-
else if (Array.isArray(value))
|
|
19
|
-
return "array";
|
|
20
|
-
return "map";
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function isUnixTimestamp(num: number): boolean {
|
|
25
|
-
const numString = num.toString();
|
|
26
|
-
// check if the number has 13 digits
|
|
27
|
-
const isLengthValid = numString.length === 13;
|
|
28
|
-
|
|
29
|
-
// check if it falls in the expected Unix timestamp range (from 1970 to 2100)
|
|
30
|
-
const isInRange = num >= 0 && num <= 4102444800000;
|
|
31
|
-
|
|
32
|
-
return isLengthValid && isInRange;
|
|
33
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
// import {
|
|
2
|
-
// type,
|
|
3
|
-
// getPropertyInPath
|
|
4
|
-
// } from "@rebasepro/app";
|
|
5
|
-
import { Properties, Property } from "@rebasepro/types";
|
|
6
|
-
// import { typeMapping } from "@rebasepro/types";
|
|
7
|
-
//
|
|
8
|
-
// export function getPropertiesMapping(originProperties: Properties,
|
|
9
|
-
// newProperties: Properties,
|
|
10
|
-
// headersMapping: Record<string, string | null>): Record<string, typeMapping> {
|
|
11
|
-
//
|
|
12
|
-
// function updateMapping(properties: Record<string, Property>, namespace?: string): Record<string, typeMapping> {
|
|
13
|
-
//
|
|
14
|
-
// const dataMapping: Record<string, typeMapping> = {};
|
|
15
|
-
//
|
|
16
|
-
// Object.keys(properties).forEach((key) => {
|
|
17
|
-
//
|
|
18
|
-
// const currentKey = namespace ? `${namespace}.${key}` : key;
|
|
19
|
-
//
|
|
20
|
-
// const property = getPropertyInPath(properties, key) as Property;
|
|
21
|
-
// // reverse lookup
|
|
22
|
-
// const mappedKey = Object.entries(headersMapping).find(([_, value]) => value === currentKey)?.[0];
|
|
23
|
-
// const inferredProperty = mappedKey ? getPropertyInPath(originProperties, mappedKey) as Property : null;
|
|
24
|
-
//
|
|
25
|
-
// if (property) {
|
|
26
|
-
// if (property.type === "map" && property.properties) {
|
|
27
|
-
// const nestedMapping = updateMapping(property.properties as Record<string, Property>, currentKey);
|
|
28
|
-
// Object.keys(nestedMapping).forEach((nestedKey) => {
|
|
29
|
-
// dataMapping[`${currentKey}.${nestedKey}`] = nestedMapping[nestedKey];
|
|
30
|
-
// });
|
|
31
|
-
// return;
|
|
32
|
-
// }
|
|
33
|
-
//
|
|
34
|
-
// if (inferredProperty) {
|
|
35
|
-
//
|
|
36
|
-
// const from = inferredProperty.type;
|
|
37
|
-
// const to = property.type;
|
|
38
|
-
// let fromSubtype: type | undefined;
|
|
39
|
-
// let toSubtype: type | undefined;
|
|
40
|
-
//
|
|
41
|
-
// if (property.type === "array" && property.of) {
|
|
42
|
-
// toSubtype = (property.of as Property).type;
|
|
43
|
-
// }
|
|
44
|
-
//
|
|
45
|
-
// if (inferredProperty?.type === "array" && inferredProperty?.of) {
|
|
46
|
-
// fromSubtype = (inferredProperty.of as Property).type;
|
|
47
|
-
// }
|
|
48
|
-
//
|
|
49
|
-
// if (from !== to || fromSubtype !== toSubtype) {
|
|
50
|
-
// dataMapping[currentKey] = {
|
|
51
|
-
// from,
|
|
52
|
-
// to,
|
|
53
|
-
// fromSubtype,
|
|
54
|
-
// toSubtype
|
|
55
|
-
// };
|
|
56
|
-
// }
|
|
57
|
-
// }
|
|
58
|
-
//
|
|
59
|
-
// }
|
|
60
|
-
//
|
|
61
|
-
// });
|
|
62
|
-
//
|
|
63
|
-
// return dataMapping;
|
|
64
|
-
// }
|
|
65
|
-
//
|
|
66
|
-
// return updateMapping(newProperties);
|
|
67
|
-
// }
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { CollectionAccessor, Entity, RebaseData } from "@rebasepro/types";
|
|
2
|
-
|
|
3
|
-
/** Rows written per request, and per transaction where the data source has one. */
|
|
4
|
-
export const IMPORT_BATCH_SIZE = 25;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* An import failure that says where it stopped.
|
|
8
|
-
*
|
|
9
|
-
* "Error saving data / null value in column "sku" violates not-null constraint"
|
|
10
|
-
* on a ten-thousand-row import named no row, and the Retry button restarted at
|
|
11
|
-
* zero — where the rows already written now conflicted, so it could never
|
|
12
|
-
* succeed. Both halves of that are what this carries.
|
|
13
|
-
*/
|
|
14
|
-
export interface ImportSaveError extends Error {
|
|
15
|
-
/** Rows written and confirmed before the failure. Where a retry resumes. */
|
|
16
|
-
committed: number;
|
|
17
|
-
/** Index of the first row that was not written, 0-based. */
|
|
18
|
-
failedFrom: number;
|
|
19
|
-
/** Index after the last row of the batch that was not written. */
|
|
20
|
-
failedTo: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** The row a bulk write takes: the values, with the chosen id as a column. */
|
|
24
|
-
function toBulkRow(entity: Partial<Entity<any>>): Record<string, unknown> {
|
|
25
|
-
const values = { ...(entity.values ?? {}) } as Record<string, unknown>;
|
|
26
|
-
if (entity.id !== undefined && entity.id !== null && entity.id !== "") {
|
|
27
|
-
// Exactly what single-row `create(values, id)` puts on the wire.
|
|
28
|
-
values.id = entity.id;
|
|
29
|
-
}
|
|
30
|
-
return values;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function isBulkUnsupported(error: unknown): boolean {
|
|
34
|
-
if ((error as { code?: string })?.code === "BULK_UNSUPPORTED") return true;
|
|
35
|
-
const message = (error as Error)?.message ?? "";
|
|
36
|
-
return /bulk writes are not supported|does not support bulk/i.test(message);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function isConflict(error: unknown): boolean {
|
|
40
|
-
const status = (error as { status?: number; statusCode?: number })?.status
|
|
41
|
-
?? (error as { statusCode?: number })?.statusCode;
|
|
42
|
-
if (status === 409) return true;
|
|
43
|
-
const code = (error as { code?: string })?.code;
|
|
44
|
-
return code === "CONFLICT" || code === "23505";
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Write one batch, all-or-nothing wherever the data source can.
|
|
49
|
-
*
|
|
50
|
-
* `POST /<collection>/bulk` validates every row before the transaction opens,
|
|
51
|
-
* names a failure by row index, and takes the `upsert` flag the preview screen
|
|
52
|
-
* promises — none of which one `create` per row inside a `Promise.all` could
|
|
53
|
-
* offer, since `Promise.all` does not cancel its siblings and every request was
|
|
54
|
-
* its own transaction.
|
|
55
|
-
*/
|
|
56
|
-
async function writeBatch(accessor: CollectionAccessor,
|
|
57
|
-
batch: Partial<Entity<any>>[],
|
|
58
|
-
bulkUnsupported: { current: boolean },
|
|
59
|
-
written: { count: number }): Promise<void> {
|
|
60
|
-
|
|
61
|
-
if (accessor.createMany && !bulkUnsupported.current) {
|
|
62
|
-
try {
|
|
63
|
-
await accessor.createMany(batch.map(toBulkRow), { upsert: true });
|
|
64
|
-
written.count = batch.length;
|
|
65
|
-
return;
|
|
66
|
-
} catch (e) {
|
|
67
|
-
if (!isBulkUnsupported(e)) throw e;
|
|
68
|
-
// A data source without bulk writes: remember it, so the failed
|
|
69
|
-
// round trip is not paid again on every later batch.
|
|
70
|
-
bulkUnsupported.current = true;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Sequential, not `Promise.all`: a rejected write does not cancel its
|
|
75
|
-
// siblings, so a parallel batch commits an indeterminate subset of itself
|
|
76
|
-
// and nobody can say which rows landed.
|
|
77
|
-
for (const entity of batch) {
|
|
78
|
-
try {
|
|
79
|
-
await accessor.create(entity.values ?? {}, entity.id);
|
|
80
|
-
} catch (e) {
|
|
81
|
-
// Without `/bulk` there is no upsert, so the preview's promise is
|
|
82
|
-
// honoured the only way left: a row that collided on an id the user
|
|
83
|
-
// supplied is overwritten. A row with no id had nothing to collide
|
|
84
|
-
// on, and every other failure is still a failure.
|
|
85
|
-
if (entity.id === undefined || !isConflict(e)) throw e;
|
|
86
|
-
await accessor.update(entity.id, entity.values ?? {});
|
|
87
|
-
}
|
|
88
|
-
written.count++;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Write imported entities in batches, reporting what was committed.
|
|
94
|
-
*
|
|
95
|
-
* Resumable on purpose: a failure at row 4 000 leaves rows 1–3 999 in the table
|
|
96
|
-
* whatever this does, so the only useful thing to report is where to carry on
|
|
97
|
-
* from. `offset` is that point — the Retry button passes back the `committed`
|
|
98
|
-
* count of the error it is retrying, instead of starting from zero and
|
|
99
|
-
* conflicting on every row that already exists.
|
|
100
|
-
*
|
|
101
|
-
* @throws {ImportSaveError} naming the rows that were not written.
|
|
102
|
-
*/
|
|
103
|
-
export async function saveImportedEntities(dataClient: RebaseData,
|
|
104
|
-
path: string,
|
|
105
|
-
data: Partial<Entity<any>>[],
|
|
106
|
-
{
|
|
107
|
-
offset = 0,
|
|
108
|
-
batchSize = IMPORT_BATCH_SIZE,
|
|
109
|
-
onBatchCommitted = () => undefined,
|
|
110
|
-
bulkUnsupported = { current: false }
|
|
111
|
-
}: {
|
|
112
|
-
offset?: number;
|
|
113
|
-
batchSize?: number;
|
|
114
|
-
onBatchCommitted?: (rowsWritten: number) => void;
|
|
115
|
-
bulkUnsupported?: { current: boolean };
|
|
116
|
-
} = {}): Promise<void> {
|
|
117
|
-
|
|
118
|
-
console.debug("Saving imported data", offset, batchSize);
|
|
119
|
-
|
|
120
|
-
const accessor = dataClient.collection(path);
|
|
121
|
-
|
|
122
|
-
for (let start = offset; start < data.length; start += batchSize) {
|
|
123
|
-
const batch = data.slice(start, start + batchSize);
|
|
124
|
-
const written = { count: 0 };
|
|
125
|
-
try {
|
|
126
|
-
await writeBatch(accessor, batch, bulkUnsupported, written);
|
|
127
|
-
} catch (e) {
|
|
128
|
-
throw Object.assign(e as Error, {
|
|
129
|
-
committed: start + written.count,
|
|
130
|
-
failedFrom: start + written.count,
|
|
131
|
-
failedTo: start + batch.length
|
|
132
|
-
}) as ImportSaveError;
|
|
133
|
-
}
|
|
134
|
-
onBatchCommitted(start + batch.length);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
onBatchCommitted(data.length);
|
|
138
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { isPrototypePollutingKey, pathTraversesPrototype } from "@rebasepro/utils";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Take an object with keys of type `address.street`, `address.city` and
|
|
5
|
-
* convert it to an object with nested objects like `{ address: { street: ..., city: ... } }`
|
|
6
|
-
*
|
|
7
|
-
* Keys here are the **header row of an uploaded file**, so they are attacker
|
|
8
|
-
* data. `res["__proto__"] = …` is the prototype setter rather than an own
|
|
9
|
-
* property, so a column named `__proto__.polluted` walked out of the accumulator
|
|
10
|
-
* and wrote onto `Object.prototype` for the life of the tab — and
|
|
11
|
-
* `constructor.prototype.x` threw a `TypeError` that surfaced as an unreadable
|
|
12
|
-
* file. Such a column is refused, not sanitised, the way `setIn` settled it
|
|
13
|
-
* (`docs/bug-classes.md` class 22).
|
|
14
|
-
*
|
|
15
|
-
* @param flatObj
|
|
16
|
-
*/
|
|
17
|
-
export function unflattenObject(flatObj: { [key: string]: any }) {
|
|
18
|
-
return Object.keys(flatObj).reduce((nestedObj, key) => {
|
|
19
|
-
// The string form, so `toPath` rewrites `__proto__[0]` to a `__proto__`
|
|
20
|
-
// segment too — the bracket branch below writes through the same setter.
|
|
21
|
-
if (pathTraversesPrototype(key)) {
|
|
22
|
-
console.warn(`Skipping column "${key}": a header may not reach the prototype chain`);
|
|
23
|
-
return nestedObj;
|
|
24
|
-
}
|
|
25
|
-
let currentObj = nestedObj;
|
|
26
|
-
const keyParts = key.split(".");
|
|
27
|
-
keyParts.forEach((keyPart, i) => {
|
|
28
|
-
|
|
29
|
-
if (/^[\w]+\[\d+\]$/.test(keyPart)) {
|
|
30
|
-
const mainPropertyName = keyPart.slice(0, keyPart.indexOf("["));
|
|
31
|
-
const index = parseInt(keyPart.slice(keyPart.indexOf("[") + 1, keyPart.indexOf("]")));
|
|
32
|
-
|
|
33
|
-
if (!currentObj[mainPropertyName]) {
|
|
34
|
-
currentObj[mainPropertyName] = []
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (i !== keyParts.length - 1) {
|
|
38
|
-
currentObj[mainPropertyName][index] = currentObj[mainPropertyName][index] || {};
|
|
39
|
-
currentObj = currentObj[mainPropertyName][index];
|
|
40
|
-
} else {
|
|
41
|
-
currentObj[mainPropertyName][index] = flatObj[key];
|
|
42
|
-
}
|
|
43
|
-
} else if (i !== keyParts.length - 1) {
|
|
44
|
-
currentObj[keyPart] = currentObj[keyPart] || {};
|
|
45
|
-
currentObj = currentObj[keyPart];
|
|
46
|
-
} else {
|
|
47
|
-
currentObj[keyPart] = flatObj[key];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
});
|
|
51
|
-
return nestedObj;
|
|
52
|
-
}, {} as { [key: string]: any });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function mapJsonParse(obj: Record<string, any>) {
|
|
56
|
-
return Object.keys(obj).reduce((acc: Record<string, any>, key) => {
|
|
57
|
-
// Same header row, same setter: `acc["__proto__"] = value` replaces the
|
|
58
|
-
// accumulator's prototype instead of adding a column.
|
|
59
|
-
if (isPrototypePollutingKey(key)) {
|
|
60
|
-
console.warn(`Skipping column "${key}": a header may not reach the prototype chain`);
|
|
61
|
-
return acc;
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
acc[key] = JSON.parse(obj[key]);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
acc[key] = obj[key];
|
|
67
|
-
}
|
|
68
|
-
return acc;
|
|
69
|
-
}, {});
|
|
70
|
-
}
|