@pilotiq/pilotiq 0.24.1 → 0.24.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/boost/guidelines.md +571 -0
  3. package/boost/skills/pilotiq-actions/SKILL.md +49 -0
  4. package/boost/skills/pilotiq-actions/rules/dispatch-modes.md +177 -0
  5. package/boost/skills/pilotiq-actions/rules/factories.md +130 -0
  6. package/boost/skills/pilotiq-actions/rules/visibility-and-authorization.md +125 -0
  7. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  9. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  10. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  11. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  12. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  13. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  14. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  15. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  16. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  17. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  18. package/dist/Pilotiq.d.ts +31 -0
  19. package/dist/Pilotiq.d.ts.map +1 -1
  20. package/dist/Pilotiq.js +3 -1
  21. package/dist/Pilotiq.js.map +1 -1
  22. package/dist/PilotiqRegistry.d.ts +13 -0
  23. package/dist/PilotiqRegistry.d.ts.map +1 -1
  24. package/dist/PilotiqRegistry.js +15 -0
  25. package/dist/PilotiqRegistry.js.map +1 -1
  26. package/dist/pageData/misc.d.ts.map +1 -1
  27. package/dist/pageData/misc.js +6 -0
  28. package/dist/pageData/misc.js.map +1 -1
  29. package/dist/pageData/navigation.d.ts +1 -0
  30. package/dist/pageData/navigation.d.ts.map +1 -1
  31. package/dist/pageData/navigation.js +3 -0
  32. package/dist/pageData/navigation.js.map +1 -1
  33. package/dist/pageData/relationPages.d.ts.map +1 -1
  34. package/dist/pageData/relationPages.js +3 -0
  35. package/dist/pageData/relationPages.js.map +1 -1
  36. package/dist/pageData/resourcePages.d.ts.map +1 -1
  37. package/dist/pageData/resourcePages.js +8 -0
  38. package/dist/pageData/resourcePages.js.map +1 -1
  39. package/dist/react/AppShell.d.ts +8 -0
  40. package/dist/react/AppShell.d.ts.map +1 -1
  41. package/dist/react/AppShell.js.map +1 -1
  42. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  43. package/dist/react/layouts/SidebarLayout.js +10 -2
  44. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  45. package/dist/react/widgets/StatsOverviewRenderer.d.ts.map +1 -1
  46. package/dist/react/widgets/StatsOverviewRenderer.js +32 -18
  47. package/dist/react/widgets/StatsOverviewRenderer.js.map +1 -1
  48. package/dist/routes/relations.d.ts.map +1 -1
  49. package/dist/routes/relations.js +25 -18
  50. package/dist/routes/relations.js.map +1 -1
  51. package/dist/routes/resources.js.map +1 -1
  52. package/package.json +10 -5
  53. package/.turbo/turbo-build.log +0 -8
  54. package/CLAUDE.md +0 -265
  55. package/src/Cluster.test.ts +0 -283
  56. package/src/Cluster.ts +0 -83
  57. package/src/Column.test.ts +0 -199
  58. package/src/Column.ts +0 -710
  59. package/src/Global.test.ts +0 -367
  60. package/src/Global.ts +0 -169
  61. package/src/Page.test.ts +0 -114
  62. package/src/Page.ts +0 -208
  63. package/src/Pilotiq.perf.test.ts +0 -252
  64. package/src/Pilotiq.test.ts +0 -129
  65. package/src/Pilotiq.ts +0 -1158
  66. package/src/PilotiqRegistry.ts +0 -36
  67. package/src/PilotiqServiceProvider.ts +0 -121
  68. package/src/RelationManager.test.ts +0 -400
  69. package/src/RelationManager.ts +0 -527
  70. package/src/RenderHook.test.ts +0 -252
  71. package/src/RenderHook.ts +0 -242
  72. package/src/Resource.test.ts +0 -284
  73. package/src/Resource.ts +0 -526
  74. package/src/RightPanel.test.ts +0 -202
  75. package/src/RightPanel.ts +0 -132
  76. package/src/Tab.test.ts +0 -91
  77. package/src/Tab.ts +0 -156
  78. package/src/UserMenuItem.ts +0 -145
  79. package/src/actions/Action.test.ts +0 -2526
  80. package/src/actions/Action.ts +0 -1515
  81. package/src/actions/ActionGroup.test.ts +0 -112
  82. package/src/actions/ActionGroup.ts +0 -173
  83. package/src/actions/attachFactory.ts +0 -172
  84. package/src/actions/bulkFactories.ts +0 -168
  85. package/src/actions/crudFactories.ts +0 -220
  86. package/src/actions/exportFactory.ts +0 -225
  87. package/src/actions/factoryHelpers.ts +0 -177
  88. package/src/actions/importFactory.ts +0 -243
  89. package/src/actions/index.ts +0 -17
  90. package/src/actions/m2mFactories.ts +0 -193
  91. package/src/actions/relationFactories.ts +0 -372
  92. package/src/applyPageHooks.test.ts +0 -463
  93. package/src/applyPageHooks.ts +0 -330
  94. package/src/authorization.test.ts +0 -483
  95. package/src/breadcrumbs.test.ts +0 -238
  96. package/src/cells/coerce.test.ts +0 -85
  97. package/src/cells/coerce.ts +0 -84
  98. package/src/clusterPaths.ts +0 -35
  99. package/src/columns/BadgeColumn.test.ts +0 -54
  100. package/src/columns/BadgeColumn.ts +0 -32
  101. package/src/columns/BooleanColumn.test.ts +0 -41
  102. package/src/columns/BooleanColumn.ts +0 -18
  103. package/src/columns/ColorColumn.test.ts +0 -37
  104. package/src/columns/ColorColumn.ts +0 -38
  105. package/src/columns/IconColumn.test.ts +0 -54
  106. package/src/columns/IconColumn.ts +0 -37
  107. package/src/columns/ImageColumn.test.ts +0 -41
  108. package/src/columns/ImageColumn.ts +0 -28
  109. package/src/columns/SelectColumn.ts +0 -98
  110. package/src/columns/TextColumn.test.ts +0 -190
  111. package/src/columns/TextColumn.ts +0 -20
  112. package/src/columns/TextInputColumn.ts +0 -68
  113. package/src/columns/ToggleColumn.ts +0 -46
  114. package/src/columns/editableColumns.test.ts +0 -238
  115. package/src/columns/index.ts +0 -9
  116. package/src/defaultGlobalPages.ts +0 -95
  117. package/src/defaultPages.test.ts +0 -634
  118. package/src/defaultPages.ts +0 -617
  119. package/src/defaultViewPage.test.ts +0 -147
  120. package/src/elements/Form.test.ts +0 -223
  121. package/src/elements/Form.ts +0 -416
  122. package/src/elements/ListTabs.ts +0 -28
  123. package/src/elements/Table.test.ts +0 -422
  124. package/src/elements/Table.ts +0 -850
  125. package/src/elements/TableGroup.test.ts +0 -260
  126. package/src/elements/TableGroup.ts +0 -334
  127. package/src/elements/dispatchAction.test.ts +0 -463
  128. package/src/elements/dispatchAction.ts +0 -355
  129. package/src/elements/dispatchForm.test.ts +0 -477
  130. package/src/elements/dispatchForm.ts +0 -1993
  131. package/src/elements/dispatchTable.test.ts +0 -1514
  132. package/src/elements/dispatchTable.ts +0 -745
  133. package/src/elements/index.ts +0 -21
  134. package/src/entries/BadgeEntry.ts +0 -39
  135. package/src/entries/CodeEntry.test.ts +0 -40
  136. package/src/entries/CodeEntry.ts +0 -52
  137. package/src/entries/ColorEntry.ts +0 -63
  138. package/src/entries/ComponentEntry.test.ts +0 -173
  139. package/src/entries/ComponentEntry.ts +0 -95
  140. package/src/entries/Entry.ts +0 -304
  141. package/src/entries/IconEntry.ts +0 -49
  142. package/src/entries/ImageEntry.ts +0 -61
  143. package/src/entries/KeyValueEntry.ts +0 -47
  144. package/src/entries/RepeatableEntry.test.ts +0 -239
  145. package/src/entries/RepeatableEntry.ts +0 -173
  146. package/src/entries/TextEntry.test.ts +0 -394
  147. package/src/entries/TextEntry.ts +0 -60
  148. package/src/entries/index.ts +0 -12
  149. package/src/entries/leaves.test.ts +0 -306
  150. package/src/entries/registry.ts +0 -54
  151. package/src/fields/BuilderField.test.ts +0 -1188
  152. package/src/fields/BuilderField.ts +0 -605
  153. package/src/fields/BuilderRelationship.test.ts +0 -811
  154. package/src/fields/CheckboxField.test.ts +0 -44
  155. package/src/fields/CheckboxField.ts +0 -27
  156. package/src/fields/CheckboxListField.test.ts +0 -99
  157. package/src/fields/CheckboxListField.ts +0 -66
  158. package/src/fields/ColorPickerField.test.ts +0 -33
  159. package/src/fields/ColorPickerField.ts +0 -25
  160. package/src/fields/DateField.ts +0 -54
  161. package/src/fields/DateTimeField.test.ts +0 -55
  162. package/src/fields/EmailField.ts +0 -16
  163. package/src/fields/Field.test.ts +0 -654
  164. package/src/fields/Field.ts +0 -817
  165. package/src/fields/FileUploadField.test.ts +0 -143
  166. package/src/fields/FileUploadField.ts +0 -159
  167. package/src/fields/HiddenField.test.ts +0 -27
  168. package/src/fields/HiddenField.ts +0 -28
  169. package/src/fields/KeyValueField.test.ts +0 -105
  170. package/src/fields/KeyValueField.ts +0 -55
  171. package/src/fields/MarkdownField.test.ts +0 -167
  172. package/src/fields/MarkdownField.ts +0 -162
  173. package/src/fields/NumberField.ts +0 -33
  174. package/src/fields/RadioField.test.ts +0 -94
  175. package/src/fields/RadioField.ts +0 -67
  176. package/src/fields/RepeaterField.test.ts +0 -1806
  177. package/src/fields/RepeaterField.ts +0 -939
  178. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  179. package/src/fields/RepeaterSimple.test.ts +0 -248
  180. package/src/fields/RowButton.test.ts +0 -219
  181. package/src/fields/RowButton.ts +0 -135
  182. package/src/fields/SelectField.test.ts +0 -192
  183. package/src/fields/SelectField.ts +0 -235
  184. package/src/fields/SliderField.test.ts +0 -50
  185. package/src/fields/SliderField.ts +0 -53
  186. package/src/fields/SlugField.ts +0 -24
  187. package/src/fields/TagsInputField.test.ts +0 -154
  188. package/src/fields/TagsInputField.ts +0 -133
  189. package/src/fields/TextField.test.ts +0 -213
  190. package/src/fields/TextField.ts +0 -177
  191. package/src/fields/TextareaField.test.ts +0 -58
  192. package/src/fields/TextareaField.ts +0 -59
  193. package/src/fields/ToggleButtonsField.test.ts +0 -106
  194. package/src/fields/ToggleButtonsField.ts +0 -59
  195. package/src/fields/ToggleField.ts +0 -16
  196. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  197. package/src/fields/optionsResolver.ts +0 -95
  198. package/src/fields/resolveField.ts +0 -28
  199. package/src/filters/BooleanFilter.ts +0 -35
  200. package/src/filters/DateRangeFilter.test.ts +0 -194
  201. package/src/filters/DateRangeFilter.ts +0 -148
  202. package/src/filters/Filter.test.ts +0 -268
  203. package/src/filters/Filter.ts +0 -184
  204. package/src/filters/FormFilter.test.ts +0 -238
  205. package/src/filters/FormFilter.ts +0 -215
  206. package/src/filters/MultiSelectFilter.test.ts +0 -119
  207. package/src/filters/MultiSelectFilter.ts +0 -78
  208. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  209. package/src/filters/QueryBuilderFilter.ts +0 -398
  210. package/src/filters/SelectFilter.ts +0 -46
  211. package/src/filters/TernaryFilter.test.ts +0 -160
  212. package/src/filters/TernaryFilter.ts +0 -72
  213. package/src/filters/TrashedFilter.test.ts +0 -149
  214. package/src/filters/TrashedFilter.ts +0 -55
  215. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  216. package/src/filters/queryBuilder/Constraint.ts +0 -115
  217. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  218. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  219. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  220. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  221. package/src/filters/queryBuilder/index.ts +0 -12
  222. package/src/icons/index.ts +0 -2
  223. package/src/icons/lucide.ts +0 -204
  224. package/src/icons/registry.test.ts +0 -56
  225. package/src/icons/registry.ts +0 -41
  226. package/src/icons/types.ts +0 -47
  227. package/src/index.ts +0 -525
  228. package/src/io/csv.test.ts +0 -142
  229. package/src/io/csv.ts +0 -170
  230. package/src/nestedRelationManagerData.test.ts +0 -547
  231. package/src/notifications/Notification.test.ts +0 -210
  232. package/src/notifications/Notification.ts +0 -354
  233. package/src/notifications/broadcast.test.ts +0 -110
  234. package/src/notifications/broadcast.ts +0 -95
  235. package/src/notifications/database.test.ts +0 -383
  236. package/src/notifications/database.ts +0 -398
  237. package/src/notifications/databaseNotifications.test.ts +0 -187
  238. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  239. package/src/notifications/dispatchNotificationAction.ts +0 -142
  240. package/src/notifications/flash.test.ts +0 -89
  241. package/src/notifications/flash.ts +0 -71
  242. package/src/notifications/index.ts +0 -45
  243. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  244. package/src/notifications/registerBroadcastAuth.ts +0 -100
  245. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  246. package/src/notifications/resolveSavedNotification.ts +0 -59
  247. package/src/notifications/types.ts +0 -93
  248. package/src/orm/m2mAccessor.ts +0 -66
  249. package/src/orm/modelDefaults.test.ts +0 -633
  250. package/src/orm/modelDefaults.ts +0 -666
  251. package/src/pageData/breadcrumbs.ts +0 -288
  252. package/src/pageData/forms.ts +0 -578
  253. package/src/pageData/helpers.ts +0 -857
  254. package/src/pageData/misc.ts +0 -347
  255. package/src/pageData/navigation.ts +0 -842
  256. package/src/pageData/relationPages.ts +0 -1248
  257. package/src/pageData/relationTabs.ts +0 -286
  258. package/src/pageData/resourcePages.ts +0 -609
  259. package/src/pageData.test.ts +0 -1545
  260. package/src/pageData.ts +0 -341
  261. package/src/plugins/index.ts +0 -8
  262. package/src/plugins/themeEditor.test.ts +0 -36
  263. package/src/plugins/themeEditor.ts +0 -45
  264. package/src/react/AppShell.tsx +0 -251
  265. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  266. package/src/react/CollabRoomContext.ts +0 -98
  267. package/src/react/CollabTextRendererRegistry.ts +0 -102
  268. package/src/react/CommandPalette.tsx +0 -375
  269. package/src/react/CurrentUserContext.tsx +0 -50
  270. package/src/react/CustomPageWrapperGate.tsx +0 -69
  271. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  272. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  273. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  274. package/src/react/FieldPresenceRegistry.ts +0 -46
  275. package/src/react/FormCollabBindingRegistry.ts +0 -242
  276. package/src/react/FormStateContext.tsx +0 -591
  277. package/src/react/HeadHooks.tsx +0 -126
  278. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  279. package/src/react/MarkdownEditorRegistry.ts +0 -107
  280. package/src/react/NotificationActionStrip.tsx +0 -263
  281. package/src/react/NotificationBell.tsx +0 -426
  282. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  283. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  284. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  285. package/src/react/PendingSuggestionsContext.tsx +0 -172
  286. package/src/react/RecordWrapperGate.tsx +0 -58
  287. package/src/react/RecordWrapperRegistry.ts +0 -39
  288. package/src/react/RenderHookSlot.tsx +0 -32
  289. package/src/react/RightSidebar.tsx +0 -257
  290. package/src/react/RightSidebarContext.tsx +0 -234
  291. package/src/react/RightSidebarTrigger.tsx +0 -53
  292. package/src/react/RowCoordsContext.tsx +0 -23
  293. package/src/react/SchemaRenderer.tsx +0 -549
  294. package/src/react/SearchTrigger.tsx +0 -46
  295. package/src/react/ThemeProvider.tsx +0 -93
  296. package/src/react/ThemeSettingsPage.tsx +0 -579
  297. package/src/react/ThemeToggle.tsx +0 -20
  298. package/src/react/Toaster.tsx +0 -158
  299. package/src/react/UserMenu.tsx +0 -196
  300. package/src/react/WidgetDataContext.tsx +0 -157
  301. package/src/react/cells/EditableCell.tsx +0 -389
  302. package/src/react/component-slots.test.ts +0 -103
  303. package/src/react/component-slots.ts +0 -116
  304. package/src/react/fieldJsHandler.test.ts +0 -166
  305. package/src/react/fieldJsHandler.ts +0 -79
  306. package/src/react/fields/BuilderInput.tsx +0 -1078
  307. package/src/react/fields/CheckboxInput.tsx +0 -39
  308. package/src/react/fields/CheckboxListInput.tsx +0 -102
  309. package/src/react/fields/ColorInput.tsx +0 -71
  310. package/src/react/fields/DateFieldInput.tsx +0 -70
  311. package/src/react/fields/DateTimeInput.tsx +0 -62
  312. package/src/react/fields/FieldShell.tsx +0 -348
  313. package/src/react/fields/FileUploadInput.tsx +0 -639
  314. package/src/react/fields/HiddenInput.tsx +0 -17
  315. package/src/react/fields/KeyValueInput.tsx +0 -230
  316. package/src/react/fields/MarkdownInput.tsx +0 -560
  317. package/src/react/fields/RadioInput.tsx +0 -81
  318. package/src/react/fields/RepeaterInput.test.ts +0 -116
  319. package/src/react/fields/RepeaterInput.tsx +0 -1420
  320. package/src/react/fields/SelectFieldInput.tsx +0 -280
  321. package/src/react/fields/SliderInput.tsx +0 -81
  322. package/src/react/fields/TagsInput.tsx +0 -283
  323. package/src/react/fields/TextLikeInput.tsx +0 -256
  324. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  325. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  326. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  327. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  328. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  329. package/src/react/fields/repeaterReconcile.ts +0 -104
  330. package/src/react/fields/rowChromeButton.tsx +0 -336
  331. package/src/react/fields/rowState.ts +0 -106
  332. package/src/react/fields/syncRowGates.test.ts +0 -202
  333. package/src/react/fields/syncRowGates.ts +0 -66
  334. package/src/react/fields/textInputControls.tsx +0 -238
  335. package/src/react/fields/useRowReorderDnd.ts +0 -78
  336. package/src/react/formStateHelpers.test.ts +0 -508
  337. package/src/react/formStateHelpers.ts +0 -381
  338. package/src/react/hooks/use-mobile.ts +0 -19
  339. package/src/react/icon-context.tsx +0 -60
  340. package/src/react/index.ts +0 -194
  341. package/src/react/layouts/SidebarLayout.tsx +0 -250
  342. package/src/react/layouts/TopbarLayout.tsx +0 -258
  343. package/src/react/navigate.tsx +0 -37
  344. package/src/react/onProviderSynced.test.ts +0 -90
  345. package/src/react/parseRecordEditUrl.test.ts +0 -122
  346. package/src/react/parseRecordEditUrl.ts +0 -94
  347. package/src/react/persistedState.ts +0 -40
  348. package/src/react/registry.ts +0 -48
  349. package/src/react/right-panel-registry.tsx +0 -47
  350. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  351. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  352. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  353. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  354. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  355. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  356. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  357. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  358. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  359. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  360. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  361. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  362. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  363. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  364. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  365. package/src/react/schemaRenderer/constants.ts +0 -50
  366. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  367. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  368. package/src/react/schemaRenderer/helpers.tsx +0 -81
  369. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  370. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  371. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  372. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  373. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  374. package/src/react/schemaRenderer/table/links.tsx +0 -112
  375. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  376. package/src/react/schemaRenderer/table/url.tsx +0 -143
  377. package/src/react/theme-preview/apply.ts +0 -99
  378. package/src/react/theme-preview/build-html.ts +0 -436
  379. package/src/react/ui/button.tsx +0 -51
  380. package/src/react/ui/calendar.tsx +0 -67
  381. package/src/react/ui/checkbox.tsx +0 -29
  382. package/src/react/ui/dialog.tsx +0 -108
  383. package/src/react/ui/dropdown-menu.tsx +0 -97
  384. package/src/react/ui/input.tsx +0 -20
  385. package/src/react/ui/label.tsx +0 -21
  386. package/src/react/ui/popover.tsx +0 -50
  387. package/src/react/ui/select.tsx +0 -169
  388. package/src/react/ui/separator.tsx +0 -25
  389. package/src/react/ui/sheet.tsx +0 -136
  390. package/src/react/ui/sidebar.tsx +0 -723
  391. package/src/react/ui/skeleton.tsx +0 -13
  392. package/src/react/ui/slider.tsx +0 -34
  393. package/src/react/ui/switch.tsx +0 -28
  394. package/src/react/ui/table.tsx +0 -105
  395. package/src/react/ui/tabs.tsx +0 -63
  396. package/src/react/ui/textarea.tsx +0 -18
  397. package/src/react/ui/tooltip.tsx +0 -64
  398. package/src/react/useResizableWidth.ts +0 -139
  399. package/src/react/utils.ts +0 -6
  400. package/src/react/widgetRegistry.test.ts +0 -43
  401. package/src/react/widgetRegistry.ts +0 -50
  402. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  403. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  404. package/src/react/widgets/ViewRenderer.tsx +0 -71
  405. package/src/relationManagerData.test.ts +0 -1595
  406. package/src/richtext/index.ts +0 -8
  407. package/src/richtext/registry.ts +0 -89
  408. package/src/routes/globals.ts +0 -148
  409. package/src/routes/guard.test.ts +0 -325
  410. package/src/routes/helpers.ts +0 -704
  411. package/src/routes/pages.ts +0 -175
  412. package/src/routes/panel.ts +0 -204
  413. package/src/routes/relations.ts +0 -1243
  414. package/src/routes/resources.ts +0 -781
  415. package/src/routes/theme.ts +0 -91
  416. package/src/routes-nested-relations.test.ts +0 -676
  417. package/src/routes-relations.test.ts +0 -972
  418. package/src/routes.test.ts +0 -2027
  419. package/src/routes.ts +0 -303
  420. package/src/schema/Alert.test.ts +0 -109
  421. package/src/schema/Alert.ts +0 -131
  422. package/src/schema/Block.ts +0 -169
  423. package/src/schema/Breadcrumbs.ts +0 -40
  424. package/src/schema/Card.ts +0 -35
  425. package/src/schema/Divider.ts +0 -20
  426. package/src/schema/Element.ts +0 -219
  427. package/src/schema/EmptyState.test.ts +0 -37
  428. package/src/schema/EmptyState.ts +0 -63
  429. package/src/schema/Fieldset.ts +0 -43
  430. package/src/schema/Grid.ts +0 -43
  431. package/src/schema/Group.ts +0 -30
  432. package/src/schema/Heading.ts +0 -39
  433. package/src/schema/Html.ts +0 -67
  434. package/src/schema/Icon.ts +0 -54
  435. package/src/schema/Image.ts +0 -57
  436. package/src/schema/LinkTag.ts +0 -41
  437. package/src/schema/Markdown.ts +0 -85
  438. package/src/schema/MetaTag.ts +0 -41
  439. package/src/schema/RelationTabs.ts +0 -71
  440. package/src/schema/ScriptTag.ts +0 -55
  441. package/src/schema/Section.ts +0 -160
  442. package/src/schema/ServerDataElement.test.ts +0 -140
  443. package/src/schema/ServerDataElement.ts +0 -156
  444. package/src/schema/SlotComponent.test.ts +0 -77
  445. package/src/schema/SlotComponent.ts +0 -71
  446. package/src/schema/Split.ts +0 -50
  447. package/src/schema/Stat.test.ts +0 -118
  448. package/src/schema/Stat.ts +0 -154
  449. package/src/schema/StatsOverview.test.ts +0 -141
  450. package/src/schema/StatsOverview.ts +0 -119
  451. package/src/schema/StyleTag.ts +0 -35
  452. package/src/schema/TableWidget.test.ts +0 -297
  453. package/src/schema/TableWidget.ts +0 -289
  454. package/src/schema/Tabs.ts +0 -79
  455. package/src/schema/Text.ts +0 -58
  456. package/src/schema/UnorderedList.ts +0 -49
  457. package/src/schema/View.test.ts +0 -111
  458. package/src/schema/View.ts +0 -127
  459. package/src/schema/Wizard.ts +0 -220
  460. package/src/schema/containers.test.ts +0 -564
  461. package/src/schema/headTags.test.ts +0 -134
  462. package/src/schema/index.ts +0 -40
  463. package/src/schema/primes.test.ts +0 -269
  464. package/src/schema/resolveSchema.test.ts +0 -379
  465. package/src/schema/resolveSchema.ts +0 -917
  466. package/src/schema/sanitize.ts +0 -58
  467. package/src/search.test.ts +0 -446
  468. package/src/search.ts +0 -178
  469. package/src/sessionFilters.test.ts +0 -375
  470. package/src/sessionFilters.ts +0 -143
  471. package/src/slot-components/index.ts +0 -10
  472. package/src/slot-components/registry.ts +0 -56
  473. package/src/styles/file-upload.css +0 -13
  474. package/src/summarizers/Summarizer.test.ts +0 -84
  475. package/src/summarizers/Summarizer.ts +0 -123
  476. package/src/summarizers/index.ts +0 -11
  477. package/src/theme/base-colors.ts +0 -68
  478. package/src/theme/chart-colors.ts +0 -50
  479. package/src/theme/colors.ts +0 -447
  480. package/src/theme/generate-css.test.ts +0 -139
  481. package/src/theme/generate-css.ts +0 -44
  482. package/src/theme/generate-scale.test.ts +0 -106
  483. package/src/theme/generate-scale.ts +0 -97
  484. package/src/theme/icon-map.ts +0 -42
  485. package/src/theme/index.ts +0 -34
  486. package/src/theme/migrate.test.ts +0 -178
  487. package/src/theme/migrate.ts +0 -81
  488. package/src/theme/presets.ts +0 -135
  489. package/src/theme/radius.ts +0 -18
  490. package/src/theme/resolve.test.ts +0 -238
  491. package/src/theme/resolve.ts +0 -96
  492. package/src/theme/spacing.ts +0 -18
  493. package/src/theme/storage.test.ts +0 -126
  494. package/src/theme/storage.ts +0 -106
  495. package/src/theme/theme-colors.ts +0 -88
  496. package/src/theme/types.ts +0 -125
  497. package/src/uploads/UploadAdapter.ts +0 -35
  498. package/src/uploads/index.ts +0 -2
  499. package/src/uploads/localUpload.test.ts +0 -70
  500. package/src/uploads/localUpload.ts +0 -84
  501. package/src/validation/Validator.ts +0 -49
  502. package/src/validation/index.ts +0 -28
  503. package/src/validation/rules.ts +0 -78
  504. package/src/validation/runValidators.ts +0 -435
  505. package/src/validation/uniqueValidator.test.ts +0 -196
  506. package/src/validation/uniqueValidator.ts +0 -133
  507. package/src/validation/validators.test.ts +0 -268
  508. package/src/vite.test.ts +0 -184
  509. package/src/vite.ts +0 -787
  510. package/src/widgets/index.ts +0 -10
  511. package/src/widgets/registry.ts +0 -45
  512. package/src/widgets.test.ts +0 -592
  513. package/tsconfig.build.json +0 -11
  514. package/tsconfig.json +0 -4
  515. package/tsconfig.test.json +0 -10
  516. package/views/react/Dashboard.tsx +0 -27
  517. package/views/react/Resources/Form.tsx +0 -102
  518. 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