@pilotiq/pilotiq 0.24.1 → 0.24.2
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/CHANGELOG.md +33 -0
- package/boost/guidelines.md +566 -0
- package/boost/skills/pilotiq-fields/SKILL.md +47 -0
- package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
- package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
- package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
- package/boost/skills/pilotiq-relations/SKILL.md +47 -0
- package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
- package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
- package/boost/skills/pilotiq-resource/SKILL.md +61 -0
- package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
- package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
- package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
- package/package.json +6 -1
- package/.turbo/turbo-build.log +0 -8
- package/CLAUDE.md +0 -265
- package/src/Cluster.test.ts +0 -283
- package/src/Cluster.ts +0 -83
- package/src/Column.test.ts +0 -199
- package/src/Column.ts +0 -710
- package/src/Global.test.ts +0 -367
- package/src/Global.ts +0 -169
- package/src/Page.test.ts +0 -114
- package/src/Page.ts +0 -208
- package/src/Pilotiq.perf.test.ts +0 -252
- package/src/Pilotiq.test.ts +0 -129
- package/src/Pilotiq.ts +0 -1158
- package/src/PilotiqRegistry.ts +0 -36
- package/src/PilotiqServiceProvider.ts +0 -121
- package/src/RelationManager.test.ts +0 -400
- package/src/RelationManager.ts +0 -527
- package/src/RenderHook.test.ts +0 -252
- package/src/RenderHook.ts +0 -242
- package/src/Resource.test.ts +0 -284
- package/src/Resource.ts +0 -526
- package/src/RightPanel.test.ts +0 -202
- package/src/RightPanel.ts +0 -132
- package/src/Tab.test.ts +0 -91
- package/src/Tab.ts +0 -156
- package/src/UserMenuItem.ts +0 -145
- package/src/actions/Action.test.ts +0 -2526
- package/src/actions/Action.ts +0 -1515
- package/src/actions/ActionGroup.test.ts +0 -112
- package/src/actions/ActionGroup.ts +0 -173
- package/src/actions/attachFactory.ts +0 -172
- package/src/actions/bulkFactories.ts +0 -168
- package/src/actions/crudFactories.ts +0 -220
- package/src/actions/exportFactory.ts +0 -225
- package/src/actions/factoryHelpers.ts +0 -177
- package/src/actions/importFactory.ts +0 -243
- package/src/actions/index.ts +0 -17
- package/src/actions/m2mFactories.ts +0 -193
- package/src/actions/relationFactories.ts +0 -372
- package/src/applyPageHooks.test.ts +0 -463
- package/src/applyPageHooks.ts +0 -330
- package/src/authorization.test.ts +0 -483
- package/src/breadcrumbs.test.ts +0 -238
- package/src/cells/coerce.test.ts +0 -85
- package/src/cells/coerce.ts +0 -84
- package/src/clusterPaths.ts +0 -35
- package/src/columns/BadgeColumn.test.ts +0 -54
- package/src/columns/BadgeColumn.ts +0 -32
- package/src/columns/BooleanColumn.test.ts +0 -41
- package/src/columns/BooleanColumn.ts +0 -18
- package/src/columns/ColorColumn.test.ts +0 -37
- package/src/columns/ColorColumn.ts +0 -38
- package/src/columns/IconColumn.test.ts +0 -54
- package/src/columns/IconColumn.ts +0 -37
- package/src/columns/ImageColumn.test.ts +0 -41
- package/src/columns/ImageColumn.ts +0 -28
- package/src/columns/SelectColumn.ts +0 -98
- package/src/columns/TextColumn.test.ts +0 -190
- package/src/columns/TextColumn.ts +0 -20
- package/src/columns/TextInputColumn.ts +0 -68
- package/src/columns/ToggleColumn.ts +0 -46
- package/src/columns/editableColumns.test.ts +0 -238
- package/src/columns/index.ts +0 -9
- package/src/defaultGlobalPages.ts +0 -95
- package/src/defaultPages.test.ts +0 -634
- package/src/defaultPages.ts +0 -617
- package/src/defaultViewPage.test.ts +0 -147
- package/src/elements/Form.test.ts +0 -223
- package/src/elements/Form.ts +0 -416
- package/src/elements/ListTabs.ts +0 -28
- package/src/elements/Table.test.ts +0 -422
- package/src/elements/Table.ts +0 -850
- package/src/elements/TableGroup.test.ts +0 -260
- package/src/elements/TableGroup.ts +0 -334
- package/src/elements/dispatchAction.test.ts +0 -463
- package/src/elements/dispatchAction.ts +0 -355
- package/src/elements/dispatchForm.test.ts +0 -477
- package/src/elements/dispatchForm.ts +0 -1993
- package/src/elements/dispatchTable.test.ts +0 -1514
- package/src/elements/dispatchTable.ts +0 -745
- package/src/elements/index.ts +0 -21
- package/src/entries/BadgeEntry.ts +0 -39
- package/src/entries/CodeEntry.test.ts +0 -40
- package/src/entries/CodeEntry.ts +0 -52
- package/src/entries/ColorEntry.ts +0 -63
- package/src/entries/ComponentEntry.test.ts +0 -173
- package/src/entries/ComponentEntry.ts +0 -95
- package/src/entries/Entry.ts +0 -304
- package/src/entries/IconEntry.ts +0 -49
- package/src/entries/ImageEntry.ts +0 -61
- package/src/entries/KeyValueEntry.ts +0 -47
- package/src/entries/RepeatableEntry.test.ts +0 -239
- package/src/entries/RepeatableEntry.ts +0 -173
- package/src/entries/TextEntry.test.ts +0 -394
- package/src/entries/TextEntry.ts +0 -60
- package/src/entries/index.ts +0 -12
- package/src/entries/leaves.test.ts +0 -306
- package/src/entries/registry.ts +0 -54
- package/src/fields/BuilderField.test.ts +0 -1188
- package/src/fields/BuilderField.ts +0 -605
- package/src/fields/BuilderRelationship.test.ts +0 -811
- package/src/fields/CheckboxField.test.ts +0 -44
- package/src/fields/CheckboxField.ts +0 -27
- package/src/fields/CheckboxListField.test.ts +0 -99
- package/src/fields/CheckboxListField.ts +0 -66
- package/src/fields/ColorPickerField.test.ts +0 -33
- package/src/fields/ColorPickerField.ts +0 -25
- package/src/fields/DateField.ts +0 -54
- package/src/fields/DateTimeField.test.ts +0 -55
- package/src/fields/EmailField.ts +0 -16
- package/src/fields/Field.test.ts +0 -654
- package/src/fields/Field.ts +0 -817
- package/src/fields/FileUploadField.test.ts +0 -143
- package/src/fields/FileUploadField.ts +0 -159
- package/src/fields/HiddenField.test.ts +0 -27
- package/src/fields/HiddenField.ts +0 -28
- package/src/fields/KeyValueField.test.ts +0 -105
- package/src/fields/KeyValueField.ts +0 -55
- package/src/fields/MarkdownField.test.ts +0 -167
- package/src/fields/MarkdownField.ts +0 -162
- package/src/fields/NumberField.ts +0 -33
- package/src/fields/RadioField.test.ts +0 -94
- package/src/fields/RadioField.ts +0 -67
- package/src/fields/RepeaterField.test.ts +0 -1806
- package/src/fields/RepeaterField.ts +0 -939
- package/src/fields/RepeaterRelationship.test.ts +0 -1923
- package/src/fields/RepeaterSimple.test.ts +0 -248
- package/src/fields/RowButton.test.ts +0 -219
- package/src/fields/RowButton.ts +0 -135
- package/src/fields/SelectField.test.ts +0 -192
- package/src/fields/SelectField.ts +0 -235
- package/src/fields/SliderField.test.ts +0 -50
- package/src/fields/SliderField.ts +0 -53
- package/src/fields/SlugField.ts +0 -24
- package/src/fields/TagsInputField.test.ts +0 -154
- package/src/fields/TagsInputField.ts +0 -133
- package/src/fields/TextField.test.ts +0 -213
- package/src/fields/TextField.ts +0 -177
- package/src/fields/TextareaField.test.ts +0 -58
- package/src/fields/TextareaField.ts +0 -59
- package/src/fields/ToggleButtonsField.test.ts +0 -106
- package/src/fields/ToggleButtonsField.ts +0 -59
- package/src/fields/ToggleField.ts +0 -16
- package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
- package/src/fields/optionsResolver.ts +0 -95
- package/src/fields/resolveField.ts +0 -28
- package/src/filters/BooleanFilter.ts +0 -35
- package/src/filters/DateRangeFilter.test.ts +0 -194
- package/src/filters/DateRangeFilter.ts +0 -148
- package/src/filters/Filter.test.ts +0 -268
- package/src/filters/Filter.ts +0 -184
- package/src/filters/FormFilter.test.ts +0 -238
- package/src/filters/FormFilter.ts +0 -215
- package/src/filters/MultiSelectFilter.test.ts +0 -119
- package/src/filters/MultiSelectFilter.ts +0 -78
- package/src/filters/QueryBuilderFilter.test.ts +0 -662
- package/src/filters/QueryBuilderFilter.ts +0 -398
- package/src/filters/SelectFilter.ts +0 -46
- package/src/filters/TernaryFilter.test.ts +0 -160
- package/src/filters/TernaryFilter.ts +0 -72
- package/src/filters/TrashedFilter.test.ts +0 -149
- package/src/filters/TrashedFilter.ts +0 -55
- package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
- package/src/filters/queryBuilder/Constraint.ts +0 -115
- package/src/filters/queryBuilder/DateConstraint.ts +0 -69
- package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
- package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
- package/src/filters/queryBuilder/TextConstraint.ts +0 -64
- package/src/filters/queryBuilder/index.ts +0 -12
- package/src/icons/index.ts +0 -2
- package/src/icons/lucide.ts +0 -204
- package/src/icons/registry.test.ts +0 -56
- package/src/icons/registry.ts +0 -41
- package/src/icons/types.ts +0 -47
- package/src/index.ts +0 -525
- package/src/io/csv.test.ts +0 -142
- package/src/io/csv.ts +0 -170
- package/src/nestedRelationManagerData.test.ts +0 -547
- package/src/notifications/Notification.test.ts +0 -210
- package/src/notifications/Notification.ts +0 -354
- package/src/notifications/broadcast.test.ts +0 -110
- package/src/notifications/broadcast.ts +0 -95
- package/src/notifications/database.test.ts +0 -383
- package/src/notifications/database.ts +0 -398
- package/src/notifications/databaseNotifications.test.ts +0 -187
- package/src/notifications/dispatchNotificationAction.test.ts +0 -341
- package/src/notifications/dispatchNotificationAction.ts +0 -142
- package/src/notifications/flash.test.ts +0 -89
- package/src/notifications/flash.ts +0 -71
- package/src/notifications/index.ts +0 -45
- package/src/notifications/registerBroadcastAuth.test.ts +0 -134
- package/src/notifications/registerBroadcastAuth.ts +0 -100
- package/src/notifications/resolveSavedNotification.test.ts +0 -82
- package/src/notifications/resolveSavedNotification.ts +0 -59
- package/src/notifications/types.ts +0 -93
- package/src/orm/m2mAccessor.ts +0 -66
- package/src/orm/modelDefaults.test.ts +0 -633
- package/src/orm/modelDefaults.ts +0 -666
- package/src/pageData/breadcrumbs.ts +0 -288
- package/src/pageData/forms.ts +0 -578
- package/src/pageData/helpers.ts +0 -857
- package/src/pageData/misc.ts +0 -347
- package/src/pageData/navigation.ts +0 -842
- package/src/pageData/relationPages.ts +0 -1248
- package/src/pageData/relationTabs.ts +0 -286
- package/src/pageData/resourcePages.ts +0 -609
- package/src/pageData.test.ts +0 -1545
- package/src/pageData.ts +0 -341
- package/src/plugins/index.ts +0 -8
- package/src/plugins/themeEditor.test.ts +0 -36
- package/src/plugins/themeEditor.ts +0 -45
- package/src/react/AppShell.tsx +0 -251
- package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
- package/src/react/CollabRoomContext.ts +0 -98
- package/src/react/CollabTextRendererRegistry.ts +0 -102
- package/src/react/CommandPalette.tsx +0 -375
- package/src/react/CurrentUserContext.tsx +0 -50
- package/src/react/CustomPageWrapperGate.tsx +0 -69
- package/src/react/CustomPageWrapperRegistry.ts +0 -45
- package/src/react/FieldFocusReporterRegistry.ts +0 -37
- package/src/react/FieldLabelSlotRegistry.ts +0 -30
- package/src/react/FieldPresenceRegistry.ts +0 -46
- package/src/react/FormCollabBindingRegistry.ts +0 -242
- package/src/react/FormStateContext.tsx +0 -591
- package/src/react/HeadHooks.tsx +0 -126
- package/src/react/MarkdownEditorRegistry.test.ts +0 -38
- package/src/react/MarkdownEditorRegistry.ts +0 -107
- package/src/react/NotificationActionStrip.tsx +0 -263
- package/src/react/NotificationBell.tsx +0 -426
- package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
- package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
- package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
- package/src/react/PendingSuggestionsContext.tsx +0 -172
- package/src/react/RecordWrapperGate.tsx +0 -58
- package/src/react/RecordWrapperRegistry.ts +0 -39
- package/src/react/RenderHookSlot.tsx +0 -32
- package/src/react/RightSidebar.tsx +0 -257
- package/src/react/RightSidebarContext.tsx +0 -234
- package/src/react/RightSidebarTrigger.tsx +0 -53
- package/src/react/RowCoordsContext.tsx +0 -23
- package/src/react/SchemaRenderer.tsx +0 -549
- package/src/react/SearchTrigger.tsx +0 -46
- package/src/react/ThemeProvider.tsx +0 -93
- package/src/react/ThemeSettingsPage.tsx +0 -579
- package/src/react/ThemeToggle.tsx +0 -20
- package/src/react/Toaster.tsx +0 -158
- package/src/react/UserMenu.tsx +0 -196
- package/src/react/WidgetDataContext.tsx +0 -157
- package/src/react/cells/EditableCell.tsx +0 -389
- package/src/react/component-slots.test.ts +0 -103
- package/src/react/component-slots.ts +0 -116
- package/src/react/fieldJsHandler.test.ts +0 -166
- package/src/react/fieldJsHandler.ts +0 -79
- package/src/react/fields/BuilderInput.tsx +0 -1078
- package/src/react/fields/CheckboxInput.tsx +0 -39
- package/src/react/fields/CheckboxListInput.tsx +0 -102
- package/src/react/fields/ColorInput.tsx +0 -71
- package/src/react/fields/DateFieldInput.tsx +0 -70
- package/src/react/fields/DateTimeInput.tsx +0 -62
- package/src/react/fields/FieldShell.tsx +0 -348
- package/src/react/fields/FileUploadInput.tsx +0 -639
- package/src/react/fields/HiddenInput.tsx +0 -17
- package/src/react/fields/KeyValueInput.tsx +0 -230
- package/src/react/fields/MarkdownInput.tsx +0 -560
- package/src/react/fields/RadioInput.tsx +0 -81
- package/src/react/fields/RepeaterInput.test.ts +0 -116
- package/src/react/fields/RepeaterInput.tsx +0 -1420
- package/src/react/fields/SelectFieldInput.tsx +0 -280
- package/src/react/fields/SliderInput.tsx +0 -81
- package/src/react/fields/TagsInput.tsx +0 -283
- package/src/react/fields/TextLikeInput.tsx +0 -256
- package/src/react/fields/ToggleButtonsInput.tsx +0 -60
- package/src/react/fields/ToggleFieldInput.tsx +0 -56
- package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
- package/src/react/fields/relationshipRenameDispatch.ts +0 -97
- package/src/react/fields/repeaterReconcile.test.ts +0 -114
- package/src/react/fields/repeaterReconcile.ts +0 -104
- package/src/react/fields/rowChromeButton.tsx +0 -336
- package/src/react/fields/rowState.ts +0 -106
- package/src/react/fields/syncRowGates.test.ts +0 -202
- package/src/react/fields/syncRowGates.ts +0 -66
- package/src/react/fields/textInputControls.tsx +0 -238
- package/src/react/fields/useRowReorderDnd.ts +0 -78
- package/src/react/formStateHelpers.test.ts +0 -508
- package/src/react/formStateHelpers.ts +0 -381
- package/src/react/hooks/use-mobile.ts +0 -19
- package/src/react/icon-context.tsx +0 -60
- package/src/react/index.ts +0 -194
- package/src/react/layouts/SidebarLayout.tsx +0 -250
- package/src/react/layouts/TopbarLayout.tsx +0 -258
- package/src/react/navigate.tsx +0 -37
- package/src/react/onProviderSynced.test.ts +0 -90
- package/src/react/parseRecordEditUrl.test.ts +0 -122
- package/src/react/parseRecordEditUrl.ts +0 -94
- package/src/react/persistedState.ts +0 -40
- package/src/react/registry.ts +0 -48
- package/src/react/right-panel-registry.tsx +0 -47
- package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
- package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
- package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
- package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
- package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
- package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
- package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
- package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
- package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
- package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
- package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
- package/src/react/schemaRenderer/action/buttons.tsx +0 -99
- package/src/react/schemaRenderer/action/helpers.ts +0 -140
- package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
- package/src/react/schemaRenderer/columnFormat.ts +0 -65
- package/src/react/schemaRenderer/constants.ts +0 -50
- package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
- package/src/react/schemaRenderer/form/renderField.tsx +0 -511
- package/src/react/schemaRenderer/helpers.tsx +0 -81
- package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
- package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
- package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
- package/src/react/schemaRenderer/table/filters.tsx +0 -1233
- package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
- package/src/react/schemaRenderer/table/links.tsx +0 -112
- package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
- package/src/react/schemaRenderer/table/url.tsx +0 -143
- package/src/react/theme-preview/apply.ts +0 -99
- package/src/react/theme-preview/build-html.ts +0 -436
- package/src/react/ui/button.tsx +0 -51
- package/src/react/ui/calendar.tsx +0 -67
- package/src/react/ui/checkbox.tsx +0 -29
- package/src/react/ui/dialog.tsx +0 -108
- package/src/react/ui/dropdown-menu.tsx +0 -97
- package/src/react/ui/input.tsx +0 -20
- package/src/react/ui/label.tsx +0 -21
- package/src/react/ui/popover.tsx +0 -50
- package/src/react/ui/select.tsx +0 -169
- package/src/react/ui/separator.tsx +0 -25
- package/src/react/ui/sheet.tsx +0 -136
- package/src/react/ui/sidebar.tsx +0 -723
- package/src/react/ui/skeleton.tsx +0 -13
- package/src/react/ui/slider.tsx +0 -34
- package/src/react/ui/switch.tsx +0 -28
- package/src/react/ui/table.tsx +0 -105
- package/src/react/ui/tabs.tsx +0 -63
- package/src/react/ui/textarea.tsx +0 -18
- package/src/react/ui/tooltip.tsx +0 -64
- package/src/react/useResizableWidth.ts +0 -139
- package/src/react/utils.ts +0 -6
- package/src/react/widgetRegistry.test.ts +0 -43
- package/src/react/widgetRegistry.ts +0 -50
- package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
- package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
- package/src/react/widgets/ViewRenderer.tsx +0 -71
- package/src/relationManagerData.test.ts +0 -1595
- package/src/richtext/index.ts +0 -8
- package/src/richtext/registry.ts +0 -89
- package/src/routes/globals.ts +0 -148
- package/src/routes/guard.test.ts +0 -325
- package/src/routes/helpers.ts +0 -704
- package/src/routes/pages.ts +0 -175
- package/src/routes/panel.ts +0 -204
- package/src/routes/relations.ts +0 -1243
- package/src/routes/resources.ts +0 -781
- package/src/routes/theme.ts +0 -91
- package/src/routes-nested-relations.test.ts +0 -676
- package/src/routes-relations.test.ts +0 -972
- package/src/routes.test.ts +0 -2027
- package/src/routes.ts +0 -303
- package/src/schema/Alert.test.ts +0 -109
- package/src/schema/Alert.ts +0 -131
- package/src/schema/Block.ts +0 -169
- package/src/schema/Breadcrumbs.ts +0 -40
- package/src/schema/Card.ts +0 -35
- package/src/schema/Divider.ts +0 -20
- package/src/schema/Element.ts +0 -219
- package/src/schema/EmptyState.test.ts +0 -37
- package/src/schema/EmptyState.ts +0 -63
- package/src/schema/Fieldset.ts +0 -43
- package/src/schema/Grid.ts +0 -43
- package/src/schema/Group.ts +0 -30
- package/src/schema/Heading.ts +0 -39
- package/src/schema/Html.ts +0 -67
- package/src/schema/Icon.ts +0 -54
- package/src/schema/Image.ts +0 -57
- package/src/schema/LinkTag.ts +0 -41
- package/src/schema/Markdown.ts +0 -85
- package/src/schema/MetaTag.ts +0 -41
- package/src/schema/RelationTabs.ts +0 -71
- package/src/schema/ScriptTag.ts +0 -55
- package/src/schema/Section.ts +0 -160
- package/src/schema/ServerDataElement.test.ts +0 -140
- package/src/schema/ServerDataElement.ts +0 -156
- package/src/schema/SlotComponent.test.ts +0 -77
- package/src/schema/SlotComponent.ts +0 -71
- package/src/schema/Split.ts +0 -50
- package/src/schema/Stat.test.ts +0 -118
- package/src/schema/Stat.ts +0 -154
- package/src/schema/StatsOverview.test.ts +0 -141
- package/src/schema/StatsOverview.ts +0 -119
- package/src/schema/StyleTag.ts +0 -35
- package/src/schema/TableWidget.test.ts +0 -297
- package/src/schema/TableWidget.ts +0 -289
- package/src/schema/Tabs.ts +0 -79
- package/src/schema/Text.ts +0 -58
- package/src/schema/UnorderedList.ts +0 -49
- package/src/schema/View.test.ts +0 -111
- package/src/schema/View.ts +0 -127
- package/src/schema/Wizard.ts +0 -220
- package/src/schema/containers.test.ts +0 -564
- package/src/schema/headTags.test.ts +0 -134
- package/src/schema/index.ts +0 -40
- package/src/schema/primes.test.ts +0 -269
- package/src/schema/resolveSchema.test.ts +0 -379
- package/src/schema/resolveSchema.ts +0 -917
- package/src/schema/sanitize.ts +0 -58
- package/src/search.test.ts +0 -446
- package/src/search.ts +0 -178
- package/src/sessionFilters.test.ts +0 -375
- package/src/sessionFilters.ts +0 -143
- package/src/slot-components/index.ts +0 -10
- package/src/slot-components/registry.ts +0 -56
- package/src/styles/file-upload.css +0 -13
- package/src/summarizers/Summarizer.test.ts +0 -84
- package/src/summarizers/Summarizer.ts +0 -123
- package/src/summarizers/index.ts +0 -11
- package/src/theme/base-colors.ts +0 -68
- package/src/theme/chart-colors.ts +0 -50
- package/src/theme/colors.ts +0 -447
- package/src/theme/generate-css.test.ts +0 -139
- package/src/theme/generate-css.ts +0 -44
- package/src/theme/generate-scale.test.ts +0 -106
- package/src/theme/generate-scale.ts +0 -97
- package/src/theme/icon-map.ts +0 -42
- package/src/theme/index.ts +0 -34
- package/src/theme/migrate.test.ts +0 -178
- package/src/theme/migrate.ts +0 -81
- package/src/theme/presets.ts +0 -135
- package/src/theme/radius.ts +0 -18
- package/src/theme/resolve.test.ts +0 -238
- package/src/theme/resolve.ts +0 -96
- package/src/theme/spacing.ts +0 -18
- package/src/theme/storage.test.ts +0 -126
- package/src/theme/storage.ts +0 -106
- package/src/theme/theme-colors.ts +0 -88
- package/src/theme/types.ts +0 -125
- package/src/uploads/UploadAdapter.ts +0 -35
- package/src/uploads/index.ts +0 -2
- package/src/uploads/localUpload.test.ts +0 -70
- package/src/uploads/localUpload.ts +0 -84
- package/src/validation/Validator.ts +0 -49
- package/src/validation/index.ts +0 -28
- package/src/validation/rules.ts +0 -78
- package/src/validation/runValidators.ts +0 -435
- package/src/validation/uniqueValidator.test.ts +0 -196
- package/src/validation/uniqueValidator.ts +0 -133
- package/src/validation/validators.test.ts +0 -268
- package/src/vite.test.ts +0 -184
- package/src/vite.ts +0 -787
- package/src/widgets/index.ts +0 -10
- package/src/widgets/registry.ts +0 -45
- package/src/widgets.test.ts +0 -592
- package/tsconfig.build.json +0 -11
- package/tsconfig.json +0 -4
- package/tsconfig.test.json +0 -10
- package/views/react/Dashboard.tsx +0 -27
- package/views/react/Resources/Form.tsx +0 -102
- package/views/react/Resources/Index.tsx +0 -49
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Relation-manager Action factories — `relationCreate / relationEdit /
|
|
3
|
-
* relationDelete / relationRestore / relationForceDelete` (hasMany +
|
|
4
|
-
* morphMany) and `relationReplicate / relationBulkReplicate` (clone
|
|
5
|
-
* with force-pinned parent attachment).
|
|
6
|
-
*
|
|
7
|
-
* Designed to be called inside `RelationManager.static table()` — the
|
|
8
|
-
* page-data builder pipes `RelationManagerContext` into that
|
|
9
|
-
* configurator so users get `basePath`, `parentId`, and the discovered
|
|
10
|
-
* Related resource without threading them by hand.
|
|
11
|
-
*
|
|
12
|
-
* Visibility predicates use `safeManagerPolicy` so the manager's
|
|
13
|
-
* `canX` (when overridden) wins, otherwise falls through to the
|
|
14
|
-
* related Resource's `canX`. Throws absorb as `false`.
|
|
15
|
-
*
|
|
16
|
-
* M2M factories (`relationAttach / relationDetach / relationBulkDetach`)
|
|
17
|
-
* live in `m2mFactories.ts`.
|
|
18
|
-
*
|
|
19
|
-
* See `docs/plans/action-split.md` for the split plan.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
Action,
|
|
24
|
-
type ActionContext,
|
|
25
|
-
type ActionResult,
|
|
26
|
-
type ReplicateOptions,
|
|
27
|
-
type ResourceLike,
|
|
28
|
-
} from './Action.js'
|
|
29
|
-
import {
|
|
30
|
-
safeManagerPolicy,
|
|
31
|
-
type RelationManager,
|
|
32
|
-
type RelationManagerContext,
|
|
33
|
-
} from '../RelationManager.js'
|
|
34
|
-
import {
|
|
35
|
-
computeMorphPayload,
|
|
36
|
-
getMorphRelationDescriptor,
|
|
37
|
-
getParentRelationDescriptor,
|
|
38
|
-
type ModelLike,
|
|
39
|
-
} from '../orm/modelDefaults.js'
|
|
40
|
-
import { buildReplica, forEachAllowed, isM2MMode, isTrashed, relationUrlPrefix } from './factoryHelpers.js'
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Compute the parent-attachment payload to force-pin onto a relation
|
|
44
|
-
* replica. For `hasMany`, returns `{ [foreignKey]: parentId }` from the
|
|
45
|
-
* parent's `static relations[name]` descriptor. For `morphMany` /
|
|
46
|
-
* `morphOne`, returns `{ <morphName>Id, <morphName>Type }` via
|
|
47
|
-
* `computeMorphPayload(parentRecord)`. Returns `{}` when no descriptor
|
|
48
|
-
* matches — the route dispatcher already auto-hides under M2M / morphTo,
|
|
49
|
-
* so missing descriptors there are a no-op rather than an error. Pure;
|
|
50
|
-
* exported for tests and re-used by both factories.
|
|
51
|
-
*/
|
|
52
|
-
function computeRelationPin(
|
|
53
|
-
ctx: RelationManagerContext,
|
|
54
|
-
): Record<string, unknown> {
|
|
55
|
-
const parentModel = (ctx.parentRecord as { constructor?: ModelLike } | null | undefined)?.constructor
|
|
56
|
-
if (!parentModel) return {}
|
|
57
|
-
const rel = ctx.relationship
|
|
58
|
-
// Polymorphic owner side first — `morphMany` carries no foreignKey
|
|
59
|
-
// and would fail the hasMany descriptor's gate.
|
|
60
|
-
if (ctx.mode === 'morphMany') {
|
|
61
|
-
const morph = getMorphRelationDescriptor(parentModel, rel)
|
|
62
|
-
if (!morph) return {}
|
|
63
|
-
try { return computeMorphPayload(ctx.parentRecord, morph) }
|
|
64
|
-
catch { return {} }
|
|
65
|
-
}
|
|
66
|
-
const desc = getParentRelationDescriptor(parentModel, rel)
|
|
67
|
-
if (!desc) return {}
|
|
68
|
-
return { [desc.foreignKey]: ctx.parentId }
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Build + persist a single relation replica. Runs the strip set
|
|
73
|
-
* (PK + soft-delete column on the **related** Resource +
|
|
74
|
-
* `opts.excludeAttributes`), force-pins the parent attachment columns,
|
|
75
|
-
* runs the optional `beforeReplicaSaved` hook, and calls
|
|
76
|
-
* `Related.model.create(...)`. Returns the model's create result so
|
|
77
|
-
* callers can read its primary key for redirect targeting.
|
|
78
|
-
*
|
|
79
|
-
* Throws when the related Resource has no model — caller (single-row
|
|
80
|
-
* factory) catches and surfaces an error notification; bulk caller
|
|
81
|
-
* checks the model presence ahead of the loop.
|
|
82
|
-
*/
|
|
83
|
-
async function persistRelationReplica(
|
|
84
|
-
_M: typeof RelationManager,
|
|
85
|
-
ctx: RelationManagerContext,
|
|
86
|
-
source: unknown,
|
|
87
|
-
opts: ReplicateOptions,
|
|
88
|
-
): Promise<unknown> {
|
|
89
|
-
const Related = ctx.related
|
|
90
|
-
if (!Related?.model || typeof Related.model.create !== 'function') {
|
|
91
|
-
throw new Error('Related Resource has no model.create')
|
|
92
|
-
}
|
|
93
|
-
const M2 = Related.model as ModelLike
|
|
94
|
-
// Force-pin the parent attachment via `pin` so `beforeReplicaSaved` can
|
|
95
|
-
// still read / override the FK if it really wants to (rare); tampered
|
|
96
|
-
// source rows can't slip a different parent in by riding their own FK
|
|
97
|
-
// column — the pin overwrites whatever value was there.
|
|
98
|
-
const { replica } = await buildReplica(source, M2, {
|
|
99
|
-
excludeAttributes: opts.excludeAttributes,
|
|
100
|
-
deletedAtColumn: Related.deletedAtColumn,
|
|
101
|
-
pin: computeRelationPin(ctx),
|
|
102
|
-
beforeReplicaSaved: opts.beforeReplicaSaved,
|
|
103
|
-
})
|
|
104
|
-
return M2.create(replica)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Single-row dispatch for `relationReplicateAction`. Resolves
|
|
109
|
-
* `ctx.record` (loaded by the route's resolveRecord hook), validates,
|
|
110
|
-
* persists the replica, and shapes the success notification. Errors
|
|
111
|
-
* are caught and surfaced as error toasts.
|
|
112
|
-
*/
|
|
113
|
-
async function runRelationReplicateRow(
|
|
114
|
-
M: typeof RelationManager,
|
|
115
|
-
ctx: RelationManagerContext,
|
|
116
|
-
hctx: ActionContext,
|
|
117
|
-
opts: ReplicateOptions,
|
|
118
|
-
): Promise<ActionResult> {
|
|
119
|
-
const source = hctx.record
|
|
120
|
-
if (!source || typeof source !== 'object') {
|
|
121
|
-
return { notify: { title: 'Replicate failed: source record missing', type: 'error' } as never }
|
|
122
|
-
}
|
|
123
|
-
const Related = ctx.related
|
|
124
|
-
if (!Related?.model || typeof Related.model.create !== 'function') {
|
|
125
|
-
return { notify: { title: 'Replicate not configured (related Resource has no model.create)', type: 'error' } as never }
|
|
126
|
-
}
|
|
127
|
-
let created: unknown
|
|
128
|
-
try {
|
|
129
|
-
created = await persistRelationReplica(M, ctx, source, opts)
|
|
130
|
-
} catch (err) {
|
|
131
|
-
return { notify: { title: `Replicate failed: ${err instanceof Error ? err.message : String(err)}`, type: 'error' } as never }
|
|
132
|
-
}
|
|
133
|
-
const overrideTitle = opts.getCreatedNotificationTitle
|
|
134
|
-
? await opts.getCreatedNotificationTitle({ replica: created, source })
|
|
135
|
-
: undefined
|
|
136
|
-
const title = overrideTitle !== undefined ? overrideTitle : `${M.getLabelSingular()} replicated`
|
|
137
|
-
// The manager-scoped `_action/:actionName` route falls back to the
|
|
138
|
-
// manager list URL when `result.redirect` is undefined, so we only
|
|
139
|
-
// emit `redirect` when the user override returned a string. That
|
|
140
|
-
// way default behavior (route owns the fallback) is unchanged.
|
|
141
|
-
const overrideRedirect = opts.getRedirectUrl
|
|
142
|
-
? await opts.getRedirectUrl({ replica: created, source })
|
|
143
|
-
: undefined
|
|
144
|
-
return {
|
|
145
|
-
...(overrideRedirect !== undefined ? { redirect: overrideRedirect } : {}),
|
|
146
|
-
notify: { title, type: 'success' } as never,
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Relation create-action factory — link to
|
|
151
|
-
* `${base}/${parentSlug}/${parentId}/${relationship}/create`.
|
|
152
|
-
*
|
|
153
|
-
* Visibility delegates to `M.canCreate(user, parentRecord)` (or the
|
|
154
|
-
* related Resource's `canCreate(user)` when the manager hasn't
|
|
155
|
-
* overridden). Drop into `headerActions([...])` from inside
|
|
156
|
-
* `RelationManager.table(table, ctx)`.
|
|
157
|
-
*/
|
|
158
|
-
export function relationCreateAction(
|
|
159
|
-
M: typeof RelationManager,
|
|
160
|
-
ctx: RelationManagerContext,
|
|
161
|
-
): Action {
|
|
162
|
-
const labelSingular = M.getLabelSingular()
|
|
163
|
-
return Action.make('create')
|
|
164
|
-
.label(`New ${labelSingular}`)
|
|
165
|
-
.href(`${relationUrlPrefix(ctx)}/create`)
|
|
166
|
-
.visible(({ user }) => {
|
|
167
|
-
// M2M managers don't have a per-pivot-row create surface — the
|
|
168
|
-
// related record is created via its own Resource, then attached
|
|
169
|
-
// via `relationAttach`. Auto-hide so dropping this factory into
|
|
170
|
-
// any M2M manager (belongsToMany / morphToMany / morphedByMany)
|
|
171
|
-
// is a no-op (visible=false) instead of a 404-on-click foot-gun.
|
|
172
|
-
if (isM2MMode(ctx.mode)) return false
|
|
173
|
-
return safeManagerPolicy(M, 'canCreate', ctx.related, user, ctx.parentRecord)
|
|
174
|
-
})
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Relation edit-action factory — link to
|
|
178
|
-
* `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/edit`.
|
|
179
|
-
*
|
|
180
|
-
* Same `recordId` semantics as `editAction`: omit for row context
|
|
181
|
-
* so the renderer substitutes `:id` per row; pass explicitly when
|
|
182
|
-
* building actions for a single-record context. Visibility delegates
|
|
183
|
-
* to `M.canEdit(user, child, parentRecord)` with fall-through to the
|
|
184
|
-
* related Resource's `canEdit(user, record)`.
|
|
185
|
-
*/
|
|
186
|
-
export function relationEditAction(
|
|
187
|
-
M: typeof RelationManager,
|
|
188
|
-
ctx: RelationManagerContext,
|
|
189
|
-
recordId?: string,
|
|
190
|
-
): Action {
|
|
191
|
-
const id = recordId ?? ':id'
|
|
192
|
-
return Action.make('edit')
|
|
193
|
-
.label('Edit')
|
|
194
|
-
.href(`${relationUrlPrefix(ctx)}/${id}/edit`)
|
|
195
|
-
.visible(({ user, record }) => {
|
|
196
|
-
// M2M: per-pivot-row "edit" doesn't exist; users edit the
|
|
197
|
-
// related record via its own Resource. Auto-hide for every M2M
|
|
198
|
-
// mode (belongsToMany / morphToMany / morphedByMany).
|
|
199
|
-
if (isM2MMode(ctx.mode)) return false
|
|
200
|
-
return safeManagerPolicy(M, 'canEdit', ctx.related, user, ctx.parentRecord, record)
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/** Relation delete-action factory — POST to
|
|
205
|
-
* `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/delete`,
|
|
206
|
-
* destructive style with a labeled confirmation. Visibility delegates
|
|
207
|
-
* to `M.canDelete(user, child, parentRecord)` with fall-through to the
|
|
208
|
-
* related Resource's `canDelete(user, record)`.
|
|
209
|
-
*/
|
|
210
|
-
export function relationDeleteAction(
|
|
211
|
-
M: typeof RelationManager,
|
|
212
|
-
ctx: RelationManagerContext,
|
|
213
|
-
recordId?: string,
|
|
214
|
-
): Action {
|
|
215
|
-
const id = recordId ?? ':id'
|
|
216
|
-
const singular = M.getLabelSingular().toLowerCase()
|
|
217
|
-
return Action.make('delete')
|
|
218
|
-
.label('Delete')
|
|
219
|
-
.destructive()
|
|
220
|
-
.method('post')
|
|
221
|
-
.action(`${relationUrlPrefix(ctx)}/${id}/delete`)
|
|
222
|
-
.confirm(`Delete this ${singular}?`)
|
|
223
|
-
.visible(async ({ user, record }) => {
|
|
224
|
-
// M2M: "delete" of the related record is destructive in a way
|
|
225
|
-
// that "detach" isn't — surface only `relationDetach` on every
|
|
226
|
-
// M2M manager (belongsToMany / morphToMany / morphedByMany).
|
|
227
|
-
// Users who genuinely want to delete the related record reach
|
|
228
|
-
// for `Action.delete(R)` on the related Resource instead.
|
|
229
|
-
if (isM2MMode(ctx.mode)) return false
|
|
230
|
-
if (ctx.related?.softDeletes && isTrashed(record, ctx.related as ResourceLike)) return false
|
|
231
|
-
return safeManagerPolicy(M, 'canDelete', ctx.related, user, ctx.parentRecord, record)
|
|
232
|
-
})
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Plan #13 polish — Restore factory for relation managers. POSTs to
|
|
237
|
-
* `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/restore`,
|
|
238
|
-
* success-styled, no confirm prompt. Auto-hides on live (non-trashed)
|
|
239
|
-
* rows AND when `M.canRestore` (or related Resource fall-through)
|
|
240
|
-
* denies. Drop into `recordActions([...])` from `RelationManager.table(table, ctx)`.
|
|
241
|
-
*/
|
|
242
|
-
export function relationRestoreAction(
|
|
243
|
-
M: typeof RelationManager,
|
|
244
|
-
ctx: RelationManagerContext,
|
|
245
|
-
recordId?: string,
|
|
246
|
-
): Action {
|
|
247
|
-
const id = recordId ?? ':id'
|
|
248
|
-
return Action.make('restore')
|
|
249
|
-
.label('Restore')
|
|
250
|
-
.color('success')
|
|
251
|
-
.method('post')
|
|
252
|
-
.action(`${relationUrlPrefix(ctx)}/${id}/restore`)
|
|
253
|
-
.visible(async ({ user, record }) => {
|
|
254
|
-
if (!ctx.related?.softDeletes) return false
|
|
255
|
-
if (!isTrashed(record, ctx.related as ResourceLike)) return false
|
|
256
|
-
return safeManagerPolicy(M, 'canRestore', ctx.related, user, ctx.parentRecord, record)
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Plan #13 polish — Force-delete factory for relation managers. POSTs
|
|
262
|
-
* to `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/force-delete`,
|
|
263
|
-
* destructive style with a permanence-aware confirmation. Auto-hides on
|
|
264
|
-
* live (non-trashed) rows and when policy denies.
|
|
265
|
-
*/
|
|
266
|
-
export function relationForceDeleteAction(
|
|
267
|
-
M: typeof RelationManager,
|
|
268
|
-
ctx: RelationManagerContext,
|
|
269
|
-
recordId?: string,
|
|
270
|
-
): Action {
|
|
271
|
-
const id = recordId ?? ':id'
|
|
272
|
-
const singular = M.getLabelSingular().toLowerCase()
|
|
273
|
-
return Action.make('forceDelete')
|
|
274
|
-
.label('Delete forever')
|
|
275
|
-
.destructive()
|
|
276
|
-
.method('post')
|
|
277
|
-
.action(`${relationUrlPrefix(ctx)}/${id}/force-delete`)
|
|
278
|
-
.confirm(`Permanently delete this ${singular}? This cannot be undone.`)
|
|
279
|
-
.visible(async ({ user, record }) => {
|
|
280
|
-
if (!ctx.related?.softDeletes) return false
|
|
281
|
-
if (!isTrashed(record, ctx.related as ResourceLike)) return false
|
|
282
|
-
return safeManagerPolicy(M, 'canForceDelete', ctx.related, user, ctx.parentRecord, record)
|
|
283
|
-
})
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Relation row-replicate factory. Clones the row's child record
|
|
288
|
-
* inside the manager's parent scope.
|
|
289
|
-
*
|
|
290
|
-
* Strips the related model's primary key, soft-delete column, and
|
|
291
|
-
* `opts.excludeAttributes`. Re-applies the parent attachment columns
|
|
292
|
-
* after the strip + before the optional `beforeReplicaSaved` hook,
|
|
293
|
-
* so user code can still mutate non-FK fields without accidentally
|
|
294
|
-
* unlinking the replica.
|
|
295
|
-
*
|
|
296
|
-
* On success the manager-scoped route falls back to the manager
|
|
297
|
-
* list URL (`${base}/${parentSlug}/${parentId}/${relationship}`)
|
|
298
|
-
* because no explicit `redirect` is returned — same default as the
|
|
299
|
-
* other handler-style relation factories.
|
|
300
|
-
*
|
|
301
|
-
* `recordId` kept in the signature for parity with the rest of the
|
|
302
|
-
* relation factory family. The dispatcher resolves the source row
|
|
303
|
-
* from the request body, so it isn't referenced here.
|
|
304
|
-
*/
|
|
305
|
-
export function relationReplicateAction(
|
|
306
|
-
M: typeof RelationManager,
|
|
307
|
-
ctx: RelationManagerContext,
|
|
308
|
-
recordId?: string,
|
|
309
|
-
opts: ReplicateOptions = {},
|
|
310
|
-
): Action {
|
|
311
|
-
void recordId
|
|
312
|
-
return Action.make('relationReplicate')
|
|
313
|
-
.label('Replicate')
|
|
314
|
-
.row()
|
|
315
|
-
.handler(async (hctx) => {
|
|
316
|
-
const result = await runRelationReplicateRow(M, ctx, hctx, opts)
|
|
317
|
-
return result
|
|
318
|
-
})
|
|
319
|
-
.visible(({ user }) => {
|
|
320
|
-
if (isM2MMode(ctx.mode) || ctx.mode === 'morphTo') return false
|
|
321
|
-
return safeManagerPolicy(M, 'canCreate', ctx.related, user, ctx.parentRecord)
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Bulk sibling — replicates every selected child row inside the
|
|
327
|
-
* manager's parent scope. Same strip + force-pin pipeline applied
|
|
328
|
-
* per row. Per-row `safeManagerPolicy(M, 'canCreate', …)` runs
|
|
329
|
-
* inside the loop so a partially-permitted selection still proceeds
|
|
330
|
-
* for the rows that pass. Rows that throw are skipped silently —
|
|
331
|
-
* the toast count reflects only successful creates.
|
|
332
|
-
*/
|
|
333
|
-
export function relationBulkReplicateAction(
|
|
334
|
-
M: typeof RelationManager,
|
|
335
|
-
ctx: RelationManagerContext,
|
|
336
|
-
opts: ReplicateOptions = {},
|
|
337
|
-
): Action {
|
|
338
|
-
const labelPlural = M.getLabel().toLowerCase()
|
|
339
|
-
const labelSingular = M.getLabelSingular().toLowerCase()
|
|
340
|
-
return Action.make('relationBulkReplicate')
|
|
341
|
-
.label('Replicate selected')
|
|
342
|
-
.bulk()
|
|
343
|
-
.confirm(`Replicate the selected ${labelPlural}?`)
|
|
344
|
-
.handler(async (hctx) => {
|
|
345
|
-
const Related = ctx.related
|
|
346
|
-
if (!Related?.model || typeof Related.model.create !== 'function') {
|
|
347
|
-
return { notify: { title: 'Replicate not configured (related Resource has no model.create)', type: 'error' } as never }
|
|
348
|
-
}
|
|
349
|
-
const records = hctx.records ?? []
|
|
350
|
-
// Per-row predicate eval preserved — users may write stateful predicates that gate per-attempt.
|
|
351
|
-
const n = await forEachAllowed(
|
|
352
|
-
records,
|
|
353
|
-
() => safeManagerPolicy(M, 'canCreate', Related, hctx.user, ctx.parentRecord),
|
|
354
|
-
async (_id, source) => { await persistRelationReplica(M, ctx, source, opts) },
|
|
355
|
-
)
|
|
356
|
-
if (n === 0) {
|
|
357
|
-
return { notify: { title: `Nothing to replicate (no permitted rows)`, type: 'warning' } as never }
|
|
358
|
-
}
|
|
359
|
-
const defaultTitle = `${n} ${n === 1 ? labelSingular : labelPlural} replicated`
|
|
360
|
-
const overrideTitle = opts.getCreatedNotificationTitle
|
|
361
|
-
? await opts.getCreatedNotificationTitle({ count: n, records })
|
|
362
|
-
: undefined
|
|
363
|
-
const title = overrideTitle !== undefined ? overrideTitle : defaultTitle
|
|
364
|
-
return {
|
|
365
|
-
notify: { title, type: 'success' } as never,
|
|
366
|
-
}
|
|
367
|
-
})
|
|
368
|
-
.visible(({ user }) => {
|
|
369
|
-
if (isM2MMode(ctx.mode) || ctx.mode === 'morphTo') return false
|
|
370
|
-
return safeManagerPolicy(M, 'canCreate', ctx.related, user, ctx.parentRecord)
|
|
371
|
-
})
|
|
372
|
-
}
|