@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.
Files changed (500) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/boost/guidelines.md +566 -0
  3. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  4. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  5. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  6. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  7. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  9. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  10. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  11. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  12. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  13. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  14. package/dist/actions/exportFactory.d.ts +10 -0
  15. package/dist/actions/exportFactory.d.ts.map +1 -1
  16. package/dist/actions/exportFactory.js +10 -0
  17. package/dist/actions/exportFactory.js.map +1 -1
  18. package/dist/react/CollabRoomContext.d.ts +5 -5
  19. package/dist/react/index.d.ts +0 -1
  20. package/dist/react/index.d.ts.map +1 -1
  21. package/dist/react/index.js +0 -1
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/routes/helpers.d.ts.map +1 -1
  24. package/dist/routes/helpers.js +6 -2
  25. package/dist/routes/helpers.js.map +1 -1
  26. package/dist/routes/relations.d.ts.map +1 -1
  27. package/dist/routes/relations.js +12 -0
  28. package/dist/routes/relations.js.map +1 -1
  29. package/package.json +6 -1
  30. package/.turbo/turbo-build.log +0 -8
  31. package/CLAUDE.md +0 -265
  32. package/dist/react/useCollabSeed.d.ts +0 -23
  33. package/dist/react/useCollabSeed.d.ts.map +0 -1
  34. package/dist/react/useCollabSeed.js +0 -82
  35. package/dist/react/useCollabSeed.js.map +0 -1
  36. package/src/Cluster.test.ts +0 -283
  37. package/src/Cluster.ts +0 -83
  38. package/src/Column.test.ts +0 -199
  39. package/src/Column.ts +0 -710
  40. package/src/Global.test.ts +0 -367
  41. package/src/Global.ts +0 -169
  42. package/src/Page.test.ts +0 -114
  43. package/src/Page.ts +0 -208
  44. package/src/Pilotiq.perf.test.ts +0 -252
  45. package/src/Pilotiq.test.ts +0 -129
  46. package/src/Pilotiq.ts +0 -1158
  47. package/src/PilotiqRegistry.ts +0 -36
  48. package/src/PilotiqServiceProvider.ts +0 -121
  49. package/src/RelationManager.test.ts +0 -400
  50. package/src/RelationManager.ts +0 -527
  51. package/src/RenderHook.test.ts +0 -252
  52. package/src/RenderHook.ts +0 -242
  53. package/src/Resource.test.ts +0 -284
  54. package/src/Resource.ts +0 -526
  55. package/src/RightPanel.test.ts +0 -202
  56. package/src/RightPanel.ts +0 -132
  57. package/src/Tab.test.ts +0 -91
  58. package/src/Tab.ts +0 -156
  59. package/src/UserMenuItem.ts +0 -145
  60. package/src/actions/Action.test.ts +0 -2526
  61. package/src/actions/Action.ts +0 -1515
  62. package/src/actions/ActionGroup.test.ts +0 -112
  63. package/src/actions/ActionGroup.ts +0 -173
  64. package/src/actions/attachFactory.ts +0 -172
  65. package/src/actions/bulkFactories.ts +0 -168
  66. package/src/actions/crudFactories.ts +0 -220
  67. package/src/actions/exportFactory.ts +0 -215
  68. package/src/actions/factoryHelpers.ts +0 -177
  69. package/src/actions/importFactory.ts +0 -243
  70. package/src/actions/index.ts +0 -17
  71. package/src/actions/m2mFactories.ts +0 -193
  72. package/src/actions/relationFactories.ts +0 -372
  73. package/src/applyPageHooks.test.ts +0 -463
  74. package/src/applyPageHooks.ts +0 -330
  75. package/src/authorization.test.ts +0 -483
  76. package/src/breadcrumbs.test.ts +0 -238
  77. package/src/cells/coerce.test.ts +0 -85
  78. package/src/cells/coerce.ts +0 -84
  79. package/src/clusterPaths.ts +0 -35
  80. package/src/columns/BadgeColumn.test.ts +0 -54
  81. package/src/columns/BadgeColumn.ts +0 -32
  82. package/src/columns/BooleanColumn.test.ts +0 -41
  83. package/src/columns/BooleanColumn.ts +0 -18
  84. package/src/columns/ColorColumn.test.ts +0 -37
  85. package/src/columns/ColorColumn.ts +0 -38
  86. package/src/columns/IconColumn.test.ts +0 -54
  87. package/src/columns/IconColumn.ts +0 -37
  88. package/src/columns/ImageColumn.test.ts +0 -41
  89. package/src/columns/ImageColumn.ts +0 -28
  90. package/src/columns/SelectColumn.ts +0 -98
  91. package/src/columns/TextColumn.test.ts +0 -190
  92. package/src/columns/TextColumn.ts +0 -20
  93. package/src/columns/TextInputColumn.ts +0 -68
  94. package/src/columns/ToggleColumn.ts +0 -46
  95. package/src/columns/editableColumns.test.ts +0 -238
  96. package/src/columns/index.ts +0 -9
  97. package/src/defaultGlobalPages.ts +0 -95
  98. package/src/defaultPages.test.ts +0 -634
  99. package/src/defaultPages.ts +0 -617
  100. package/src/defaultViewPage.test.ts +0 -147
  101. package/src/elements/Form.test.ts +0 -223
  102. package/src/elements/Form.ts +0 -416
  103. package/src/elements/ListTabs.ts +0 -28
  104. package/src/elements/Table.test.ts +0 -422
  105. package/src/elements/Table.ts +0 -850
  106. package/src/elements/TableGroup.test.ts +0 -260
  107. package/src/elements/TableGroup.ts +0 -334
  108. package/src/elements/dispatchAction.test.ts +0 -463
  109. package/src/elements/dispatchAction.ts +0 -355
  110. package/src/elements/dispatchForm.test.ts +0 -477
  111. package/src/elements/dispatchForm.ts +0 -1993
  112. package/src/elements/dispatchTable.test.ts +0 -1514
  113. package/src/elements/dispatchTable.ts +0 -745
  114. package/src/elements/index.ts +0 -21
  115. package/src/entries/BadgeEntry.ts +0 -39
  116. package/src/entries/CodeEntry.test.ts +0 -40
  117. package/src/entries/CodeEntry.ts +0 -52
  118. package/src/entries/ColorEntry.ts +0 -63
  119. package/src/entries/ComponentEntry.test.ts +0 -173
  120. package/src/entries/ComponentEntry.ts +0 -95
  121. package/src/entries/Entry.ts +0 -304
  122. package/src/entries/IconEntry.ts +0 -49
  123. package/src/entries/ImageEntry.ts +0 -61
  124. package/src/entries/KeyValueEntry.ts +0 -47
  125. package/src/entries/RepeatableEntry.test.ts +0 -239
  126. package/src/entries/RepeatableEntry.ts +0 -173
  127. package/src/entries/TextEntry.test.ts +0 -394
  128. package/src/entries/TextEntry.ts +0 -60
  129. package/src/entries/index.ts +0 -12
  130. package/src/entries/leaves.test.ts +0 -306
  131. package/src/entries/registry.ts +0 -54
  132. package/src/fields/BuilderField.test.ts +0 -1188
  133. package/src/fields/BuilderField.ts +0 -605
  134. package/src/fields/BuilderRelationship.test.ts +0 -811
  135. package/src/fields/CheckboxField.test.ts +0 -44
  136. package/src/fields/CheckboxField.ts +0 -27
  137. package/src/fields/CheckboxListField.test.ts +0 -99
  138. package/src/fields/CheckboxListField.ts +0 -66
  139. package/src/fields/ColorPickerField.test.ts +0 -33
  140. package/src/fields/ColorPickerField.ts +0 -25
  141. package/src/fields/DateField.ts +0 -54
  142. package/src/fields/DateTimeField.test.ts +0 -55
  143. package/src/fields/EmailField.ts +0 -16
  144. package/src/fields/Field.test.ts +0 -654
  145. package/src/fields/Field.ts +0 -817
  146. package/src/fields/FileUploadField.test.ts +0 -143
  147. package/src/fields/FileUploadField.ts +0 -159
  148. package/src/fields/HiddenField.test.ts +0 -27
  149. package/src/fields/HiddenField.ts +0 -28
  150. package/src/fields/KeyValueField.test.ts +0 -105
  151. package/src/fields/KeyValueField.ts +0 -55
  152. package/src/fields/MarkdownField.test.ts +0 -167
  153. package/src/fields/MarkdownField.ts +0 -162
  154. package/src/fields/NumberField.ts +0 -33
  155. package/src/fields/RadioField.test.ts +0 -94
  156. package/src/fields/RadioField.ts +0 -67
  157. package/src/fields/RepeaterField.test.ts +0 -1806
  158. package/src/fields/RepeaterField.ts +0 -939
  159. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  160. package/src/fields/RepeaterSimple.test.ts +0 -248
  161. package/src/fields/RowButton.test.ts +0 -219
  162. package/src/fields/RowButton.ts +0 -135
  163. package/src/fields/SelectField.test.ts +0 -192
  164. package/src/fields/SelectField.ts +0 -235
  165. package/src/fields/SliderField.test.ts +0 -50
  166. package/src/fields/SliderField.ts +0 -53
  167. package/src/fields/SlugField.ts +0 -24
  168. package/src/fields/TagsInputField.test.ts +0 -154
  169. package/src/fields/TagsInputField.ts +0 -133
  170. package/src/fields/TextField.test.ts +0 -213
  171. package/src/fields/TextField.ts +0 -177
  172. package/src/fields/TextareaField.test.ts +0 -58
  173. package/src/fields/TextareaField.ts +0 -59
  174. package/src/fields/ToggleButtonsField.test.ts +0 -106
  175. package/src/fields/ToggleButtonsField.ts +0 -59
  176. package/src/fields/ToggleField.ts +0 -16
  177. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  178. package/src/fields/optionsResolver.ts +0 -95
  179. package/src/fields/resolveField.ts +0 -28
  180. package/src/filters/BooleanFilter.ts +0 -35
  181. package/src/filters/DateRangeFilter.test.ts +0 -194
  182. package/src/filters/DateRangeFilter.ts +0 -148
  183. package/src/filters/Filter.test.ts +0 -268
  184. package/src/filters/Filter.ts +0 -184
  185. package/src/filters/FormFilter.test.ts +0 -238
  186. package/src/filters/FormFilter.ts +0 -215
  187. package/src/filters/MultiSelectFilter.test.ts +0 -119
  188. package/src/filters/MultiSelectFilter.ts +0 -78
  189. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  190. package/src/filters/QueryBuilderFilter.ts +0 -398
  191. package/src/filters/SelectFilter.ts +0 -46
  192. package/src/filters/TernaryFilter.test.ts +0 -160
  193. package/src/filters/TernaryFilter.ts +0 -72
  194. package/src/filters/TrashedFilter.test.ts +0 -149
  195. package/src/filters/TrashedFilter.ts +0 -55
  196. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  197. package/src/filters/queryBuilder/Constraint.ts +0 -115
  198. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  199. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  200. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  201. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  202. package/src/filters/queryBuilder/index.ts +0 -12
  203. package/src/icons/index.ts +0 -2
  204. package/src/icons/lucide.ts +0 -204
  205. package/src/icons/registry.test.ts +0 -56
  206. package/src/icons/registry.ts +0 -41
  207. package/src/icons/types.ts +0 -47
  208. package/src/index.ts +0 -525
  209. package/src/io/csv.test.ts +0 -142
  210. package/src/io/csv.ts +0 -170
  211. package/src/nestedRelationManagerData.test.ts +0 -547
  212. package/src/notifications/Notification.test.ts +0 -210
  213. package/src/notifications/Notification.ts +0 -354
  214. package/src/notifications/broadcast.test.ts +0 -110
  215. package/src/notifications/broadcast.ts +0 -95
  216. package/src/notifications/database.test.ts +0 -383
  217. package/src/notifications/database.ts +0 -398
  218. package/src/notifications/databaseNotifications.test.ts +0 -187
  219. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  220. package/src/notifications/dispatchNotificationAction.ts +0 -142
  221. package/src/notifications/flash.test.ts +0 -89
  222. package/src/notifications/flash.ts +0 -71
  223. package/src/notifications/index.ts +0 -45
  224. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  225. package/src/notifications/registerBroadcastAuth.ts +0 -100
  226. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  227. package/src/notifications/resolveSavedNotification.ts +0 -59
  228. package/src/notifications/types.ts +0 -93
  229. package/src/orm/m2mAccessor.ts +0 -66
  230. package/src/orm/modelDefaults.test.ts +0 -633
  231. package/src/orm/modelDefaults.ts +0 -666
  232. package/src/pageData/breadcrumbs.ts +0 -288
  233. package/src/pageData/forms.ts +0 -578
  234. package/src/pageData/helpers.ts +0 -857
  235. package/src/pageData/misc.ts +0 -347
  236. package/src/pageData/navigation.ts +0 -842
  237. package/src/pageData/relationPages.ts +0 -1248
  238. package/src/pageData/relationTabs.ts +0 -286
  239. package/src/pageData/resourcePages.ts +0 -609
  240. package/src/pageData.test.ts +0 -1545
  241. package/src/pageData.ts +0 -341
  242. package/src/plugins/index.ts +0 -8
  243. package/src/plugins/themeEditor.test.ts +0 -36
  244. package/src/plugins/themeEditor.ts +0 -45
  245. package/src/react/AppShell.tsx +0 -251
  246. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  247. package/src/react/CollabRoomContext.ts +0 -98
  248. package/src/react/CollabTextRendererRegistry.ts +0 -102
  249. package/src/react/CommandPalette.tsx +0 -375
  250. package/src/react/CurrentUserContext.tsx +0 -50
  251. package/src/react/CustomPageWrapperGate.tsx +0 -69
  252. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  253. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  254. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  255. package/src/react/FieldPresenceRegistry.ts +0 -46
  256. package/src/react/FormCollabBindingRegistry.ts +0 -242
  257. package/src/react/FormStateContext.tsx +0 -591
  258. package/src/react/HeadHooks.tsx +0 -126
  259. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  260. package/src/react/MarkdownEditorRegistry.ts +0 -107
  261. package/src/react/NotificationActionStrip.tsx +0 -263
  262. package/src/react/NotificationBell.tsx +0 -426
  263. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  264. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  265. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  266. package/src/react/PendingSuggestionsContext.tsx +0 -172
  267. package/src/react/RecordWrapperGate.tsx +0 -58
  268. package/src/react/RecordWrapperRegistry.ts +0 -39
  269. package/src/react/RenderHookSlot.tsx +0 -32
  270. package/src/react/RightSidebar.tsx +0 -257
  271. package/src/react/RightSidebarContext.tsx +0 -234
  272. package/src/react/RightSidebarTrigger.tsx +0 -53
  273. package/src/react/RowCoordsContext.tsx +0 -23
  274. package/src/react/SchemaRenderer.tsx +0 -549
  275. package/src/react/SearchTrigger.tsx +0 -46
  276. package/src/react/ThemeProvider.tsx +0 -93
  277. package/src/react/ThemeSettingsPage.tsx +0 -579
  278. package/src/react/ThemeToggle.tsx +0 -20
  279. package/src/react/Toaster.tsx +0 -158
  280. package/src/react/UserMenu.tsx +0 -196
  281. package/src/react/WidgetDataContext.tsx +0 -157
  282. package/src/react/cells/EditableCell.tsx +0 -389
  283. package/src/react/component-slots.test.ts +0 -103
  284. package/src/react/component-slots.ts +0 -116
  285. package/src/react/fieldJsHandler.test.ts +0 -166
  286. package/src/react/fieldJsHandler.ts +0 -79
  287. package/src/react/fields/BuilderInput.tsx +0 -1078
  288. package/src/react/fields/CheckboxInput.tsx +0 -39
  289. package/src/react/fields/CheckboxListInput.tsx +0 -102
  290. package/src/react/fields/ColorInput.tsx +0 -71
  291. package/src/react/fields/DateFieldInput.tsx +0 -70
  292. package/src/react/fields/DateTimeInput.tsx +0 -62
  293. package/src/react/fields/FieldShell.tsx +0 -348
  294. package/src/react/fields/FileUploadInput.tsx +0 -639
  295. package/src/react/fields/HiddenInput.tsx +0 -17
  296. package/src/react/fields/KeyValueInput.tsx +0 -230
  297. package/src/react/fields/MarkdownInput.tsx +0 -560
  298. package/src/react/fields/RadioInput.tsx +0 -81
  299. package/src/react/fields/RepeaterInput.test.ts +0 -116
  300. package/src/react/fields/RepeaterInput.tsx +0 -1420
  301. package/src/react/fields/SelectFieldInput.tsx +0 -280
  302. package/src/react/fields/SliderInput.tsx +0 -81
  303. package/src/react/fields/TagsInput.tsx +0 -283
  304. package/src/react/fields/TextLikeInput.tsx +0 -256
  305. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  306. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  307. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  308. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  309. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  310. package/src/react/fields/repeaterReconcile.ts +0 -104
  311. package/src/react/fields/rowChromeButton.tsx +0 -336
  312. package/src/react/fields/rowState.ts +0 -106
  313. package/src/react/fields/syncRowGates.test.ts +0 -202
  314. package/src/react/fields/syncRowGates.ts +0 -66
  315. package/src/react/fields/textInputControls.tsx +0 -238
  316. package/src/react/fields/useRowReorderDnd.ts +0 -78
  317. package/src/react/formStateHelpers.test.ts +0 -508
  318. package/src/react/formStateHelpers.ts +0 -381
  319. package/src/react/hooks/use-mobile.ts +0 -19
  320. package/src/react/icon-context.tsx +0 -60
  321. package/src/react/index.ts +0 -195
  322. package/src/react/layouts/SidebarLayout.tsx +0 -250
  323. package/src/react/layouts/TopbarLayout.tsx +0 -258
  324. package/src/react/navigate.tsx +0 -37
  325. package/src/react/onProviderSynced.test.ts +0 -90
  326. package/src/react/parseRecordEditUrl.test.ts +0 -122
  327. package/src/react/parseRecordEditUrl.ts +0 -94
  328. package/src/react/persistedState.ts +0 -40
  329. package/src/react/registry.ts +0 -48
  330. package/src/react/right-panel-registry.tsx +0 -47
  331. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  332. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  333. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  334. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  335. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  336. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  337. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  338. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  339. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  340. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  341. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  342. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  343. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  344. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  345. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  346. package/src/react/schemaRenderer/constants.ts +0 -50
  347. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  348. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  349. package/src/react/schemaRenderer/helpers.tsx +0 -81
  350. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  351. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  352. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  353. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  354. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  355. package/src/react/schemaRenderer/table/links.tsx +0 -112
  356. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  357. package/src/react/schemaRenderer/table/url.tsx +0 -143
  358. package/src/react/theme-preview/apply.ts +0 -99
  359. package/src/react/theme-preview/build-html.ts +0 -436
  360. package/src/react/ui/button.tsx +0 -51
  361. package/src/react/ui/calendar.tsx +0 -67
  362. package/src/react/ui/checkbox.tsx +0 -29
  363. package/src/react/ui/dialog.tsx +0 -108
  364. package/src/react/ui/dropdown-menu.tsx +0 -97
  365. package/src/react/ui/input.tsx +0 -20
  366. package/src/react/ui/label.tsx +0 -21
  367. package/src/react/ui/popover.tsx +0 -50
  368. package/src/react/ui/select.tsx +0 -169
  369. package/src/react/ui/separator.tsx +0 -25
  370. package/src/react/ui/sheet.tsx +0 -136
  371. package/src/react/ui/sidebar.tsx +0 -723
  372. package/src/react/ui/skeleton.tsx +0 -13
  373. package/src/react/ui/slider.tsx +0 -34
  374. package/src/react/ui/switch.tsx +0 -28
  375. package/src/react/ui/table.tsx +0 -105
  376. package/src/react/ui/tabs.tsx +0 -63
  377. package/src/react/ui/textarea.tsx +0 -18
  378. package/src/react/ui/tooltip.tsx +0 -64
  379. package/src/react/useCollabSeed.ts +0 -86
  380. package/src/react/useResizableWidth.ts +0 -139
  381. package/src/react/utils.ts +0 -6
  382. package/src/react/widgetRegistry.test.ts +0 -43
  383. package/src/react/widgetRegistry.ts +0 -50
  384. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  385. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  386. package/src/react/widgets/ViewRenderer.tsx +0 -71
  387. package/src/relationManagerData.test.ts +0 -1595
  388. package/src/richtext/index.ts +0 -8
  389. package/src/richtext/registry.ts +0 -89
  390. package/src/routes/globals.ts +0 -148
  391. package/src/routes/guard.test.ts +0 -325
  392. package/src/routes/helpers.ts +0 -700
  393. package/src/routes/pages.ts +0 -175
  394. package/src/routes/panel.ts +0 -204
  395. package/src/routes/relations.ts +0 -1227
  396. package/src/routes/resources.ts +0 -781
  397. package/src/routes/theme.ts +0 -91
  398. package/src/routes-nested-relations.test.ts +0 -676
  399. package/src/routes-relations.test.ts +0 -972
  400. package/src/routes.test.ts +0 -2027
  401. package/src/routes.ts +0 -303
  402. package/src/schema/Alert.test.ts +0 -109
  403. package/src/schema/Alert.ts +0 -131
  404. package/src/schema/Block.ts +0 -169
  405. package/src/schema/Breadcrumbs.ts +0 -40
  406. package/src/schema/Card.ts +0 -35
  407. package/src/schema/Divider.ts +0 -20
  408. package/src/schema/Element.ts +0 -219
  409. package/src/schema/EmptyState.test.ts +0 -37
  410. package/src/schema/EmptyState.ts +0 -63
  411. package/src/schema/Fieldset.ts +0 -43
  412. package/src/schema/Grid.ts +0 -43
  413. package/src/schema/Group.ts +0 -30
  414. package/src/schema/Heading.ts +0 -39
  415. package/src/schema/Html.ts +0 -67
  416. package/src/schema/Icon.ts +0 -54
  417. package/src/schema/Image.ts +0 -57
  418. package/src/schema/LinkTag.ts +0 -41
  419. package/src/schema/Markdown.ts +0 -85
  420. package/src/schema/MetaTag.ts +0 -41
  421. package/src/schema/RelationTabs.ts +0 -71
  422. package/src/schema/ScriptTag.ts +0 -55
  423. package/src/schema/Section.ts +0 -160
  424. package/src/schema/ServerDataElement.test.ts +0 -140
  425. package/src/schema/ServerDataElement.ts +0 -156
  426. package/src/schema/SlotComponent.test.ts +0 -77
  427. package/src/schema/SlotComponent.ts +0 -71
  428. package/src/schema/Split.ts +0 -50
  429. package/src/schema/Stat.test.ts +0 -118
  430. package/src/schema/Stat.ts +0 -154
  431. package/src/schema/StatsOverview.test.ts +0 -141
  432. package/src/schema/StatsOverview.ts +0 -119
  433. package/src/schema/StyleTag.ts +0 -35
  434. package/src/schema/TableWidget.test.ts +0 -297
  435. package/src/schema/TableWidget.ts +0 -289
  436. package/src/schema/Tabs.ts +0 -79
  437. package/src/schema/Text.ts +0 -58
  438. package/src/schema/UnorderedList.ts +0 -49
  439. package/src/schema/View.test.ts +0 -111
  440. package/src/schema/View.ts +0 -127
  441. package/src/schema/Wizard.ts +0 -220
  442. package/src/schema/containers.test.ts +0 -564
  443. package/src/schema/headTags.test.ts +0 -134
  444. package/src/schema/index.ts +0 -40
  445. package/src/schema/primes.test.ts +0 -269
  446. package/src/schema/resolveSchema.test.ts +0 -379
  447. package/src/schema/resolveSchema.ts +0 -917
  448. package/src/schema/sanitize.ts +0 -58
  449. package/src/search.test.ts +0 -446
  450. package/src/search.ts +0 -178
  451. package/src/sessionFilters.test.ts +0 -375
  452. package/src/sessionFilters.ts +0 -143
  453. package/src/slot-components/index.ts +0 -10
  454. package/src/slot-components/registry.ts +0 -56
  455. package/src/styles/file-upload.css +0 -13
  456. package/src/summarizers/Summarizer.test.ts +0 -84
  457. package/src/summarizers/Summarizer.ts +0 -123
  458. package/src/summarizers/index.ts +0 -11
  459. package/src/theme/base-colors.ts +0 -68
  460. package/src/theme/chart-colors.ts +0 -50
  461. package/src/theme/colors.ts +0 -447
  462. package/src/theme/generate-css.test.ts +0 -139
  463. package/src/theme/generate-css.ts +0 -44
  464. package/src/theme/generate-scale.test.ts +0 -106
  465. package/src/theme/generate-scale.ts +0 -97
  466. package/src/theme/icon-map.ts +0 -42
  467. package/src/theme/index.ts +0 -34
  468. package/src/theme/migrate.test.ts +0 -178
  469. package/src/theme/migrate.ts +0 -81
  470. package/src/theme/presets.ts +0 -135
  471. package/src/theme/radius.ts +0 -18
  472. package/src/theme/resolve.test.ts +0 -238
  473. package/src/theme/resolve.ts +0 -96
  474. package/src/theme/spacing.ts +0 -18
  475. package/src/theme/storage.test.ts +0 -126
  476. package/src/theme/storage.ts +0 -106
  477. package/src/theme/theme-colors.ts +0 -88
  478. package/src/theme/types.ts +0 -125
  479. package/src/uploads/UploadAdapter.ts +0 -35
  480. package/src/uploads/index.ts +0 -2
  481. package/src/uploads/localUpload.test.ts +0 -70
  482. package/src/uploads/localUpload.ts +0 -84
  483. package/src/validation/Validator.ts +0 -49
  484. package/src/validation/index.ts +0 -28
  485. package/src/validation/rules.ts +0 -78
  486. package/src/validation/runValidators.ts +0 -435
  487. package/src/validation/uniqueValidator.test.ts +0 -196
  488. package/src/validation/uniqueValidator.ts +0 -133
  489. package/src/validation/validators.test.ts +0 -268
  490. package/src/vite.test.ts +0 -184
  491. package/src/vite.ts +0 -787
  492. package/src/widgets/index.ts +0 -10
  493. package/src/widgets/registry.ts +0 -45
  494. package/src/widgets.test.ts +0 -592
  495. package/tsconfig.build.json +0 -11
  496. package/tsconfig.json +0 -4
  497. package/tsconfig.test.json +0 -10
  498. package/views/react/Dashboard.tsx +0 -27
  499. package/views/react/Resources/Form.tsx +0 -102
  500. package/views/react/Resources/Index.tsx +0 -49
