@pilotiq/pilotiq 0.24.1 → 0.24.3
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 +57 -0
- package/boost/guidelines.md +571 -0
- package/boost/skills/pilotiq-actions/SKILL.md +49 -0
- package/boost/skills/pilotiq-actions/rules/dispatch-modes.md +177 -0
- package/boost/skills/pilotiq-actions/rules/factories.md +130 -0
- package/boost/skills/pilotiq-actions/rules/visibility-and-authorization.md +125 -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/dist/Pilotiq.d.ts +31 -0
- package/dist/Pilotiq.d.ts.map +1 -1
- package/dist/Pilotiq.js +3 -1
- package/dist/Pilotiq.js.map +1 -1
- package/dist/PilotiqRegistry.d.ts +13 -0
- package/dist/PilotiqRegistry.d.ts.map +1 -1
- package/dist/PilotiqRegistry.js +15 -0
- package/dist/PilotiqRegistry.js.map +1 -1
- package/dist/pageData/misc.d.ts.map +1 -1
- package/dist/pageData/misc.js +6 -0
- package/dist/pageData/misc.js.map +1 -1
- package/dist/pageData/navigation.d.ts +1 -0
- package/dist/pageData/navigation.d.ts.map +1 -1
- package/dist/pageData/navigation.js +3 -0
- package/dist/pageData/navigation.js.map +1 -1
- package/dist/pageData/relationPages.d.ts.map +1 -1
- package/dist/pageData/relationPages.js +3 -0
- package/dist/pageData/relationPages.js.map +1 -1
- package/dist/pageData/resourcePages.d.ts.map +1 -1
- package/dist/pageData/resourcePages.js +8 -0
- package/dist/pageData/resourcePages.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.map +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/widgets/StatsOverviewRenderer.d.ts.map +1 -1
- package/dist/react/widgets/StatsOverviewRenderer.js +32 -18
- package/dist/react/widgets/StatsOverviewRenderer.js.map +1 -1
- package/dist/routes/relations.d.ts.map +1 -1
- package/dist/routes/relations.js +25 -18
- package/dist/routes/relations.js.map +1 -1
- package/dist/routes/resources.js.map +1 -1
- package/package.json +10 -5
- 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
package/src/routes.ts
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import type { Router } from '@rudderjs/router'
|
|
2
|
-
import type { MiddlewareHandler } from '@rudderjs/contracts'
|
|
3
|
-
import type { Pilotiq } from './Pilotiq.js'
|
|
4
|
-
import { Form } from './elements/Form.js'
|
|
5
|
-
import { dispatchFormSubmit, findForms, selectForm } from './elements/dispatchForm.js'
|
|
6
|
-
import { RESERVED_RELATIONSHIP_TOKENS } from './RelationManager.js'
|
|
7
|
-
import { Table } from './elements/Table.js'
|
|
8
|
-
import { Column } from './Column.js'
|
|
9
|
-
import type { ClusterClass } from './Cluster.js'
|
|
10
|
-
import { wantsJson } from './routes/helpers.js'
|
|
11
|
-
|
|
12
|
-
// `routes.ts` is split into a directory of focused modules under
|
|
13
|
-
// `./routes/`. This file is the orchestrator — boot-time validation
|
|
14
|
-
// loops + the per-Resource / per-Global / per-Page registration
|
|
15
|
-
// dispatchers. See `docs/plans/routes-split.md` for the per-phase map.
|
|
16
|
-
import { registerPanelRoutes } from './routes/panel.js'
|
|
17
|
-
import { registerResourceRoutes } from './routes/resources.js'
|
|
18
|
-
import { registerGlobalRoutes } from './routes/globals.js'
|
|
19
|
-
import { registerCustomPageRoutes } from './routes/pages.js'
|
|
20
|
-
import { registerThemeRoutes } from './routes/theme.js'
|
|
21
|
-
|
|
22
|
-
export function registerPilotiqRoutes(
|
|
23
|
-
router: Router,
|
|
24
|
-
pilotiq: Pilotiq,
|
|
25
|
-
): void {
|
|
26
|
-
const cfg = pilotiq.getConfig()
|
|
27
|
-
const base = cfg.path
|
|
28
|
-
|
|
29
|
-
// Fail fast at boot — a silent 404 at request time is much harder to
|
|
30
|
-
// debug than a clear error here. Dangling-reference checks run even
|
|
31
|
-
// when `cfg.clusters` is empty.
|
|
32
|
-
const clusterSet = new Set(cfg.clusters)
|
|
33
|
-
const assertClusterRegistered = (
|
|
34
|
-
kind: 'Resource' | 'Global' | 'Page',
|
|
35
|
-
items: Array<{ name: string; cluster?: ClusterClass }>,
|
|
36
|
-
): void => {
|
|
37
|
-
for (const item of items) {
|
|
38
|
-
if (item.cluster === undefined) continue
|
|
39
|
-
if (!clusterSet.has(item.cluster)) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
`[Pilotiq] ${kind} ${item.name} references cluster ${item.cluster.name} which is not registered. ` +
|
|
42
|
-
`Add it to Pilotiq.clusters([…]).`,
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
assertClusterRegistered('Resource', cfg.resources)
|
|
48
|
-
assertClusterRegistered('Global', cfg.globals)
|
|
49
|
-
assertClusterRegistered('Page', cfg.pages)
|
|
50
|
-
|
|
51
|
-
if (cfg.clusters.length > 0) {
|
|
52
|
-
const seenClusterSlug = new Set<string>()
|
|
53
|
-
for (const C of cfg.clusters) {
|
|
54
|
-
const s = C.getSlug()
|
|
55
|
-
if (s === '' || /^_/.test(s) || s === 'theme' || s === 'api') {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`[Pilotiq] Cluster ${C.name} uses reserved slug "${s}". ` +
|
|
58
|
-
`Cluster slugs cannot be empty, start with "_", or equal "theme" / "api".`,
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
if (seenClusterSlug.has(s)) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`[Pilotiq] Two clusters share slug "${s}". Cluster slugs must be unique.`,
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
seenClusterSlug.add(s)
|
|
67
|
-
}
|
|
68
|
-
// Top-level (no cluster) child slugs must not collide with cluster
|
|
69
|
-
// slugs — `<panel-base>/<slug>` would resolve to the cluster first.
|
|
70
|
-
const assertNoSlugCollision = <T extends { name: string; cluster?: ClusterClass; getSlug(): string }>(
|
|
71
|
-
kind: 'Resource' | 'Global' | 'Page',
|
|
72
|
-
items: T[],
|
|
73
|
-
skip?: (item: T) => boolean,
|
|
74
|
-
): void => {
|
|
75
|
-
for (const item of items) {
|
|
76
|
-
if (item.cluster || (skip?.(item) ?? false)) continue
|
|
77
|
-
if (seenClusterSlug.has(item.getSlug())) {
|
|
78
|
-
const hint = kind === 'Resource'
|
|
79
|
-
? ` Either rename the resource or move it inside the cluster.`
|
|
80
|
-
: ''
|
|
81
|
-
throw new Error(
|
|
82
|
-
`[Pilotiq] ${kind} ${item.name} slug "${item.getSlug()}" collides with a registered cluster slug.${hint}`,
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
assertNoSlugCollision('Resource', cfg.resources)
|
|
88
|
-
assertNoSlugCollision('Global', cfg.globals)
|
|
89
|
-
assertNoSlugCollision('Page', cfg.pages, P => P === cfg.dashboardPage)
|
|
90
|
-
// landingPage sanity — a cluster's landing page must be inside the
|
|
91
|
-
// cluster (or the redirect would jump out of the cluster URL space).
|
|
92
|
-
for (const C of cfg.clusters) {
|
|
93
|
-
const lp = C.landingPage
|
|
94
|
-
if (lp === undefined) continue
|
|
95
|
-
if (!cfg.pages.includes(lp)) {
|
|
96
|
-
throw new Error(
|
|
97
|
-
`[Pilotiq] Cluster ${C.name}.landingPage references ${lp.name} which is not registered in Pilotiq.pages([…]).`,
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
if (lp.cluster !== C) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`[Pilotiq] Cluster ${C.name}.landingPage = ${lp.name}, but ${lp.name}.cluster does not point back at ${C.name}.`,
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Plan #11 — fail fast at boot when any relation manager's
|
|
109
|
-
// `relationship` collides with a reserved URL token. A silent 404 at
|
|
110
|
-
// request time is much harder to debug.
|
|
111
|
-
//
|
|
112
|
-
// Phase B nested resources — same validation walks managers declared
|
|
113
|
-
// via `M.relations()` (one level deep). Depth-3+ is rejected here too:
|
|
114
|
-
// declaring `relations()` on a nested manager isn't supported in
|
|
115
|
-
// Phase B (Filament also caps at depth 2).
|
|
116
|
-
for (const R of cfg.resources) {
|
|
117
|
-
for (const M of R.relations()) {
|
|
118
|
-
const rel = M.getRelationship()
|
|
119
|
-
if (RESERVED_RELATIONSHIP_TOKENS.has(rel)) {
|
|
120
|
-
throw new Error(
|
|
121
|
-
`[Pilotiq] RelationManager ${M.name} on ${R.name} uses reserved relationship "${rel}". ` +
|
|
122
|
-
`Reserved tokens: ${[...RESERVED_RELATIONSHIP_TOKENS].join(', ')}. Rename it.`,
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
for (const N of M.relations()) {
|
|
126
|
-
const nestedRel = N.getRelationship()
|
|
127
|
-
if (RESERVED_RELATIONSHIP_TOKENS.has(nestedRel)) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
`[Pilotiq] Nested RelationManager ${N.name} under ${M.name} on ${R.name} uses reserved relationship "${nestedRel}". ` +
|
|
130
|
-
`Reserved tokens: ${[...RESERVED_RELATIONSHIP_TOKENS].join(', ')}. Rename it.`,
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
if (N.relations().length > 0) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`[Pilotiq] Nested RelationManager ${N.name} under ${M.name} on ${R.name} declares its own relations(). ` +
|
|
136
|
-
`Phase B caps nesting at depth 2 (admin-table reference frameworks cap at depth 2 too). Drop the nested relations() override.`,
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Record sub-pages — boot-time validation of slugs declared under
|
|
144
|
-
// `Resource.pages().record`. The route URL is
|
|
145
|
-
// `${resourceBase}/${slug}/:id/${subPageSlug}`, so the sub-page slug
|
|
146
|
-
// shares the same URL slot as a relation-manager's relationship. We
|
|
147
|
-
// run the slug-pattern check, the reserved-token check, and the
|
|
148
|
-
// manager-collision check before mounting any routes — a misconfigured
|
|
149
|
-
// sub-page is a dev-time error, not a runtime 404.
|
|
150
|
-
const RECORD_PAGE_SLUG_PATTERN = /^[A-Za-z0-9_-]+$/
|
|
151
|
-
for (const R of cfg.resources) {
|
|
152
|
-
const recordPages = R.getRecordPages()
|
|
153
|
-
const subPageSlugs = Object.keys(recordPages)
|
|
154
|
-
if (subPageSlugs.length === 0) continue
|
|
155
|
-
const managerSlugs = new Set(R.relations().map(M => M.getRelationship()))
|
|
156
|
-
for (const subPageSlug of subPageSlugs) {
|
|
157
|
-
if (!RECORD_PAGE_SLUG_PATTERN.test(subPageSlug)) {
|
|
158
|
-
throw new Error(
|
|
159
|
-
`[Pilotiq] Record sub-page slug ${JSON.stringify(subPageSlug)} on ${R.name} ` +
|
|
160
|
-
`must match /^[A-Za-z0-9_-]+$/. Rename it.`,
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
if (RESERVED_RELATIONSHIP_TOKENS.has(subPageSlug)) {
|
|
164
|
-
throw new Error(
|
|
165
|
-
`[Pilotiq] Record sub-page slug "${subPageSlug}" on ${R.name} collides with a reserved URL token. ` +
|
|
166
|
-
`Reserved tokens: ${[...RESERVED_RELATIONSHIP_TOKENS].join(', ')}. Rename it.`,
|
|
167
|
-
)
|
|
168
|
-
}
|
|
169
|
-
if (managerSlugs.has(subPageSlug)) {
|
|
170
|
-
throw new Error(
|
|
171
|
-
`[Pilotiq] Record sub-page slug "${subPageSlug}" on ${R.name} collides with relation manager relationship "${subPageSlug}". ` +
|
|
172
|
-
`Sub-page slugs and relation slugs share the same URL slot — rename one.`,
|
|
173
|
-
)
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Reorderable rows + editable cell columns — fail fast at boot when a
|
|
179
|
-
// Resource declares either capability but its bound model can't
|
|
180
|
-
// persist. We invoke `R.table(Table.make())` once per resource (same
|
|
181
|
-
// call shape `defaultPages` uses at request time) and inspect both
|
|
182
|
-
// markers in a single pass. The model.reorder / model.update checks
|
|
183
|
-
// are symmetric with Plan #13's restore/forceDelete guards. Results
|
|
184
|
-
// cached per-resource so the route loop below can decide whether to
|
|
185
|
-
// mount `_reorder` / `_cell`.
|
|
186
|
-
const reorderEnabled = new Map<string, string>() // slug → column
|
|
187
|
-
const editableEnabled = new Set<string>()
|
|
188
|
-
for (const R of cfg.resources) {
|
|
189
|
-
let probe: ReturnType<typeof Table.make> | undefined
|
|
190
|
-
try { probe = R.table(Table.make()) }
|
|
191
|
-
catch { continue } // user-side throw — neither flag applies
|
|
192
|
-
|
|
193
|
-
const probeColumn = probe.getReorderableColumn()
|
|
194
|
-
if (probeColumn !== undefined) {
|
|
195
|
-
if (!R.model || typeof R.model.reorder !== 'function') {
|
|
196
|
-
throw new Error(
|
|
197
|
-
`[Pilotiq] ${R.name}.table() calls reorderable("${probeColumn}") but the bound model has no reorder(ids) method. ` +
|
|
198
|
-
`Implement \`async reorder(ids)\` on the rudder Model (or remove the .reorderable() call).`,
|
|
199
|
-
)
|
|
200
|
-
}
|
|
201
|
-
reorderEnabled.set(R.getSlug(), probeColumn)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const hasEditable = (probe.getChildren() ?? [])
|
|
205
|
-
.some(c => c instanceof Column && c.isEditable())
|
|
206
|
-
if (hasEditable) {
|
|
207
|
-
if (!R.model || typeof R.model.update !== 'function') {
|
|
208
|
-
throw new Error(
|
|
209
|
-
`[Pilotiq] ${R.name}.table() declares an editable cell column ` +
|
|
210
|
-
`(TextInputColumn / ToggleColumn / SelectColumn) but the bound ` +
|
|
211
|
-
`model has no update(id, data) method. Set Resource.model = M ` +
|
|
212
|
-
`(rudder ORM convention) or drop the editable column.`,
|
|
213
|
-
)
|
|
214
|
-
}
|
|
215
|
-
editableEnabled.add(R.getSlug())
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// ── `Pilotiq.guard()` — panel-wide 401 layer ──────────
|
|
220
|
-
// Documented as the unauthenticated-request gate, but until 2026-05-21
|
|
221
|
-
// only `_uploads` consulted it — every other route relied on
|
|
222
|
-
// `cfg.user` returning null + `R.canX(user, …)` defaulting to true,
|
|
223
|
-
// so an app that wired `guard(req => Auth.check())` but shipped any
|
|
224
|
-
// Resource without `canAccess` ended up with an unauthenticated,
|
|
225
|
-
// fully-readable admin panel. Wrap every core panel route in one
|
|
226
|
-
// group so the guard runs in front of every handler.
|
|
227
|
-
const guardMiddleware: MiddlewareHandler = async (req, res, next) => {
|
|
228
|
-
if (cfg.guard) {
|
|
229
|
-
const allowed = await cfg.guard(req)
|
|
230
|
-
if (!allowed) {
|
|
231
|
-
res.status(401)
|
|
232
|
-
if (wantsJson(req)) return res.json({ ok: false, error: 'Unauthorized' })
|
|
233
|
-
return res.send('Unauthorized')
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return next()
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
router.group({ middleware: [guardMiddleware] }, () => {
|
|
240
|
-
// ── Panel-level sibling routes ────────────────────────
|
|
241
|
-
// Dashboard, _uploads, _widget, _search, _notifications.
|
|
242
|
-
// Pulled out 2026-05-12 (Phase 2 of the routes.ts split).
|
|
243
|
-
registerPanelRoutes(router, pilotiq, base)
|
|
244
|
-
|
|
245
|
-
// ── Resource routes ───────────────────────────────────
|
|
246
|
-
// List / view / create / edit / delete + soft-delete / actions /
|
|
247
|
-
// widgets / deferred-table / reorder / per-row editable cells / the
|
|
248
|
-
// four form-state companion endpoints / record sub-pages. Each
|
|
249
|
-
// Resource also fans out into its registered relation managers
|
|
250
|
-
// (depth-1 + depth-2). Pulled out 2026-05-12 (Phase 5 of the
|
|
251
|
-
// routes.ts split).
|
|
252
|
-
for (const R of cfg.resources) {
|
|
253
|
-
registerResourceRoutes(router, pilotiq, R, base, {
|
|
254
|
-
reorderable: reorderEnabled.has(R.getSlug()),
|
|
255
|
-
editable: editableEnabled.has(R.getSlug()),
|
|
256
|
-
})
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// ── Globals (singletons — 2-segment, no /:id) ────────
|
|
260
|
-
// Pulled out 2026-05-12 (Phase 3 of the routes.ts split).
|
|
261
|
-
for (const G of cfg.globals) {
|
|
262
|
-
registerGlobalRoutes(router, pilotiq, G, base)
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// ── Custom pages (2-segment, slug route) ──────────────
|
|
266
|
-
// Pulled out 2026-05-12 (Phase 3 of the routes.ts split).
|
|
267
|
-
for (const PageClass of cfg.pages) {
|
|
268
|
-
// The dashboard page lives at `${base}` (panel routes handle it);
|
|
269
|
-
// skip it here so we don't register a duplicate `${pageUrl}` route
|
|
270
|
-
// or a broken `${base}/` (when `slug = ''`).
|
|
271
|
-
if (cfg.dashboardPage === PageClass) continue
|
|
272
|
-
registerCustomPageRoutes(router, pilotiq, PageClass, base)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// ── Theme editor ──────────────────────────────────────
|
|
276
|
-
// Pulled out 2026-05-12 (Phase 3 of the routes.ts split).
|
|
277
|
-
if (cfg.themeEditor) {
|
|
278
|
-
registerThemeRoutes(router, pilotiq, base)
|
|
279
|
-
}
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
// Plugin route hook — runs AFTER all core routes register so plugins
|
|
283
|
-
// can mount their own HTTP surface alongside the panel's. Order
|
|
284
|
-
// matches the registration order on `.use()` / `.plugins([…])`. Each
|
|
285
|
-
// plugin owns its own URL convention; pilotiq's underscore-prefixed
|
|
286
|
-
// sibling-route precedent (`_search`, `_uploads`, `_widget`,
|
|
287
|
-
// `_notifications`) is the recommended shape. Failures inside a
|
|
288
|
-
// plugin's hook propagate — boot order is "register all core, then
|
|
289
|
-
// each plugin in order"; a throw on hook N stops hooks N+1..N+M.
|
|
290
|
-
//
|
|
291
|
-
// Plugin routes mount OUTSIDE the guard group — plugins own their
|
|
292
|
-
// own auth posture (e.g. public webhooks, custom auth handshakes).
|
|
293
|
-
// Plugin authors that want the panel guard should consult
|
|
294
|
-
// `cfg.guard` themselves at the top of their handlers.
|
|
295
|
-
for (const plugin of pilotiq.getPlugins()) {
|
|
296
|
-
plugin.registerRoutes?.(router, pilotiq)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// ─── Lifecycle helpers exported for tests ────────────────
|
|
301
|
-
export { dispatchFormSubmit, findForms, selectForm }
|
|
302
|
-
export { loadTableRecords, parseTableQuery, findTables } from './elements/dispatchTable.js'
|
|
303
|
-
export type { Form }
|
package/src/schema/Alert.test.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { Alert } from './Alert.js'
|
|
5
|
-
import { Action } from '../actions/Action.js'
|
|
6
|
-
import { resolveSchema, _resetResolverRegistry } from './resolveSchema.js'
|
|
7
|
-
|
|
8
|
-
beforeEach(() => _resetResolverRegistry())
|
|
9
|
-
|
|
10
|
-
describe('Alert schema primitive', () => {
|
|
11
|
-
it('emits content + info default + no title key', () => {
|
|
12
|
-
const meta = Alert.make('Heads up').toMeta()
|
|
13
|
-
assert.equal(meta.type, 'alert')
|
|
14
|
-
assert.equal(meta.content, 'Heads up')
|
|
15
|
-
assert.equal(meta.alertType, 'info')
|
|
16
|
-
assert.equal('title' in meta, false)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('honors warning / success / danger', () => {
|
|
20
|
-
assert.equal(Alert.make('a').warning().toMeta().alertType, 'warning')
|
|
21
|
-
assert.equal(Alert.make('a').success().toMeta().alertType, 'success')
|
|
22
|
-
assert.equal(Alert.make('a').danger().toMeta().alertType, 'danger')
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('emits title when set', () => {
|
|
26
|
-
const meta = Alert.make('body').title('Heads up').toMeta()
|
|
27
|
-
assert.equal(meta.title, 'Heads up')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('actions(...) lands on _children and resolves into meta.children', async () => {
|
|
31
|
-
const upgrade = Action.make('upgrade').label('Upgrade').url('/billing')
|
|
32
|
-
const tree = [Alert.make('Free tier limits reached').warning().actions([upgrade])]
|
|
33
|
-
const out = await resolveSchema(tree)
|
|
34
|
-
assert.equal(out[0]!.type, 'alert')
|
|
35
|
-
const children = (out[0]!.children ?? []) as Array<{ type: string; name?: string }>
|
|
36
|
-
assert.equal(children.length, 1)
|
|
37
|
-
assert.equal(children[0]!.type, 'action')
|
|
38
|
-
assert.equal(children[0]!.name, 'upgrade')
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('actions visibility evaluates against the schema context', async () => {
|
|
42
|
-
const a = Action.make('admin-only').label('Admin').visible(({ user }) => Boolean(user))
|
|
43
|
-
const b = Action.make('always') .label('Both' )
|
|
44
|
-
const tree = [Alert.make('hi').actions([a, b])]
|
|
45
|
-
|
|
46
|
-
// No user → admin-only action drops out.
|
|
47
|
-
const noUser = await resolveSchema(tree, {})
|
|
48
|
-
const noUserChildren = (noUser[0]!.children ?? []) as Array<{ name?: string }>
|
|
49
|
-
assert.equal(noUserChildren.length, 1)
|
|
50
|
-
assert.equal(noUserChildren[0]!.name, 'always')
|
|
51
|
-
|
|
52
|
-
// User present → both survive.
|
|
53
|
-
const withUser = await resolveSchema(tree, { user: { name: 'Sue' } })
|
|
54
|
-
const withUserChildren = (withUser[0]!.children ?? []) as Array<{ name?: string }>
|
|
55
|
-
assert.equal(withUserChildren.length, 2)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('without actions(...) emits no children key', async () => {
|
|
59
|
-
const tree = [Alert.make('plain').info()]
|
|
60
|
-
const out = await resolveSchema(tree)
|
|
61
|
-
assert.equal('children' in out[0]!, false)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
// ─── Filament v5 chrome polish (2026-05-08, audit gap #8) ──
|
|
65
|
-
|
|
66
|
-
it('controls(...) is an alias for actions(...)', async () => {
|
|
67
|
-
const a = Action.make('upgrade').label('Upgrade').url('/billing')
|
|
68
|
-
const tree = [Alert.make('hi').controls([a])]
|
|
69
|
-
const out = await resolveSchema(tree)
|
|
70
|
-
const children = (out[0]!.children ?? []) as Array<{ type: string; name?: string }>
|
|
71
|
-
assert.equal(children.length, 1)
|
|
72
|
-
assert.equal(children[0]!.name, 'upgrade')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('controlActions(...) is the variadic spread alias', async () => {
|
|
76
|
-
const a = Action.make('upgrade').label('Upgrade').url('/billing')
|
|
77
|
-
const b = Action.make('learnMore').label('Read more').url('/docs')
|
|
78
|
-
const tree = [Alert.make('hi').controlActions(a, b)]
|
|
79
|
-
const out = await resolveSchema(tree)
|
|
80
|
-
const children = (out[0]!.children ?? []) as Array<{ name?: string }>
|
|
81
|
-
assert.equal(children.length, 2)
|
|
82
|
-
assert.equal(children[0]!.name, 'upgrade')
|
|
83
|
-
assert.equal(children[1]!.name, 'learnMore')
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('dismissible() emits dismissible: true on meta; absent by default', () => {
|
|
87
|
-
assert.equal('dismissible' in Alert.make('a').toMeta(), false)
|
|
88
|
-
assert.equal(Alert.make('a').dismissible().toMeta().dismissible, true)
|
|
89
|
-
assert.equal('dismissible' in Alert.make('a').dismissible(false).toMeta(), false)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('persistDismissal(key) auto-arms dismissible() and stamps the key', () => {
|
|
93
|
-
const meta = Alert.make('a').persistDismissal('billing-2026-q2').toMeta()
|
|
94
|
-
assert.equal(meta.dismissible, true)
|
|
95
|
-
assert.equal(meta.persistDismissal, 'billing-2026-q2')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('iconColor() emits the override only when set', () => {
|
|
99
|
-
assert.equal('iconColor' in Alert.make('a').toMeta(), false)
|
|
100
|
-
assert.equal(Alert.make('a').iconColor('destructive').toMeta().iconColor, 'destructive')
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('footerActionsAlignment() emits only when non-default', () => {
|
|
104
|
-
assert.equal('actionsAlignment' in Alert.make('a').toMeta(), false)
|
|
105
|
-
assert.equal('actionsAlignment' in Alert.make('a').footerActionsAlignment('start').toMeta(), false)
|
|
106
|
-
assert.equal(Alert.make('a').footerActionsAlignment('center').toMeta().actionsAlignment, 'center')
|
|
107
|
-
assert.equal(Alert.make('a').footerActionsAlignment('end').toMeta().actionsAlignment, 'end')
|
|
108
|
-
})
|
|
109
|
-
})
|
package/src/schema/Alert.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { Element } from './Element.js'
|
|
2
|
-
import type { Action } from '../actions/Action.js'
|
|
3
|
-
import type { IconColor } from './Icon.js'
|
|
4
|
-
|
|
5
|
-
export type AlertType = 'info' | 'warning' | 'success' | 'danger'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Alignment for the footer-actions row inside an `Alert` (Filament v5
|
|
9
|
-
* parity). `'start'` aligns the buttons to the leading edge (LTR =
|
|
10
|
-
* left), `'center'` to the middle, `'end'` to the trailing edge (LTR =
|
|
11
|
-
* right). Defaults to `'start'`.
|
|
12
|
-
*/
|
|
13
|
-
export type AlertActionsAlignment = 'start' | 'center' | 'end'
|
|
14
|
-
|
|
15
|
-
export class Alert extends Element {
|
|
16
|
-
private _alertType: AlertType = 'info'
|
|
17
|
-
private _title?: string
|
|
18
|
-
private _dismissible = false
|
|
19
|
-
private _persistKey?: string
|
|
20
|
-
private _iconColor?: IconColor
|
|
21
|
-
private _actionsAlignment: AlertActionsAlignment = 'start'
|
|
22
|
-
|
|
23
|
-
private constructor(private content: string) {
|
|
24
|
-
super()
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
static make(content: string): Alert {
|
|
28
|
-
return new Alert(content)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
alertType(t: AlertType): this { this._alertType = t; return this }
|
|
32
|
-
title(t: string): this { this._title = t; return this }
|
|
33
|
-
|
|
34
|
-
info(): this { return this.alertType('info') }
|
|
35
|
-
warning(): this { return this.alertType('warning') }
|
|
36
|
-
success(): this { return this.alertType('success') }
|
|
37
|
-
danger(): this { return this.alertType('danger') }
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Action buttons rendered as a footer row below the alert body —
|
|
41
|
-
* matches the reference admin's `Callout` shape (in-callout CTAs like
|
|
42
|
-
* "Upgrade" or "Read changelog"). Same wiring as `Heading.actions(...)`
|
|
43
|
-
* and `EmptyState.footer(...)` — actions land on `_children` and the
|
|
44
|
-
* standard schema walker resolves them so `Action.evaluate(ctx)`
|
|
45
|
-
* (visibility / authorize) fires unchanged.
|
|
46
|
-
*/
|
|
47
|
-
actions(actions: Action[]): this {
|
|
48
|
-
this._children = actions
|
|
49
|
-
return this
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Filament v5 parity alias for `actions([...])`. Identical semantics. */
|
|
53
|
-
controls(actions: Action[]): this {
|
|
54
|
-
return this.actions(actions)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Filament v5 parity — variadic `controlActions(a, b, c, …)` matches
|
|
59
|
-
* the spread shape `controlActions(Action::make(...), Action::make(...))`.
|
|
60
|
-
*/
|
|
61
|
-
controlActions(...actions: Action[]): this {
|
|
62
|
-
return this.actions(actions)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Toggle the close (`×`) button rendered in the alert's top-right
|
|
67
|
-
* corner. Off by default (matches today's behaviour). Dismissal is
|
|
68
|
-
* per-mount (component-local state) unless paired with
|
|
69
|
-
* `persistDismissal(key)`, which writes to `localStorage` so the
|
|
70
|
-
* alert stays hidden across reloads.
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* Alert.make('Heads up — billing downgrades on Friday.')
|
|
74
|
-
* .warning()
|
|
75
|
-
* .dismissible()
|
|
76
|
-
* .persistDismissal('billing-downgrade-2026-q2')
|
|
77
|
-
*/
|
|
78
|
-
dismissible(value: boolean = true): this {
|
|
79
|
-
this._dismissible = value
|
|
80
|
-
return this
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Persist dismissal under a stable localStorage key. Auto-arms
|
|
85
|
-
* `dismissible(true)` so the close button shows up. The key is
|
|
86
|
-
* stored under `pilotiq.alert.<key>` to namespace from other
|
|
87
|
-
* pilotiq localStorage entries; users only see the leaf segment.
|
|
88
|
-
*/
|
|
89
|
-
persistDismissal(key: string): this {
|
|
90
|
-
this._persistKey = key
|
|
91
|
-
this._dismissible = true
|
|
92
|
-
return this
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Override the icon color independent of the alert type. By default
|
|
97
|
-
* the renderer picks an icon hue matching `alertType`
|
|
98
|
-
* (info/warning/success/danger); call this to force a different one
|
|
99
|
-
* — e.g. a `warning`-typed alert with a `'destructive'` icon when
|
|
100
|
-
* the message escalates partway through a flow.
|
|
101
|
-
*/
|
|
102
|
-
iconColor(color: IconColor): this {
|
|
103
|
-
this._iconColor = color
|
|
104
|
-
return this
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Align the footer actions row. Defaults to `'start'` (LTR-left).
|
|
109
|
-
* Use `'end'` for "primary action sits opposite the close button"
|
|
110
|
-
* layouts; `'center'` for short single-button alerts.
|
|
111
|
-
*/
|
|
112
|
-
footerActionsAlignment(alignment: AlertActionsAlignment): this {
|
|
113
|
-
this._actionsAlignment = alignment
|
|
114
|
-
return this
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
getType(): string { return 'alert' }
|
|
118
|
-
|
|
119
|
-
toMeta() {
|
|
120
|
-
return {
|
|
121
|
-
type: 'alert' as const,
|
|
122
|
-
content: this.content,
|
|
123
|
-
alertType: this._alertType,
|
|
124
|
-
...(this._title !== undefined ? { title: this._title } : {}),
|
|
125
|
-
...(this._dismissible ? { dismissible: true } : {}),
|
|
126
|
-
...(this._persistKey !== undefined ? { persistDismissal: this._persistKey } : {}),
|
|
127
|
-
...(this._iconColor !== undefined ? { iconColor: this._iconColor } : {}),
|
|
128
|
-
...(this._actionsAlignment !== 'start' ? { actionsAlignment: this._actionsAlignment } : {}),
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|