@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.
Files changed (480) hide show
  1. package/CHANGELOG.md +33 -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/package.json +6 -1
  15. package/.turbo/turbo-build.log +0 -8
  16. package/CLAUDE.md +0 -265
  17. package/src/Cluster.test.ts +0 -283
  18. package/src/Cluster.ts +0 -83
  19. package/src/Column.test.ts +0 -199
  20. package/src/Column.ts +0 -710
  21. package/src/Global.test.ts +0 -367
  22. package/src/Global.ts +0 -169
  23. package/src/Page.test.ts +0 -114
  24. package/src/Page.ts +0 -208
  25. package/src/Pilotiq.perf.test.ts +0 -252
  26. package/src/Pilotiq.test.ts +0 -129
  27. package/src/Pilotiq.ts +0 -1158
  28. package/src/PilotiqRegistry.ts +0 -36
  29. package/src/PilotiqServiceProvider.ts +0 -121
  30. package/src/RelationManager.test.ts +0 -400
  31. package/src/RelationManager.ts +0 -527
  32. package/src/RenderHook.test.ts +0 -252
  33. package/src/RenderHook.ts +0 -242
  34. package/src/Resource.test.ts +0 -284
  35. package/src/Resource.ts +0 -526
  36. package/src/RightPanel.test.ts +0 -202
  37. package/src/RightPanel.ts +0 -132
  38. package/src/Tab.test.ts +0 -91
  39. package/src/Tab.ts +0 -156
  40. package/src/UserMenuItem.ts +0 -145
  41. package/src/actions/Action.test.ts +0 -2526
  42. package/src/actions/Action.ts +0 -1515
  43. package/src/actions/ActionGroup.test.ts +0 -112
  44. package/src/actions/ActionGroup.ts +0 -173
  45. package/src/actions/attachFactory.ts +0 -172
  46. package/src/actions/bulkFactories.ts +0 -168
  47. package/src/actions/crudFactories.ts +0 -220
  48. package/src/actions/exportFactory.ts +0 -225
  49. package/src/actions/factoryHelpers.ts +0 -177
  50. package/src/actions/importFactory.ts +0 -243
  51. package/src/actions/index.ts +0 -17
  52. package/src/actions/m2mFactories.ts +0 -193
  53. package/src/actions/relationFactories.ts +0 -372
  54. package/src/applyPageHooks.test.ts +0 -463
  55. package/src/applyPageHooks.ts +0 -330
  56. package/src/authorization.test.ts +0 -483
  57. package/src/breadcrumbs.test.ts +0 -238
  58. package/src/cells/coerce.test.ts +0 -85
  59. package/src/cells/coerce.ts +0 -84
  60. package/src/clusterPaths.ts +0 -35
  61. package/src/columns/BadgeColumn.test.ts +0 -54
  62. package/src/columns/BadgeColumn.ts +0 -32
  63. package/src/columns/BooleanColumn.test.ts +0 -41
  64. package/src/columns/BooleanColumn.ts +0 -18
  65. package/src/columns/ColorColumn.test.ts +0 -37
  66. package/src/columns/ColorColumn.ts +0 -38
  67. package/src/columns/IconColumn.test.ts +0 -54
  68. package/src/columns/IconColumn.ts +0 -37
  69. package/src/columns/ImageColumn.test.ts +0 -41
  70. package/src/columns/ImageColumn.ts +0 -28
  71. package/src/columns/SelectColumn.ts +0 -98
  72. package/src/columns/TextColumn.test.ts +0 -190
  73. package/src/columns/TextColumn.ts +0 -20
  74. package/src/columns/TextInputColumn.ts +0 -68
  75. package/src/columns/ToggleColumn.ts +0 -46
  76. package/src/columns/editableColumns.test.ts +0 -238
  77. package/src/columns/index.ts +0 -9
  78. package/src/defaultGlobalPages.ts +0 -95
  79. package/src/defaultPages.test.ts +0 -634
  80. package/src/defaultPages.ts +0 -617
  81. package/src/defaultViewPage.test.ts +0 -147
  82. package/src/elements/Form.test.ts +0 -223
  83. package/src/elements/Form.ts +0 -416
  84. package/src/elements/ListTabs.ts +0 -28
  85. package/src/elements/Table.test.ts +0 -422
  86. package/src/elements/Table.ts +0 -850
  87. package/src/elements/TableGroup.test.ts +0 -260
  88. package/src/elements/TableGroup.ts +0 -334
  89. package/src/elements/dispatchAction.test.ts +0 -463
  90. package/src/elements/dispatchAction.ts +0 -355
  91. package/src/elements/dispatchForm.test.ts +0 -477
  92. package/src/elements/dispatchForm.ts +0 -1993
  93. package/src/elements/dispatchTable.test.ts +0 -1514
  94. package/src/elements/dispatchTable.ts +0 -745
  95. package/src/elements/index.ts +0 -21
  96. package/src/entries/BadgeEntry.ts +0 -39
  97. package/src/entries/CodeEntry.test.ts +0 -40
  98. package/src/entries/CodeEntry.ts +0 -52
  99. package/src/entries/ColorEntry.ts +0 -63
  100. package/src/entries/ComponentEntry.test.ts +0 -173
  101. package/src/entries/ComponentEntry.ts +0 -95
  102. package/src/entries/Entry.ts +0 -304
  103. package/src/entries/IconEntry.ts +0 -49
  104. package/src/entries/ImageEntry.ts +0 -61
  105. package/src/entries/KeyValueEntry.ts +0 -47
  106. package/src/entries/RepeatableEntry.test.ts +0 -239
  107. package/src/entries/RepeatableEntry.ts +0 -173
  108. package/src/entries/TextEntry.test.ts +0 -394
  109. package/src/entries/TextEntry.ts +0 -60
  110. package/src/entries/index.ts +0 -12
  111. package/src/entries/leaves.test.ts +0 -306
  112. package/src/entries/registry.ts +0 -54
  113. package/src/fields/BuilderField.test.ts +0 -1188
  114. package/src/fields/BuilderField.ts +0 -605
  115. package/src/fields/BuilderRelationship.test.ts +0 -811
  116. package/src/fields/CheckboxField.test.ts +0 -44
  117. package/src/fields/CheckboxField.ts +0 -27
  118. package/src/fields/CheckboxListField.test.ts +0 -99
  119. package/src/fields/CheckboxListField.ts +0 -66
  120. package/src/fields/ColorPickerField.test.ts +0 -33
  121. package/src/fields/ColorPickerField.ts +0 -25
  122. package/src/fields/DateField.ts +0 -54
  123. package/src/fields/DateTimeField.test.ts +0 -55
  124. package/src/fields/EmailField.ts +0 -16
  125. package/src/fields/Field.test.ts +0 -654
  126. package/src/fields/Field.ts +0 -817
  127. package/src/fields/FileUploadField.test.ts +0 -143
  128. package/src/fields/FileUploadField.ts +0 -159
  129. package/src/fields/HiddenField.test.ts +0 -27
  130. package/src/fields/HiddenField.ts +0 -28
  131. package/src/fields/KeyValueField.test.ts +0 -105
  132. package/src/fields/KeyValueField.ts +0 -55
  133. package/src/fields/MarkdownField.test.ts +0 -167
  134. package/src/fields/MarkdownField.ts +0 -162
  135. package/src/fields/NumberField.ts +0 -33
  136. package/src/fields/RadioField.test.ts +0 -94
  137. package/src/fields/RadioField.ts +0 -67
  138. package/src/fields/RepeaterField.test.ts +0 -1806
  139. package/src/fields/RepeaterField.ts +0 -939
  140. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  141. package/src/fields/RepeaterSimple.test.ts +0 -248
  142. package/src/fields/RowButton.test.ts +0 -219
  143. package/src/fields/RowButton.ts +0 -135
  144. package/src/fields/SelectField.test.ts +0 -192
  145. package/src/fields/SelectField.ts +0 -235
  146. package/src/fields/SliderField.test.ts +0 -50
  147. package/src/fields/SliderField.ts +0 -53
  148. package/src/fields/SlugField.ts +0 -24
  149. package/src/fields/TagsInputField.test.ts +0 -154
  150. package/src/fields/TagsInputField.ts +0 -133
  151. package/src/fields/TextField.test.ts +0 -213
  152. package/src/fields/TextField.ts +0 -177
  153. package/src/fields/TextareaField.test.ts +0 -58
  154. package/src/fields/TextareaField.ts +0 -59
  155. package/src/fields/ToggleButtonsField.test.ts +0 -106
  156. package/src/fields/ToggleButtonsField.ts +0 -59
  157. package/src/fields/ToggleField.ts +0 -16
  158. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  159. package/src/fields/optionsResolver.ts +0 -95
  160. package/src/fields/resolveField.ts +0 -28
  161. package/src/filters/BooleanFilter.ts +0 -35
  162. package/src/filters/DateRangeFilter.test.ts +0 -194
  163. package/src/filters/DateRangeFilter.ts +0 -148
  164. package/src/filters/Filter.test.ts +0 -268
  165. package/src/filters/Filter.ts +0 -184
  166. package/src/filters/FormFilter.test.ts +0 -238
  167. package/src/filters/FormFilter.ts +0 -215
  168. package/src/filters/MultiSelectFilter.test.ts +0 -119
  169. package/src/filters/MultiSelectFilter.ts +0 -78
  170. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  171. package/src/filters/QueryBuilderFilter.ts +0 -398
  172. package/src/filters/SelectFilter.ts +0 -46
  173. package/src/filters/TernaryFilter.test.ts +0 -160
  174. package/src/filters/TernaryFilter.ts +0 -72
  175. package/src/filters/TrashedFilter.test.ts +0 -149
  176. package/src/filters/TrashedFilter.ts +0 -55
  177. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  178. package/src/filters/queryBuilder/Constraint.ts +0 -115
  179. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  180. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  181. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  182. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  183. package/src/filters/queryBuilder/index.ts +0 -12
  184. package/src/icons/index.ts +0 -2
  185. package/src/icons/lucide.ts +0 -204
  186. package/src/icons/registry.test.ts +0 -56
  187. package/src/icons/registry.ts +0 -41
  188. package/src/icons/types.ts +0 -47
  189. package/src/index.ts +0 -525
  190. package/src/io/csv.test.ts +0 -142
  191. package/src/io/csv.ts +0 -170
  192. package/src/nestedRelationManagerData.test.ts +0 -547
  193. package/src/notifications/Notification.test.ts +0 -210
  194. package/src/notifications/Notification.ts +0 -354
  195. package/src/notifications/broadcast.test.ts +0 -110
  196. package/src/notifications/broadcast.ts +0 -95
  197. package/src/notifications/database.test.ts +0 -383
  198. package/src/notifications/database.ts +0 -398
  199. package/src/notifications/databaseNotifications.test.ts +0 -187
  200. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  201. package/src/notifications/dispatchNotificationAction.ts +0 -142
  202. package/src/notifications/flash.test.ts +0 -89
  203. package/src/notifications/flash.ts +0 -71
  204. package/src/notifications/index.ts +0 -45
  205. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  206. package/src/notifications/registerBroadcastAuth.ts +0 -100
  207. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  208. package/src/notifications/resolveSavedNotification.ts +0 -59
  209. package/src/notifications/types.ts +0 -93
  210. package/src/orm/m2mAccessor.ts +0 -66
  211. package/src/orm/modelDefaults.test.ts +0 -633
  212. package/src/orm/modelDefaults.ts +0 -666
  213. package/src/pageData/breadcrumbs.ts +0 -288
  214. package/src/pageData/forms.ts +0 -578
  215. package/src/pageData/helpers.ts +0 -857
  216. package/src/pageData/misc.ts +0 -347
  217. package/src/pageData/navigation.ts +0 -842
  218. package/src/pageData/relationPages.ts +0 -1248
  219. package/src/pageData/relationTabs.ts +0 -286
  220. package/src/pageData/resourcePages.ts +0 -609
  221. package/src/pageData.test.ts +0 -1545
  222. package/src/pageData.ts +0 -341
  223. package/src/plugins/index.ts +0 -8
  224. package/src/plugins/themeEditor.test.ts +0 -36
  225. package/src/plugins/themeEditor.ts +0 -45
  226. package/src/react/AppShell.tsx +0 -251
  227. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  228. package/src/react/CollabRoomContext.ts +0 -98
  229. package/src/react/CollabTextRendererRegistry.ts +0 -102
  230. package/src/react/CommandPalette.tsx +0 -375
  231. package/src/react/CurrentUserContext.tsx +0 -50
  232. package/src/react/CustomPageWrapperGate.tsx +0 -69
  233. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  234. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  235. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  236. package/src/react/FieldPresenceRegistry.ts +0 -46
  237. package/src/react/FormCollabBindingRegistry.ts +0 -242
  238. package/src/react/FormStateContext.tsx +0 -591
  239. package/src/react/HeadHooks.tsx +0 -126
  240. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  241. package/src/react/MarkdownEditorRegistry.ts +0 -107
  242. package/src/react/NotificationActionStrip.tsx +0 -263
  243. package/src/react/NotificationBell.tsx +0 -426
  244. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  245. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  246. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  247. package/src/react/PendingSuggestionsContext.tsx +0 -172
  248. package/src/react/RecordWrapperGate.tsx +0 -58
  249. package/src/react/RecordWrapperRegistry.ts +0 -39
  250. package/src/react/RenderHookSlot.tsx +0 -32
  251. package/src/react/RightSidebar.tsx +0 -257
  252. package/src/react/RightSidebarContext.tsx +0 -234
  253. package/src/react/RightSidebarTrigger.tsx +0 -53
  254. package/src/react/RowCoordsContext.tsx +0 -23
  255. package/src/react/SchemaRenderer.tsx +0 -549
  256. package/src/react/SearchTrigger.tsx +0 -46
  257. package/src/react/ThemeProvider.tsx +0 -93
  258. package/src/react/ThemeSettingsPage.tsx +0 -579
  259. package/src/react/ThemeToggle.tsx +0 -20
  260. package/src/react/Toaster.tsx +0 -158
  261. package/src/react/UserMenu.tsx +0 -196
  262. package/src/react/WidgetDataContext.tsx +0 -157
  263. package/src/react/cells/EditableCell.tsx +0 -389
  264. package/src/react/component-slots.test.ts +0 -103
  265. package/src/react/component-slots.ts +0 -116
  266. package/src/react/fieldJsHandler.test.ts +0 -166
  267. package/src/react/fieldJsHandler.ts +0 -79
  268. package/src/react/fields/BuilderInput.tsx +0 -1078
  269. package/src/react/fields/CheckboxInput.tsx +0 -39
  270. package/src/react/fields/CheckboxListInput.tsx +0 -102
  271. package/src/react/fields/ColorInput.tsx +0 -71
  272. package/src/react/fields/DateFieldInput.tsx +0 -70
  273. package/src/react/fields/DateTimeInput.tsx +0 -62
  274. package/src/react/fields/FieldShell.tsx +0 -348
  275. package/src/react/fields/FileUploadInput.tsx +0 -639
  276. package/src/react/fields/HiddenInput.tsx +0 -17
  277. package/src/react/fields/KeyValueInput.tsx +0 -230
  278. package/src/react/fields/MarkdownInput.tsx +0 -560
  279. package/src/react/fields/RadioInput.tsx +0 -81
  280. package/src/react/fields/RepeaterInput.test.ts +0 -116
  281. package/src/react/fields/RepeaterInput.tsx +0 -1420
  282. package/src/react/fields/SelectFieldInput.tsx +0 -280
  283. package/src/react/fields/SliderInput.tsx +0 -81
  284. package/src/react/fields/TagsInput.tsx +0 -283
  285. package/src/react/fields/TextLikeInput.tsx +0 -256
  286. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  287. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  288. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  289. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  290. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  291. package/src/react/fields/repeaterReconcile.ts +0 -104
  292. package/src/react/fields/rowChromeButton.tsx +0 -336
  293. package/src/react/fields/rowState.ts +0 -106
  294. package/src/react/fields/syncRowGates.test.ts +0 -202
  295. package/src/react/fields/syncRowGates.ts +0 -66
  296. package/src/react/fields/textInputControls.tsx +0 -238
  297. package/src/react/fields/useRowReorderDnd.ts +0 -78
  298. package/src/react/formStateHelpers.test.ts +0 -508
  299. package/src/react/formStateHelpers.ts +0 -381
  300. package/src/react/hooks/use-mobile.ts +0 -19
  301. package/src/react/icon-context.tsx +0 -60
  302. package/src/react/index.ts +0 -194
  303. package/src/react/layouts/SidebarLayout.tsx +0 -250
  304. package/src/react/layouts/TopbarLayout.tsx +0 -258
  305. package/src/react/navigate.tsx +0 -37
  306. package/src/react/onProviderSynced.test.ts +0 -90
  307. package/src/react/parseRecordEditUrl.test.ts +0 -122
  308. package/src/react/parseRecordEditUrl.ts +0 -94
  309. package/src/react/persistedState.ts +0 -40
  310. package/src/react/registry.ts +0 -48
  311. package/src/react/right-panel-registry.tsx +0 -47
  312. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  313. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  314. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  315. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  316. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  317. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  318. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  319. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  320. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  321. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  322. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  323. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  324. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  325. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  326. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  327. package/src/react/schemaRenderer/constants.ts +0 -50
  328. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  329. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  330. package/src/react/schemaRenderer/helpers.tsx +0 -81
  331. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  332. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  333. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  334. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  335. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  336. package/src/react/schemaRenderer/table/links.tsx +0 -112
  337. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  338. package/src/react/schemaRenderer/table/url.tsx +0 -143
  339. package/src/react/theme-preview/apply.ts +0 -99
  340. package/src/react/theme-preview/build-html.ts +0 -436
  341. package/src/react/ui/button.tsx +0 -51
  342. package/src/react/ui/calendar.tsx +0 -67
  343. package/src/react/ui/checkbox.tsx +0 -29
  344. package/src/react/ui/dialog.tsx +0 -108
  345. package/src/react/ui/dropdown-menu.tsx +0 -97
  346. package/src/react/ui/input.tsx +0 -20
  347. package/src/react/ui/label.tsx +0 -21
  348. package/src/react/ui/popover.tsx +0 -50
  349. package/src/react/ui/select.tsx +0 -169
  350. package/src/react/ui/separator.tsx +0 -25
  351. package/src/react/ui/sheet.tsx +0 -136
  352. package/src/react/ui/sidebar.tsx +0 -723
  353. package/src/react/ui/skeleton.tsx +0 -13
  354. package/src/react/ui/slider.tsx +0 -34
  355. package/src/react/ui/switch.tsx +0 -28
  356. package/src/react/ui/table.tsx +0 -105
  357. package/src/react/ui/tabs.tsx +0 -63
  358. package/src/react/ui/textarea.tsx +0 -18
  359. package/src/react/ui/tooltip.tsx +0 -64
  360. package/src/react/useResizableWidth.ts +0 -139
  361. package/src/react/utils.ts +0 -6
  362. package/src/react/widgetRegistry.test.ts +0 -43
  363. package/src/react/widgetRegistry.ts +0 -50
  364. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  365. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  366. package/src/react/widgets/ViewRenderer.tsx +0 -71
  367. package/src/relationManagerData.test.ts +0 -1595
  368. package/src/richtext/index.ts +0 -8
  369. package/src/richtext/registry.ts +0 -89
  370. package/src/routes/globals.ts +0 -148
  371. package/src/routes/guard.test.ts +0 -325
  372. package/src/routes/helpers.ts +0 -704
  373. package/src/routes/pages.ts +0 -175
  374. package/src/routes/panel.ts +0 -204
  375. package/src/routes/relations.ts +0 -1243
  376. package/src/routes/resources.ts +0 -781
  377. package/src/routes/theme.ts +0 -91
  378. package/src/routes-nested-relations.test.ts +0 -676
  379. package/src/routes-relations.test.ts +0 -972
  380. package/src/routes.test.ts +0 -2027
  381. package/src/routes.ts +0 -303
  382. package/src/schema/Alert.test.ts +0 -109
  383. package/src/schema/Alert.ts +0 -131
  384. package/src/schema/Block.ts +0 -169
  385. package/src/schema/Breadcrumbs.ts +0 -40
  386. package/src/schema/Card.ts +0 -35
  387. package/src/schema/Divider.ts +0 -20
  388. package/src/schema/Element.ts +0 -219
  389. package/src/schema/EmptyState.test.ts +0 -37
  390. package/src/schema/EmptyState.ts +0 -63
  391. package/src/schema/Fieldset.ts +0 -43
  392. package/src/schema/Grid.ts +0 -43
  393. package/src/schema/Group.ts +0 -30
  394. package/src/schema/Heading.ts +0 -39
  395. package/src/schema/Html.ts +0 -67
  396. package/src/schema/Icon.ts +0 -54
  397. package/src/schema/Image.ts +0 -57
  398. package/src/schema/LinkTag.ts +0 -41
  399. package/src/schema/Markdown.ts +0 -85
  400. package/src/schema/MetaTag.ts +0 -41
  401. package/src/schema/RelationTabs.ts +0 -71
  402. package/src/schema/ScriptTag.ts +0 -55
  403. package/src/schema/Section.ts +0 -160
  404. package/src/schema/ServerDataElement.test.ts +0 -140
  405. package/src/schema/ServerDataElement.ts +0 -156
  406. package/src/schema/SlotComponent.test.ts +0 -77
  407. package/src/schema/SlotComponent.ts +0 -71
  408. package/src/schema/Split.ts +0 -50
  409. package/src/schema/Stat.test.ts +0 -118
  410. package/src/schema/Stat.ts +0 -154
  411. package/src/schema/StatsOverview.test.ts +0 -141
  412. package/src/schema/StatsOverview.ts +0 -119
  413. package/src/schema/StyleTag.ts +0 -35
  414. package/src/schema/TableWidget.test.ts +0 -297
  415. package/src/schema/TableWidget.ts +0 -289
  416. package/src/schema/Tabs.ts +0 -79
  417. package/src/schema/Text.ts +0 -58
  418. package/src/schema/UnorderedList.ts +0 -49
  419. package/src/schema/View.test.ts +0 -111
  420. package/src/schema/View.ts +0 -127
  421. package/src/schema/Wizard.ts +0 -220
  422. package/src/schema/containers.test.ts +0 -564
  423. package/src/schema/headTags.test.ts +0 -134
  424. package/src/schema/index.ts +0 -40
  425. package/src/schema/primes.test.ts +0 -269
  426. package/src/schema/resolveSchema.test.ts +0 -379
  427. package/src/schema/resolveSchema.ts +0 -917
  428. package/src/schema/sanitize.ts +0 -58
  429. package/src/search.test.ts +0 -446
  430. package/src/search.ts +0 -178
  431. package/src/sessionFilters.test.ts +0 -375
  432. package/src/sessionFilters.ts +0 -143
  433. package/src/slot-components/index.ts +0 -10
  434. package/src/slot-components/registry.ts +0 -56
  435. package/src/styles/file-upload.css +0 -13
  436. package/src/summarizers/Summarizer.test.ts +0 -84
  437. package/src/summarizers/Summarizer.ts +0 -123
  438. package/src/summarizers/index.ts +0 -11
  439. package/src/theme/base-colors.ts +0 -68
  440. package/src/theme/chart-colors.ts +0 -50
  441. package/src/theme/colors.ts +0 -447
  442. package/src/theme/generate-css.test.ts +0 -139
  443. package/src/theme/generate-css.ts +0 -44
  444. package/src/theme/generate-scale.test.ts +0 -106
  445. package/src/theme/generate-scale.ts +0 -97
  446. package/src/theme/icon-map.ts +0 -42
  447. package/src/theme/index.ts +0 -34
  448. package/src/theme/migrate.test.ts +0 -178
  449. package/src/theme/migrate.ts +0 -81
  450. package/src/theme/presets.ts +0 -135
  451. package/src/theme/radius.ts +0 -18
  452. package/src/theme/resolve.test.ts +0 -238
  453. package/src/theme/resolve.ts +0 -96
  454. package/src/theme/spacing.ts +0 -18
  455. package/src/theme/storage.test.ts +0 -126
  456. package/src/theme/storage.ts +0 -106
  457. package/src/theme/theme-colors.ts +0 -88
  458. package/src/theme/types.ts +0 -125
  459. package/src/uploads/UploadAdapter.ts +0 -35
  460. package/src/uploads/index.ts +0 -2
  461. package/src/uploads/localUpload.test.ts +0 -70
  462. package/src/uploads/localUpload.ts +0 -84
  463. package/src/validation/Validator.ts +0 -49
  464. package/src/validation/index.ts +0 -28
  465. package/src/validation/rules.ts +0 -78
  466. package/src/validation/runValidators.ts +0 -435
  467. package/src/validation/uniqueValidator.test.ts +0 -196
  468. package/src/validation/uniqueValidator.ts +0 -133
  469. package/src/validation/validators.test.ts +0 -268
  470. package/src/vite.test.ts +0 -184
  471. package/src/vite.ts +0 -787
  472. package/src/widgets/index.ts +0 -10
  473. package/src/widgets/registry.ts +0 -45
  474. package/src/widgets.test.ts +0 -592
  475. package/tsconfig.build.json +0 -11
  476. package/tsconfig.json +0 -4
  477. package/tsconfig.test.json +0 -10
  478. package/views/react/Dashboard.tsx +0 -27
  479. package/views/react/Resources/Form.tsx +0 -102
  480. package/views/react/Resources/Index.tsx +0 -49
