@pilotiq/pilotiq 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/CHANGELOG.md +142 -0
- package/CLAUDE.md +59 -3
- package/dist/Pilotiq.d.ts +83 -0
- package/dist/Pilotiq.d.ts.map +1 -1
- package/dist/Pilotiq.js +39 -0
- package/dist/Pilotiq.js.map +1 -1
- package/dist/actions/Action.d.ts +27 -99
- package/dist/actions/Action.d.ts.map +1 -1
- package/dist/actions/Action.js +52 -754
- package/dist/actions/Action.js.map +1 -1
- package/dist/actions/bulkFactories.d.ts +46 -0
- package/dist/actions/bulkFactories.d.ts.map +1 -0
- package/dist/actions/bulkFactories.js +144 -0
- package/dist/actions/bulkFactories.js.map +1 -0
- package/dist/actions/crudFactories.d.ts +94 -0
- package/dist/actions/crudFactories.d.ts.map +1 -0
- package/dist/actions/crudFactories.js +209 -0
- package/dist/actions/crudFactories.js.map +1 -0
- package/dist/actions/factoryHelpers.d.ts +108 -0
- package/dist/actions/factoryHelpers.d.ts.map +1 -0
- package/dist/actions/factoryHelpers.js +138 -0
- package/dist/actions/factoryHelpers.js.map +1 -0
- package/dist/actions/m2mFactories.d.ts +47 -0
- package/dist/actions/m2mFactories.d.ts.map +1 -0
- package/dist/actions/m2mFactories.js +173 -0
- package/dist/actions/m2mFactories.js.map +1 -0
- package/dist/actions/relationFactories.d.ts +93 -0
- package/dist/actions/relationFactories.d.ts.map +1 -0
- package/dist/actions/relationFactories.js +321 -0
- package/dist/actions/relationFactories.js.map +1 -0
- package/dist/elements/dispatchForm.js +1 -1
- package/dist/elements/dispatchForm.js.map +1 -1
- package/dist/elements/dispatchTable.js +1 -1
- package/dist/elements/dispatchTable.js.map +1 -1
- package/dist/fields/Field.d.ts +31 -0
- package/dist/fields/Field.d.ts.map +1 -1
- package/dist/fields/Field.js +25 -0
- package/dist/fields/Field.js.map +1 -1
- package/dist/pageData/breadcrumbs.d.ts +42 -0
- package/dist/pageData/breadcrumbs.d.ts.map +1 -0
- package/dist/pageData/breadcrumbs.js +172 -0
- package/dist/pageData/breadcrumbs.js.map +1 -0
- package/dist/pageData/forms.d.ts +137 -0
- package/dist/pageData/forms.d.ts.map +1 -0
- package/dist/pageData/forms.js +427 -0
- package/dist/pageData/forms.js.map +1 -0
- package/dist/pageData/helpers.d.ts +239 -0
- package/dist/pageData/helpers.d.ts.map +1 -0
- package/dist/pageData/helpers.js +703 -0
- package/dist/pageData/helpers.js.map +1 -0
- package/dist/pageData/misc.d.ts +76 -0
- package/dist/pageData/misc.d.ts.map +1 -0
- package/dist/pageData/misc.js +263 -0
- package/dist/pageData/misc.js.map +1 -0
- package/dist/pageData/navigation.d.ts +292 -0
- package/dist/pageData/navigation.d.ts.map +1 -0
- package/dist/pageData/navigation.js +591 -0
- package/dist/pageData/navigation.js.map +1 -0
- package/dist/pageData/relationPages.d.ts +172 -0
- package/dist/pageData/relationPages.d.ts.map +1 -0
- package/dist/pageData/relationPages.js +867 -0
- package/dist/pageData/relationPages.js.map +1 -0
- package/dist/pageData/relationTabs.d.ts +65 -0
- package/dist/pageData/relationTabs.d.ts.map +1 -0
- package/dist/pageData/relationTabs.js +258 -0
- package/dist/pageData/relationTabs.js.map +1 -0
- package/dist/pageData/resourcePages.d.ts +48 -0
- package/dist/pageData/resourcePages.d.ts.map +1 -0
- package/dist/pageData/resourcePages.js +504 -0
- package/dist/pageData/resourcePages.js.map +1 -0
- package/dist/pageData.d.ts +12 -792
- package/dist/pageData.d.ts.map +1 -1
- package/dist/pageData.js +24 -3797
- package/dist/pageData.js.map +1 -1
- package/dist/react/AppShell.d.ts +8 -0
- package/dist/react/AppShell.d.ts.map +1 -1
- package/dist/react/AppShell.js +11 -1
- package/dist/react/AppShell.js.map +1 -1
- package/dist/react/CollabExtensionFactoryRegistry.d.ts +47 -0
- package/dist/react/CollabExtensionFactoryRegistry.d.ts.map +1 -0
- package/dist/react/CollabExtensionFactoryRegistry.js +14 -0
- package/dist/react/CollabExtensionFactoryRegistry.js.map +1 -0
- package/dist/react/CollabRoomContext.d.ts +37 -0
- package/dist/react/CollabRoomContext.d.ts.map +1 -0
- package/dist/react/CollabRoomContext.js +12 -0
- package/dist/react/CollabRoomContext.js.map +1 -0
- package/dist/react/FormCollabBindingRegistry.d.ts +62 -0
- package/dist/react/FormCollabBindingRegistry.d.ts.map +1 -0
- package/dist/react/FormCollabBindingRegistry.js +14 -0
- package/dist/react/FormCollabBindingRegistry.js.map +1 -0
- package/dist/react/RecordWrapperGate.d.ts +25 -0
- package/dist/react/RecordWrapperGate.d.ts.map +1 -0
- package/dist/react/RecordWrapperGate.js +30 -0
- package/dist/react/RecordWrapperGate.js.map +1 -0
- package/dist/react/RecordWrapperRegistry.d.ts +31 -0
- package/dist/react/RecordWrapperRegistry.d.ts.map +1 -0
- package/dist/react/RecordWrapperRegistry.js +15 -0
- package/dist/react/RecordWrapperRegistry.js.map +1 -0
- package/dist/react/SchemaRenderer.d.ts +17 -23
- package/dist/react/SchemaRenderer.d.ts.map +1 -1
- package/dist/react/SchemaRenderer.js +71 -3647
- package/dist/react/SchemaRenderer.js.map +1 -1
- package/dist/react/component-slots.d.ts +103 -0
- package/dist/react/component-slots.d.ts.map +1 -0
- package/dist/react/component-slots.js +18 -0
- package/dist/react/component-slots.js.map +1 -0
- package/dist/react/fields/BuilderInput.d.ts.map +1 -1
- package/dist/react/fields/BuilderInput.js +21 -117
- package/dist/react/fields/BuilderInput.js.map +1 -1
- package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
- package/dist/react/fields/MarkdownInput.js +1 -3
- package/dist/react/fields/MarkdownInput.js.map +1 -1
- package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
- package/dist/react/fields/RepeaterInput.js +22 -127
- package/dist/react/fields/RepeaterInput.js.map +1 -1
- package/dist/react/fields/rowState.d.ts +40 -0
- package/dist/react/fields/rowState.d.ts.map +1 -0
- package/dist/react/fields/rowState.js +60 -0
- package/dist/react/fields/rowState.js.map +1 -0
- package/dist/react/fields/useRowReorderDnd.d.ts +28 -0
- package/dist/react/fields/useRowReorderDnd.d.ts.map +1 -0
- package/dist/react/fields/useRowReorderDnd.js +51 -0
- package/dist/react/fields/useRowReorderDnd.js.map +1 -0
- package/dist/react/index.d.ts +9 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +8 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/layouts/SidebarLayout.d.ts +1 -1
- package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
- package/dist/react/layouts/SidebarLayout.js +10 -2
- package/dist/react/layouts/SidebarLayout.js.map +1 -1
- package/dist/react/layouts/TopbarLayout.d.ts +1 -1
- package/dist/react/layouts/TopbarLayout.d.ts.map +1 -1
- package/dist/react/layouts/TopbarLayout.js +19 -11
- package/dist/react/layouts/TopbarLayout.js.map +1 -1
- package/dist/react/parseRecordEditUrl.d.ts +29 -0
- package/dist/react/parseRecordEditUrl.d.ts.map +1 -0
- package/dist/react/parseRecordEditUrl.js +25 -0
- package/dist/react/parseRecordEditUrl.js.map +1 -0
- package/dist/react/persistedState.d.ts +19 -0
- package/dist/react/persistedState.d.ts.map +1 -0
- package/dist/react/persistedState.js +51 -0
- package/dist/react/persistedState.js.map +1 -0
- package/dist/react/schemaRenderer/AlertRenderer.d.ts +12 -0
- package/dist/react/schemaRenderer/AlertRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/AlertRenderer.js +61 -0
- package/dist/react/schemaRenderer/AlertRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/EntryRenderer.d.ts +13 -0
- package/dist/react/schemaRenderer/EntryRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/EntryRenderer.js +277 -0
- package/dist/react/schemaRenderer/EntryRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/SectionRenderer.d.ts +16 -0
- package/dist/react/schemaRenderer/SectionRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/SectionRenderer.js +62 -0
- package/dist/react/schemaRenderer/SectionRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/SimpleElements.d.ts +25 -0
- package/dist/react/schemaRenderer/SimpleElements.d.ts.map +1 -0
- package/dist/react/schemaRenderer/SimpleElements.js +147 -0
- package/dist/react/schemaRenderer/SimpleElements.js.map +1 -0
- package/dist/react/schemaRenderer/TabsRenderer.d.ts +17 -0
- package/dist/react/schemaRenderer/TabsRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/TabsRenderer.js +31 -0
- package/dist/react/schemaRenderer/TabsRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/WizardRenderer.d.ts +34 -0
- package/dist/react/schemaRenderer/WizardRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/WizardRenderer.js +208 -0
- package/dist/react/schemaRenderer/WizardRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts +21 -0
- package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/ActionGroupTrigger.js +82 -0
- package/dist/react/schemaRenderer/action/ActionGroupTrigger.js.map +1 -0
- package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts +30 -0
- package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/ActionModalDialog.js +182 -0
- package/dist/react/schemaRenderer/action/ActionModalDialog.js.map +1 -0
- package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts +17 -0
- package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/ConfirmActionDialog.js +19 -0
- package/dist/react/schemaRenderer/action/ConfirmActionDialog.js.map +1 -0
- package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts +16 -0
- package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/HandlerActionButton.js +16 -0
- package/dist/react/schemaRenderer/action/HandlerActionButton.js.map +1 -0
- package/dist/react/schemaRenderer/action/MethodActionButton.d.ts +22 -0
- package/dist/react/schemaRenderer/action/MethodActionButton.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/MethodActionButton.js +26 -0
- package/dist/react/schemaRenderer/action/MethodActionButton.js.map +1 -0
- package/dist/react/schemaRenderer/action/buttons.d.ts +18 -0
- package/dist/react/schemaRenderer/action/buttons.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/buttons.js +74 -0
- package/dist/react/schemaRenderer/action/buttons.js.map +1 -0
- package/dist/react/schemaRenderer/action/helpers.d.ts +26 -0
- package/dist/react/schemaRenderer/action/helpers.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/helpers.js +126 -0
- package/dist/react/schemaRenderer/action/helpers.js.map +1 -0
- package/dist/react/schemaRenderer/action/renderAction.d.ts +21 -0
- package/dist/react/schemaRenderer/action/renderAction.d.ts.map +1 -0
- package/dist/react/schemaRenderer/action/renderAction.js +102 -0
- package/dist/react/schemaRenderer/action/renderAction.js.map +1 -0
- package/dist/react/schemaRenderer/columnFormat.d.ts +10 -0
- package/dist/react/schemaRenderer/columnFormat.d.ts.map +1 -0
- package/dist/react/schemaRenderer/columnFormat.js +76 -0
- package/dist/react/schemaRenderer/columnFormat.js.map +1 -0
- package/dist/react/schemaRenderer/constants.d.ts +8 -0
- package/dist/react/schemaRenderer/constants.d.ts.map +1 -0
- package/dist/react/schemaRenderer/constants.js +45 -0
- package/dist/react/schemaRenderer/constants.js.map +1 -0
- package/dist/react/schemaRenderer/form/FormRenderer.d.ts +29 -0
- package/dist/react/schemaRenderer/form/FormRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/form/FormRenderer.js +152 -0
- package/dist/react/schemaRenderer/form/FormRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/form/renderField.d.ts +6 -0
- package/dist/react/schemaRenderer/form/renderField.d.ts.map +1 -0
- package/dist/react/schemaRenderer/form/renderField.js +239 -0
- package/dist/react/schemaRenderer/form/renderField.js.map +1 -0
- package/dist/react/schemaRenderer/helpers.d.ts +32 -0
- package/dist/react/schemaRenderer/helpers.d.ts.map +1 -0
- package/dist/react/schemaRenderer/helpers.js +52 -0
- package/dist/react/schemaRenderer/helpers.js.map +1 -0
- package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts +60 -0
- package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/CardsLayoutBody.js +189 -0
- package/dist/react/schemaRenderer/table/CardsLayoutBody.js.map +1 -0
- package/dist/react/schemaRenderer/table/TableRenderer.d.ts +29 -0
- package/dist/react/schemaRenderer/table/TableRenderer.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/TableRenderer.js +85 -0
- package/dist/react/schemaRenderer/table/TableRenderer.js.map +1 -0
- package/dist/react/schemaRenderer/table/TableRendererBody.d.ts +18 -0
- package/dist/react/schemaRenderer/table/TableRendererBody.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/TableRendererBody.js +555 -0
- package/dist/react/schemaRenderer/table/TableRendererBody.js.map +1 -0
- package/dist/react/schemaRenderer/table/filters.d.ts +263 -0
- package/dist/react/schemaRenderer/table/filters.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/filters.js +497 -0
- package/dist/react/schemaRenderer/table/filters.js.map +1 -0
- package/dist/react/schemaRenderer/table/formatCell.d.ts +11 -0
- package/dist/react/schemaRenderer/table/formatCell.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/formatCell.js +172 -0
- package/dist/react/schemaRenderer/table/formatCell.js.map +1 -0
- package/dist/react/schemaRenderer/table/links.d.ts +42 -0
- package/dist/react/schemaRenderer/table/links.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/links.js +55 -0
- package/dist/react/schemaRenderer/table/links.js.map +1 -0
- package/dist/react/schemaRenderer/table/renderRowActions.d.ts +13 -0
- package/dist/react/schemaRenderer/table/renderRowActions.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/renderRowActions.js +25 -0
- package/dist/react/schemaRenderer/table/renderRowActions.js.map +1 -0
- package/dist/react/schemaRenderer/table/url.d.ts +41 -0
- package/dist/react/schemaRenderer/table/url.d.ts.map +1 -0
- package/dist/react/schemaRenderer/table/url.js +114 -0
- package/dist/react/schemaRenderer/table/url.js.map +1 -0
- package/dist/routes/globals.d.ts +13 -0
- package/dist/routes/globals.d.ts.map +1 -0
- package/dist/routes/globals.js +131 -0
- package/dist/routes/globals.js.map +1 -0
- package/dist/routes/helpers.d.ts +217 -0
- package/dist/routes/helpers.d.ts.map +1 -0
- package/dist/routes/helpers.js +498 -0
- package/dist/routes/helpers.js.map +1 -0
- package/dist/routes/pages.d.ts +15 -0
- package/dist/routes/pages.d.ts.map +1 -0
- package/dist/routes/pages.js +145 -0
- package/dist/routes/pages.js.map +1 -0
- package/dist/routes/panel.d.ts +19 -0
- package/dist/routes/panel.d.ts.map +1 -0
- package/dist/routes/panel.js +191 -0
- package/dist/routes/panel.js.map +1 -0
- package/dist/routes/relations.d.ts +21 -0
- package/dist/routes/relations.d.ts.map +1 -0
- package/dist/routes/relations.js +1239 -0
- package/dist/routes/relations.js.map +1 -0
- package/dist/routes/resources.d.ts +28 -0
- package/dist/routes/resources.d.ts.map +1 -0
- package/dist/routes/resources.js +741 -0
- package/dist/routes/resources.js.map +1 -0
- package/dist/routes/theme.d.ts +12 -0
- package/dist/routes/theme.d.ts.map +1 -0
- package/dist/routes/theme.js +82 -0
- package/dist/routes/theme.js.map +1 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +64 -3078
- package/dist/routes.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +26 -5
- package/dist/vite.js.map +1 -1
- package/package.json +2 -1
- package/src/Pilotiq.ts +95 -0
- package/src/actions/Action.ts +79 -723
- package/src/actions/bulkFactories.ts +168 -0
- package/src/actions/crudFactories.ts +220 -0
- package/src/actions/factoryHelpers.ts +177 -0
- package/src/actions/m2mFactories.ts +193 -0
- package/src/actions/relationFactories.ts +372 -0
- package/src/elements/dispatchForm.ts +1 -1
- package/src/elements/dispatchTable.ts +1 -1
- package/src/fields/Field.ts +39 -0
- package/src/pageData/breadcrumbs.ts +288 -0
- package/src/pageData/forms.ts +578 -0
- package/src/pageData/helpers.ts +764 -0
- package/src/pageData/misc.ts +347 -0
- package/src/pageData/navigation.ts +779 -0
- package/src/pageData/relationPages.ts +1246 -0
- package/src/pageData/relationTabs.ts +286 -0
- package/src/pageData/resourcePages.ts +593 -0
- package/src/pageData.ts +122 -4731
- package/src/react/AppShell.tsx +27 -1
- package/src/react/CollabExtensionFactoryRegistry.ts +55 -0
- package/src/react/CollabRoomContext.ts +42 -0
- package/src/react/FormCollabBindingRegistry.ts +72 -0
- package/src/react/RecordWrapperGate.tsx +40 -0
- package/src/react/RecordWrapperRegistry.ts +39 -0
- package/src/react/SchemaRenderer.tsx +230 -6479
- package/src/react/component-slots.test.ts +103 -0
- package/src/react/component-slots.ts +116 -0
- package/src/react/fields/BuilderInput.tsx +29 -117
- package/src/react/fields/MarkdownInput.tsx +0 -1
- package/src/react/fields/RepeaterInput.tsx +29 -130
- package/src/react/fields/rowState.ts +106 -0
- package/src/react/fields/useRowReorderDnd.ts +78 -0
- package/src/react/index.ts +38 -0
- package/src/react/layouts/SidebarLayout.tsx +39 -28
- package/src/react/layouts/TopbarLayout.tsx +70 -57
- package/src/react/parseRecordEditUrl.test.ts +75 -0
- package/src/react/parseRecordEditUrl.ts +55 -0
- package/src/react/persistedState.ts +40 -0
- package/src/react/schemaRenderer/AlertRenderer.tsx +112 -0
- package/src/react/schemaRenderer/EntryRenderer.tsx +501 -0
- package/src/react/schemaRenderer/SectionRenderer.tsx +120 -0
- package/src/react/schemaRenderer/SimpleElements.tsx +306 -0
- package/src/react/schemaRenderer/TabsRenderer.tsx +62 -0
- package/src/react/schemaRenderer/WizardRenderer.tsx +338 -0
- package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +177 -0
- package/src/react/schemaRenderer/action/ActionModalDialog.tsx +273 -0
- package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +61 -0
- package/src/react/schemaRenderer/action/HandlerActionButton.tsx +43 -0
- package/src/react/schemaRenderer/action/MethodActionButton.tsx +64 -0
- package/src/react/schemaRenderer/action/buttons.tsx +99 -0
- package/src/react/schemaRenderer/action/helpers.ts +140 -0
- package/src/react/schemaRenderer/action/renderAction.tsx +245 -0
- package/src/react/schemaRenderer/columnFormat.ts +65 -0
- package/src/react/schemaRenderer/constants.ts +50 -0
- package/src/react/schemaRenderer/form/FormRenderer.tsx +233 -0
- package/src/react/schemaRenderer/form/renderField.tsx +511 -0
- package/src/react/schemaRenderer/helpers.tsx +81 -0
- package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +308 -0
- package/src/react/schemaRenderer/table/TableRenderer.tsx +123 -0
- package/src/react/schemaRenderer/table/TableRendererBody.tsx +974 -0
- package/src/react/schemaRenderer/table/filters.tsx +1233 -0
- package/src/react/schemaRenderer/table/formatCell.tsx +264 -0
- package/src/react/schemaRenderer/table/links.tsx +112 -0
- package/src/react/schemaRenderer/table/renderRowActions.tsx +52 -0
- package/src/react/schemaRenderer/table/url.tsx +143 -0
- package/src/routes/globals.ts +154 -0
- package/src/routes/helpers.ts +668 -0
- package/src/routes/pages.ts +173 -0
- package/src/routes/panel.ts +204 -0
- package/src/routes/relations.ts +1219 -0
- package/src/routes/resources.ts +786 -0
- package/src/routes/theme.ts +109 -0
- package/src/routes.test.ts +1 -1
- package/src/routes.ts +64 -3176
- package/src/schema/TableWidget.test.ts +2 -2
- package/src/theme/migrate.test.ts +178 -0
- package/src/vite.test.ts +184 -0
- package/src/vite.ts +26 -4
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRUD single-row Action factories — `create / edit / view / delete /
|
|
3
|
+
* replicate / restore / forceDelete`, plus the notification `markAsRead`
|
|
4
|
+
* factory.
|
|
5
|
+
*
|
|
6
|
+
* Each factory builds and returns a configured `Action`. The matching
|
|
7
|
+
* `static` methods on the `Action` class are thin delegators that call
|
|
8
|
+
* into these functions, preserving the public `Action.create(R, base)`
|
|
9
|
+
* call shape.
|
|
10
|
+
*
|
|
11
|
+
* See `docs/plans/action-split.md` for the split plan.
|
|
12
|
+
*/
|
|
13
|
+
import { Action } from './Action.js';
|
|
14
|
+
import { buildReplica, callPredicate, isTrashed, resourceBase } from './factoryHelpers.js';
|
|
15
|
+
/** Create-action factory — link to `${basePath}/${R.slug}/create`.
|
|
16
|
+
* Auto-hides when `R.canCreate(user)` returns false. */
|
|
17
|
+
export function createAction(R, basePath) {
|
|
18
|
+
return Action.make('create')
|
|
19
|
+
.label(`New ${R.labelSingular}`)
|
|
20
|
+
.href(`${resourceBase(basePath, R)}/create`)
|
|
21
|
+
.visible(({ user }) => callPredicate(R.canCreate, user));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Edit-action factory — link to the resource's edit page.
|
|
25
|
+
*
|
|
26
|
+
* Pass `recordId` when building actions for a single-record context
|
|
27
|
+
* (e.g. `ViewPage.getActions()`); the URL is baked at config time.
|
|
28
|
+
* Omit `recordId` for row context (`Table.recordActions(...)`); the
|
|
29
|
+
* URL keeps the `:id` template and the renderer substitutes per-row.
|
|
30
|
+
*
|
|
31
|
+
* Auto-hides when `R.canEdit(user, record)` returns false. For row
|
|
32
|
+
* context the per-row record threads in via `loadTableRecords`'s
|
|
33
|
+
* per-row eval; for view-page context, `resolveSchema` provides the
|
|
34
|
+
* resolved record on the eval context.
|
|
35
|
+
*/
|
|
36
|
+
export function editAction(R, basePath, recordId) {
|
|
37
|
+
const id = recordId ?? ':id';
|
|
38
|
+
return Action.make('edit')
|
|
39
|
+
.label('Edit')
|
|
40
|
+
.href(`${resourceBase(basePath, R)}/${id}/edit`)
|
|
41
|
+
.visible(({ user, record }) => callPredicate(R.canEdit, user, record));
|
|
42
|
+
}
|
|
43
|
+
/** View-action factory — link to the resource's view page. See `editAction` for the `recordId` semantics.
|
|
44
|
+
* Auto-hides when `R.canView(user, record)` returns false. */
|
|
45
|
+
export function viewAction(R, basePath, recordId) {
|
|
46
|
+
const id = recordId ?? ':id';
|
|
47
|
+
return Action.make('view')
|
|
48
|
+
.label('View')
|
|
49
|
+
.href(`${resourceBase(basePath, R)}/${id}`)
|
|
50
|
+
.visible(({ user, record }) => callPredicate(R.canView, user, record));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Delete-action factory — POSTs to the resource's delete route,
|
|
54
|
+
* destructive style, with a confirmation prompt referencing the
|
|
55
|
+
* resource label. Same `recordId` semantics as `editAction`.
|
|
56
|
+
* Auto-hides when `R.canDelete(user, record)` returns false.
|
|
57
|
+
*
|
|
58
|
+
* Plan #13 — when `R.softDeletes = true`, additionally hides on
|
|
59
|
+
* rows whose `deletedAtColumn` is set (already-trashed rows get the
|
|
60
|
+
* Restore + ForceDelete pair instead, surfaced via the matching
|
|
61
|
+
* factories below).
|
|
62
|
+
*/
|
|
63
|
+
export function deleteAction(R, basePath, recordId) {
|
|
64
|
+
const id = recordId ?? ':id';
|
|
65
|
+
return Action.make('delete')
|
|
66
|
+
.label('Delete')
|
|
67
|
+
.destructive()
|
|
68
|
+
.method('post')
|
|
69
|
+
.action(`${resourceBase(basePath, R)}/${id}/delete`)
|
|
70
|
+
.confirm(`Delete this ${R.labelSingular.toLowerCase()}?`)
|
|
71
|
+
.visible(async ({ user, record }) => {
|
|
72
|
+
if (R.softDeletes && isTrashed(record, R))
|
|
73
|
+
return false;
|
|
74
|
+
return callPredicate(R.canDelete, user, record);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Replicate-action factory — handler-style. Loads the source record
|
|
79
|
+
* from `ctx.record` (the `_action/:actionName` route already resolves
|
|
80
|
+
* it through `R.query(ctx)` for row + single-target placements),
|
|
81
|
+
* strips PK + soft-delete column + any `opts.excludeAttributes`,
|
|
82
|
+
* optionally runs `opts.beforeReplicaSaved`, and creates a new row
|
|
83
|
+
* via `R.model.create(...)`. Redirects to the new record's edit page
|
|
84
|
+
* on success so the user can review + tweak before saving again.
|
|
85
|
+
*
|
|
86
|
+
* `recordId` kept in the signature for parity with `delete / edit /
|
|
87
|
+
* view` so users can swap factories without rewriting call sites; the
|
|
88
|
+
* dispatcher resolves the source record from the URL and hands it to
|
|
89
|
+
* the handler as `ctx.record`, so we don't reference `recordId` here.
|
|
90
|
+
*
|
|
91
|
+
* Auto-hides when `R.canCreate(user)` returns false — replicating
|
|
92
|
+
* writes a new row, so the gate is `canCreate`, not `canView`.
|
|
93
|
+
*/
|
|
94
|
+
export function replicateAction(R, basePath, recordId, opts = {}) {
|
|
95
|
+
void recordId;
|
|
96
|
+
return Action.make('replicate')
|
|
97
|
+
.label('Replicate')
|
|
98
|
+
.handler(async (ctx) => {
|
|
99
|
+
const source = ctx.record;
|
|
100
|
+
if (!source || typeof source !== 'object') {
|
|
101
|
+
return { notify: { title: 'Replicate failed: source record missing', type: 'error' } };
|
|
102
|
+
}
|
|
103
|
+
const M = R.model;
|
|
104
|
+
if (!M || typeof M.create !== 'function') {
|
|
105
|
+
return { notify: { title: 'Replicate not configured (resource has no model.create)', type: 'error' } };
|
|
106
|
+
}
|
|
107
|
+
let replica;
|
|
108
|
+
let pkCol;
|
|
109
|
+
try {
|
|
110
|
+
({ replica, pkCol } = await buildReplica(source, M, {
|
|
111
|
+
excludeAttributes: opts.excludeAttributes,
|
|
112
|
+
deletedAtColumn: R.deletedAtColumn,
|
|
113
|
+
beforeReplicaSaved: opts.beforeReplicaSaved,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
return { notify: { title: `Replicate failed: ${err instanceof Error ? err.message : String(err)}`, type: 'error' } };
|
|
118
|
+
}
|
|
119
|
+
let created;
|
|
120
|
+
try {
|
|
121
|
+
created = await M.create(replica);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
return { notify: { title: `Replicate failed: ${err instanceof Error ? err.message : String(err)}`, type: 'error' } };
|
|
125
|
+
}
|
|
126
|
+
const newId = created?.[pkCol];
|
|
127
|
+
const defaultRedirect = newId !== undefined && newId !== null
|
|
128
|
+
? `${resourceBase(basePath, R)}/${String(newId)}/edit`
|
|
129
|
+
: `${resourceBase(basePath, R)}`;
|
|
130
|
+
// `!== undefined` rather than `??` so an override returning
|
|
131
|
+
// `null`/empty-string isn't silently swallowed (see
|
|
132
|
+
// feedback_nullish_swallows_explicit_null).
|
|
133
|
+
const overrideRedirect = opts.getRedirectUrl
|
|
134
|
+
? await opts.getRedirectUrl({ replica: created, source })
|
|
135
|
+
: undefined;
|
|
136
|
+
const redirect = overrideRedirect !== undefined ? overrideRedirect : defaultRedirect;
|
|
137
|
+
const overrideTitle = opts.getCreatedNotificationTitle
|
|
138
|
+
? await opts.getCreatedNotificationTitle({ replica: created, source })
|
|
139
|
+
: undefined;
|
|
140
|
+
const title = overrideTitle !== undefined ? overrideTitle : `${R.labelSingular} replicated`;
|
|
141
|
+
return {
|
|
142
|
+
redirect,
|
|
143
|
+
notify: { title, type: 'success' },
|
|
144
|
+
};
|
|
145
|
+
})
|
|
146
|
+
.visible(({ user }) => callPredicate(R.canCreate, user));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Plan #13 — Restore factory. POSTs to the resource's restore route,
|
|
150
|
+
* success-styled, no confirm prompt (restoration is reversible).
|
|
151
|
+
* Auto-hides on live (non-trashed) rows AND when `R.canRestore(user,
|
|
152
|
+
* record)` returns false. Same `recordId` semantics as `editAction`.
|
|
153
|
+
*/
|
|
154
|
+
export function restoreAction(R, basePath, recordId) {
|
|
155
|
+
const id = recordId ?? ':id';
|
|
156
|
+
return Action.make('restore')
|
|
157
|
+
.label('Restore')
|
|
158
|
+
.color('success')
|
|
159
|
+
.method('post')
|
|
160
|
+
.action(`${resourceBase(basePath, R)}/${id}/restore`)
|
|
161
|
+
.visible(async ({ user, record }) => {
|
|
162
|
+
if (!isTrashed(record, R))
|
|
163
|
+
return false;
|
|
164
|
+
return callPredicate(R.canRestore, user, record);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Plan #13 — Force-delete factory. POSTs to the resource's
|
|
169
|
+
* force-delete route, destructive-styled, with a stricter confirm
|
|
170
|
+
* prompt referencing permanence. Auto-hides on live (non-trashed)
|
|
171
|
+
* rows AND when `R.canForceDelete(user, record)` returns false.
|
|
172
|
+
*/
|
|
173
|
+
export function forceDeleteAction(R, basePath, recordId) {
|
|
174
|
+
const id = recordId ?? ':id';
|
|
175
|
+
return Action.make('forceDelete')
|
|
176
|
+
.label('Delete forever')
|
|
177
|
+
.destructive()
|
|
178
|
+
.method('post')
|
|
179
|
+
.action(`${resourceBase(basePath, R)}/${id}/force-delete`)
|
|
180
|
+
.confirm(`Permanently delete this ${R.labelSingular.toLowerCase()}? This cannot be undone.`)
|
|
181
|
+
.visible(async ({ user, record }) => {
|
|
182
|
+
if (!isTrashed(record, R))
|
|
183
|
+
return false;
|
|
184
|
+
return callPredicate(R.canForceDelete, user, record);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Mark-as-read factory — POSTs to the panel's notification read
|
|
189
|
+
* endpoint for the given notification id. The endpoint
|
|
190
|
+
* (`${base}/_notifications/:id/read`) is mounted by
|
|
191
|
+
* `Pilotiq.databaseNotifications()`, so calling this without
|
|
192
|
+
* opting into the bell surface produces an Action whose POST 404s.
|
|
193
|
+
*
|
|
194
|
+
* `notificationId` is baked at config time. For row context where
|
|
195
|
+
* the id varies per row, omit it and the URL keeps the `:id`
|
|
196
|
+
* template; the renderer substitutes per-row at render time
|
|
197
|
+
* (parallel to `editAction`'s row form).
|
|
198
|
+
*
|
|
199
|
+
* No auto-visibility. Wrap in `.visible(({ record }) => !record.readAt)`
|
|
200
|
+
* to hide on already-read rows.
|
|
201
|
+
*/
|
|
202
|
+
export function markAsReadAction(basePath, notificationId) {
|
|
203
|
+
const id = notificationId ?? ':id';
|
|
204
|
+
return Action.make('markAsRead')
|
|
205
|
+
.label('Mark as read')
|
|
206
|
+
.method('post')
|
|
207
|
+
.action(`${basePath}/_notifications/${id}/read`);
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=crudFactories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crudFactories.js","sourceRoot":"","sources":["../../src/actions/crudFactories.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the Action factory modules — `crudFactories.ts`,
|
|
3
|
+
* `bulkFactories.ts`, `relationFactories.ts`, `m2mFactories.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Lives in its own file so the per-phase factory modules stay focused
|
|
6
|
+
* on their own factory bodies. Anything consumed by 2+ phase files
|
|
7
|
+
* lands here; phase-local helpers stay alongside their phase's
|
|
8
|
+
* factories.
|
|
9
|
+
*
|
|
10
|
+
* See `docs/plans/action-split.md` for the split plan.
|
|
11
|
+
*/
|
|
12
|
+
import type { ResourceLike } from './Action.js';
|
|
13
|
+
import type { RelationManagerContext } from '../RelationManager.js';
|
|
14
|
+
/** Cluster-aware resource base path. Mirrors `clusterPaths.resourceBasePath`
|
|
15
|
+
* but uses the structural `ResourceLike` shape so `Action.ts` stays
|
|
16
|
+
* cycle-free against `Resource.ts`. */
|
|
17
|
+
export declare function resourceBase(basePath: string, R: ResourceLike): string;
|
|
18
|
+
/** Call a (possibly undefined) Resource predicate. When unset, the
|
|
19
|
+
* predicate is treated as "allowed" (returns true) so the factory
|
|
20
|
+
* doesn't hide actions on Resources that haven't opted into Plan #10. */
|
|
21
|
+
export declare function callPredicate(fn: ((user: unknown, record?: unknown) => boolean | Promise<boolean>) | undefined, user: unknown, record?: unknown): boolean | Promise<boolean>;
|
|
22
|
+
/** Read `record[R.deletedAtColumn ?? 'deletedAt']` and return true when
|
|
23
|
+
* the row is currently trashed (soft-deleted). Permissive on shape —
|
|
24
|
+
* bare `null` / `undefined` count as live; any other truthy value is
|
|
25
|
+
* trashed. */
|
|
26
|
+
export declare function isTrashed(record: unknown, R: ResourceLike): boolean;
|
|
27
|
+
/** True when a `RelationManagerContext.mode` denotes a pivot-mutation
|
|
28
|
+
* shape — i.e. a many-to-many relation. All three modes share the
|
|
29
|
+
* `attach` / `detach` / `sync` accessor surface (the rudder ORM stamps
|
|
30
|
+
* + filters the polymorphic discriminator transparently for the morph
|
|
31
|
+
* variants). The `relationCreate / Edit / Delete` factories auto-hide
|
|
32
|
+
* under any of these modes because per-pivot-row create / edit / delete
|
|
33
|
+
* is meaningless — users create the related record via its own Resource,
|
|
34
|
+
* then attach via `relationAttach`. */
|
|
35
|
+
export declare function isM2MMode(mode: RelationManagerContext['mode']): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Build the URL prefix for a relation factory action. Without
|
|
38
|
+
* a `chain` (depth-1 manager), this is the familiar
|
|
39
|
+
* `${base}/${parentSlug}/${parentId}/${relationship}`. With a chain
|
|
40
|
+
* (depth-2 nested manager), it threads the outer record + relationship
|
|
41
|
+
* between the parent slug and the leaf parent id:
|
|
42
|
+
*
|
|
43
|
+
* `${base}/${parentSlug}/${chain[0].recordId}/${chain[0].relationship}/${parentId}/${relationship}`
|
|
44
|
+
*
|
|
45
|
+
* Pure; takes a `RelationManagerContext` and emits a string. The leaf
|
|
46
|
+
* record id (and trailing `/edit`, `/delete`, etc.) gets appended by
|
|
47
|
+
* the caller.
|
|
48
|
+
*/
|
|
49
|
+
export declare function relationUrlPrefix(ctx: RelationManagerContext): string;
|
|
50
|
+
/** Options bag for `buildReplica`. Optional fields explicitly accept
|
|
51
|
+
* `undefined` so call sites can pass `opts.excludeAttributes` through
|
|
52
|
+
* unconditionally under `exactOptionalPropertyTypes: true`. */
|
|
53
|
+
export interface BuildReplicaOptions {
|
|
54
|
+
/** Attribute keys to drop from the replicated payload IN ADDITION TO
|
|
55
|
+
* the model's primary key and soft-delete column. */
|
|
56
|
+
excludeAttributes?: readonly string[] | undefined;
|
|
57
|
+
/** Soft-delete column name on the source Resource. Defaults to
|
|
58
|
+
* `'deletedAt'`. Read separately from the model because the column
|
|
59
|
+
* lives on the Resource shape (`R.deletedAtColumn`) rather than on
|
|
60
|
+
* the model itself. */
|
|
61
|
+
deletedAtColumn?: string | undefined;
|
|
62
|
+
/** Force-pinned columns applied AFTER the strip and BEFORE the user
|
|
63
|
+
* `beforeReplicaSaved` mutator. Used by the relation replicate
|
|
64
|
+
* factories to re-stamp the parent attachment FK / morph columns
|
|
65
|
+
* so a tampered source row can't slip a different parent in. */
|
|
66
|
+
pin?: Record<string, unknown> | undefined;
|
|
67
|
+
/** Optional user mutator. Runs after the strip + pin. */
|
|
68
|
+
beforeReplicaSaved?: ((replica: Record<string, unknown>, source: unknown) => Record<string, unknown> | Promise<Record<string, unknown>>) | undefined;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build a replica payload from a source record. Used by every replicate
|
|
72
|
+
* factory (`replicateAction / bulkReplicateAction / relationReplicateAction
|
|
73
|
+
* / relationBulkReplicateAction`).
|
|
74
|
+
*
|
|
75
|
+
* Strips the model's primary key (`model.primaryKey`, defaulting to
|
|
76
|
+
* `'id'`), the soft-delete column (defaulting to `'deletedAt'`), and any
|
|
77
|
+
* `excludeAttributes` keys. Applies `pin` columns (parent attachment
|
|
78
|
+
* for relation factories), then runs the optional `beforeReplicaSaved`
|
|
79
|
+
* user mutator. Returns the replica AND the resolved primary-key column
|
|
80
|
+
* name (callers need it to read `created[pkCol]` for redirect URLs).
|
|
81
|
+
*
|
|
82
|
+
* Does NOT call `model.create` — callers wrap their own create + error
|
|
83
|
+
* handling around the returned replica.
|
|
84
|
+
*/
|
|
85
|
+
export declare function buildReplica(source: unknown, model: {
|
|
86
|
+
primaryKey?: string;
|
|
87
|
+
}, opts?: BuildReplicaOptions): Promise<{
|
|
88
|
+
replica: Record<string, unknown>;
|
|
89
|
+
pkCol: string;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Iterate `records`, run the policy probe in parallel up-front (only
|
|
93
|
+
* allowed rows enter the serial work loop), call `op(id, record)` per
|
|
94
|
+
* allowed row, swallow per-row throws (the aggregate notification shows
|
|
95
|
+
* the count succeeded). Returns the success count.
|
|
96
|
+
*
|
|
97
|
+
* Used by every bulk handler (`bulkDeleteAction / bulkRestoreAction /
|
|
98
|
+
* bulkForceDeleteAction / bulkReplicateAction / relationBulkReplicateAction
|
|
99
|
+
* / relationBulkDetachAction`-style pattern).
|
|
100
|
+
*
|
|
101
|
+
* Rows whose `record.id` coerces to an empty string are skipped without
|
|
102
|
+
* counting them as an attempt. The policy probe runs via `Promise.all`
|
|
103
|
+
* so backend round-trips parallelize, but the write loop stays serial
|
|
104
|
+
* (no transaction in v1 — concurrent writes would muddy failure
|
|
105
|
+
* semantics).
|
|
106
|
+
*/
|
|
107
|
+
export declare function forEachAllowed(records: readonly unknown[], isAllowed: (record: unknown, index: number) => boolean | Promise<boolean>, op: (id: string, record: unknown, index: number) => Promise<void>): Promise<number>;
|
|
108
|
+
//# sourceMappingURL=factoryHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factoryHelpers.d.ts","sourceRoot":"","sources":["../../src/actions/factoryHelpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAEnE;;wCAEwC;AACxC,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAGtE;AAED;;yEAEyE;AACzE,wBAAgB,aAAa,CAC3B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,EACjF,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAG5B;AAED;;;eAGe;AACf,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CAKnE;AAED;;;;;;;wCAOwC;AACxC,wBAAgB,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,GAAG,OAAO,CAEvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,CAQrE;AAED;;gEAEgE;AAChE,MAAM,WAAW,mBAAmB;IAClC;0DACsD;IACtD,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACjD;;;4BAGwB;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC;;;qEAGiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzC,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,CAAC,CACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAG,OAAO,KACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;CAC7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,OAAO,EACf,KAAK,EAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/B,IAAI,GAAI,mBAAwB,GAC/B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAI,SAAS,OAAO,EAAE,EAC7B,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACzE,EAAE,EAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACvE,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the Action factory modules — `crudFactories.ts`,
|
|
3
|
+
* `bulkFactories.ts`, `relationFactories.ts`, `m2mFactories.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Lives in its own file so the per-phase factory modules stay focused
|
|
6
|
+
* on their own factory bodies. Anything consumed by 2+ phase files
|
|
7
|
+
* lands here; phase-local helpers stay alongside their phase's
|
|
8
|
+
* factories.
|
|
9
|
+
*
|
|
10
|
+
* See `docs/plans/action-split.md` for the split plan.
|
|
11
|
+
*/
|
|
12
|
+
/** Cluster-aware resource base path. Mirrors `clusterPaths.resourceBasePath`
|
|
13
|
+
* but uses the structural `ResourceLike` shape so `Action.ts` stays
|
|
14
|
+
* cycle-free against `Resource.ts`. */
|
|
15
|
+
export function resourceBase(basePath, R) {
|
|
16
|
+
if (R.cluster)
|
|
17
|
+
return `${basePath}/${R.cluster.getSlug()}/${R.getSlug()}`;
|
|
18
|
+
return `${basePath}/${R.getSlug()}`;
|
|
19
|
+
}
|
|
20
|
+
/** Call a (possibly undefined) Resource predicate. When unset, the
|
|
21
|
+
* predicate is treated as "allowed" (returns true) so the factory
|
|
22
|
+
* doesn't hide actions on Resources that haven't opted into Plan #10. */
|
|
23
|
+
export function callPredicate(fn, user, record) {
|
|
24
|
+
if (!fn)
|
|
25
|
+
return true;
|
|
26
|
+
return fn(user, record);
|
|
27
|
+
}
|
|
28
|
+
/** Read `record[R.deletedAtColumn ?? 'deletedAt']` and return true when
|
|
29
|
+
* the row is currently trashed (soft-deleted). Permissive on shape —
|
|
30
|
+
* bare `null` / `undefined` count as live; any other truthy value is
|
|
31
|
+
* trashed. */
|
|
32
|
+
export function isTrashed(record, R) {
|
|
33
|
+
if (!record || typeof record !== 'object')
|
|
34
|
+
return false;
|
|
35
|
+
const col = R.deletedAtColumn ?? 'deletedAt';
|
|
36
|
+
const v = record[col];
|
|
37
|
+
return v !== null && v !== undefined;
|
|
38
|
+
}
|
|
39
|
+
/** True when a `RelationManagerContext.mode` denotes a pivot-mutation
|
|
40
|
+
* shape — i.e. a many-to-many relation. All three modes share the
|
|
41
|
+
* `attach` / `detach` / `sync` accessor surface (the rudder ORM stamps
|
|
42
|
+
* + filters the polymorphic discriminator transparently for the morph
|
|
43
|
+
* variants). The `relationCreate / Edit / Delete` factories auto-hide
|
|
44
|
+
* under any of these modes because per-pivot-row create / edit / delete
|
|
45
|
+
* is meaningless — users create the related record via its own Resource,
|
|
46
|
+
* then attach via `relationAttach`. */
|
|
47
|
+
export function isM2MMode(mode) {
|
|
48
|
+
return mode === 'belongsToMany' || mode === 'morphToMany' || mode === 'morphedByMany';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build the URL prefix for a relation factory action. Without
|
|
52
|
+
* a `chain` (depth-1 manager), this is the familiar
|
|
53
|
+
* `${base}/${parentSlug}/${parentId}/${relationship}`. With a chain
|
|
54
|
+
* (depth-2 nested manager), it threads the outer record + relationship
|
|
55
|
+
* between the parent slug and the leaf parent id:
|
|
56
|
+
*
|
|
57
|
+
* `${base}/${parentSlug}/${chain[0].recordId}/${chain[0].relationship}/${parentId}/${relationship}`
|
|
58
|
+
*
|
|
59
|
+
* Pure; takes a `RelationManagerContext` and emits a string. The leaf
|
|
60
|
+
* record id (and trailing `/edit`, `/delete`, etc.) gets appended by
|
|
61
|
+
* the caller.
|
|
62
|
+
*/
|
|
63
|
+
export function relationUrlPrefix(ctx) {
|
|
64
|
+
const head = `${ctx.basePath}/${ctx.parentSlug}`;
|
|
65
|
+
const chain = ctx.chain ?? [];
|
|
66
|
+
let mid = '';
|
|
67
|
+
for (const step of chain) {
|
|
68
|
+
mid += `/${step.recordId}/${step.relationship}`;
|
|
69
|
+
}
|
|
70
|
+
return `${head}${mid}/${ctx.parentId}/${ctx.relationship}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a replica payload from a source record. Used by every replicate
|
|
74
|
+
* factory (`replicateAction / bulkReplicateAction / relationReplicateAction
|
|
75
|
+
* / relationBulkReplicateAction`).
|
|
76
|
+
*
|
|
77
|
+
* Strips the model's primary key (`model.primaryKey`, defaulting to
|
|
78
|
+
* `'id'`), the soft-delete column (defaulting to `'deletedAt'`), and any
|
|
79
|
+
* `excludeAttributes` keys. Applies `pin` columns (parent attachment
|
|
80
|
+
* for relation factories), then runs the optional `beforeReplicaSaved`
|
|
81
|
+
* user mutator. Returns the replica AND the resolved primary-key column
|
|
82
|
+
* name (callers need it to read `created[pkCol]` for redirect URLs).
|
|
83
|
+
*
|
|
84
|
+
* Does NOT call `model.create` — callers wrap their own create + error
|
|
85
|
+
* handling around the returned replica.
|
|
86
|
+
*/
|
|
87
|
+
export async function buildReplica(source, model, opts = {}) {
|
|
88
|
+
const pkCol = model.primaryKey ?? 'id';
|
|
89
|
+
const trashedCol = opts.deletedAtColumn ?? 'deletedAt';
|
|
90
|
+
const skip = new Set([pkCol, trashedCol, ...(opts.excludeAttributes ?? [])]);
|
|
91
|
+
let replica = {};
|
|
92
|
+
for (const [k, v] of Object.entries(source)) {
|
|
93
|
+
if (skip.has(k))
|
|
94
|
+
continue;
|
|
95
|
+
replica[k] = v;
|
|
96
|
+
}
|
|
97
|
+
if (opts.pin)
|
|
98
|
+
Object.assign(replica, opts.pin);
|
|
99
|
+
if (opts.beforeReplicaSaved) {
|
|
100
|
+
replica = await opts.beforeReplicaSaved(replica, source);
|
|
101
|
+
}
|
|
102
|
+
return { replica, pkCol };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Iterate `records`, run the policy probe in parallel up-front (only
|
|
106
|
+
* allowed rows enter the serial work loop), call `op(id, record)` per
|
|
107
|
+
* allowed row, swallow per-row throws (the aggregate notification shows
|
|
108
|
+
* the count succeeded). Returns the success count.
|
|
109
|
+
*
|
|
110
|
+
* Used by every bulk handler (`bulkDeleteAction / bulkRestoreAction /
|
|
111
|
+
* bulkForceDeleteAction / bulkReplicateAction / relationBulkReplicateAction
|
|
112
|
+
* / relationBulkDetachAction`-style pattern).
|
|
113
|
+
*
|
|
114
|
+
* Rows whose `record.id` coerces to an empty string are skipped without
|
|
115
|
+
* counting them as an attempt. The policy probe runs via `Promise.all`
|
|
116
|
+
* so backend round-trips parallelize, but the write loop stays serial
|
|
117
|
+
* (no transaction in v1 — concurrent writes would muddy failure
|
|
118
|
+
* semantics).
|
|
119
|
+
*/
|
|
120
|
+
export async function forEachAllowed(records, isAllowed, op) {
|
|
121
|
+
const allowedFlags = await Promise.all(records.map((r, i) => isAllowed(r, i)));
|
|
122
|
+
let n = 0;
|
|
123
|
+
for (let i = 0; i < records.length; i++) {
|
|
124
|
+
if (!allowedFlags[i])
|
|
125
|
+
continue;
|
|
126
|
+
const record = records[i];
|
|
127
|
+
const id = String(record?.id ?? '');
|
|
128
|
+
if (!id)
|
|
129
|
+
continue;
|
|
130
|
+
try {
|
|
131
|
+
await op(id, record, i);
|
|
132
|
+
n++;
|
|
133
|
+
}
|
|
134
|
+
catch { /* skip — agg notify shows total */ }
|
|
135
|
+
}
|
|
136
|
+
return n;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=factoryHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factoryHelpers.js","sourceRoot":"","sources":["../../src/actions/factoryHelpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M2M relation Action factories — `relationAttach` (header, modal-form
|
|
3
|
+
* picker → POST `_action/relationAttach`), `relationDetach` (row, direct
|
|
4
|
+
* POST to `_detach/:childId`), `relationBulkDetach` (bulk, handler-
|
|
5
|
+
* dispatched).
|
|
6
|
+
*
|
|
7
|
+
* Sibling of `relationCreate / Edit / Delete` for every M2M mode
|
|
8
|
+
* (`belongsToMany`, `morphToMany` (owning polymorphic side),
|
|
9
|
+
* `morphedByMany` (inverse polymorphic side)). All three modes share
|
|
10
|
+
* the same `attach` / `detach` / `sync` accessor surface — the rudder
|
|
11
|
+
* ORM stamps + filters the polymorphic discriminator on the morph
|
|
12
|
+
* variants automatically, so pilotiq's pivot factories are mode-agnostic
|
|
13
|
+
* beyond the visibility gate.
|
|
14
|
+
*
|
|
15
|
+
* All three auto-hide outside any M2M mode so dropping a factory into
|
|
16
|
+
* a non-M2M manager is a no-op (visible=false) instead of a confusing
|
|
17
|
+
* 404.
|
|
18
|
+
*
|
|
19
|
+
* The first and third route through the manager-scoped
|
|
20
|
+
* `_action/:actionName` endpoint (added in routes.ts) so handlers
|
|
21
|
+
* see `ctx.relation = { parent, parentId, relationship }`.
|
|
22
|
+
*
|
|
23
|
+
* See `docs/plans/action-split.md` for the split plan.
|
|
24
|
+
*/
|
|
25
|
+
import { Action } from './Action.js';
|
|
26
|
+
import { type RelationManager, type RelationManagerContext } from '../RelationManager.js';
|
|
27
|
+
/** Header-placement attach factory — opens a modal with a SelectField
|
|
28
|
+
* listing related records that aren't already attached, and POSTs the
|
|
29
|
+
* selected id to the manager's `_action/relationAttach` endpoint.
|
|
30
|
+
*
|
|
31
|
+
* Visibility delegates to `M.canAttach(user, parentRecord)` AND
|
|
32
|
+
* guards against being dropped into a non-M2M manager. */
|
|
33
|
+
export declare function relationAttachAction(M: typeof RelationManager, ctx: RelationManagerContext): Action;
|
|
34
|
+
/** Row-placement detach factory — POSTs to
|
|
35
|
+
* `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/_detach`,
|
|
36
|
+
* destructive style with a confirmation prompt that says "Detach"
|
|
37
|
+
* (not "Delete") so users understand the target record stays.
|
|
38
|
+
* Visibility delegates to `M.canDetach`. */
|
|
39
|
+
export declare function relationDetachAction(M: typeof RelationManager, ctx: RelationManagerContext, recordId?: string): Action;
|
|
40
|
+
/** Bulk-placement bulk-detach factory — handler-dispatched. Calls
|
|
41
|
+
* `parent.related(rel).detach(ids)` for the selected rows. Visibility
|
|
42
|
+
* delegates to `M.canAttach` (acts like a "manager admin" gate; we
|
|
43
|
+
* intentionally don't enforce per-row `canDetach` on the visibility
|
|
44
|
+
* side because the bulk button needs to be visible before the user
|
|
45
|
+
* has selected anything — per-row gating happens inside the handler). */
|
|
46
|
+
export declare function relationBulkDetachAction(M: typeof RelationManager, ctx: RelationManagerContext): Action;
|
|
47
|
+
//# sourceMappingURL=m2mFactories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"m2mFactories.d.ts","sourceRoot":"","sources":["../../src/actions/m2mFactories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,aAAa,CAAA;AACvD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAA;AAsC9B;;;;;2DAK2D;AAC3D,wBAAgB,oBAAoB,CAClC,CAAC,EAAI,OAAO,eAAe,EAC3B,GAAG,EAAE,sBAAsB,GAC1B,MAAM,CA4CR;AAED;;;;6CAI6C;AAC7C,wBAAgB,oBAAoB,CAClC,CAAC,EAAS,OAAO,eAAe,EAChC,GAAG,EAAO,sBAAsB,EAChC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAaR;AAED;;;;;0EAK0E;AAC1E,wBAAgB,wBAAwB,CACtC,CAAC,EAAI,OAAO,eAAe,EAC3B,GAAG,EAAE,sBAAsB,GAC1B,MAAM,CAoCR"}
|