@@ -1,398 +0,0 @@
1
- /**
2
- * Database-backed notifications — server-side store helpers.
3
- *
4
- * Pilotiq doesn't ship a Prisma model; we read/write the
5
- * `notification` table that `@rudderjs/notification`'s
6
- * `NotificationProvider` publishes (`prisma/schema/notification.prisma`).
7
- * Apps that want bell-icon notifications add `NotificationProvider` to
8
- * their providers list and run `prisma generate`/`db push`; pilotiq
9
- * then queries the same table via `@rudderjs/orm`'s `ModelRegistry`
10
- * adapter so the wire shape matches what
11
- * `Notifier.send(user, new MyNotification())` already writes.
12
- *
13
- * `@rudderjs/orm` is a runtime soft-import — pilotiq has no hard
14
- * dependency on it. When the host app hasn't installed orm (or no
15
- * adapter is registered), every helper resolves to a clean
16
- * "store unavailable" sentinel rather than throwing.
17
- */
18
-
19
- import type { NotificationMeta, NotificationType } from './Notification.js'
20
- import type { NotificationActionMeta } from './types.js'
21
-
22
- /** Wire shape returned by the list endpoint to the bell client. */
23
- export interface DatabaseNotificationMeta {
24
- /** Stable PK from the `notification.id` column. */
25
- id: string
26
- /** Unix-ms timestamp the row was created. */
27
- createdAt: number
28
- /** ISO `read_at` timestamp; absent when unread. */
29
- readAt?: string
30
- /** Display title — read from the `data` JSON `title` key. */
31
- title: string
32
- /** Optional supporting text. */
33
- body?: string
34
- /** Optional UI tint. Mirrors the transient toast types so the bell can
35
- * share badge styling with the toaster. */
36
- type?: NotificationType
37
- /** Optional icon (registry name). */
38
- icon?: string
39
- /** Optional click-through URL. When set, clicking the row navigates
40
- * there + marks the notification as read. */
41
- url?: string
42
- /** Optional action strip rendered below the body. Round-trips
43
- * verbatim through the `data.actions` JSON column (`Notification`
44
- * emits the slim wire shape; `rowToMeta` validates each entry and
45
- * drops malformed ones with a `console.warn` rather than failing
46
- * the dropdown). */
47
- actions?: NotificationActionMeta[]
48
- }
49
-
50
- /** Raw row shape on the `notification` table — matches the schema
51
- * shipped by `@rudderjs/notification`. The `data` column is a
52
- * JSON-encoded string blob. */
53
- interface NotificationRow {
54
- id: string
55
- notifiable_id: string
56
- notifiable_type: string
57
- type: string
58
- data: string | Record<string, unknown>
59
- read_at: string | null
60
- created_at: string
61
- updated_at: string
62
- }
63
-
64
- /** Minimal query surface we use against the orm adapter. */
65
- interface QB {
66
- where(column: string, value: unknown): QB
67
- where(column: string, op: string, value: unknown): QB
68
- orderBy(column: string, dir?: 'ASC' | 'DESC'): QB
69
- paginate(page: number, perPage?: number): Promise<{ data: unknown[]; total: number }>
70
- get?(): Promise<unknown[]>
71
- count?(): Promise<number>
72
- update?(data: Record<string, unknown>): Promise<unknown>
73
- updateAll?(data: Record<string, unknown>): Promise<number>
74
- create?(data: Record<string, unknown>): Promise<unknown>
75
- }
76
-
77
- /** Test-injected adapter override; `null` falls back to dynamic import. */
78
- let _testAdapter: { query: <T>(table: string) => QB } | null | 'unset' = 'unset'
79
-
80
- /** Soft-resolved orm adapter. `null` when no orm adapter is registered.
81
- *
82
- * Prefers the rudder service container (`app().make('db')`) — the
83
- * orm-prisma / orm-drizzle providers register the adapter as a
84
- * globalThis-rooted singleton there, so this resolution path survives
85
- * the Vite SSR module-cache duplication that breaks shared singletons
86
- * in raw ES module land. Falls back to `ModelRegistry.get()` for
87
- * setups that wired the adapter directly.
88
- *
89
- * Both modules are imported indirectly so TypeScript doesn't try to
90
- * resolve them at type-check time — pilotiq doesn't peer-depend on
91
- * `@rudderjs/orm` or `@rudderjs/core` (the bell-icon is opt-in).
92
- */
93
- async function adapter(): Promise<{ query: <T>(table: string) => QB } | null> {
94
- if (_testAdapter !== 'unset') return _testAdapter
95
- const fromContainer = await resolveFromContainer()
96
- if (fromContainer) return fromContainer
97
- return resolveFromOrmModule()
98
- }
99
-
100
- async function resolveFromContainer(): Promise<{ query: <T>(table: string) => QB } | null> {
101
- const moduleName = '@rudderjs/core'
102
- try {
103
- const mod = await import(/* @vite-ignore */ moduleName) as {
104
- app?: () => { make(key: string): unknown }
105
- }
106
- if (!mod.app) return null
107
- const adapter = mod.app().make('db')
108
- if (!adapter || typeof adapter !== 'object') return null
109
- if (typeof (adapter as { query?: unknown }).query !== 'function') return null
110
- return adapter as { query: <T>(table: string) => QB }
111
- } catch {
112
- return null
113
- }
114
- }
115
-
116
- async function resolveFromOrmModule(): Promise<{ query: <T>(table: string) => QB } | null> {
117
- const moduleName = '@rudderjs/orm'
118
- try {
119
- const mod = await import(/* @vite-ignore */ moduleName) as {
120
- ModelRegistry?: { get(): { query: <T>(table: string) => QB } | null }
121
- }
122
- return mod.ModelRegistry?.get() ?? null
123
- } catch {
124
- return null
125
- }
126
- }
127
-
128
- /** Notification-table row JSON-decoded `data` payload. We always store
129
- * pilotiq's `NotificationMeta` shape; rows written by
130
- * `@rudderjs/notification.Notifier.send(...)` may carry arbitrary
131
- * application keys — we surface what we can recognize and ignore the rest. */
132
- function parseRowData(raw: string | Record<string, unknown>): Record<string, unknown> {
133
- if (typeof raw !== 'string') return raw
134
- try { return JSON.parse(raw) as Record<string, unknown> }
135
- catch { return {} }
136
- }
137
-
138
- function rowToMeta(row: NotificationRow): DatabaseNotificationMeta {
139
- const data = parseRowData(row.data)
140
- const meta: DatabaseNotificationMeta = {
141
- id: row.id,
142
- createdAt: Date.parse(row.created_at) || Date.now(),
143
- title: typeof data['title'] === 'string' ? (data['title'] as string) : '',
144
- }
145
- if (row.read_at) meta.readAt = row.read_at
146
- if (typeof data['body'] === 'string') meta.body = data['body'] as string
147
- if (typeof data['icon'] === 'string') meta.icon = data['icon'] as string
148
- if (typeof data['url'] === 'string') meta.url = data['url'] as string
149
- if (
150
- data['type'] === 'info' || data['type'] === 'success' ||
151
- data['type'] === 'warning' || data['type'] === 'error'
152
- ) {
153
- meta.type = data['type']
154
- }
155
- const actions = parseStoredActions(data['actions'])
156
- if (actions.length > 0) meta.actions = actions
157
- return meta
158
- }
159
-
160
- /**
161
- * Validate the stored action array shape — the `data.actions` column
162
- * is end-user controllable through the `Notification` builder, so we
163
- * defend in depth: malformed entries are dropped with a warning rather
164
- * than crashing the bell dropdown render.
165
- *
166
- * Required: `name: string`, `label: string`, exactly one of `url` /
167
- * `post` / `handler` set to a string.
168
- */
169
- function parseStoredActions(raw: unknown): NotificationActionMeta[] {
170
- if (!Array.isArray(raw)) return []
171
- const out: NotificationActionMeta[] = []
172
- for (const entry of raw) {
173
- if (!entry || typeof entry !== 'object') continue
174
- const e = entry as Record<string, unknown>
175
- if (typeof e['name'] !== 'string' || !e['name']) { warnDrop(e, 'missing name'); continue }
176
- if (typeof e['label'] !== 'string' || !e['label']) { warnDrop(e, 'missing label'); continue }
177
- const url = typeof e['url'] === 'string' ? e['url'] as string : undefined
178
- const post = typeof e['post'] === 'string' ? e['post'] as string : undefined
179
- const handler = typeof e['handler'] === 'string' ? e['handler'] as string : undefined
180
- const dispatchModes = [url, post, handler].filter(v => v !== undefined).length
181
- if (dispatchModes !== 1) { warnDrop(e, 'must set exactly one of url/post/handler'); continue }
182
-
183
- const action: NotificationActionMeta = { name: e['name'] as string, label: e['label'] as string }
184
- if (url !== undefined) action.url = url
185
- if (post !== undefined) action.post = post
186
- if (handler !== undefined) action.handler = handler
187
- if (e['payload'] && typeof e['payload'] === 'object' && !Array.isArray(e['payload'])) {
188
- action.payload = e['payload'] as Record<string, unknown>
189
- }
190
- if (typeof e['color'] === 'string') action.color = e['color'] as never
191
- if (typeof e['icon'] === 'string') action.icon = e['icon'] as string
192
- if (e['outlined'] === true) action.outlined = true
193
- if (typeof e['size'] === 'string') action.size = e['size'] as never
194
- if (e['openUrlInNewTab'] === true) action.openUrlInNewTab = true
195
- if (e['markAsRead'] === true) action.markAsRead = true
196
- out.push(action)
197
- }
198
- return out
199
- }
200
-
201
- function warnDrop(entry: Record<string, unknown>, reason: string): void {
202
- // Only warn in non-production — keep the bell quiet on prod where
203
- // a dropped row is preferable to console spam.
204
- if (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'production') return
205
-
206
- console.warn(
207
- `[Pilotiq] notification action dropped: ${reason}. Entry:`,
208
- entry,
209
- )
210
- }
211
-
212
- export interface ListOptions {
213
- /** `notifiable_type` column value. */
214
- notifiableType: string
215
- /** `notifiable_id` column value (typically the user's id). */
216
- notifiableId: string
217
- /** Hard cap on rows returned. Default 25. */
218
- limit?: number
219
- /** When true, only rows with `read_at IS NULL` are returned. */
220
- unreadOnly?: boolean
221
- }
222
-
223
- export interface ListResult {
224
- notifications: DatabaseNotificationMeta[]
225
- unreadCount: number
226
- }
227
-
228
- /**
229
- * Fetch the latest notifications for a notifiable + the unread count.
230
- * Returns `{ notifications: [], unreadCount: 0 }` when no orm adapter is
231
- * registered — apps without a database stay quiet rather than 500.
232
- */
233
- export async function listForUser(opts: ListOptions): Promise<ListResult> {
234
- const adp = await adapter()
235
- if (!adp) return { notifications: [], unreadCount: 0 }
236
-
237
- const limit = opts.limit ?? 25
238
- let q: QB = adp.query<NotificationRow>('notification')
239
- .where('notifiable_type', opts.notifiableType)
240
- .where('notifiable_id', opts.notifiableId)
241
- if (opts.unreadOnly) q = q.where('read_at', null)
242
- q = q.orderBy('created_at', 'DESC')
243
-
244
- const [page, count] = await Promise.all([
245
- q.paginate(1, limit),
246
- unreadCount({ notifiableType: opts.notifiableType, notifiableId: opts.notifiableId }),
247
- ])
248
- const rows = (page.data as NotificationRow[]).map(rowToMeta)
249
- return { notifications: rows, unreadCount: count }
250
- }
251
-
252
- /**
253
- * Fetch a single row by id, scoped to the notifiable. Returns
254
- * `undefined` when no row matches (already-deleted / wrong owner /
255
- * store unavailable). Used by the notification action route to look
256
- * up the stored `data.actions` array before dispatching.
257
- */
258
- export async function findOneForUser(
259
- id: string,
260
- opts: { notifiableType: string; notifiableId: string },
261
- ): Promise<DatabaseNotificationMeta | undefined> {
262
- const adp = await adapter()
263
- if (!adp) return undefined
264
- const q = adp.query<NotificationRow>('notification')
265
- .where('notifiable_type', opts.notifiableType)
266
- .where('notifiable_id', opts.notifiableId)
267
- .where('id', id)
268
- const page = await q.paginate(1, 1)
269
- const row = (page.data as NotificationRow[])[0]
270
- if (!row) return undefined
271
- return rowToMeta(row)
272
- }
273
-
274
- /** Count rows with `read_at IS NULL` for the notifiable. */
275
- export async function unreadCount(opts: {
276
- notifiableType: string
277
- notifiableId: string
278
- }): Promise<number> {
279
- const adp = await adapter()
280
- if (!adp) return 0
281
- const q = adp.query<NotificationRow>('notification')
282
- .where('notifiable_type', opts.notifiableType)
283
- .where('notifiable_id', opts.notifiableId)
284
- .where('read_at', null)
285
- // Cheap path when the adapter implements `count()`; fall back to
286
- // paginate(1,1).total which both Prisma and Drizzle adapters support.
287
- if (q.count) return q.count()
288
- const page = await q.paginate(1, 1)
289
- return page.total
290
- }
291
-
292
- /**
293
- * Mark a single notification row as read. Always scoped to
294
- * `notifiableId` so a tampered POST can't mark another user's row.
295
- *
296
- * Returns `true` when a row was updated, `false` when no row matched
297
- * (already-deleted / wrong owner / store unavailable).
298
- */
299
- export async function markAsRead(
300
- id: string,
301
- opts: { notifiableType: string; notifiableId: string },
302
- ): Promise<boolean> {
303
- const adp = await adapter()
304
- if (!adp) return false
305
- const q = adp.query<NotificationRow>('notification')
306
- .where('notifiable_type', opts.notifiableType)
307
- .where('notifiable_id', opts.notifiableId)
308
- .where('id', id)
309
- if (!q.updateAll) return false
310
- const n = await q.updateAll({ read_at: new Date().toISOString() })
311
- return n > 0
312
- }
313
-
314
- /** Mark a row unread again — used by the bell's "mark unread" affordance. */
315
- export async function markAsUnread(
316
- id: string,
317
- opts: { notifiableType: string; notifiableId: string },
318
- ): Promise<boolean> {
319
- const adp = await adapter()
320
- if (!adp) return false
321
- const q = adp.query<NotificationRow>('notification')
322
- .where('notifiable_type', opts.notifiableType)
323
- .where('notifiable_id', opts.notifiableId)
324
- .where('id', id)
325
- if (!q.updateAll) return false
326
- const n = await q.updateAll({ read_at: null })
327
- return n > 0
328
- }
329
-
330
- /** Mark every unread notification for the notifiable as read. */
331
- export async function markAllAsRead(opts: {
332
- notifiableType: string
333
- notifiableId: string
334
- }): Promise<number> {
335
- const adp = await adapter()
336
- if (!adp) return 0
337
- const q = adp.query<NotificationRow>('notification')
338
- .where('notifiable_type', opts.notifiableType)
339
- .where('notifiable_id', opts.notifiableId)
340
- .where('read_at', null)
341
- if (!q.updateAll) return 0
342
- return q.updateAll({ read_at: new Date().toISOString() })
343
- }
344
-
345
- /**
346
- * Insert a notification row directly. Powers
347
- * `Notification.make(...).sendToDatabase(recipient)`. Throws when the
348
- * orm adapter isn't registered — the caller has explicitly asked to
349
- * persist, so silent no-op would hide a real config error.
350
- */
351
- export async function persist(opts: {
352
- notifiableType: string
353
- notifiableId: string
354
- type?: string
355
- data: NotificationMeta & Record<string, unknown>
356
- }): Promise<{ id: string }> {
357
- const adp = await adapter()
358
- if (!adp) {
359
- throw new Error(
360
- '[Pilotiq] sendToDatabase() called but no @rudderjs/orm adapter is registered. ' +
361
- 'Add a database provider (orm-prisma / orm-drizzle) to your providers list, ' +
362
- "or call .sendToDatabase() only when the orm is wired up.",
363
- )
364
- }
365
- const q = adp.query<NotificationRow>('notification')
366
- if (!q.create) {
367
- throw new Error('[Pilotiq] orm adapter does not support `query.create()`.')
368
- }
369
- const id = `pn_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`
370
- const now = new Date().toISOString()
371
- await q.create({
372
- id,
373
- notifiable_id: opts.notifiableId,
374
- notifiable_type: opts.notifiableType,
375
- type: opts.type ?? 'PilotiqNotification',
376
- data: JSON.stringify(opts.data),
377
- read_at: null,
378
- created_at: now,
379
- updated_at: now,
380
- })
381
- return { id }
382
- }
383
-
384
- /** @internal — test seam. Inject a fake adapter (or `null` to mimic
385
- * "store unavailable"). Pass `undefined` to clear and fall back to the
386
- * dynamic `@rudderjs/orm` import. Tests should clear in `afterEach`. */
387
- export function _setTestAdapter(
388
- adp: { query: <T>(table: string) => QB } | null | undefined,
389
- ): void {
390
- _testAdapter = adp === undefined ? 'unset' : adp
391
- }
392
-
393
- /** @internal — exposed for tests; lets a unit test inject a fake
394
- * ModelRegistry without monkey-patching dynamic-import. */
395
- export const _internal = {
396
- parseRowData,
397
- rowToMeta,
398
- }
@@ -1,187 +0,0 @@
1
- /**
2
- * Builder + panelInfo() integration tests for
3
- * `Pilotiq.databaseNotifications()`. The transport layer (the
4
- * `_notifications` route family) is exercised via the storage tests +
5
- * `database.test.ts`; here we lock down the wire shape consumers
6
- * actually depend on.
7
- */
8
- import { describe, it } from 'node:test'
9
- import assert from 'node:assert/strict'
10
-
11
- import { Pilotiq } from '../Pilotiq.js'
12
- import { panelInfo } from '../pageData.js'
13
-
14
- describe('Pilotiq.databaseNotifications() — builder', () => {
15
- it('opt-out by default — cfg.databaseNotifications is undefined', () => {
16
- const cfg = Pilotiq.make('admin').getConfig()
17
- assert.equal(cfg.databaseNotifications, undefined)
18
- })
19
-
20
- it('toggle without options enables with defaults', () => {
21
- const cfg = Pilotiq.make('admin').databaseNotifications().getConfig()
22
- assert.equal(cfg.databaseNotifications?.enabled, true)
23
- assert.equal(cfg.databaseNotifications?.position, undefined)
24
- assert.equal(cfg.databaseNotifications?.polling, undefined)
25
- })
26
-
27
- it('options round-trip', () => {
28
- const cfg = Pilotiq.make('admin').databaseNotifications({
29
- position: 'sidebar',
30
- polling: 10,
31
- pageSize: 50,
32
- badgeColor: 'success',
33
- trigger: { icon: 'bell', label: 'Inbox' },
34
- }).getConfig()
35
- assert.equal(cfg.databaseNotifications?.position, 'sidebar')
36
- assert.equal(cfg.databaseNotifications?.polling, 10)
37
- assert.equal(cfg.databaseNotifications?.pageSize, 50)
38
- assert.equal(cfg.databaseNotifications?.badgeColor, 'success')
39
- assert.equal(cfg.databaseNotifications?.trigger?.icon, 'bell')
40
- })
41
-
42
- it('null polling round-trips (disable auto-poll)', () => {
43
- const cfg = Pilotiq.make('admin').databaseNotifications({ polling: null }).getConfig()
44
- assert.equal(cfg.databaseNotifications?.polling, null)
45
- })
46
-
47
- it('databaseNotificationsPolling sugar updates the slot', () => {
48
- const cfg = Pilotiq.make('admin')
49
- .databaseNotifications()
50
- .databaseNotificationsPolling(120)
51
- .getConfig()
52
- assert.equal(cfg.databaseNotifications?.polling, 120)
53
- })
54
-
55
- it('databaseNotificationsPolling is a no-op when not enabled', () => {
56
- const cfg = Pilotiq.make('admin').databaseNotificationsPolling(5).getConfig()
57
- assert.equal(cfg.databaseNotifications, undefined)
58
- })
59
-
60
- it('databaseNotificationsPosition sugar updates the slot', () => {
61
- const cfg = Pilotiq.make('admin')
62
- .databaseNotifications()
63
- .databaseNotificationsPosition('sidebar')
64
- .getConfig()
65
- assert.equal(cfg.databaseNotifications?.position, 'sidebar')
66
- })
67
- })
68
-
69
- describe('panelInfo() — databaseNotifications meta', () => {
70
- it('absent when never opted in', async () => {
71
- const panel = await panelInfo(Pilotiq.make('admin'))
72
- assert.equal((panel as Record<string, unknown>)['databaseNotifications'], undefined)
73
- })
74
-
75
- it('absent when no user resolves', async () => {
76
- const p = Pilotiq.make('admin').databaseNotifications()
77
- const panel = await panelInfo(p)
78
- assert.equal((panel as Record<string, unknown>)['databaseNotifications'], undefined)
79
- })
80
-
81
- it('present with resolver + defaults', async () => {
82
- const p = Pilotiq.make('admin')
83
- .user(() => ({ id: 1, name: 'Sue' }))
84
- .databaseNotifications()
85
- const panel = await panelInfo(p)
86
- const dn = (panel as any).databaseNotifications
87
- assert.ok(dn, 'databaseNotifications is present')
88
- assert.equal(dn.position, 'topbar')
89
- assert.equal(dn.polling, 30)
90
- assert.equal(dn.pageSize, 25)
91
- assert.equal(dn.badgeColor, 'primary')
92
- assert.equal(dn.listUrl, '/admin/_notifications')
93
- assert.equal(dn.readAllUrl, '/admin/_notifications/read-all')
94
- assert.equal(dn.readUrl, '/admin/_notifications/:id/read')
95
- assert.equal(dn.unreadUrl, '/admin/_notifications/:id/unread')
96
- assert.equal(dn.actionUrl, '/admin/_notifications/:id/_action/:actionName')
97
- })
98
-
99
- it('honors custom path for URL building', async () => {
100
- const p = Pilotiq.make('admin')
101
- .path('/dashboard')
102
- .user(() => ({ id: 1 }))
103
- .databaseNotifications()
104
- const panel = await panelInfo(p)
105
- const dn = (panel as any).databaseNotifications
106
- assert.equal(dn.listUrl, '/dashboard/_notifications')
107
- })
108
-
109
- it('null polling round-trips to the wire', async () => {
110
- const p = Pilotiq.make('admin')
111
- .user(() => ({ id: 1 }))
112
- .databaseNotifications({ polling: null })
113
- const panel = await panelInfo(p)
114
- const dn = (panel as any).databaseNotifications
115
- assert.equal(dn.polling, null)
116
- })
117
-
118
- it('per-call options override defaults', async () => {
119
- const p = Pilotiq.make('admin')
120
- .user(() => ({ id: 1 }))
121
- .databaseNotifications({
122
- position: 'sidebar',
123
- polling: 5,
124
- pageSize: 10,
125
- badgeColor: 'warning',
126
- })
127
- const panel = await panelInfo(p)
128
- const dn = (panel as any).databaseNotifications
129
- assert.equal(dn.position, 'sidebar')
130
- assert.equal(dn.polling, 5)
131
- assert.equal(dn.pageSize, 10)
132
- assert.equal(dn.badgeColor, 'warning')
133
- })
134
-
135
- it('trigger overrides ride through to the wire', async () => {
136
- const p = Pilotiq.make('admin')
137
- .user(() => ({ id: 1 }))
138
- .databaseNotifications({ trigger: { icon: 'bell', label: 'Inbox' } })
139
- const panel = await panelInfo(p)
140
- const dn = (panel as any).databaseNotifications
141
- assert.deepEqual(dn.trigger, { icon: 'bell', label: 'Inbox' })
142
- })
143
- })
144
-
145
- describe('panelInfo() — broadcast (Phase 2)', () => {
146
- it('absent when broadcast wasn\'t enabled', async () => {
147
- const p = Pilotiq.make('admin')
148
- .user(() => ({ id: 1 }))
149
- .databaseNotifications()
150
- const panel = await panelInfo(p)
151
- const dn = (panel as any).databaseNotifications
152
- assert.equal(dn.broadcast, undefined)
153
- })
154
-
155
- it('present when databaseNotificationsBroadcast() is called', async () => {
156
- const p = Pilotiq.make('admin')
157
- .user(() => ({ id: 42 }))
158
- .databaseNotifications()
159
- .databaseNotificationsBroadcast()
160
- const panel = await panelInfo(p)
161
- const dn = (panel as any).databaseNotifications
162
- assert.ok(dn.broadcast, 'broadcast meta is present')
163
- assert.equal(dn.broadcast.channel, 'private-pilotiq-notifications.42')
164
- assert.equal(dn.broadcast.event, 'notification.created')
165
- assert.equal(dn.broadcast.wsUrl, '') // empty -> client falls back to same-origin
166
- })
167
-
168
- it('honors a custom wsUrl', async () => {
169
- const p = Pilotiq.make('admin')
170
- .user(() => ({ id: 'u-1' }))
171
- .databaseNotifications({ broadcast: { wsUrl: 'wss://x.test/ws' } })
172
- const panel = await panelInfo(p)
173
- const dn = (panel as any).databaseNotifications
174
- assert.equal(dn.broadcast.wsUrl, 'wss://x.test/ws')
175
- assert.equal(dn.broadcast.channel, 'private-pilotiq-notifications.u-1')
176
- })
177
-
178
- it('absent when user has no id (channel cannot be scoped)', async () => {
179
- const p = Pilotiq.make('admin')
180
- .user(() => ({ name: 'Anonymous' }) as unknown as { id: string })
181
- .databaseNotifications()
182
- .databaseNotificationsBroadcast()
183
- const panel = await panelInfo(p)
184
- const dn = (panel as any).databaseNotifications
185
- assert.equal(dn?.broadcast, undefined)
186
- })
187
- })