@pilotiq/pilotiq 0.23.1 → 0.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/boost/guidelines.md +566 -0
- package/boost/skills/pilotiq-fields/SKILL.md +47 -0
- package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
- package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
- package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
- package/boost/skills/pilotiq-relations/SKILL.md +47 -0
- package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
- package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
- package/boost/skills/pilotiq-resource/SKILL.md +61 -0
- package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
- package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
- package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
- package/dist/actions/exportFactory.d.ts +10 -0
- package/dist/actions/exportFactory.d.ts.map +1 -1
- package/dist/actions/exportFactory.js +10 -0
- package/dist/actions/exportFactory.js.map +1 -1
- package/dist/react/CollabRoomContext.d.ts +5 -5
- package/dist/react/index.d.ts +0 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +0 -1
- package/dist/react/index.js.map +1 -1
- package/dist/routes/helpers.d.ts.map +1 -1
- package/dist/routes/helpers.js +6 -2
- package/dist/routes/helpers.js.map +1 -1
- package/dist/routes/relations.d.ts.map +1 -1
- package/dist/routes/relations.js +12 -0
- package/dist/routes/relations.js.map +1 -1
- package/package.json +6 -1
- package/.turbo/turbo-build.log +0 -8
- package/CLAUDE.md +0 -265
- package/dist/react/useCollabSeed.d.ts +0 -23
- package/dist/react/useCollabSeed.d.ts.map +0 -1
- package/dist/react/useCollabSeed.js +0 -82
- package/dist/react/useCollabSeed.js.map +0 -1
- 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 -215
- 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 -195
- 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/useCollabSeed.ts +0 -86
- 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 -700
- package/src/routes/pages.ts +0 -175
- package/src/routes/panel.ts +0 -204
- package/src/routes/relations.ts +0 -1227
- 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/pages.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import type { Router } from '@rudderjs/router'
|
|
2
|
-
import { view } from '@rudderjs/view'
|
|
3
|
-
import type { Pilotiq } from '../Pilotiq.js'
|
|
4
|
-
import type { Page } from '../Page.js'
|
|
5
|
-
import { resolveSchema, type SchemaContext } from '../schema/resolveSchema.js'
|
|
6
|
-
import { dispatchFormSubmit, findForms, selectForm } from '../elements/dispatchForm.js'
|
|
7
|
-
import { dispatchAction, parseActionBody } from '../elements/dispatchAction.js'
|
|
8
|
-
import { pageBasePath } from '../clusterPaths.js'
|
|
9
|
-
import {
|
|
10
|
-
panelInfo, callPageSchema, tagFormActions, tagActionDispatch,
|
|
11
|
-
customPageData,
|
|
12
|
-
} from '../pageData.js'
|
|
13
|
-
import {
|
|
14
|
-
wantsJson,
|
|
15
|
-
readFormBody,
|
|
16
|
-
normalizeRedirect,
|
|
17
|
-
splitMeta,
|
|
18
|
-
forbidden,
|
|
19
|
-
policyAccess,
|
|
20
|
-
resolveDispatchTarget,
|
|
21
|
-
handleFormState,
|
|
22
|
-
handleFormWizard,
|
|
23
|
-
handleFormCreateOption,
|
|
24
|
-
handleFormMentions,
|
|
25
|
-
handleWidgetData,
|
|
26
|
-
sendActionResult,
|
|
27
|
-
sendRedirectResponse,
|
|
28
|
-
} from './helpers.js'
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Register the routes for a single custom Page — the optional widget /
|
|
32
|
-
* form-state companions, the GET render, action dispatch, and the
|
|
33
|
-
* page-level POST (when the page's schema includes a `Form`).
|
|
34
|
-
*
|
|
35
|
-
* Pulled out of `registerPilotiqRoutes` in 2026-05-12 (Phase 3 of the
|
|
36
|
-
* routes.ts split). Called once per `cfg.pages` entry. The caller is
|
|
37
|
-
* responsible for skipping the dashboard page (it's served by the
|
|
38
|
-
* panel-base GET).
|
|
39
|
-
*/
|
|
40
|
-
export function registerCustomPageRoutes(
|
|
41
|
-
router: Router,
|
|
42
|
-
pilotiq: Pilotiq,
|
|
43
|
-
PageClass: typeof Page,
|
|
44
|
-
base: string,
|
|
45
|
-
): void {
|
|
46
|
-
const cfg = pilotiq.getConfig()
|
|
47
|
-
const pageSlug = PageClass.getSlug()
|
|
48
|
-
const pageUrl = pageBasePath(base, PageClass)
|
|
49
|
-
|
|
50
|
-
// Plan #15 — per-page widget polling endpoint. Mirrors the
|
|
51
|
-
// panel-scope `${base}/_widget/:id` but resolves the custom page's
|
|
52
|
-
// schema instead of the dashboard's.
|
|
53
|
-
router.post(`${pageUrl}/_widget/:id`, async (req, res) => {
|
|
54
|
-
const user = await pilotiq.resolveUser(req)
|
|
55
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, true)
|
|
56
|
-
return handleWidgetData(req, res, pilotiq, { kind: 'page', pageSlug }, req.params['id']!)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
// Plan #5 partial-resolve endpoint for custom pages with reactive forms.
|
|
60
|
-
// POST ${base}/${pageSlug}/_form/:formId/state
|
|
61
|
-
router.post(`${pageUrl}/_form/:formId/state`, async (req, res) => {
|
|
62
|
-
const user = await pilotiq.resolveUser(req)
|
|
63
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, true)
|
|
64
|
-
const formId = req.params['formId']!
|
|
65
|
-
return handleFormState(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// Plan #8 wizard step-validate endpoint for custom pages.
|
|
69
|
-
router.post(`${pageUrl}/_form/:formId/wizard`, async (req, res) => {
|
|
70
|
-
const user = await pilotiq.resolveUser(req)
|
|
71
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, true)
|
|
72
|
-
const formId = req.params['formId']!
|
|
73
|
-
return handleFormWizard(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// Async-mention endpoint for custom pages.
|
|
77
|
-
router.post(`${pageUrl}/_form/:formId/mentions`, async (req, res) => {
|
|
78
|
-
const user = await pilotiq.resolveUser(req)
|
|
79
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, true)
|
|
80
|
-
const formId = req.params['formId']!
|
|
81
|
-
return handleFormMentions(req, res, pilotiq, { kind: 'page', pageSlug }, formId)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// SelectField inline-create modal endpoint for custom pages.
|
|
85
|
-
router.post(`${pageUrl}/_form/:formId/create-option/:fieldName`, async (req, res) => {
|
|
86
|
-
const user = await pilotiq.resolveUser(req)
|
|
87
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, true)
|
|
88
|
-
const formId = req.params['formId']!
|
|
89
|
-
const fieldName = req.params['fieldName']!
|
|
90
|
-
return handleFormCreateOption(req, res, pilotiq, { kind: 'page', pageSlug }, formId, fieldName)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
router.get(pageUrl, async (req, res) => {
|
|
94
|
-
const user = await pilotiq.resolveUser(req)
|
|
95
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, wantsJson(req))
|
|
96
|
-
const data = await customPageData(pilotiq, pageSlug, req)
|
|
97
|
-
return view('pilotiq.slug', data ?? {})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
// Action dispatch — POST ${base}/${pageSlug}/_action/:actionName
|
|
101
|
-
router.post(`${pageUrl}/_action/:actionName`, async (req, res) => {
|
|
102
|
-
const user = await pilotiq.resolveUser(req)
|
|
103
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, wantsJson(req))
|
|
104
|
-
|
|
105
|
-
const actionName = req.params['actionName']!
|
|
106
|
-
const json = wantsJson(req)
|
|
107
|
-
const body = await readFormBody(req)
|
|
108
|
-
const input = parseActionBody(body)
|
|
109
|
-
|
|
110
|
-
const ctx: SchemaContext = user !== null ? { user: user as NonNullable<SchemaContext['user']> } : {}
|
|
111
|
-
const elements = await callPageSchema(PageClass, ctx)
|
|
112
|
-
tagActionDispatch(elements, pageUrl)
|
|
113
|
-
const target = resolveDispatchTarget(elements, actionName)
|
|
114
|
-
if (!target) {
|
|
115
|
-
if (json) { res.status(404); return res.json({ ok: false, error: `Action "${actionName}" not found` }) }
|
|
116
|
-
res.status(404)
|
|
117
|
-
return res.send(`Action "${actionName}" not found on page`)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const result = await dispatchAction(target.action, {
|
|
121
|
-
...input,
|
|
122
|
-
request: req,
|
|
123
|
-
user,
|
|
124
|
-
...(target.rowField ? { rowField: target.rowField } : {}),
|
|
125
|
-
...(target.formSchema ? { formSchema: target.formSchema } : {}),
|
|
126
|
-
})
|
|
127
|
-
return sendActionResult(req, res, json, result, base, pageUrl)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
// Custom pages can also accept submits when their schema includes a Form.
|
|
131
|
-
router.post(pageUrl, async (req, res) => {
|
|
132
|
-
const body = await readFormBody(req)
|
|
133
|
-
const { values, formId } = splitMeta(body)
|
|
134
|
-
const json = wantsJson(req)
|
|
135
|
-
|
|
136
|
-
const user = await pilotiq.resolveUser(req)
|
|
137
|
-
if (!await policyAccess(PageClass, user)) return forbidden(res, json)
|
|
138
|
-
|
|
139
|
-
const ctx: SchemaContext = user !== null ? { user: user as NonNullable<SchemaContext['user']> } : {}
|
|
140
|
-
const elements = await callPageSchema(PageClass, ctx)
|
|
141
|
-
tagFormActions(elements, pageUrl)
|
|
142
|
-
const form = selectForm(findForms(elements), formId)
|
|
143
|
-
if (!form) {
|
|
144
|
-
if (json) { res.status(404); return res.json({ ok: false, error: 'No form found on page' }) }
|
|
145
|
-
res.status(404)
|
|
146
|
-
return res.send('No form found on page')
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const result = await dispatchFormSubmit(form, values, { values, basePath: base })
|
|
150
|
-
|
|
151
|
-
if (!result.ok) {
|
|
152
|
-
if (json) {
|
|
153
|
-
res.status(422)
|
|
154
|
-
return res.json({ ok: false, errors: result.errors })
|
|
155
|
-
}
|
|
156
|
-
form.withValues(values).withErrors(result.errors)
|
|
157
|
-
const schemaData = await resolveSchema(elements, ctx)
|
|
158
|
-
res.status(422)
|
|
159
|
-
return view('pilotiq.slug', {
|
|
160
|
-
pageType: 'page',
|
|
161
|
-
panel: await panelInfo(pilotiq, req),
|
|
162
|
-
page: PageClass.toMeta(),
|
|
163
|
-
schemaData,
|
|
164
|
-
basePath: base,
|
|
165
|
-
layout: cfg.layout,
|
|
166
|
-
hasErrors: true,
|
|
167
|
-
})
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const redirect = normalizeRedirect(result.redirect, base) ?? pageUrl
|
|
171
|
-
return sendRedirectResponse(req, res, json, redirect, result.notifications,
|
|
172
|
-
result.relationshipRenames.length > 0 ? { relationshipRenames: result.relationshipRenames } : undefined,
|
|
173
|
-
)
|
|
174
|
-
})
|
|
175
|
-
}
|
package/src/routes/panel.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import type { Router } from '@rudderjs/router'
|
|
2
|
-
import type { AppRequest } from '@rudderjs/contracts'
|
|
3
|
-
import { view } from '@rudderjs/view'
|
|
4
|
-
import type { Pilotiq } from '../Pilotiq.js'
|
|
5
|
-
import { dashboardData, searchData } from '../pageData.js'
|
|
6
|
-
import {
|
|
7
|
-
listForUser as listDatabaseNotifications,
|
|
8
|
-
markAsRead as markDatabaseNotificationAsRead,
|
|
9
|
-
markAsUnread as markDatabaseNotificationAsUnread,
|
|
10
|
-
markAllAsRead as markAllDatabaseNotificationsAsRead,
|
|
11
|
-
} from '../notifications/database.js'
|
|
12
|
-
import { dispatchNotificationAction } from '../notifications/dispatchNotificationAction.js'
|
|
13
|
-
import { registerBroadcastAuth } from '../notifications/registerBroadcastAuth.js'
|
|
14
|
-
import {
|
|
15
|
-
wantsJson,
|
|
16
|
-
forbidden,
|
|
17
|
-
policyAccess,
|
|
18
|
-
handleWidgetData,
|
|
19
|
-
handleUploadRequest,
|
|
20
|
-
} from './helpers.js'
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Register the panel-level sibling routes — the ones that don't belong
|
|
24
|
-
* to any individual Resource / Global / custom Page:
|
|
25
|
-
*
|
|
26
|
-
* - `GET ${base}` — dashboard
|
|
27
|
-
* - `POST ${base}/_uploads` — `FileUpload` field POST target
|
|
28
|
-
* - `POST ${base}/_widget/:id` — Plan #15 dashboard widget polling
|
|
29
|
-
* - `GET ${base}/_search` — Plan #12 global search
|
|
30
|
-
* - `${base}/_notifications/...` — bell-icon dropdown endpoints (only
|
|
31
|
-
* mounted when `Pilotiq.databaseNotifications()` was called)
|
|
32
|
-
*
|
|
33
|
-
* Plus the broadcast-auth registration that the notifications path
|
|
34
|
-
* needs in the same `if` branch. Reads `cfg = pilotiq.getConfig()`
|
|
35
|
-
* internally so the call site only has to thread the basePath.
|
|
36
|
-
*/
|
|
37
|
-
export function registerPanelRoutes(
|
|
38
|
-
router: Router,
|
|
39
|
-
pilotiq: Pilotiq,
|
|
40
|
-
base: string,
|
|
41
|
-
): void {
|
|
42
|
-
const cfg = pilotiq.getConfig()
|
|
43
|
-
|
|
44
|
-
// ── Dashboard (1-segment) ─────────────────────────────
|
|
45
|
-
router.get(base, async (req, res) => {
|
|
46
|
-
// Plan #15 — when `panel.dashboard(P)` is set, gate the dashboard
|
|
47
|
-
// route through the page's `canAccess` predicate. Same posture as
|
|
48
|
-
// custom pages — fail-closed on throw.
|
|
49
|
-
if (cfg.dashboardPage) {
|
|
50
|
-
const user = await pilotiq.resolveUser(req)
|
|
51
|
-
if (!await policyAccess(cfg.dashboardPage!, user)) {
|
|
52
|
-
return forbidden(res, wantsJson(req))
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return view('pilotiq.dashboard', await dashboardData(pilotiq, req))
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
// ── File uploads (FileUpload field POST target) ───────
|
|
59
|
-
router.post(`${base}/_uploads`, async (req, res) => {
|
|
60
|
-
return handleUploadRequest(req, res, pilotiq)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// ── Plan #15 dashboard widget polling ─────────────────
|
|
64
|
-
// POST ${base}/_widget/:id — re-resolves the dashboard page schema,
|
|
65
|
-
// finds widget by id, runs `getServerData(ctx)`. Body: `{ filter? }`.
|
|
66
|
-
// Mounted unconditionally — widgetData() returns 404 when no
|
|
67
|
-
// dashboard page is registered, so this stays cheap when unused.
|
|
68
|
-
router.post(`${base}/_widget/:id`, async (req, res) => {
|
|
69
|
-
if (cfg.dashboardPage) {
|
|
70
|
-
const user = await pilotiq.resolveUser(req)
|
|
71
|
-
if (!await policyAccess(cfg.dashboardPage!, user)) return forbidden(res, true)
|
|
72
|
-
}
|
|
73
|
-
return handleWidgetData(req, res, pilotiq, { kind: 'panel' }, req.params['id']!)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// ── Plan #12 global search ────────────────────────────
|
|
77
|
-
// GET ${base}/_search?q=…&limit=… → { ok, results }
|
|
78
|
-
// No 403 on unrecognised users — `searchAllResources` filters per
|
|
79
|
-
// resource. The Pilotiq.guard() layer above is the panel-level gate.
|
|
80
|
-
router.get(`${base}/_search`, async (req, res) => {
|
|
81
|
-
const query = req.query as Record<string, unknown> | undefined
|
|
82
|
-
const rawQ = query?.['q']
|
|
83
|
-
const q = typeof rawQ === 'string' ? rawQ.slice(0, 200) : ''
|
|
84
|
-
const data = await searchData(pilotiq, q, req)
|
|
85
|
-
return res.json(data)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// ── Database notifications (bell-icon dropdown) ───────
|
|
89
|
-
// Only mounted when `Pilotiq.databaseNotifications()` was called.
|
|
90
|
-
// Every route 401s when no user resolves so a non-authenticated
|
|
91
|
-
// request never sees another user's inbox. The `notifiable_type`
|
|
92
|
-
// value is configurable but defaults to `'users'` to match
|
|
93
|
-
// `@rudderjs/notification`'s `DatabaseChannel` writes.
|
|
94
|
-
if (cfg.databaseNotifications?.enabled) {
|
|
95
|
-
const dn = cfg.databaseNotifications
|
|
96
|
-
const notifiableType = dn.notifiableType ?? 'users'
|
|
97
|
-
const pageSize = dn.pageSize ?? 25
|
|
98
|
-
|
|
99
|
-
/** Resolve `{ id }` from the panel's user resolver. Returns null
|
|
100
|
-
* when no user / unknown id — every route then 401s. The user
|
|
101
|
-
* object is opaque to pilotiq; we duck-type `.id`. */
|
|
102
|
-
const resolveUserId = async (req: AppRequest): Promise<string | null> => {
|
|
103
|
-
const user = await pilotiq.resolveUser(req)
|
|
104
|
-
if (!user || typeof user !== 'object') return null
|
|
105
|
-
const id = (user as { id?: unknown }).id
|
|
106
|
-
if (id === undefined || id === null) return null
|
|
107
|
-
return String(id)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// GET ${base}/_notifications → { notifications, unreadCount }
|
|
111
|
-
router.get(`${base}/_notifications`, async (req, res) => {
|
|
112
|
-
const id = await resolveUserId(req)
|
|
113
|
-
if (id === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
|
|
114
|
-
const url = new URL(req.url ?? '/', 'http://localhost')
|
|
115
|
-
const unreadOnly = url.searchParams.get('unread') === 'true'
|
|
116
|
-
const limitRaw = Number(url.searchParams.get('limit') ?? pageSize)
|
|
117
|
-
const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? Math.min(limitRaw, 100) : pageSize
|
|
118
|
-
const data = await listDatabaseNotifications({
|
|
119
|
-
notifiableType,
|
|
120
|
-
notifiableId: id,
|
|
121
|
-
limit,
|
|
122
|
-
unreadOnly,
|
|
123
|
-
})
|
|
124
|
-
return res.json({ ok: true, ...data })
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
// POST ${base}/_notifications/:id/read
|
|
128
|
-
router.post(`${base}/_notifications/:id/read`, async (req, res) => {
|
|
129
|
-
const userId = await resolveUserId(req)
|
|
130
|
-
if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
|
|
131
|
-
const rowId = (req.params as Record<string, string | undefined>)['id'] ?? ''
|
|
132
|
-
const updated = await markDatabaseNotificationAsRead(rowId, {
|
|
133
|
-
notifiableType,
|
|
134
|
-
notifiableId: userId,
|
|
135
|
-
})
|
|
136
|
-
return res.json({ ok: updated })
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
// POST ${base}/_notifications/:id/unread
|
|
140
|
-
router.post(`${base}/_notifications/:id/unread`, async (req, res) => {
|
|
141
|
-
const userId = await resolveUserId(req)
|
|
142
|
-
if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
|
|
143
|
-
const rowId = (req.params as Record<string, string | undefined>)['id'] ?? ''
|
|
144
|
-
const updated = await markDatabaseNotificationAsUnread(rowId, {
|
|
145
|
-
notifiableType,
|
|
146
|
-
notifiableId: userId,
|
|
147
|
-
})
|
|
148
|
-
return res.json({ ok: updated })
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
// POST ${base}/_notifications/read-all
|
|
152
|
-
router.post(`${base}/_notifications/read-all`, async (req, res) => {
|
|
153
|
-
const userId = await resolveUserId(req)
|
|
154
|
-
if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
|
|
155
|
-
const count = await markAllDatabaseNotificationsAsRead({
|
|
156
|
-
notifiableType,
|
|
157
|
-
notifiableId: userId,
|
|
158
|
-
})
|
|
159
|
-
return res.json({ ok: true, count })
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
// POST ${base}/_notifications/:id/_action/:actionName
|
|
163
|
-
//
|
|
164
|
-
// Notification action dispatch — looks up the stored action on the
|
|
165
|
-
// row, resolves the named handler against the panel's
|
|
166
|
-
// `notificationHandlers` registry, and runs it with the row's
|
|
167
|
-
// stored payload. Optionally flips `read_at` server-side when the
|
|
168
|
-
// action carried `markAsRead: true`.
|
|
169
|
-
//
|
|
170
|
-
// Defends in depth: 404s on missing row / wrong owner / action
|
|
171
|
-
// missing / non-string handler / unknown registry name. Body is
|
|
172
|
-
// ignored — payload reads exclusively from the stored row, so a
|
|
173
|
-
// tampered client can't inject extra payload keys.
|
|
174
|
-
router.post(`${base}/_notifications/:id/_action/:actionName`, async (req, res) => {
|
|
175
|
-
const user = await pilotiq.resolveUser(req)
|
|
176
|
-
const userId = user && typeof user === 'object'
|
|
177
|
-
? ((user as { id?: unknown }).id !== undefined && (user as { id?: unknown }).id !== null
|
|
178
|
-
? String((user as { id: unknown }).id) : null)
|
|
179
|
-
: null
|
|
180
|
-
if (userId === null) { res.status(401); return res.json({ ok: false, error: 'Not authenticated' }) }
|
|
181
|
-
|
|
182
|
-
const params = (req.params as Record<string, string | undefined>)
|
|
183
|
-
const result = await dispatchNotificationAction(pilotiq, {
|
|
184
|
-
notificationId: params['id'] ?? '',
|
|
185
|
-
actionName: params['actionName'] ?? '',
|
|
186
|
-
notifiableType,
|
|
187
|
-
notifiableId: userId,
|
|
188
|
-
user,
|
|
189
|
-
request: req,
|
|
190
|
-
})
|
|
191
|
-
if (!result.ok) {
|
|
192
|
-
res.status(result.status)
|
|
193
|
-
return res.json({ ok: false, error: result.error })
|
|
194
|
-
}
|
|
195
|
-
return res.json(result)
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
// Phase 2 — register the broadcast auth callback for private
|
|
199
|
-
// `pilotiq-notifications.<userId>` channels. Soft-fails when
|
|
200
|
-
// `@rudderjs/broadcast` isn't installed; apps that haven't enabled
|
|
201
|
-
// broadcast on the toggle stay quiet either way.
|
|
202
|
-
void registerBroadcastAuth(pilotiq)
|
|
203
|
-
}
|
|
204
|
-
}
|