@pilotiq/pilotiq 0.24.1 → 0.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/boost/guidelines.md +566 -0
- package/boost/skills/pilotiq-fields/SKILL.md +47 -0
- package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
- package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
- package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
- package/boost/skills/pilotiq-relations/SKILL.md +47 -0
- package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
- package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
- package/boost/skills/pilotiq-resource/SKILL.md +61 -0
- package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
- package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
- package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
- package/package.json +6 -1
- package/.turbo/turbo-build.log +0 -8
- package/CLAUDE.md +0 -265
- package/src/Cluster.test.ts +0 -283
- package/src/Cluster.ts +0 -83
- package/src/Column.test.ts +0 -199
- package/src/Column.ts +0 -710
- package/src/Global.test.ts +0 -367
- package/src/Global.ts +0 -169
- package/src/Page.test.ts +0 -114
- package/src/Page.ts +0 -208
- package/src/Pilotiq.perf.test.ts +0 -252
- package/src/Pilotiq.test.ts +0 -129
- package/src/Pilotiq.ts +0 -1158
- package/src/PilotiqRegistry.ts +0 -36
- package/src/PilotiqServiceProvider.ts +0 -121
- package/src/RelationManager.test.ts +0 -400
- package/src/RelationManager.ts +0 -527
- package/src/RenderHook.test.ts +0 -252
- package/src/RenderHook.ts +0 -242
- package/src/Resource.test.ts +0 -284
- package/src/Resource.ts +0 -526
- package/src/RightPanel.test.ts +0 -202
- package/src/RightPanel.ts +0 -132
- package/src/Tab.test.ts +0 -91
- package/src/Tab.ts +0 -156
- package/src/UserMenuItem.ts +0 -145
- package/src/actions/Action.test.ts +0 -2526
- package/src/actions/Action.ts +0 -1515
- package/src/actions/ActionGroup.test.ts +0 -112
- package/src/actions/ActionGroup.ts +0 -173
- package/src/actions/attachFactory.ts +0 -172
- package/src/actions/bulkFactories.ts +0 -168
- package/src/actions/crudFactories.ts +0 -220
- package/src/actions/exportFactory.ts +0 -225
- package/src/actions/factoryHelpers.ts +0 -177
- package/src/actions/importFactory.ts +0 -243
- package/src/actions/index.ts +0 -17
- package/src/actions/m2mFactories.ts +0 -193
- package/src/actions/relationFactories.ts +0 -372
- package/src/applyPageHooks.test.ts +0 -463
- package/src/applyPageHooks.ts +0 -330
- package/src/authorization.test.ts +0 -483
- package/src/breadcrumbs.test.ts +0 -238
- package/src/cells/coerce.test.ts +0 -85
- package/src/cells/coerce.ts +0 -84
- package/src/clusterPaths.ts +0 -35
- package/src/columns/BadgeColumn.test.ts +0 -54
- package/src/columns/BadgeColumn.ts +0 -32
- package/src/columns/BooleanColumn.test.ts +0 -41
- package/src/columns/BooleanColumn.ts +0 -18
- package/src/columns/ColorColumn.test.ts +0 -37
- package/src/columns/ColorColumn.ts +0 -38
- package/src/columns/IconColumn.test.ts +0 -54
- package/src/columns/IconColumn.ts +0 -37
- package/src/columns/ImageColumn.test.ts +0 -41
- package/src/columns/ImageColumn.ts +0 -28
- package/src/columns/SelectColumn.ts +0 -98
- package/src/columns/TextColumn.test.ts +0 -190
- package/src/columns/TextColumn.ts +0 -20
- package/src/columns/TextInputColumn.ts +0 -68
- package/src/columns/ToggleColumn.ts +0 -46
- package/src/columns/editableColumns.test.ts +0 -238
- package/src/columns/index.ts +0 -9
- package/src/defaultGlobalPages.ts +0 -95
- package/src/defaultPages.test.ts +0 -634
- package/src/defaultPages.ts +0 -617
- package/src/defaultViewPage.test.ts +0 -147
- package/src/elements/Form.test.ts +0 -223
- package/src/elements/Form.ts +0 -416
- package/src/elements/ListTabs.ts +0 -28
- package/src/elements/Table.test.ts +0 -422
- package/src/elements/Table.ts +0 -850
- package/src/elements/TableGroup.test.ts +0 -260
- package/src/elements/TableGroup.ts +0 -334
- package/src/elements/dispatchAction.test.ts +0 -463
- package/src/elements/dispatchAction.ts +0 -355
- package/src/elements/dispatchForm.test.ts +0 -477
- package/src/elements/dispatchForm.ts +0 -1993
- package/src/elements/dispatchTable.test.ts +0 -1514
- package/src/elements/dispatchTable.ts +0 -745
- package/src/elements/index.ts +0 -21
- package/src/entries/BadgeEntry.ts +0 -39
- package/src/entries/CodeEntry.test.ts +0 -40
- package/src/entries/CodeEntry.ts +0 -52
- package/src/entries/ColorEntry.ts +0 -63
- package/src/entries/ComponentEntry.test.ts +0 -173
- package/src/entries/ComponentEntry.ts +0 -95
- package/src/entries/Entry.ts +0 -304
- package/src/entries/IconEntry.ts +0 -49
- package/src/entries/ImageEntry.ts +0 -61
- package/src/entries/KeyValueEntry.ts +0 -47
- package/src/entries/RepeatableEntry.test.ts +0 -239
- package/src/entries/RepeatableEntry.ts +0 -173
- package/src/entries/TextEntry.test.ts +0 -394
- package/src/entries/TextEntry.ts +0 -60
- package/src/entries/index.ts +0 -12
- package/src/entries/leaves.test.ts +0 -306
- package/src/entries/registry.ts +0 -54
- package/src/fields/BuilderField.test.ts +0 -1188
- package/src/fields/BuilderField.ts +0 -605
- package/src/fields/BuilderRelationship.test.ts +0 -811
- package/src/fields/CheckboxField.test.ts +0 -44
- package/src/fields/CheckboxField.ts +0 -27
- package/src/fields/CheckboxListField.test.ts +0 -99
- package/src/fields/CheckboxListField.ts +0 -66
- package/src/fields/ColorPickerField.test.ts +0 -33
- package/src/fields/ColorPickerField.ts +0 -25
- package/src/fields/DateField.ts +0 -54
- package/src/fields/DateTimeField.test.ts +0 -55
- package/src/fields/EmailField.ts +0 -16
- package/src/fields/Field.test.ts +0 -654
- package/src/fields/Field.ts +0 -817
- package/src/fields/FileUploadField.test.ts +0 -143
- package/src/fields/FileUploadField.ts +0 -159
- package/src/fields/HiddenField.test.ts +0 -27
- package/src/fields/HiddenField.ts +0 -28
- package/src/fields/KeyValueField.test.ts +0 -105
- package/src/fields/KeyValueField.ts +0 -55
- package/src/fields/MarkdownField.test.ts +0 -167
- package/src/fields/MarkdownField.ts +0 -162
- package/src/fields/NumberField.ts +0 -33
- package/src/fields/RadioField.test.ts +0 -94
- package/src/fields/RadioField.ts +0 -67
- package/src/fields/RepeaterField.test.ts +0 -1806
- package/src/fields/RepeaterField.ts +0 -939
- package/src/fields/RepeaterRelationship.test.ts +0 -1923
- package/src/fields/RepeaterSimple.test.ts +0 -248
- package/src/fields/RowButton.test.ts +0 -219
- package/src/fields/RowButton.ts +0 -135
- package/src/fields/SelectField.test.ts +0 -192
- package/src/fields/SelectField.ts +0 -235
- package/src/fields/SliderField.test.ts +0 -50
- package/src/fields/SliderField.ts +0 -53
- package/src/fields/SlugField.ts +0 -24
- package/src/fields/TagsInputField.test.ts +0 -154
- package/src/fields/TagsInputField.ts +0 -133
- package/src/fields/TextField.test.ts +0 -213
- package/src/fields/TextField.ts +0 -177
- package/src/fields/TextareaField.test.ts +0 -58
- package/src/fields/TextareaField.ts +0 -59
- package/src/fields/ToggleButtonsField.test.ts +0 -106
- package/src/fields/ToggleButtonsField.ts +0 -59
- package/src/fields/ToggleField.ts +0 -16
- package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
- package/src/fields/optionsResolver.ts +0 -95
- package/src/fields/resolveField.ts +0 -28
- package/src/filters/BooleanFilter.ts +0 -35
- package/src/filters/DateRangeFilter.test.ts +0 -194
- package/src/filters/DateRangeFilter.ts +0 -148
- package/src/filters/Filter.test.ts +0 -268
- package/src/filters/Filter.ts +0 -184
- package/src/filters/FormFilter.test.ts +0 -238
- package/src/filters/FormFilter.ts +0 -215
- package/src/filters/MultiSelectFilter.test.ts +0 -119
- package/src/filters/MultiSelectFilter.ts +0 -78
- package/src/filters/QueryBuilderFilter.test.ts +0 -662
- package/src/filters/QueryBuilderFilter.ts +0 -398
- package/src/filters/SelectFilter.ts +0 -46
- package/src/filters/TernaryFilter.test.ts +0 -160
- package/src/filters/TernaryFilter.ts +0 -72
- package/src/filters/TrashedFilter.test.ts +0 -149
- package/src/filters/TrashedFilter.ts +0 -55
- package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
- package/src/filters/queryBuilder/Constraint.ts +0 -115
- package/src/filters/queryBuilder/DateConstraint.ts +0 -69
- package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
- package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
- package/src/filters/queryBuilder/TextConstraint.ts +0 -64
- package/src/filters/queryBuilder/index.ts +0 -12
- package/src/icons/index.ts +0 -2
- package/src/icons/lucide.ts +0 -204
- package/src/icons/registry.test.ts +0 -56
- package/src/icons/registry.ts +0 -41
- package/src/icons/types.ts +0 -47
- package/src/index.ts +0 -525
- package/src/io/csv.test.ts +0 -142
- package/src/io/csv.ts +0 -170
- package/src/nestedRelationManagerData.test.ts +0 -547
- package/src/notifications/Notification.test.ts +0 -210
- package/src/notifications/Notification.ts +0 -354
- package/src/notifications/broadcast.test.ts +0 -110
- package/src/notifications/broadcast.ts +0 -95
- package/src/notifications/database.test.ts +0 -383
- package/src/notifications/database.ts +0 -398
- package/src/notifications/databaseNotifications.test.ts +0 -187
- package/src/notifications/dispatchNotificationAction.test.ts +0 -341
- package/src/notifications/dispatchNotificationAction.ts +0 -142
- package/src/notifications/flash.test.ts +0 -89
- package/src/notifications/flash.ts +0 -71
- package/src/notifications/index.ts +0 -45
- package/src/notifications/registerBroadcastAuth.test.ts +0 -134
- package/src/notifications/registerBroadcastAuth.ts +0 -100
- package/src/notifications/resolveSavedNotification.test.ts +0 -82
- package/src/notifications/resolveSavedNotification.ts +0 -59
- package/src/notifications/types.ts +0 -93
- package/src/orm/m2mAccessor.ts +0 -66
- package/src/orm/modelDefaults.test.ts +0 -633
- package/src/orm/modelDefaults.ts +0 -666
- package/src/pageData/breadcrumbs.ts +0 -288
- package/src/pageData/forms.ts +0 -578
- package/src/pageData/helpers.ts +0 -857
- package/src/pageData/misc.ts +0 -347
- package/src/pageData/navigation.ts +0 -842
- package/src/pageData/relationPages.ts +0 -1248
- package/src/pageData/relationTabs.ts +0 -286
- package/src/pageData/resourcePages.ts +0 -609
- package/src/pageData.test.ts +0 -1545
- package/src/pageData.ts +0 -341
- package/src/plugins/index.ts +0 -8
- package/src/plugins/themeEditor.test.ts +0 -36
- package/src/plugins/themeEditor.ts +0 -45
- package/src/react/AppShell.tsx +0 -251
- package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
- package/src/react/CollabRoomContext.ts +0 -98
- package/src/react/CollabTextRendererRegistry.ts +0 -102
- package/src/react/CommandPalette.tsx +0 -375
- package/src/react/CurrentUserContext.tsx +0 -50
- package/src/react/CustomPageWrapperGate.tsx +0 -69
- package/src/react/CustomPageWrapperRegistry.ts +0 -45
- package/src/react/FieldFocusReporterRegistry.ts +0 -37
- package/src/react/FieldLabelSlotRegistry.ts +0 -30
- package/src/react/FieldPresenceRegistry.ts +0 -46
- package/src/react/FormCollabBindingRegistry.ts +0 -242
- package/src/react/FormStateContext.tsx +0 -591
- package/src/react/HeadHooks.tsx +0 -126
- package/src/react/MarkdownEditorRegistry.test.ts +0 -38
- package/src/react/MarkdownEditorRegistry.ts +0 -107
- package/src/react/NotificationActionStrip.tsx +0 -263
- package/src/react/NotificationBell.tsx +0 -426
- package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
- package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
- package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
- package/src/react/PendingSuggestionsContext.tsx +0 -172
- package/src/react/RecordWrapperGate.tsx +0 -58
- package/src/react/RecordWrapperRegistry.ts +0 -39
- package/src/react/RenderHookSlot.tsx +0 -32
- package/src/react/RightSidebar.tsx +0 -257
- package/src/react/RightSidebarContext.tsx +0 -234
- package/src/react/RightSidebarTrigger.tsx +0 -53
- package/src/react/RowCoordsContext.tsx +0 -23
- package/src/react/SchemaRenderer.tsx +0 -549
- package/src/react/SearchTrigger.tsx +0 -46
- package/src/react/ThemeProvider.tsx +0 -93
- package/src/react/ThemeSettingsPage.tsx +0 -579
- package/src/react/ThemeToggle.tsx +0 -20
- package/src/react/Toaster.tsx +0 -158
- package/src/react/UserMenu.tsx +0 -196
- package/src/react/WidgetDataContext.tsx +0 -157
- package/src/react/cells/EditableCell.tsx +0 -389
- package/src/react/component-slots.test.ts +0 -103
- package/src/react/component-slots.ts +0 -116
- package/src/react/fieldJsHandler.test.ts +0 -166
- package/src/react/fieldJsHandler.ts +0 -79
- package/src/react/fields/BuilderInput.tsx +0 -1078
- package/src/react/fields/CheckboxInput.tsx +0 -39
- package/src/react/fields/CheckboxListInput.tsx +0 -102
- package/src/react/fields/ColorInput.tsx +0 -71
- package/src/react/fields/DateFieldInput.tsx +0 -70
- package/src/react/fields/DateTimeInput.tsx +0 -62
- package/src/react/fields/FieldShell.tsx +0 -348
- package/src/react/fields/FileUploadInput.tsx +0 -639
- package/src/react/fields/HiddenInput.tsx +0 -17
- package/src/react/fields/KeyValueInput.tsx +0 -230
- package/src/react/fields/MarkdownInput.tsx +0 -560
- package/src/react/fields/RadioInput.tsx +0 -81
- package/src/react/fields/RepeaterInput.test.ts +0 -116
- package/src/react/fields/RepeaterInput.tsx +0 -1420
- package/src/react/fields/SelectFieldInput.tsx +0 -280
- package/src/react/fields/SliderInput.tsx +0 -81
- package/src/react/fields/TagsInput.tsx +0 -283
- package/src/react/fields/TextLikeInput.tsx +0 -256
- package/src/react/fields/ToggleButtonsInput.tsx +0 -60
- package/src/react/fields/ToggleFieldInput.tsx +0 -56
- package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
- package/src/react/fields/relationshipRenameDispatch.ts +0 -97
- package/src/react/fields/repeaterReconcile.test.ts +0 -114
- package/src/react/fields/repeaterReconcile.ts +0 -104
- package/src/react/fields/rowChromeButton.tsx +0 -336
- package/src/react/fields/rowState.ts +0 -106
- package/src/react/fields/syncRowGates.test.ts +0 -202
- package/src/react/fields/syncRowGates.ts +0 -66
- package/src/react/fields/textInputControls.tsx +0 -238
- package/src/react/fields/useRowReorderDnd.ts +0 -78
- package/src/react/formStateHelpers.test.ts +0 -508
- package/src/react/formStateHelpers.ts +0 -381
- package/src/react/hooks/use-mobile.ts +0 -19
- package/src/react/icon-context.tsx +0 -60
- package/src/react/index.ts +0 -194
- package/src/react/layouts/SidebarLayout.tsx +0 -250
- package/src/react/layouts/TopbarLayout.tsx +0 -258
- package/src/react/navigate.tsx +0 -37
- package/src/react/onProviderSynced.test.ts +0 -90
- package/src/react/parseRecordEditUrl.test.ts +0 -122
- package/src/react/parseRecordEditUrl.ts +0 -94
- package/src/react/persistedState.ts +0 -40
- package/src/react/registry.ts +0 -48
- package/src/react/right-panel-registry.tsx +0 -47
- package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
- package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
- package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
- package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
- package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
- package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
- package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
- package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
- package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
- package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
- package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
- package/src/react/schemaRenderer/action/buttons.tsx +0 -99
- package/src/react/schemaRenderer/action/helpers.ts +0 -140
- package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
- package/src/react/schemaRenderer/columnFormat.ts +0 -65
- package/src/react/schemaRenderer/constants.ts +0 -50
- package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
- package/src/react/schemaRenderer/form/renderField.tsx +0 -511
- package/src/react/schemaRenderer/helpers.tsx +0 -81
- package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
- package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
- package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
- package/src/react/schemaRenderer/table/filters.tsx +0 -1233
- package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
- package/src/react/schemaRenderer/table/links.tsx +0 -112
- package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
- package/src/react/schemaRenderer/table/url.tsx +0 -143
- package/src/react/theme-preview/apply.ts +0 -99
- package/src/react/theme-preview/build-html.ts +0 -436
- package/src/react/ui/button.tsx +0 -51
- package/src/react/ui/calendar.tsx +0 -67
- package/src/react/ui/checkbox.tsx +0 -29
- package/src/react/ui/dialog.tsx +0 -108
- package/src/react/ui/dropdown-menu.tsx +0 -97
- package/src/react/ui/input.tsx +0 -20
- package/src/react/ui/label.tsx +0 -21
- package/src/react/ui/popover.tsx +0 -50
- package/src/react/ui/select.tsx +0 -169
- package/src/react/ui/separator.tsx +0 -25
- package/src/react/ui/sheet.tsx +0 -136
- package/src/react/ui/sidebar.tsx +0 -723
- package/src/react/ui/skeleton.tsx +0 -13
- package/src/react/ui/slider.tsx +0 -34
- package/src/react/ui/switch.tsx +0 -28
- package/src/react/ui/table.tsx +0 -105
- package/src/react/ui/tabs.tsx +0 -63
- package/src/react/ui/textarea.tsx +0 -18
- package/src/react/ui/tooltip.tsx +0 -64
- package/src/react/useResizableWidth.ts +0 -139
- package/src/react/utils.ts +0 -6
- package/src/react/widgetRegistry.test.ts +0 -43
- package/src/react/widgetRegistry.ts +0 -50
- package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
- package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
- package/src/react/widgets/ViewRenderer.tsx +0 -71
- package/src/relationManagerData.test.ts +0 -1595
- package/src/richtext/index.ts +0 -8
- package/src/richtext/registry.ts +0 -89
- package/src/routes/globals.ts +0 -148
- package/src/routes/guard.test.ts +0 -325
- package/src/routes/helpers.ts +0 -704
- package/src/routes/pages.ts +0 -175
- package/src/routes/panel.ts +0 -204
- package/src/routes/relations.ts +0 -1243
- package/src/routes/resources.ts +0 -781
- package/src/routes/theme.ts +0 -91
- package/src/routes-nested-relations.test.ts +0 -676
- package/src/routes-relations.test.ts +0 -972
- package/src/routes.test.ts +0 -2027
- package/src/routes.ts +0 -303
- package/src/schema/Alert.test.ts +0 -109
- package/src/schema/Alert.ts +0 -131
- package/src/schema/Block.ts +0 -169
- package/src/schema/Breadcrumbs.ts +0 -40
- package/src/schema/Card.ts +0 -35
- package/src/schema/Divider.ts +0 -20
- package/src/schema/Element.ts +0 -219
- package/src/schema/EmptyState.test.ts +0 -37
- package/src/schema/EmptyState.ts +0 -63
- package/src/schema/Fieldset.ts +0 -43
- package/src/schema/Grid.ts +0 -43
- package/src/schema/Group.ts +0 -30
- package/src/schema/Heading.ts +0 -39
- package/src/schema/Html.ts +0 -67
- package/src/schema/Icon.ts +0 -54
- package/src/schema/Image.ts +0 -57
- package/src/schema/LinkTag.ts +0 -41
- package/src/schema/Markdown.ts +0 -85
- package/src/schema/MetaTag.ts +0 -41
- package/src/schema/RelationTabs.ts +0 -71
- package/src/schema/ScriptTag.ts +0 -55
- package/src/schema/Section.ts +0 -160
- package/src/schema/ServerDataElement.test.ts +0 -140
- package/src/schema/ServerDataElement.ts +0 -156
- package/src/schema/SlotComponent.test.ts +0 -77
- package/src/schema/SlotComponent.ts +0 -71
- package/src/schema/Split.ts +0 -50
- package/src/schema/Stat.test.ts +0 -118
- package/src/schema/Stat.ts +0 -154
- package/src/schema/StatsOverview.test.ts +0 -141
- package/src/schema/StatsOverview.ts +0 -119
- package/src/schema/StyleTag.ts +0 -35
- package/src/schema/TableWidget.test.ts +0 -297
- package/src/schema/TableWidget.ts +0 -289
- package/src/schema/Tabs.ts +0 -79
- package/src/schema/Text.ts +0 -58
- package/src/schema/UnorderedList.ts +0 -49
- package/src/schema/View.test.ts +0 -111
- package/src/schema/View.ts +0 -127
- package/src/schema/Wizard.ts +0 -220
- package/src/schema/containers.test.ts +0 -564
- package/src/schema/headTags.test.ts +0 -134
- package/src/schema/index.ts +0 -40
- package/src/schema/primes.test.ts +0 -269
- package/src/schema/resolveSchema.test.ts +0 -379
- package/src/schema/resolveSchema.ts +0 -917
- package/src/schema/sanitize.ts +0 -58
- package/src/search.test.ts +0 -446
- package/src/search.ts +0 -178
- package/src/sessionFilters.test.ts +0 -375
- package/src/sessionFilters.ts +0 -143
- package/src/slot-components/index.ts +0 -10
- package/src/slot-components/registry.ts +0 -56
- package/src/styles/file-upload.css +0 -13
- package/src/summarizers/Summarizer.test.ts +0 -84
- package/src/summarizers/Summarizer.ts +0 -123
- package/src/summarizers/index.ts +0 -11
- package/src/theme/base-colors.ts +0 -68
- package/src/theme/chart-colors.ts +0 -50
- package/src/theme/colors.ts +0 -447
- package/src/theme/generate-css.test.ts +0 -139
- package/src/theme/generate-css.ts +0 -44
- package/src/theme/generate-scale.test.ts +0 -106
- package/src/theme/generate-scale.ts +0 -97
- package/src/theme/icon-map.ts +0 -42
- package/src/theme/index.ts +0 -34
- package/src/theme/migrate.test.ts +0 -178
- package/src/theme/migrate.ts +0 -81
- package/src/theme/presets.ts +0 -135
- package/src/theme/radius.ts +0 -18
- package/src/theme/resolve.test.ts +0 -238
- package/src/theme/resolve.ts +0 -96
- package/src/theme/spacing.ts +0 -18
- package/src/theme/storage.test.ts +0 -126
- package/src/theme/storage.ts +0 -106
- package/src/theme/theme-colors.ts +0 -88
- package/src/theme/types.ts +0 -125
- package/src/uploads/UploadAdapter.ts +0 -35
- package/src/uploads/index.ts +0 -2
- package/src/uploads/localUpload.test.ts +0 -70
- package/src/uploads/localUpload.ts +0 -84
- package/src/validation/Validator.ts +0 -49
- package/src/validation/index.ts +0 -28
- package/src/validation/rules.ts +0 -78
- package/src/validation/runValidators.ts +0 -435
- package/src/validation/uniqueValidator.test.ts +0 -196
- package/src/validation/uniqueValidator.ts +0 -133
- package/src/validation/validators.test.ts +0 -268
- package/src/vite.test.ts +0 -184
- package/src/vite.ts +0 -787
- package/src/widgets/index.ts +0 -10
- package/src/widgets/registry.ts +0 -45
- package/src/widgets.test.ts +0 -592
- package/tsconfig.build.json +0 -11
- package/tsconfig.json +0 -4
- package/tsconfig.test.json +0 -10
- package/views/react/Dashboard.tsx +0 -27
- package/views/react/Resources/Form.tsx +0 -102
- package/views/react/Resources/Index.tsx +0 -49
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Boot-time broadcast auth registration — unit tests. Uses the
|
|
3
|
-
* `_setTestBroadcastAuth` seam to inject a fake `@rudderjs/broadcast`
|
|
4
|
-
* module so we can capture the (pattern, callback) pair pilotiq registers
|
|
5
|
-
* and assert the auth callback's gating logic.
|
|
6
|
-
*/
|
|
7
|
-
import { describe, it, afterEach } from 'node:test'
|
|
8
|
-
import assert from 'node:assert/strict'
|
|
9
|
-
|
|
10
|
-
import { Pilotiq } from '../Pilotiq.js'
|
|
11
|
-
import {
|
|
12
|
-
registerBroadcastAuth,
|
|
13
|
-
_setTestBroadcastAuth,
|
|
14
|
-
} from './registerBroadcastAuth.js'
|
|
15
|
-
|
|
16
|
-
type AuthCallback = (
|
|
17
|
-
req: { headers: Record<string, string | string[] | undefined>; url: string; token?: string },
|
|
18
|
-
channel: string,
|
|
19
|
-
) => Promise<boolean | Record<string, unknown>>
|
|
20
|
-
|
|
21
|
-
function makeFakeBroadcast() {
|
|
22
|
-
const registrations: { pattern: string; callback: AuthCallback }[] = []
|
|
23
|
-
return {
|
|
24
|
-
registrations,
|
|
25
|
-
mod: {
|
|
26
|
-
registerAuth(pattern: string, callback: AuthCallback) {
|
|
27
|
-
registrations.push({ pattern, callback })
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe('registerBroadcastAuth()', () => {
|
|
34
|
-
afterEach(() => _setTestBroadcastAuth(undefined))
|
|
35
|
-
|
|
36
|
-
it('no-ops when databaseNotifications() wasn\'t called', async () => {
|
|
37
|
-
const fake = makeFakeBroadcast()
|
|
38
|
-
_setTestBroadcastAuth(fake.mod)
|
|
39
|
-
await registerBroadcastAuth(Pilotiq.make('a'))
|
|
40
|
-
assert.equal(fake.registrations.length, 0)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('no-ops when broadcast wasn\'t enabled', async () => {
|
|
44
|
-
const fake = makeFakeBroadcast()
|
|
45
|
-
_setTestBroadcastAuth(fake.mod)
|
|
46
|
-
const p = Pilotiq.make('a').databaseNotifications()
|
|
47
|
-
await registerBroadcastAuth(p)
|
|
48
|
-
assert.equal(fake.registrations.length, 0)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('no-ops when @rudderjs/broadcast is unavailable', async () => {
|
|
52
|
-
_setTestBroadcastAuth(null)
|
|
53
|
-
const p = Pilotiq.make('a')
|
|
54
|
-
.databaseNotifications()
|
|
55
|
-
.databaseNotificationsBroadcast()
|
|
56
|
-
await registerBroadcastAuth(p)
|
|
57
|
-
// No throw == soft-fail OK
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('registers the private-pilotiq-notifications.* pattern', async () => {
|
|
61
|
-
const fake = makeFakeBroadcast()
|
|
62
|
-
_setTestBroadcastAuth(fake.mod)
|
|
63
|
-
const p = Pilotiq.make('a')
|
|
64
|
-
.databaseNotifications()
|
|
65
|
-
.databaseNotificationsBroadcast()
|
|
66
|
-
await registerBroadcastAuth(p)
|
|
67
|
-
assert.equal(fake.registrations.length, 1)
|
|
68
|
-
assert.equal(fake.registrations[0]!.pattern, 'private-pilotiq-notifications.*')
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('auth callback returns true when the user.id matches the channel id', async () => {
|
|
72
|
-
const fake = makeFakeBroadcast()
|
|
73
|
-
_setTestBroadcastAuth(fake.mod)
|
|
74
|
-
const p = Pilotiq.make('a')
|
|
75
|
-
.user(() => ({ id: 42, name: 'Sue' }))
|
|
76
|
-
.databaseNotifications()
|
|
77
|
-
.databaseNotificationsBroadcast()
|
|
78
|
-
await registerBroadcastAuth(p)
|
|
79
|
-
const cb = fake.registrations[0]!.callback
|
|
80
|
-
const result = await cb(
|
|
81
|
-
{ headers: {}, url: '/ws' },
|
|
82
|
-
'private-pilotiq-notifications.42',
|
|
83
|
-
)
|
|
84
|
-
assert.equal(result, true)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('auth callback returns false on user-id mismatch', async () => {
|
|
88
|
-
const fake = makeFakeBroadcast()
|
|
89
|
-
_setTestBroadcastAuth(fake.mod)
|
|
90
|
-
const p = Pilotiq.make('a')
|
|
91
|
-
.user(() => ({ id: 42 }))
|
|
92
|
-
.databaseNotifications()
|
|
93
|
-
.databaseNotificationsBroadcast()
|
|
94
|
-
await registerBroadcastAuth(p)
|
|
95
|
-
const cb = fake.registrations[0]!.callback
|
|
96
|
-
const result = await cb(
|
|
97
|
-
{ headers: {}, url: '/ws' },
|
|
98
|
-
'private-pilotiq-notifications.7',
|
|
99
|
-
)
|
|
100
|
-
assert.equal(result, false)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('auth callback returns false when no user resolves', async () => {
|
|
104
|
-
const fake = makeFakeBroadcast()
|
|
105
|
-
_setTestBroadcastAuth(fake.mod)
|
|
106
|
-
const p = Pilotiq.make('a')
|
|
107
|
-
.user(() => null)
|
|
108
|
-
.databaseNotifications()
|
|
109
|
-
.databaseNotificationsBroadcast()
|
|
110
|
-
await registerBroadcastAuth(p)
|
|
111
|
-
const cb = fake.registrations[0]!.callback
|
|
112
|
-
const result = await cb(
|
|
113
|
-
{ headers: {}, url: '/ws' },
|
|
114
|
-
'private-pilotiq-notifications.42',
|
|
115
|
-
)
|
|
116
|
-
assert.equal(result, false)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('auth callback returns false when channel name is malformed', async () => {
|
|
120
|
-
const fake = makeFakeBroadcast()
|
|
121
|
-
_setTestBroadcastAuth(fake.mod)
|
|
122
|
-
const p = Pilotiq.make('a')
|
|
123
|
-
.user(() => ({ id: 1 }))
|
|
124
|
-
.databaseNotifications()
|
|
125
|
-
.databaseNotificationsBroadcast()
|
|
126
|
-
await registerBroadcastAuth(p)
|
|
127
|
-
const cb = fake.registrations[0]!.callback
|
|
128
|
-
const result = await cb(
|
|
129
|
-
{ headers: {}, url: '/ws' },
|
|
130
|
-
'private-other-thing.1',
|
|
131
|
-
)
|
|
132
|
-
assert.equal(result, false)
|
|
133
|
-
})
|
|
134
|
-
})
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Broadcast auth-callback registration. Runs once at panel boot when
|
|
3
|
-
* `Pilotiq.databaseNotifications({ broadcast: true })` is set; gates
|
|
4
|
-
* subscriptions to `private-pilotiq-notifications.${userId}` on the
|
|
5
|
-
* current user resolving to `userId`.
|
|
6
|
-
*
|
|
7
|
-
* Idempotent — calling twice for the same panel only registers once
|
|
8
|
-
* (the broadcast auth registry stores by pattern, so re-registration
|
|
9
|
-
* would just overwrite with the same callback). The pattern is namespaced
|
|
10
|
-
* by panel base-path so two panels in one app don't fight over the same
|
|
11
|
-
* registration slot.
|
|
12
|
-
*
|
|
13
|
-
* `@rudderjs/broadcast` is soft-imported via variable-string indirection
|
|
14
|
-
* so pilotiq stays zero-dep on broadcast — apps that don't enable
|
|
15
|
-
* broadcast don't need the package installed.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { Pilotiq } from '../Pilotiq.js'
|
|
19
|
-
|
|
20
|
-
/** Mirror of `@rudderjs/broadcast`'s `BroadcastAuthRequest` — copied to
|
|
21
|
-
* avoid a hard import dependency. We use a structural subset; broadcast
|
|
22
|
-
* passes the full object through but we only consume `headers` + `url`. */
|
|
23
|
-
interface BroadcastAuthRequest {
|
|
24
|
-
headers: Record<string, string | string[] | undefined>
|
|
25
|
-
url: string
|
|
26
|
-
token?: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface BroadcastModule {
|
|
30
|
-
registerAuth?(
|
|
31
|
-
pattern: string,
|
|
32
|
-
callback: (req: BroadcastAuthRequest, channel: string) => Promise<boolean | Record<string, unknown>>,
|
|
33
|
-
): void
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let _testModule: BroadcastModule | null | 'unset' = 'unset'
|
|
37
|
-
|
|
38
|
-
/** Register the auth callback for `private-pilotiq-notifications.*`.
|
|
39
|
-
* Soft-fails when `@rudderjs/broadcast` isn't installed.
|
|
40
|
-
*
|
|
41
|
-
* The auth callback receives a synthetic request — the WebSocket
|
|
42
|
-
* upgrade carries cookies / Authorization headers but lacks the rudder
|
|
43
|
-
* request shape pilotiq's user resolver expects. We pass the original
|
|
44
|
-
* upgrade headers + url through under the same `req` key the resolver
|
|
45
|
-
* reads from; apps using `@rudderjs/auth` see cookies and resolve as
|
|
46
|
-
* usual. Apps that need the raw Hono context can read it from the
|
|
47
|
-
* `headers` object. */
|
|
48
|
-
export async function registerBroadcastAuth(pilotiq: Pilotiq): Promise<void> {
|
|
49
|
-
const cfg = pilotiq.getConfig()
|
|
50
|
-
if (!cfg.databaseNotifications?.enabled) return
|
|
51
|
-
if (!cfg.databaseNotifications.broadcast) return
|
|
52
|
-
|
|
53
|
-
const mod = await loadBroadcast()
|
|
54
|
-
if (!mod?.registerAuth) return
|
|
55
|
-
|
|
56
|
-
// Pattern matches every `private-pilotiq-notifications.<id>` channel.
|
|
57
|
-
// Wildcard `*` is the broadcast package's single-segment match — fine
|
|
58
|
-
// for numeric / uuid-style ids.
|
|
59
|
-
mod.registerAuth('private-pilotiq-notifications.*', async (req, channel) => {
|
|
60
|
-
const expectedId = parseChannelUserId(channel)
|
|
61
|
-
if (expectedId === null) return false
|
|
62
|
-
// Pilotiq's user resolver takes "the request" and returns a user
|
|
63
|
-
// object. The broadcast upgrade-req carries headers but not the full
|
|
64
|
-
// rudder request shape — apps using `@rudderjs/auth` read from
|
|
65
|
-
// `req.headers.cookie` so this works for the common case. For custom
|
|
66
|
-
// resolvers that read deeper request state, register your own
|
|
67
|
-
// callback before pilotiq's via `Broadcast.channel(...)`.
|
|
68
|
-
const user = await pilotiq.resolveUser(req)
|
|
69
|
-
if (!user || typeof user !== 'object') return false
|
|
70
|
-
const id = (user as { id?: unknown }).id
|
|
71
|
-
if (id === undefined || id === null) return false
|
|
72
|
-
return String(id) === expectedId
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function parseChannelUserId(channel: string): string | null {
|
|
77
|
-
const prefix = 'private-pilotiq-notifications.'
|
|
78
|
-
if (!channel.startsWith(prefix)) return null
|
|
79
|
-
const id = channel.slice(prefix.length)
|
|
80
|
-
return id === '' ? null : id
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function loadBroadcast(): Promise<BroadcastModule | null> {
|
|
84
|
-
if (_testModule !== 'unset') return _testModule
|
|
85
|
-
const moduleName = '@rudderjs/broadcast'
|
|
86
|
-
try {
|
|
87
|
-
const mod = await import(/* @vite-ignore */ moduleName) as Partial<BroadcastModule>
|
|
88
|
-
if (typeof mod.registerAuth !== 'function') return null
|
|
89
|
-
return mod as BroadcastModule
|
|
90
|
-
} catch {
|
|
91
|
-
return null
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** @internal — test seam; injects a fake `@rudderjs/broadcast` module
|
|
96
|
-
* so we can assert the pattern + callback shape without spinning up a
|
|
97
|
-
* real WebSocket server. */
|
|
98
|
-
export function _setTestBroadcastAuth(mod: BroadcastModule | null | undefined): void {
|
|
99
|
-
_testModule = mod === undefined ? 'unset' : mod
|
|
100
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import { Form } from '../elements/Form.js'
|
|
5
|
-
import { Notification, _resetNotificationIdSeq } from './Notification.js'
|
|
6
|
-
import { resolveSavedNotification } from './resolveSavedNotification.js'
|
|
7
|
-
|
|
8
|
-
describe('resolveSavedNotification', () => {
|
|
9
|
-
beforeEach(() => _resetNotificationIdSeq())
|
|
10
|
-
|
|
11
|
-
it('returns null when nothing is configured', () => {
|
|
12
|
-
const form = Form.make<{ id: number }>()
|
|
13
|
-
const got = resolveSavedNotification(form, 'create', { id: 1 }, { values: {} })
|
|
14
|
-
assert.equal(got, null)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('disableSavedNotification beats every other spec', () => {
|
|
18
|
-
const form = Form.make<{ id: number }>()
|
|
19
|
-
.savedNotification('Saved')
|
|
20
|
-
.createdNotification('Created')
|
|
21
|
-
.disableSavedNotification()
|
|
22
|
-
const got = resolveSavedNotification(form, 'create', { id: 1 }, { values: {} })
|
|
23
|
-
assert.equal(got, null)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('string spec produces a success notification with that title', () => {
|
|
27
|
-
const form = Form.make<{ id: number }>().savedNotification('Saved')
|
|
28
|
-
const got = resolveSavedNotification(form, 'update', { id: 1 }, { values: {} })
|
|
29
|
-
assert.ok(got)
|
|
30
|
-
assert.equal(got!.type, 'success')
|
|
31
|
-
assert.equal(got!.title, 'Saved')
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('mode-specific createdNotification wins over savedNotification in create mode', () => {
|
|
35
|
-
const form = Form.make<{ id: number }>()
|
|
36
|
-
.savedNotification('Saved')
|
|
37
|
-
.createdNotification('Created')
|
|
38
|
-
const got = resolveSavedNotification(form, 'create', { id: 1 }, { values: {} })
|
|
39
|
-
assert.equal(got!.title, 'Created')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('createdNotification does NOT apply in update mode (falls back to shared)', () => {
|
|
43
|
-
const form = Form.make<{ id: number }>()
|
|
44
|
-
.savedNotification('Saved')
|
|
45
|
-
.createdNotification('Created')
|
|
46
|
-
const got = resolveSavedNotification(form, 'update', { id: 1 }, { values: {} })
|
|
47
|
-
assert.equal(got!.title, 'Saved')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('null mode-spec suppresses the toast for that mode but not the other', () => {
|
|
51
|
-
const form = Form.make<{ id: number }>()
|
|
52
|
-
.savedNotification('Saved')
|
|
53
|
-
.createdNotification(null)
|
|
54
|
-
const create = resolveSavedNotification(form, 'create', { id: 1 }, { values: {} })
|
|
55
|
-
const update = resolveSavedNotification(form, 'update', { id: 1 }, { values: {} })
|
|
56
|
-
assert.equal(create, null)
|
|
57
|
-
assert.equal(update!.title, 'Saved')
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('function spec receives record + ctx and is recursively resolved', () => {
|
|
61
|
-
const form = Form.make<{ id: number; name: string }>()
|
|
62
|
-
.savedNotification((record) => `Saved #${record.id}`)
|
|
63
|
-
const got = resolveSavedNotification(form, 'update', { id: 7, name: 'a' }, { values: {} })
|
|
64
|
-
assert.equal(got!.title, 'Saved #7')
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('Notification builder spec passes through to meta', () => {
|
|
68
|
-
const form = Form.make<{ id: number }>()
|
|
69
|
-
.savedNotification(Notification.make('Done').warning().body('details'))
|
|
70
|
-
const got = resolveSavedNotification(form, 'update', { id: 1 }, { values: {} })
|
|
71
|
-
assert.equal(got!.type, 'warning')
|
|
72
|
-
assert.equal(got!.title, 'Done')
|
|
73
|
-
assert.equal(got!.body, 'details')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('NotificationMeta object spec passes through unchanged', () => {
|
|
77
|
-
const meta = { id: 'fixed', type: 'info' as const, title: 'Note' }
|
|
78
|
-
const form = Form.make<{ id: number }>().savedNotification(meta)
|
|
79
|
-
const got = resolveSavedNotification(form, 'update', { id: 1 }, { values: {} })
|
|
80
|
-
assert.deepEqual(got, meta)
|
|
81
|
-
})
|
|
82
|
-
})
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the saved-notification spec on a `Form` into a concrete
|
|
3
|
-
* `NotificationMeta`, or `null` when notifications are explicitly
|
|
4
|
-
* disabled. Used by `dispatchFormSubmit` to attach the success toast to
|
|
5
|
-
* its result.
|
|
6
|
-
*
|
|
7
|
-
* Resolution order:
|
|
8
|
-
* 1. If the form has `disableSavedNotification()` → null.
|
|
9
|
-
* 2. Mode-specific spec (`createdNotification` for create) wins over
|
|
10
|
-
* generic `savedNotification` when set.
|
|
11
|
-
* 3. `null` spec returns null (explicitly suppress the toast for that
|
|
12
|
-
* mode while keeping the generic fallback for the other mode).
|
|
13
|
-
* 4. String spec → success toast with that title.
|
|
14
|
-
* 5. Function spec → invoked with `(record, ctx)` and re-resolved.
|
|
15
|
-
* 6. `Notification` builder or `NotificationMeta` → passes through.
|
|
16
|
-
*/
|
|
17
|
-
import { Notification, type NotificationMeta } from './Notification.js'
|
|
18
|
-
import type { Form, FormContext, SavedNotificationHandler } from '../elements/Form.js'
|
|
19
|
-
|
|
20
|
-
export type SavedNotificationMode = 'create' | 'update'
|
|
21
|
-
|
|
22
|
-
export function resolveSavedNotification<R>(
|
|
23
|
-
form: Form<R>,
|
|
24
|
-
mode: SavedNotificationMode,
|
|
25
|
-
record: R,
|
|
26
|
-
ctx: FormContext<R>,
|
|
27
|
-
): NotificationMeta | null {
|
|
28
|
-
if (form.isSavedNotificationDisabled()) return null
|
|
29
|
-
|
|
30
|
-
const modeSpec = mode === 'create' ? form.getCreatedNotification() : undefined
|
|
31
|
-
const sharedSpec = form.getSavedNotification()
|
|
32
|
-
const spec = modeSpec !== undefined ? modeSpec : sharedSpec
|
|
33
|
-
|
|
34
|
-
if (spec === undefined) return null
|
|
35
|
-
return resolveSpec(spec, record, ctx)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function resolveSpec<R>(
|
|
39
|
-
spec: SavedNotificationHandler<R>,
|
|
40
|
-
record: R,
|
|
41
|
-
ctx: FormContext<R>,
|
|
42
|
-
): NotificationMeta | null {
|
|
43
|
-
if (spec === null) return null
|
|
44
|
-
|
|
45
|
-
if (typeof spec === 'function') {
|
|
46
|
-
const next = spec(record, ctx)
|
|
47
|
-
return next === null ? null : resolveSpec(next as SavedNotificationHandler<R>, record, ctx)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (typeof spec === 'string') {
|
|
51
|
-
return Notification.make(spec).success().toMeta()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (spec instanceof Notification) {
|
|
55
|
-
return spec.toMeta()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return spec
|
|
59
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import type { ActionColor, ActionSize, DownloadEnvelope } from '../actions/Action.js'
|
|
2
|
-
import type { NotificationMeta } from './Notification.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Minimal notifiable contract used by `Notification.sendToDatabase()`
|
|
6
|
-
* and the bell-icon endpoints. Mirrors the shape `@rudderjs/notification`
|
|
7
|
-
* already publishes — `id` (string or number) is the only required
|
|
8
|
-
* field. We coerce to string when writing the `notifiable_id` column so
|
|
9
|
-
* mixed `number`/`string` ids stay consistent on disk.
|
|
10
|
-
*/
|
|
11
|
-
export interface Notifiable {
|
|
12
|
-
readonly id: string | number
|
|
13
|
-
readonly email?: string
|
|
14
|
-
readonly name?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Slim wire shape emitted by `Notification.actions([Action…])`. Same
|
|
19
|
-
* format on the transient toast meta, the persisted database row's
|
|
20
|
-
* `data.actions` JSON, and the `_notifications` list endpoint — so the
|
|
21
|
-
* bell client and the toaster can share render code.
|
|
22
|
-
*
|
|
23
|
-
* Exactly one of `url` / `post` / `handler` is set. The serializer in
|
|
24
|
-
* `Notification.ts` enforces mutual exclusion at config time and rejects
|
|
25
|
-
* Action features that don't make sense in a notification context
|
|
26
|
-
* (modal-form, submit, bulk placement) with a clear error.
|
|
27
|
-
*/
|
|
28
|
-
export interface NotificationActionMeta {
|
|
29
|
-
/** Stable name; used as the registry key for handler dispatch and
|
|
30
|
-
* as the action identifier the route's URL carries. */
|
|
31
|
-
name: string
|
|
32
|
-
label: string
|
|
33
|
-
/** Click navigates here. */
|
|
34
|
-
url?: string
|
|
35
|
-
/** Click submits a `<form method="post" action="…">`. */
|
|
36
|
-
post?: string
|
|
37
|
-
/** Registry key — looked up via `Pilotiq.notificationHandlers({…})`
|
|
38
|
-
* at request time. The matching handler runs server-side; the bell
|
|
39
|
-
* client renders a button that POSTs to the notification action
|
|
40
|
-
* endpoint. */
|
|
41
|
-
handler?: string
|
|
42
|
-
/** Per-fire context the handler receives on `ctx.payload`. JSON-only
|
|
43
|
-
* (`Date`/`Map`/etc don't survive — stringify them yourself). Stored
|
|
44
|
-
* alongside the action when the row is persisted. */
|
|
45
|
-
payload?: Record<string, unknown>
|
|
46
|
-
color?: ActionColor
|
|
47
|
-
icon?: string
|
|
48
|
-
outlined?: boolean
|
|
49
|
-
size?: ActionSize
|
|
50
|
-
openUrlInNewTab?: boolean
|
|
51
|
-
/**
|
|
52
|
-
* When set, firing this action also flips the notification's
|
|
53
|
-
* `read_at` column. Url/post variants fire the read POST as a
|
|
54
|
-
* client-side side-effect; handler dispatch handles it server-side
|
|
55
|
-
* inside the action route so the round-trip is one request.
|
|
56
|
-
*/
|
|
57
|
-
markAsRead?: boolean
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Server-side handler signature for `Pilotiq.notificationHandlers({…})`
|
|
62
|
-
* registry entries. Mirrors the `ActionHandler` from
|
|
63
|
-
* `dispatchAction` minus row context (notifications don't carry one),
|
|
64
|
-
* plus `payload` (the per-fire context the action carried) and
|
|
65
|
-
* `notificationId` (the row the click came from).
|
|
66
|
-
*/
|
|
67
|
-
export type NotificationActionHandler = (
|
|
68
|
-
ctx: NotificationActionContext,
|
|
69
|
-
) => Promise<NotificationActionResult | undefined> | NotificationActionResult | undefined
|
|
70
|
-
|
|
71
|
-
export interface NotificationActionContext {
|
|
72
|
-
/** Resolved by `pilotiq.resolveUser(req)` before the route fires.
|
|
73
|
-
* Always present — the route gates on auth before reaching the
|
|
74
|
-
* registry. */
|
|
75
|
-
user: unknown
|
|
76
|
-
/** Per-fire context the action carried. Empty object when the action
|
|
77
|
-
* was created without `.payload({…})`. */
|
|
78
|
-
payload: Record<string, unknown>
|
|
79
|
-
/** Database row id this click came from. */
|
|
80
|
-
notificationId: string
|
|
81
|
-
/** Raw request — same opaque shape that flows into Resource action
|
|
82
|
-
* handlers, in case a handler needs cookies / headers. */
|
|
83
|
-
request?: unknown
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export interface NotificationActionResult {
|
|
87
|
-
/** SPA-navigate after the handler completes. */
|
|
88
|
-
redirect?: string
|
|
89
|
-
/** Toast(s) to flash after the handler completes. */
|
|
90
|
-
notify?: NotificationMeta | NotificationMeta[]
|
|
91
|
-
/** File-download envelope (parallel to dispatchAction). */
|
|
92
|
-
download?: DownloadEnvelope
|
|
93
|
-
}
|
package/src/orm/m2mAccessor.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The M2M pivot-mutation surface exposed by `@rudderjs/orm`. Returned
|
|
3
|
-
* from per-relation accessor methods installed on parent prototypes
|
|
4
|
-
* (e.g. `user.roles()` → `{ attach, detach, sync }`).
|
|
5
|
-
*
|
|
6
|
-
* Each method is optional in the structural type because some test
|
|
7
|
-
* doubles only stub the subset they exercise — `resolveM2MAccessor`
|
|
8
|
-
* gates on `attach || detach` being callable to filter unrelated
|
|
9
|
-
* shapes (e.g. a deferred QB Proxy from `parent.related()`).
|
|
10
|
-
*/
|
|
11
|
-
export interface M2MAccessor {
|
|
12
|
-
attach?(input: unknown): Promise<void>
|
|
13
|
-
detach?(input?: unknown): Promise<unknown>
|
|
14
|
-
sync?(desiredIds: ReadonlyArray<string | number>): Promise<unknown>
|
|
15
|
-
/**
|
|
16
|
-
* Update extras on an existing pivot row without touching either side
|
|
17
|
-
* of the relation. Returns the number of rows updated (0 when no
|
|
18
|
-
* matching pivot exists). Optional on the structural shape; pilotiq's
|
|
19
|
-
* `Repeater.relationship.pivotColumns([…])` pipeline gates on its
|
|
20
|
-
* presence and throws a clear error when missing (rudder ORM ships
|
|
21
|
-
* it from `feat(orm): pivot-extras read/update + per-id sync` —
|
|
22
|
-
* see `~/Projects/rudder/docs/plans/2026-05-06-belongs-to-many-pivot-extras.md`).
|
|
23
|
-
*/
|
|
24
|
-
updatePivot?(relatedId: string | number, data: Record<string, unknown>): Promise<number>
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Resolve the M2M pivot-mutation accessor for `parent[rel]`. Two
|
|
29
|
-
* shapes are supported, in this order:
|
|
30
|
-
*
|
|
31
|
-
* 1. `parent[rel]()` — the real `@rudderjs/orm` shape installed by
|
|
32
|
-
* `_installBelongsToManyMethods` / `_installMorphPivotMethods`
|
|
33
|
-
* (e.g. `post.tags()` returns `{ attach, detach, sync }`).
|
|
34
|
-
* 2. `parent.related(rel)` — legacy / test-double shape that returns
|
|
35
|
-
* the accessor directly. Kept so existing pilotiq tests built
|
|
36
|
-
* around `parent.related(...)` mocks keep passing.
|
|
37
|
-
*
|
|
38
|
-
* Returns `undefined` when neither shape exposes a callable `attach`
|
|
39
|
-
* AND a callable `detach` — caller should surface a clear error
|
|
40
|
-
* (different copy depending on whether they're inside an Action handler
|
|
41
|
-
* or a `Repeater.relationship` save).
|
|
42
|
-
*
|
|
43
|
-
* Note `parent.related(rel)` returns a deferred-QB Proxy in the real
|
|
44
|
-
* ORM, NOT an attach/detach accessor — see
|
|
45
|
-
* `feedback_m2m_accessor_shape.md`. The shape-1 instance-method form is
|
|
46
|
-
* the canonical lookup; the related() fallback is purely a test-mock
|
|
47
|
-
* affordance.
|
|
48
|
-
*/
|
|
49
|
-
export function resolveM2MAccessor(parent: unknown, rel: string): M2MAccessor | undefined {
|
|
50
|
-
if (!parent || typeof parent !== 'object') return undefined
|
|
51
|
-
// Shape 1: parent[rel]() — real ORM. Prototype-installed method.
|
|
52
|
-
const inst = (parent as Record<string, unknown>)[rel]
|
|
53
|
-
if (typeof inst === 'function') {
|
|
54
|
-
try {
|
|
55
|
-
const out = (inst as () => unknown).call(parent) as M2MAccessor | undefined
|
|
56
|
-
if (out && (typeof out.attach === 'function' || typeof out.detach === 'function')) return out
|
|
57
|
-
} catch { /* fall through to legacy shape */ }
|
|
58
|
-
}
|
|
59
|
-
// Shape 2: parent.related(rel) — legacy / test-mock shape.
|
|
60
|
-
const relatedFn = (parent as { related?: (n: string) => unknown }).related
|
|
61
|
-
if (typeof relatedFn === 'function') {
|
|
62
|
-
const out = relatedFn.call(parent, rel) as M2MAccessor | undefined
|
|
63
|
-
if (out && (typeof out.attach === 'function' || typeof out.detach === 'function')) return out
|
|
64
|
-
}
|
|
65
|
-
return undefined
|
|
66
|
-
}
|