package/src/Resource.ts DELETED
@@ -1,526 +0,0 @@
1
- import type { Element } from './schema/Element.js'
2
- import type { Form } from './elements/Form.js'
3
- import { Table } from './elements/Table.js'
4
- import type { Page } from './Page.js'
5
- import type { ModelLike, ModelQuery, QueryContext } from './orm/modelDefaults.js'
6
- import type { IconValue } from './icons/types.js'
7
- import { defaultPages } from './defaultPages.js'
8
- import type { RelationManager } from './RelationManager.js'
9
- import type { SchemaContext } from './schema/resolveSchema.js'
10
- import type { ClusterClass } from './Cluster.js'
11
- import { resourceBasePath } from './clusterPaths.js'
12
-
13
- /** Map of resource page roles to Page subclasses. */
14
- export interface ResourcePages {
15
- index?: typeof Page
16
- create?: typeof Page
17
- edit?: typeof Page
18
- view?: typeof Page
19
- /**
20
- * Record-scoped custom sub-pages. Each entry is a `Page` subclass
21
- * mounted at `${resourceBase}/${slug}/:id/${subPageSlug}`. Tabs show
22
- * up in the `RelationTabs` sub-nav strip between the `__edit` tab
23
- * and the relation-manager tabs.
24
- *
25
- * Sub-page slugs are validated at panel boot:
26
- * - Must match `[A-Za-z0-9_-]+`.
27
- * - Must not collide with reserved tokens (`edit`, `delete`,
28
- * `restore`, `force-delete`, `_form`, `_action`, `_search`,
29
- * `_uploads`, `_attach`, `_detach`, `_bulk-detach`, `create`).
30
- * - Must not collide with any `RelationManager.relationship` on
31
- * the same resource.
32
- *
33
- * Each sub-page receives the loaded record in `ctx.record` and runs
34
- * its own `Page.canAccess(user, record)` gate after the parent
35
- * resource's `canAccess` + `canView` predicates have passed.
36
- */
37
- record?: Record<string, typeof Page>
38
- }
39
-
40
- /** Pill color tokens for `navigationBadgeColor`. Matches the shared color
41
- * palette used by `ListTab.badgeColor` so the renderer can re-use the
42
- * same Tailwind utility map. */
43
- export type NavigationBadgeColor =
44
- | 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'info'
45
-
46
- /** Returned by `navigationBadge`: a string/number to render as a pill,
47
- * or undefined to render no pill. May be async. Errors thrown from this
48
- * handler are swallowed by `panelInfo()` so a flaky count never blanks
49
- * the page. */
50
- export type NavigationBadgeHandler =
51
- () => string | number | undefined | Promise<string | number | undefined>
52
-
53
- /**
54
- * Per-resource collab configuration. Set via `static collab = true` (the
55
- * 90% case — opts the edit page in with presence) or via the object form
56
- * for finer control. Omitting `static collab` entirely keeps the resource
57
- * collab-free even when the `@pilotiq-pro/collab` plugin is registered.
58
- *
59
- * pages — page roles where collab activates. `'edit'` syncs values +
60
- * presence; `'view'` is presence-only (the page is read-only,
61
- * value-sync would be moot). Defaults to `['edit']`.
62
- * presence — when false, suppress the awareness layer (focus chips,
63
- * cursor positions) while keeping value-sync. Defaults to true.
64
- *
65
- * Field-level `.collab(false)` always wins over this setting — opting the
66
- * resource in then opting individual fields out is the supported shape.
67
- */
68
- export interface ResourceCollabConfig {
69
- pages: ReadonlyArray<'edit' | 'view'>
70
- presence: boolean
71
- }
72
-
73
- /** Raw shape accepted by `static collab` before normalization. `true` is a
74
- * shorthand for `{ pages: ['edit'], presence: true }`. */
75
- export type ResourceCollabInput = boolean | {
76
- pages?: ReadonlyArray<'edit' | 'view'>
77
- presence?: boolean
78
- }
79
-
80
- /**
81
- * Abstract Resource base class. **All methods are static** — resources are
82
- * registered by class, not by instance. Routes look up the class and call
83
- * statics directly.
84
- *
85
- * Subclasses override `form()`, `table()`, `detail()`, and `pages()` to
86
- * shape the resource. Defaults make the most-common case (CRUD with a
87
- * form + a table) work with minimal boilerplate; 2.2 will fill in
88
- * auto-generated default Page classes.
89
- */
90
- export abstract class Resource {
91
- /** Human-readable plural label, e.g. `'Articles'`. */
92
- static label: string = 'Resources'
93
-
94
- /** Singular label, e.g. `'Article'`. */
95
- static labelSingular: string = 'Resource'
96
-
97
- /** Breadcrumb label override. Falls through to `label`. Use this when
98
- * the breadcrumb chain reads better with a different word than the
99
- * sidebar / page-title plural — e.g. `label = 'Blog Posts'` paired
100
- * with `breadcrumb = 'Posts'` for a tighter chain. */
101
- static breadcrumb: string | undefined = undefined
102
-
103
- /** URL slug. Derived from `label` when unset. */
104
- static slug: string = ''
105
-
106
- /** Sidebar / nav icon. Either a kebab-case registry name (e.g.,
107
- * `'file'`) or a React component reference imported from any icon
108
- * library (e.g., `import { Newspaper } from 'lucide-react'`).
109
- * See `@pilotiq/pilotiq/icons` for the registry; component refs
110
- * resolve via the Vite-plugin `_components.ts` manifest. */
111
- static icon: IconValue = 'file'
112
-
113
- // ─── Plan #9: navigation metadata ──────────────────────────
114
- // Static fields evaluated once at panel-config time; only
115
- // `navigationBadge` runs per request. See docs/plans/resource-navigation.md.
116
-
117
- /** Group label this resource renders under in the sidebar. Items
118
- * without a group land in an unnamed top section. */
119
- static navigationGroup: string | undefined = undefined
120
-
121
- /** Sort key within a group. Lower sorts first; ties fall back to
122
- * registration order. Items without a sort go after sorted items. */
123
- static navigationSort: number | undefined = undefined
124
-
125
- /** Sidebar label override. `Resource.label` still drives page titles. */
126
- static navigationLabel: string | undefined = undefined
127
-
128
- /** Sidebar icon override. Same `IconValue` contract as `icon`. */
129
- static navigationIcon: IconValue = undefined
130
-
131
- /** Server-eval'd badge handler; rendered as a small pill next to the
132
- * label. Errors thrown here are swallowed so a broken count never
133
- * breaks page render. */
134
- static navigationBadge: NavigationBadgeHandler | undefined = undefined
135
-
136
- /** Pill color for the badge. */
137
- static navigationBadgeColor: NavigationBadgeColor = 'default'
138
-
139
- /** Class name (`Resource.name` / `Global.name` / `Page.name`) of a
140
- * parent nav item. Renders nested under the parent when set; renders
141
- * at top level when the name doesn't resolve. */
142
- static navigationParentItem: string | undefined = undefined
143
-
144
- /**
145
- * Cluster this resource belongs to. When set, the resource's URLs gain
146
- * the cluster's slug as a prefix segment (e.g. `/admin/content/articles`
147
- * instead of `/admin/articles`) and the resource nests under the
148
- * cluster's nav entry instead of appearing at the panel top level.
149
- *
150
- * The referenced class must be registered via `Pilotiq.clusters([…])`;
151
- * boot fails otherwise.
152
- */
153
- static cluster?: ClusterClass
154
-
155
- /** Column that names a record when referring to it in search results,
156
- * breadcrumbs, or relation pickers. Resolution order at the call site
157
- * is `recordTitleAttribute` → `'name'` → `'title'` → `'id'`. */
158
- static recordTitleAttribute: string | undefined = undefined
159
-
160
- /**
161
- * Optional ORM model. When set, `defaultPages` auto-fills `Form.save`,
162
- * `Form.loadRecord`, `Table.records`, and `Resource.deleteRecord` so
163
- * the common CRUD case needs no manual wiring. Anything explicitly
164
- * configured on `form()` / `table()` still wins.
165
- *
166
- * Any object satisfying `ModelLike` works — `@rudderjs/orm` `Model`
167
- * subclasses do so structurally via their static methods.
168
- */
169
- static model?: ModelLike
170
-
171
- /**
172
- * Hook for scoping every query against this resource's table — list
173
- * pages, global search, find-by-PK loads (record load for view / edit
174
- * pages, policy lookups). Default returns `this.model.query()`.
175
- *
176
- * Override to install tenant scopes, default ordering, eager-load
177
- * defaults, or any other always-on filter:
178
- *
179
- * @example
180
- * static override query(ctx) {
181
- * return super.query(ctx).where('tenantId', (ctx?.user as any)?.tenantId)
182
- * }
183
- *
184
- * @example
185
- * static override query(ctx) {
186
- * return super.query(ctx).orderBy('createdAt', 'DESC')
187
- * }
188
- *
189
- * Soft-delete restore / force-delete routes deliberately bypass this
190
- * — they build their own `query().withTrashed()` chain so a scope that
191
- * hides trashed rows doesn't hide records the operator is trying to
192
- * recover. Everything else routes through here.
193
- *
194
- * Throws when `static model` isn't set; subclasses without a model
195
- * must override `query()` directly to return whatever query builder
196
- * they're driving.
197
- */
198
- static query(_ctx?: QueryContext): ModelQuery {
199
- if (!this.model) {
200
- throw new Error(
201
- `[Pilotiq] ${this.name}.query() requires \`static model = …\` to be set, ` +
202
- `or override \`static query(ctx)\` directly to return a custom ModelQuery.`,
203
- )
204
- }
205
- return this.model.query()
206
- }
207
-
208
- // ─── Plan #13: soft deletes ────────────────────────────────
209
- // Opt-in: when true, pilotiq routes the standard delete action
210
- // through `model.delete()` (which writes `deletedAt`), surfaces a
211
- // TrashedFilter on the list page, swaps the row-action set on
212
- // trashed rows (Restore + Force-delete instead of Edit + Delete),
213
- // and exposes two new POST routes: `/:id/restore` and
214
- // `/:id/force-delete`. The rudder ORM side must also opt in
215
- // (`Model.softDeletes = true`) for the underlying behavior to
216
- // engage — pilotiq throws a clear boot error when the flag is
217
- // set here but the model lacks `restore` / `forceDelete`.
218
-
219
- /** Enable soft-delete UX (TrashedFilter, Restore action,
220
- * Force-delete action, soft-delete-aware row visibility). Default
221
- * `false`. Requires `Resource.model` to be set, with
222
- * `Model.softDeletes = true` on the rudder side. */
223
- static softDeletes: boolean = false
224
-
225
- /** Column name carrying the soft-delete timestamp on each row.
226
- * Per-row visibility predicates and the trashed-row branch in
227
- * `Action.delete` consult `record[deletedAtColumn]`. Default
228
- * matches rudder's `'deletedAt'`. */
229
- static deletedAtColumn: string = 'deletedAt'
230
-
231
- /** Persist the active list filter / search / sort slice on the
232
- * user's session so revisiting the resource lands on the same view.
233
- * No-ops silently when `@rudderjs/session` isn't mounted. */
234
- static persistFiltersInSession: boolean = false
235
-
236
- /** Skip server-side row loading on list pages; the client paints a
237
- * skeleton and fetches rows from `GET {base}/{slug}/_table` after
238
- * mount. URL chrome (filters / search / page / group) still mirrors
239
- * on the SSR pass so the skeleton frame doesn't reset visible state. */
240
- static deferLoading: boolean = false
241
-
242
- // ─── Plan #12: global search ───────────────────────────────
243
- // Opt-in: resources with `globalSearch = false` are skipped by the
244
- // panel-level Cmd+K palette. Defaults below derive everything from
245
- // already-shipped surfaces (`recordTitleAttribute`, `Column.searchable()`,
246
- // the standard view URL) so the common case needs zero overrides.
247
-
248
- /** Include this resource in Cmd+K palette results. Default `false` —
249
- * quiet resources don't pollute results until users opt in. */
250
- static globalSearch: boolean = false
251
-
252
- /**
253
- * Columns the default search query LIKE-matches against. The default
254
- * dedupes `recordTitleAttribute` (Plan #9) with every searchable
255
- * column on the resource's table. Override to constrain or extend.
256
- * Returning an empty array effectively opts the resource out even
257
- * when `globalSearch=true`.
258
- */
259
- static globallySearchableAttributes(): string[] {
260
- const attrs = new Set<string>()
261
- if (this.recordTitleAttribute) attrs.add(this.recordTitleAttribute)
262
- // Materialise the resource's configured table once and read every
263
- // `searchable()` column off it. The Table builder is a pure
264
- // configuration call (no DB hits, no I/O), so doing this per
265
- // search request is fine; resources that don't want this can
266
- // override `globallySearchableAttributes()` directly.
267
- try {
268
- const table = this.table(Table.make())
269
- for (const col of table.getColumns()) {
270
- if (col.isSearchable()) attrs.add(col.name)
271
- }
272
- } catch { /* defensive — bad user table()? skip */ }
273
- return [...attrs]
274
- }
275
-
276
- /**
277
- * Title shown in the palette result row. Default resolution chain:
278
- * `record[recordTitleAttribute]` → `record.name` → `record.title` →
279
- * `record.id`. Override to customise (e.g. include the id).
280
- */
281
- static getGlobalSearchResultTitle(record: unknown): string {
282
- const r = record as Record<string, unknown> | null | undefined
283
- if (!r) return ''
284
- if (this.recordTitleAttribute && r[this.recordTitleAttribute] !== undefined) {
285
- return String(r[this.recordTitleAttribute])
286
- }
287
- if (r['name'] !== undefined) return String(r['name'])
288
- if (r['title'] !== undefined) return String(r['title'])
289
- if (r['id'] !== undefined) return String(r['id'])
290
- return ''
291
- }
292
-
293
- /**
294
- * Optional second-line text under the title. Returning `undefined`
295
- * tells the renderer to skip the subtitle row. Useful for status,
296
- * timestamps, or category pills.
297
- */
298
- static getGlobalSearchResultSubtitle(_record: unknown): string | undefined {
299
- return undefined
300
- }
301
-
302
- /**
303
- * URL the palette navigates to on Enter. Default uses the View page
304
- * when one exists, else the Edit page, else the resource list. Pass
305
- * `base` (the panel base path) so overrides don't have to thread it
306
- * through the panel config.
307
- */
308
- static getGlobalSearchResultUrl(record: unknown, base: string): string {
309
- const r = record as Record<string, unknown> | null | undefined
310
- const prefix = resourceBasePath(base, this)
311
- if (!r) return prefix
312
- const id = r['id']
313
- if (id === undefined || id === null) return prefix
314
- return `${prefix}/${String(id)}`
315
- }
316
-
317
- /**
318
- * Override the default LIKE-on-attributes search query. Return a
319
- * `ModelQuery` (still chainable through `paginate(1, limit)`) for
320
- * advanced cases — joins, full-text, `pg_trgm`. Returning `undefined`
321
- * (the default) falls through to the framework-built query.
322
- */
323
- static getGlobalSearchQuery(_needle: string): ModelQuery | undefined {
324
- return undefined
325
- }
326
-
327
- // ─── Realtime collab opt-in ────────────────────────────────
328
- // Opt-in per resource. The `@pilotiq-pro/collab` plugin registers the
329
- // global singletons (transport, Tiptap extension factory, RecordWrapper
330
- // factory); resources with `static collab` unset stay collab-free even
331
- // when the plugin is installed. Field-level `.collab(false)` overrides
332
- // this setting per field.
333
-
334
- /** Enable collab on this resource. `true` is the 90% case — shorthand
335
- * for `{ pages: ['edit'], presence: true }`. Use the object form to
336
- * narrow which page roles activate or to suppress presence. Default
337
- * `false` (collab off — the WS room is never opened for this resource). */
338
- static collab: ResourceCollabInput = false
339
-
340
- /**
341
- * Normalize `static collab` into the canonical wire shape, or return
342
- * `null` when the resource has opted out. Centralizes the `true` →
343
- * defaults expansion and the `{ pages?: … }` merge.
344
- *
345
- * Result lands on `panelInfo().recordCollab[slug]`; the gate reads it
346
- * to decide whether to mount the record wrapper.
347
- */
348
- static getResolvedCollabConfig(): ResourceCollabConfig | null {
349
- const raw = this.collab
350
- if (raw === false || raw == null) return null
351
- if (raw === true) return { pages: ['edit'], presence: true }
352
- return {
353
- pages: raw.pages ?? ['edit'],
354
- presence: raw.presence ?? true,
355
- }
356
- }
357
-
358
- // ─── Plan #10: authorization predicates ────────────────────
359
- // All async, all default `true`. Routes call them with the resolved
360
- // user (from `Pilotiq.user(fn)`); the renderer threads the same user
361
- // into nav-tree filtering and `Action.create/edit/view/delete`
362
- // factories. Override per-resource with role/policy logic. The user
363
- // argument is whatever `Pilotiq.user(req => …)` returns — opaque to
364
- // pilotiq, your shape.
365
-
366
- /** Coarse "should this resource exist for this user at all" gate.
367
- * Failing `canAccess` drops the resource from the nav tree entirely
368
- * and 403s every route under it. */
369
- static async canAccess(_user: unknown): Promise<boolean> { return true }
370
-
371
- /** Allowed to load the index/list page. Item still appears in nav
372
- * when `canAccess` passes but `canViewAny` fails — the URL just 403s. */
373
- static async canViewAny(_user: unknown): Promise<boolean> { return true }
374
-
375
- /** Allowed to load the read-only view page for a given record. */
376
- static async canView(_user: unknown, _record: unknown): Promise<boolean> { return true }
377
-
378
- /** Allowed to access the create page + invoke the create form.
379
- * Auto-hides `Action.create(R, …)` triggers that haven't set an
380
- * explicit `.visible()` rule. */
381
- static async canCreate(_user: unknown): Promise<boolean> { return true }
382
-
383
- /** Allowed to edit a given record. Auto-hides `Action.edit(R, …)`
384
- * triggers without an explicit `.visible()` rule. */
385
- static async canEdit(_user: unknown, _record: unknown): Promise<boolean> { return true }
386
-
387
- /** Allowed to delete a given record. Auto-hides `Action.delete(R, …)`
388
- * triggers without an explicit `.visible()` rule. */
389
- static async canDelete(_user: unknown, _record: unknown): Promise<boolean> { return true }
390
-
391
- /** Plan #13 — allowed to restore a soft-deleted record. Defaults
392
- * `true`; auto-hides `Action.restore(R, …)` when false. Only
393
- * checked on resources with `softDeletes = true`. */
394
- static async canRestore(_user: unknown, _record: unknown): Promise<boolean> { return true }
395
-
396
- /** Plan #13 — allowed to permanently delete a soft-deleted record.
397
- * Defaults to whatever `canDelete` returns when this method is *not*
398
- * overridden — soft-delete restore is generally lower-privilege
399
- * than force-delete, but force-delete inheriting from delete is the
400
- * conservative starting point. Override this to tighten or loosen
401
- * independently. Only checked on resources with `softDeletes = true`.
402
- *
403
- * The `safeForceDeletePolicy` helper (used by routes + `Action.forceDelete`
404
- * visibility) detects the un-overridden case via reference equality
405
- * against `Resource.canForceDelete` — same trick Plan #11 uses for
406
- * `safeManagerPolicy`. Don't reassign `Resource.canForceDelete`
407
- * outside of subclass overrides; it'd break the detection globally. */
408
- static async canForceDelete(this: ResourceClass, user: unknown, record: unknown): Promise<boolean> {
409
- return this.canDelete(user, record)
410
- }
411
-
412
- /**
413
- * Configure the form used by `create` and `edit` pages by default.
414
- * Receives a fresh `Form` instance; return the configured form.
415
- */
416
- static form(form: Form): Form { return form }
417
-
418
- /**
419
- * Configure the table used by the `index` page by default.
420
- * Receives a fresh `Table` instance; return the configured table.
421
- */
422
- static table(table: Table): Table { return table }
423
-
424
- /**
425
- * Schema for the read-only `view` page. Receives the loaded record.
426
- * Returns an array of Elements (typically Sections + display elements).
427
- */
428
- static detail(_record: unknown): Element[] { return [] }
429
-
430
- /**
431
- * Plan #15 — schema rendered above the list-page table. Default `[]`.
432
- * Typical use: dashboard widgets that contextualize the list (KPI cards,
433
- * charts, status alerts). Anything Element-typed is allowed —
434
- * `Group / Card / Section` for layout, `Stat / StatsOverview / Chart /
435
- * TableWidget / View` for server-data widgets, `Heading / Alert` for
436
- * static chrome. Resolves with the same `SchemaContext` passed to the
437
- * list page's schema (carries `mode: 'table'`, `basePath`, `user`).
438
- * Server-data widgets inside resolve in parallel via the shared
439
- * `_widgetData` map and re-fetch through `POST {base}/{slug}/_widget/:id`.
440
- * The hook only fires after `Resource.canAccess(user)` passes (route-level
441
- * gate) — there's no extra per-hook authorization.
442
- */
443
- static headerSchema(_ctx?: SchemaContext): Element[] | Promise<Element[]> { return [] }
444
-
445
- /**
446
- * Plan #15 — schema rendered below the list-page table. Default `[]`.
447
- * Same shape and posture as `headerSchema()`; useful for footnotes,
448
- * legends, or "longest-running…" tables that contextualize the list
449
- * from below.
450
- */
451
- static footerSchema(_ctx?: SchemaContext): Element[] | Promise<Element[]> { return [] }
452
-
453
- /**
454
- * Delete a record by id. Falls through to `model.delete(id)` when
455
- * `static model` is set; otherwise throws so the user knows to wire
456
- * something up. Override on the subclass for custom delete logic.
457
- * Wired up by the `POST {base}/{slug}/{id}/delete` route.
458
- */
459
- static async deleteRecord(id: string): Promise<void> {
460
- if (this.model) {
461
- await this.model.delete(id)
462
- return
463
- }
464
- throw new Error(
465
- `[Pilotiq] ${this.name}: no deleteRecord(id) implementation. Set Resource.model = … or override Resource.deleteRecord to wire up deletion.`,
466
- )
467
- }
468
-
469
- /**
470
- * User-overridable page map. Return any subset of `{ index, create, edit, view }`
471
- * to override the auto-generated defaults; missing keys fall through to
472
- * defaults via `resolvePages()`.
473
- */
474
- static pages(): ResourcePages { return {} }
475
-
476
- /**
477
- * Resolved page map: defaults from `defaultPages(this)` overlaid with whatever
478
- * `pages()` returns. This is what routing consumes (wired in 2.3).
479
- */
480
- static resolvePages(): ResourcePages {
481
- const defaults = defaultPages(this as unknown as ResourceClass)
482
- const overrides = this.pages()
483
- return { ...defaults, ...overrides }
484
- }
485
-
486
- /**
487
- * Sugar over `resolvePages().record ?? {}` for callers that only need
488
- * the record-scoped sub-pages (route registration, tab insertion, boot
489
- * validation). Returns an empty object when no record sub-pages are
490
- * declared so callers can iterate without a defensive null check.
491
- */
492
- static getRecordPages(): Record<string, typeof Page> {
493
- return this.resolvePages().record ?? {}
494
- }
495
-
496
- /**
497
- * Plan #11 — relation managers mounted under this resource's edit /
498
- * view pages. Each entry is a `RelationManager` subclass; routes are
499
- * registered under `${base}/${slug}/:id/${manager.relationship}`.
500
- * Default empty.
501
- */
502
- static relations(): Array<typeof RelationManager> { return [] }
503
-
504
- /** URL slug, derived from `label` when not set explicitly. */
505
- static getSlug(): string {
506
- return this.slug || this.label.toLowerCase().replace(/\s+/g, '-')
507
- }
508
-
509
- /** Sidebar label: `navigationLabel` override falls through to `label`. */
510
- static getNavigationLabel(): string {
511
- return this.navigationLabel ?? this.label
512
- }
513
-
514
- /** Breadcrumb label: `breadcrumb` override falls through to `label`. */
515
- static getBreadcrumb(): string {
516
- return this.breadcrumb ?? this.label
517
- }
518
-
519
- /** Sidebar icon: `navigationIcon` override falls through to `icon`. */
520
- static getNavigationIcon(): IconValue {
521
- return this.navigationIcon ?? this.icon
522
- }
523
- }
524
-
525
- /** Constructor type for `Resource` subclasses. Used in panel registration. */
526
- export type ResourceClass = typeof Resource