@pilotiq/pilotiq 0.7.2 → 0.8.0

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 (367) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/CHANGELOG.md +142 -0
  3. package/CLAUDE.md +59 -3
  4. package/dist/Pilotiq.d.ts +83 -0
  5. package/dist/Pilotiq.d.ts.map +1 -1
  6. package/dist/Pilotiq.js +39 -0
  7. package/dist/Pilotiq.js.map +1 -1
  8. package/dist/actions/Action.d.ts +27 -99
  9. package/dist/actions/Action.d.ts.map +1 -1
  10. package/dist/actions/Action.js +52 -754
  11. package/dist/actions/Action.js.map +1 -1
  12. package/dist/actions/bulkFactories.d.ts +46 -0
  13. package/dist/actions/bulkFactories.d.ts.map +1 -0
  14. package/dist/actions/bulkFactories.js +144 -0
  15. package/dist/actions/bulkFactories.js.map +1 -0
  16. package/dist/actions/crudFactories.d.ts +94 -0
  17. package/dist/actions/crudFactories.d.ts.map +1 -0
  18. package/dist/actions/crudFactories.js +209 -0
  19. package/dist/actions/crudFactories.js.map +1 -0
  20. package/dist/actions/factoryHelpers.d.ts +108 -0
  21. package/dist/actions/factoryHelpers.d.ts.map +1 -0
  22. package/dist/actions/factoryHelpers.js +138 -0
  23. package/dist/actions/factoryHelpers.js.map +1 -0
  24. package/dist/actions/m2mFactories.d.ts +47 -0
  25. package/dist/actions/m2mFactories.d.ts.map +1 -0
  26. package/dist/actions/m2mFactories.js +173 -0
  27. package/dist/actions/m2mFactories.js.map +1 -0
  28. package/dist/actions/relationFactories.d.ts +93 -0
  29. package/dist/actions/relationFactories.d.ts.map +1 -0
  30. package/dist/actions/relationFactories.js +321 -0
  31. package/dist/actions/relationFactories.js.map +1 -0
  32. package/dist/elements/dispatchForm.js +1 -1
  33. package/dist/elements/dispatchForm.js.map +1 -1
  34. package/dist/elements/dispatchTable.js +1 -1
  35. package/dist/elements/dispatchTable.js.map +1 -1
  36. package/dist/fields/Field.d.ts +31 -0
  37. package/dist/fields/Field.d.ts.map +1 -1
  38. package/dist/fields/Field.js +25 -0
  39. package/dist/fields/Field.js.map +1 -1
  40. package/dist/pageData/breadcrumbs.d.ts +42 -0
  41. package/dist/pageData/breadcrumbs.d.ts.map +1 -0
  42. package/dist/pageData/breadcrumbs.js +172 -0
  43. package/dist/pageData/breadcrumbs.js.map +1 -0
  44. package/dist/pageData/forms.d.ts +137 -0
  45. package/dist/pageData/forms.d.ts.map +1 -0
  46. package/dist/pageData/forms.js +427 -0
  47. package/dist/pageData/forms.js.map +1 -0
  48. package/dist/pageData/helpers.d.ts +239 -0
  49. package/dist/pageData/helpers.d.ts.map +1 -0
  50. package/dist/pageData/helpers.js +703 -0
  51. package/dist/pageData/helpers.js.map +1 -0
  52. package/dist/pageData/misc.d.ts +76 -0
  53. package/dist/pageData/misc.d.ts.map +1 -0
  54. package/dist/pageData/misc.js +263 -0
  55. package/dist/pageData/misc.js.map +1 -0
  56. package/dist/pageData/navigation.d.ts +292 -0
  57. package/dist/pageData/navigation.d.ts.map +1 -0
  58. package/dist/pageData/navigation.js +591 -0
  59. package/dist/pageData/navigation.js.map +1 -0
  60. package/dist/pageData/relationPages.d.ts +172 -0
  61. package/dist/pageData/relationPages.d.ts.map +1 -0
  62. package/dist/pageData/relationPages.js +867 -0
  63. package/dist/pageData/relationPages.js.map +1 -0
  64. package/dist/pageData/relationTabs.d.ts +65 -0
  65. package/dist/pageData/relationTabs.d.ts.map +1 -0
  66. package/dist/pageData/relationTabs.js +258 -0
  67. package/dist/pageData/relationTabs.js.map +1 -0
  68. package/dist/pageData/resourcePages.d.ts +48 -0
  69. package/dist/pageData/resourcePages.d.ts.map +1 -0
  70. package/dist/pageData/resourcePages.js +504 -0
  71. package/dist/pageData/resourcePages.js.map +1 -0
  72. package/dist/pageData.d.ts +12 -792
  73. package/dist/pageData.d.ts.map +1 -1
  74. package/dist/pageData.js +24 -3797
  75. package/dist/pageData.js.map +1 -1
  76. package/dist/react/AppShell.d.ts +8 -0
  77. package/dist/react/AppShell.d.ts.map +1 -1
  78. package/dist/react/AppShell.js +11 -1
  79. package/dist/react/AppShell.js.map +1 -1
  80. package/dist/react/CollabExtensionFactoryRegistry.d.ts +47 -0
  81. package/dist/react/CollabExtensionFactoryRegistry.d.ts.map +1 -0
  82. package/dist/react/CollabExtensionFactoryRegistry.js +14 -0
  83. package/dist/react/CollabExtensionFactoryRegistry.js.map +1 -0
  84. package/dist/react/CollabRoomContext.d.ts +37 -0
  85. package/dist/react/CollabRoomContext.d.ts.map +1 -0
  86. package/dist/react/CollabRoomContext.js +12 -0
  87. package/dist/react/CollabRoomContext.js.map +1 -0
  88. package/dist/react/FormCollabBindingRegistry.d.ts +62 -0
  89. package/dist/react/FormCollabBindingRegistry.d.ts.map +1 -0
  90. package/dist/react/FormCollabBindingRegistry.js +14 -0
  91. package/dist/react/FormCollabBindingRegistry.js.map +1 -0
  92. package/dist/react/RecordWrapperGate.d.ts +25 -0
  93. package/dist/react/RecordWrapperGate.d.ts.map +1 -0
  94. package/dist/react/RecordWrapperGate.js +30 -0
  95. package/dist/react/RecordWrapperGate.js.map +1 -0
  96. package/dist/react/RecordWrapperRegistry.d.ts +31 -0
  97. package/dist/react/RecordWrapperRegistry.d.ts.map +1 -0
  98. package/dist/react/RecordWrapperRegistry.js +15 -0
  99. package/dist/react/RecordWrapperRegistry.js.map +1 -0
  100. package/dist/react/SchemaRenderer.d.ts +17 -23
  101. package/dist/react/SchemaRenderer.d.ts.map +1 -1
  102. package/dist/react/SchemaRenderer.js +71 -3647
  103. package/dist/react/SchemaRenderer.js.map +1 -1
  104. package/dist/react/component-slots.d.ts +103 -0
  105. package/dist/react/component-slots.d.ts.map +1 -0
  106. package/dist/react/component-slots.js +18 -0
  107. package/dist/react/component-slots.js.map +1 -0
  108. package/dist/react/fields/BuilderInput.d.ts.map +1 -1
  109. package/dist/react/fields/BuilderInput.js +21 -117
  110. package/dist/react/fields/BuilderInput.js.map +1 -1
  111. package/dist/react/fields/MarkdownInput.d.ts.map +1 -1
  112. package/dist/react/fields/MarkdownInput.js +1 -3
  113. package/dist/react/fields/MarkdownInput.js.map +1 -1
  114. package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
  115. package/dist/react/fields/RepeaterInput.js +22 -127
  116. package/dist/react/fields/RepeaterInput.js.map +1 -1
  117. package/dist/react/fields/rowState.d.ts +40 -0
  118. package/dist/react/fields/rowState.d.ts.map +1 -0
  119. package/dist/react/fields/rowState.js +60 -0
  120. package/dist/react/fields/rowState.js.map +1 -0
  121. package/dist/react/fields/useRowReorderDnd.d.ts +28 -0
  122. package/dist/react/fields/useRowReorderDnd.d.ts.map +1 -0
  123. package/dist/react/fields/useRowReorderDnd.js +51 -0
  124. package/dist/react/fields/useRowReorderDnd.js.map +1 -0
  125. package/dist/react/index.d.ts +9 -0
  126. package/dist/react/index.d.ts.map +1 -1
  127. package/dist/react/index.js +8 -0
  128. package/dist/react/index.js.map +1 -1
  129. package/dist/react/layouts/SidebarLayout.d.ts +1 -1
  130. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  131. package/dist/react/layouts/SidebarLayout.js +10 -2
  132. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  133. package/dist/react/layouts/TopbarLayout.d.ts +1 -1
  134. package/dist/react/layouts/TopbarLayout.d.ts.map +1 -1
  135. package/dist/react/layouts/TopbarLayout.js +19 -11
  136. package/dist/react/layouts/TopbarLayout.js.map +1 -1
  137. package/dist/react/parseRecordEditUrl.d.ts +29 -0
  138. package/dist/react/parseRecordEditUrl.d.ts.map +1 -0
  139. package/dist/react/parseRecordEditUrl.js +25 -0
  140. package/dist/react/parseRecordEditUrl.js.map +1 -0
  141. package/dist/react/persistedState.d.ts +19 -0
  142. package/dist/react/persistedState.d.ts.map +1 -0
  143. package/dist/react/persistedState.js +51 -0
  144. package/dist/react/persistedState.js.map +1 -0
  145. package/dist/react/schemaRenderer/AlertRenderer.d.ts +12 -0
  146. package/dist/react/schemaRenderer/AlertRenderer.d.ts.map +1 -0
  147. package/dist/react/schemaRenderer/AlertRenderer.js +61 -0
  148. package/dist/react/schemaRenderer/AlertRenderer.js.map +1 -0
  149. package/dist/react/schemaRenderer/EntryRenderer.d.ts +13 -0
  150. package/dist/react/schemaRenderer/EntryRenderer.d.ts.map +1 -0
  151. package/dist/react/schemaRenderer/EntryRenderer.js +277 -0
  152. package/dist/react/schemaRenderer/EntryRenderer.js.map +1 -0
  153. package/dist/react/schemaRenderer/SectionRenderer.d.ts +16 -0
  154. package/dist/react/schemaRenderer/SectionRenderer.d.ts.map +1 -0
  155. package/dist/react/schemaRenderer/SectionRenderer.js +62 -0
  156. package/dist/react/schemaRenderer/SectionRenderer.js.map +1 -0
  157. package/dist/react/schemaRenderer/SimpleElements.d.ts +25 -0
  158. package/dist/react/schemaRenderer/SimpleElements.d.ts.map +1 -0
  159. package/dist/react/schemaRenderer/SimpleElements.js +147 -0
  160. package/dist/react/schemaRenderer/SimpleElements.js.map +1 -0
  161. package/dist/react/schemaRenderer/TabsRenderer.d.ts +17 -0
  162. package/dist/react/schemaRenderer/TabsRenderer.d.ts.map +1 -0
  163. package/dist/react/schemaRenderer/TabsRenderer.js +31 -0
  164. package/dist/react/schemaRenderer/TabsRenderer.js.map +1 -0
  165. package/dist/react/schemaRenderer/WizardRenderer.d.ts +34 -0
  166. package/dist/react/schemaRenderer/WizardRenderer.d.ts.map +1 -0
  167. package/dist/react/schemaRenderer/WizardRenderer.js +208 -0
  168. package/dist/react/schemaRenderer/WizardRenderer.js.map +1 -0
  169. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts +21 -0
  170. package/dist/react/schemaRenderer/action/ActionGroupTrigger.d.ts.map +1 -0
  171. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js +82 -0
  172. package/dist/react/schemaRenderer/action/ActionGroupTrigger.js.map +1 -0
  173. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts +30 -0
  174. package/dist/react/schemaRenderer/action/ActionModalDialog.d.ts.map +1 -0
  175. package/dist/react/schemaRenderer/action/ActionModalDialog.js +182 -0
  176. package/dist/react/schemaRenderer/action/ActionModalDialog.js.map +1 -0
  177. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts +17 -0
  178. package/dist/react/schemaRenderer/action/ConfirmActionDialog.d.ts.map +1 -0
  179. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js +19 -0
  180. package/dist/react/schemaRenderer/action/ConfirmActionDialog.js.map +1 -0
  181. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts +16 -0
  182. package/dist/react/schemaRenderer/action/HandlerActionButton.d.ts.map +1 -0
  183. package/dist/react/schemaRenderer/action/HandlerActionButton.js +16 -0
  184. package/dist/react/schemaRenderer/action/HandlerActionButton.js.map +1 -0
  185. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts +22 -0
  186. package/dist/react/schemaRenderer/action/MethodActionButton.d.ts.map +1 -0
  187. package/dist/react/schemaRenderer/action/MethodActionButton.js +26 -0
  188. package/dist/react/schemaRenderer/action/MethodActionButton.js.map +1 -0
  189. package/dist/react/schemaRenderer/action/buttons.d.ts +18 -0
  190. package/dist/react/schemaRenderer/action/buttons.d.ts.map +1 -0
  191. package/dist/react/schemaRenderer/action/buttons.js +74 -0
  192. package/dist/react/schemaRenderer/action/buttons.js.map +1 -0
  193. package/dist/react/schemaRenderer/action/helpers.d.ts +26 -0
  194. package/dist/react/schemaRenderer/action/helpers.d.ts.map +1 -0
  195. package/dist/react/schemaRenderer/action/helpers.js +126 -0
  196. package/dist/react/schemaRenderer/action/helpers.js.map +1 -0
  197. package/dist/react/schemaRenderer/action/renderAction.d.ts +21 -0
  198. package/dist/react/schemaRenderer/action/renderAction.d.ts.map +1 -0
  199. package/dist/react/schemaRenderer/action/renderAction.js +102 -0
  200. package/dist/react/schemaRenderer/action/renderAction.js.map +1 -0
  201. package/dist/react/schemaRenderer/columnFormat.d.ts +10 -0
  202. package/dist/react/schemaRenderer/columnFormat.d.ts.map +1 -0
  203. package/dist/react/schemaRenderer/columnFormat.js +76 -0
  204. package/dist/react/schemaRenderer/columnFormat.js.map +1 -0
  205. package/dist/react/schemaRenderer/constants.d.ts +8 -0
  206. package/dist/react/schemaRenderer/constants.d.ts.map +1 -0
  207. package/dist/react/schemaRenderer/constants.js +45 -0
  208. package/dist/react/schemaRenderer/constants.js.map +1 -0
  209. package/dist/react/schemaRenderer/form/FormRenderer.d.ts +29 -0
  210. package/dist/react/schemaRenderer/form/FormRenderer.d.ts.map +1 -0
  211. package/dist/react/schemaRenderer/form/FormRenderer.js +152 -0
  212. package/dist/react/schemaRenderer/form/FormRenderer.js.map +1 -0
  213. package/dist/react/schemaRenderer/form/renderField.d.ts +6 -0
  214. package/dist/react/schemaRenderer/form/renderField.d.ts.map +1 -0
  215. package/dist/react/schemaRenderer/form/renderField.js +239 -0
  216. package/dist/react/schemaRenderer/form/renderField.js.map +1 -0
  217. package/dist/react/schemaRenderer/helpers.d.ts +32 -0
  218. package/dist/react/schemaRenderer/helpers.d.ts.map +1 -0
  219. package/dist/react/schemaRenderer/helpers.js +52 -0
  220. package/dist/react/schemaRenderer/helpers.js.map +1 -0
  221. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts +60 -0
  222. package/dist/react/schemaRenderer/table/CardsLayoutBody.d.ts.map +1 -0
  223. package/dist/react/schemaRenderer/table/CardsLayoutBody.js +189 -0
  224. package/dist/react/schemaRenderer/table/CardsLayoutBody.js.map +1 -0
  225. package/dist/react/schemaRenderer/table/TableRenderer.d.ts +29 -0
  226. package/dist/react/schemaRenderer/table/TableRenderer.d.ts.map +1 -0
  227. package/dist/react/schemaRenderer/table/TableRenderer.js +85 -0
  228. package/dist/react/schemaRenderer/table/TableRenderer.js.map +1 -0
  229. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts +18 -0
  230. package/dist/react/schemaRenderer/table/TableRendererBody.d.ts.map +1 -0
  231. package/dist/react/schemaRenderer/table/TableRendererBody.js +555 -0
  232. package/dist/react/schemaRenderer/table/TableRendererBody.js.map +1 -0
  233. package/dist/react/schemaRenderer/table/filters.d.ts +263 -0
  234. package/dist/react/schemaRenderer/table/filters.d.ts.map +1 -0
  235. package/dist/react/schemaRenderer/table/filters.js +497 -0
  236. package/dist/react/schemaRenderer/table/filters.js.map +1 -0
  237. package/dist/react/schemaRenderer/table/formatCell.d.ts +11 -0
  238. package/dist/react/schemaRenderer/table/formatCell.d.ts.map +1 -0
  239. package/dist/react/schemaRenderer/table/formatCell.js +172 -0
  240. package/dist/react/schemaRenderer/table/formatCell.js.map +1 -0
  241. package/dist/react/schemaRenderer/table/links.d.ts +42 -0
  242. package/dist/react/schemaRenderer/table/links.d.ts.map +1 -0
  243. package/dist/react/schemaRenderer/table/links.js +55 -0
  244. package/dist/react/schemaRenderer/table/links.js.map +1 -0
  245. package/dist/react/schemaRenderer/table/renderRowActions.d.ts +13 -0
  246. package/dist/react/schemaRenderer/table/renderRowActions.d.ts.map +1 -0
  247. package/dist/react/schemaRenderer/table/renderRowActions.js +25 -0
  248. package/dist/react/schemaRenderer/table/renderRowActions.js.map +1 -0
  249. package/dist/react/schemaRenderer/table/url.d.ts +41 -0
  250. package/dist/react/schemaRenderer/table/url.d.ts.map +1 -0
  251. package/dist/react/schemaRenderer/table/url.js +114 -0
  252. package/dist/react/schemaRenderer/table/url.js.map +1 -0
  253. package/dist/routes/globals.d.ts +13 -0
  254. package/dist/routes/globals.d.ts.map +1 -0
  255. package/dist/routes/globals.js +131 -0
  256. package/dist/routes/globals.js.map +1 -0
  257. package/dist/routes/helpers.d.ts +217 -0
  258. package/dist/routes/helpers.d.ts.map +1 -0
  259. package/dist/routes/helpers.js +498 -0
  260. package/dist/routes/helpers.js.map +1 -0
  261. package/dist/routes/pages.d.ts +15 -0
  262. package/dist/routes/pages.d.ts.map +1 -0
  263. package/dist/routes/pages.js +145 -0
  264. package/dist/routes/pages.js.map +1 -0
  265. package/dist/routes/panel.d.ts +19 -0
  266. package/dist/routes/panel.d.ts.map +1 -0
  267. package/dist/routes/panel.js +191 -0
  268. package/dist/routes/panel.js.map +1 -0
  269. package/dist/routes/relations.d.ts +21 -0
  270. package/dist/routes/relations.d.ts.map +1 -0
  271. package/dist/routes/relations.js +1239 -0
  272. package/dist/routes/relations.js.map +1 -0
  273. package/dist/routes/resources.d.ts +28 -0
  274. package/dist/routes/resources.d.ts.map +1 -0
  275. package/dist/routes/resources.js +741 -0
  276. package/dist/routes/resources.js.map +1 -0
  277. package/dist/routes/theme.d.ts +12 -0
  278. package/dist/routes/theme.d.ts.map +1 -0
  279. package/dist/routes/theme.js +82 -0
  280. package/dist/routes/theme.js.map +1 -0
  281. package/dist/routes.d.ts.map +1 -1
  282. package/dist/routes.js +64 -3078
  283. package/dist/routes.js.map +1 -1
  284. package/dist/vite.d.ts +1 -0
  285. package/dist/vite.d.ts.map +1 -1
  286. package/dist/vite.js +26 -5
  287. package/dist/vite.js.map +1 -1
  288. package/package.json +2 -1
  289. package/src/Pilotiq.ts +95 -0
  290. package/src/actions/Action.ts +79 -723
  291. package/src/actions/bulkFactories.ts +168 -0
  292. package/src/actions/crudFactories.ts +220 -0
  293. package/src/actions/factoryHelpers.ts +177 -0
  294. package/src/actions/m2mFactories.ts +193 -0
  295. package/src/actions/relationFactories.ts +372 -0
  296. package/src/elements/dispatchForm.ts +1 -1
  297. package/src/elements/dispatchTable.ts +1 -1
  298. package/src/fields/Field.ts +39 -0
  299. package/src/pageData/breadcrumbs.ts +288 -0
  300. package/src/pageData/forms.ts +578 -0
  301. package/src/pageData/helpers.ts +764 -0
  302. package/src/pageData/misc.ts +347 -0
  303. package/src/pageData/navigation.ts +779 -0
  304. package/src/pageData/relationPages.ts +1246 -0
  305. package/src/pageData/relationTabs.ts +286 -0
  306. package/src/pageData/resourcePages.ts +593 -0
  307. package/src/pageData.ts +122 -4731
  308. package/src/react/AppShell.tsx +27 -1
  309. package/src/react/CollabExtensionFactoryRegistry.ts +55 -0
  310. package/src/react/CollabRoomContext.ts +42 -0
  311. package/src/react/FormCollabBindingRegistry.ts +72 -0
  312. package/src/react/RecordWrapperGate.tsx +40 -0
  313. package/src/react/RecordWrapperRegistry.ts +39 -0
  314. package/src/react/SchemaRenderer.tsx +230 -6479
  315. package/src/react/component-slots.test.ts +103 -0
  316. package/src/react/component-slots.ts +116 -0
  317. package/src/react/fields/BuilderInput.tsx +29 -117
  318. package/src/react/fields/MarkdownInput.tsx +0 -1
  319. package/src/react/fields/RepeaterInput.tsx +29 -130
  320. package/src/react/fields/rowState.ts +106 -0
  321. package/src/react/fields/useRowReorderDnd.ts +78 -0
  322. package/src/react/index.ts +38 -0
  323. package/src/react/layouts/SidebarLayout.tsx +39 -28
  324. package/src/react/layouts/TopbarLayout.tsx +70 -57
  325. package/src/react/parseRecordEditUrl.test.ts +75 -0
  326. package/src/react/parseRecordEditUrl.ts +55 -0
  327. package/src/react/persistedState.ts +40 -0
  328. package/src/react/schemaRenderer/AlertRenderer.tsx +112 -0
  329. package/src/react/schemaRenderer/EntryRenderer.tsx +501 -0
  330. package/src/react/schemaRenderer/SectionRenderer.tsx +120 -0
  331. package/src/react/schemaRenderer/SimpleElements.tsx +306 -0
  332. package/src/react/schemaRenderer/TabsRenderer.tsx +62 -0
  333. package/src/react/schemaRenderer/WizardRenderer.tsx +338 -0
  334. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +177 -0
  335. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +273 -0
  336. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +61 -0
  337. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +43 -0
  338. package/src/react/schemaRenderer/action/MethodActionButton.tsx +64 -0
  339. package/src/react/schemaRenderer/action/buttons.tsx +99 -0
  340. package/src/react/schemaRenderer/action/helpers.ts +140 -0
  341. package/src/react/schemaRenderer/action/renderAction.tsx +245 -0
  342. package/src/react/schemaRenderer/columnFormat.ts +65 -0
  343. package/src/react/schemaRenderer/constants.ts +50 -0
  344. package/src/react/schemaRenderer/form/FormRenderer.tsx +233 -0
  345. package/src/react/schemaRenderer/form/renderField.tsx +511 -0
  346. package/src/react/schemaRenderer/helpers.tsx +81 -0
  347. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +308 -0
  348. package/src/react/schemaRenderer/table/TableRenderer.tsx +123 -0
  349. package/src/react/schemaRenderer/table/TableRendererBody.tsx +974 -0
  350. package/src/react/schemaRenderer/table/filters.tsx +1233 -0
  351. package/src/react/schemaRenderer/table/formatCell.tsx +264 -0
  352. package/src/react/schemaRenderer/table/links.tsx +112 -0
  353. package/src/react/schemaRenderer/table/renderRowActions.tsx +52 -0
  354. package/src/react/schemaRenderer/table/url.tsx +143 -0
  355. package/src/routes/globals.ts +154 -0
  356. package/src/routes/helpers.ts +668 -0
  357. package/src/routes/pages.ts +173 -0
  358. package/src/routes/panel.ts +204 -0
  359. package/src/routes/relations.ts +1219 -0
  360. package/src/routes/resources.ts +786 -0
  361. package/src/routes/theme.ts +109 -0
  362. package/src/routes.test.ts +1 -1
  363. package/src/routes.ts +64 -3176
  364. package/src/schema/TableWidget.test.ts +2 -2
  365. package/src/theme/migrate.test.ts +178 -0
  366. package/src/vite.test.ts +184 -0
  367. package/src/vite.ts +26 -4
@@ -0,0 +1,209 @@
1
+ /**
2
+ * CRUD single-row Action factories — `create / edit / view / delete /
3
+ * replicate / restore / forceDelete`, plus the notification `markAsRead`
4
+ * factory.
5
+ *
6
+ * Each factory builds and returns a configured `Action`. The matching
7
+ * `static` methods on the `Action` class are thin delegators that call
8
+ * into these functions, preserving the public `Action.create(R, base)`
9
+ * call shape.
10
+ *
11
+ * See `docs/plans/action-split.md` for the split plan.
12
+ */
13
+ import { Action } from './Action.js';
14
+ import { buildReplica, callPredicate, isTrashed, resourceBase } from './factoryHelpers.js';
15
+ /** Create-action factory — link to `${basePath}/${R.slug}/create`.
16
+ * Auto-hides when `R.canCreate(user)` returns false. */
17
+ export function createAction(R, basePath) {
18
+ return Action.make('create')
19
+ .label(`New ${R.labelSingular}`)
20
+ .href(`${resourceBase(basePath, R)}/create`)
21
+ .visible(({ user }) => callPredicate(R.canCreate, user));
22
+ }
23
+ /**
24
+ * Edit-action factory — link to the resource's edit page.
25
+ *
26
+ * Pass `recordId` when building actions for a single-record context
27
+ * (e.g. `ViewPage.getActions()`); the URL is baked at config time.
28
+ * Omit `recordId` for row context (`Table.recordActions(...)`); the
29
+ * URL keeps the `:id` template and the renderer substitutes per-row.
30
+ *
31
+ * Auto-hides when `R.canEdit(user, record)` returns false. For row
32
+ * context the per-row record threads in via `loadTableRecords`'s
33
+ * per-row eval; for view-page context, `resolveSchema` provides the
34
+ * resolved record on the eval context.
35
+ */
36
+ export function editAction(R, basePath, recordId) {
37
+ const id = recordId ?? ':id';
38
+ return Action.make('edit')
39
+ .label('Edit')
40
+ .href(`${resourceBase(basePath, R)}/${id}/edit`)
41
+ .visible(({ user, record }) => callPredicate(R.canEdit, user, record));
42
+ }
43
+ /** View-action factory — link to the resource's view page. See `editAction` for the `recordId` semantics.
44
+ * Auto-hides when `R.canView(user, record)` returns false. */
45
+ export function viewAction(R, basePath, recordId) {
46
+ const id = recordId ?? ':id';
47
+ return Action.make('view')
48
+ .label('View')
49
+ .href(`${resourceBase(basePath, R)}/${id}`)
50
+ .visible(({ user, record }) => callPredicate(R.canView, user, record));
51
+ }
52
+ /**
53
+ * Delete-action factory — POSTs to the resource's delete route,
54
+ * destructive style, with a confirmation prompt referencing the
55
+ * resource label. Same `recordId` semantics as `editAction`.
56
+ * Auto-hides when `R.canDelete(user, record)` returns false.
57
+ *
58
+ * Plan #13 — when `R.softDeletes = true`, additionally hides on
59
+ * rows whose `deletedAtColumn` is set (already-trashed rows get the
60
+ * Restore + ForceDelete pair instead, surfaced via the matching
61
+ * factories below).
62
+ */
63
+ export function deleteAction(R, basePath, recordId) {
64
+ const id = recordId ?? ':id';
65
+ return Action.make('delete')
66
+ .label('Delete')
67
+ .destructive()
68
+ .method('post')
69
+ .action(`${resourceBase(basePath, R)}/${id}/delete`)
70
+ .confirm(`Delete this ${R.labelSingular.toLowerCase()}?`)
71
+ .visible(async ({ user, record }) => {
72
+ if (R.softDeletes && isTrashed(record, R))
73
+ return false;
74
+ return callPredicate(R.canDelete, user, record);
75
+ });
76
+ }
77
+ /**
78
+ * Replicate-action factory — handler-style. Loads the source record
79
+ * from `ctx.record` (the `_action/:actionName` route already resolves
80
+ * it through `R.query(ctx)` for row + single-target placements),
81
+ * strips PK + soft-delete column + any `opts.excludeAttributes`,
82
+ * optionally runs `opts.beforeReplicaSaved`, and creates a new row
83
+ * via `R.model.create(...)`. Redirects to the new record's edit page
84
+ * on success so the user can review + tweak before saving again.
85
+ *
86
+ * `recordId` kept in the signature for parity with `delete / edit /
87
+ * view` so users can swap factories without rewriting call sites; the
88
+ * dispatcher resolves the source record from the URL and hands it to
89
+ * the handler as `ctx.record`, so we don't reference `recordId` here.
90
+ *
91
+ * Auto-hides when `R.canCreate(user)` returns false — replicating
92
+ * writes a new row, so the gate is `canCreate`, not `canView`.
93
+ */
94
+ export function replicateAction(R, basePath, recordId, opts = {}) {
95
+ void recordId;
96
+ return Action.make('replicate')
97
+ .label('Replicate')
98
+ .handler(async (ctx) => {
99
+ const source = ctx.record;
100
+ if (!source || typeof source !== 'object') {
101
+ return { notify: { title: 'Replicate failed: source record missing', type: 'error' } };
102
+ }
103
+ const M = R.model;
104
+ if (!M || typeof M.create !== 'function') {
105
+ return { notify: { title: 'Replicate not configured (resource has no model.create)', type: 'error' } };
106
+ }
107
+ let replica;
108
+ let pkCol;
109
+ try {
110
+ ({ replica, pkCol } = await buildReplica(source, M, {
111
+ excludeAttributes: opts.excludeAttributes,
112
+ deletedAtColumn: R.deletedAtColumn,
113
+ beforeReplicaSaved: opts.beforeReplicaSaved,
114
+ }));
115
+ }
116
+ catch (err) {
117
+ return { notify: { title: `Replicate failed: ${err instanceof Error ? err.message : String(err)}`, type: 'error' } };
118
+ }
119
+ let created;
120
+ try {
121
+ created = await M.create(replica);
122
+ }
123
+ catch (err) {
124
+ return { notify: { title: `Replicate failed: ${err instanceof Error ? err.message : String(err)}`, type: 'error' } };
125
+ }
126
+ const newId = created?.[pkCol];
127
+ const defaultRedirect = newId !== undefined && newId !== null
128
+ ? `${resourceBase(basePath, R)}/${String(newId)}/edit`
129
+ : `${resourceBase(basePath, R)}`;
130
+ // `!== undefined` rather than `??` so an override returning
131
+ // `null`/empty-string isn't silently swallowed (see
132
+ // feedback_nullish_swallows_explicit_null).
133
+ const overrideRedirect = opts.getRedirectUrl
134
+ ? await opts.getRedirectUrl({ replica: created, source })
135
+ : undefined;
136
+ const redirect = overrideRedirect !== undefined ? overrideRedirect : defaultRedirect;
137
+ const overrideTitle = opts.getCreatedNotificationTitle
138
+ ? await opts.getCreatedNotificationTitle({ replica: created, source })
139
+ : undefined;
140
+ const title = overrideTitle !== undefined ? overrideTitle : `${R.labelSingular} replicated`;
141
+ return {
142
+ redirect,
143
+ notify: { title, type: 'success' },
144
+ };
145
+ })
146
+ .visible(({ user }) => callPredicate(R.canCreate, user));
147
+ }
148
+ /**
149
+ * Plan #13 — Restore factory. POSTs to the resource's restore route,
150
+ * success-styled, no confirm prompt (restoration is reversible).
151
+ * Auto-hides on live (non-trashed) rows AND when `R.canRestore(user,
152
+ * record)` returns false. Same `recordId` semantics as `editAction`.
153
+ */
154
+ export function restoreAction(R, basePath, recordId) {
155
+ const id = recordId ?? ':id';
156
+ return Action.make('restore')
157
+ .label('Restore')
158
+ .color('success')
159
+ .method('post')
160
+ .action(`${resourceBase(basePath, R)}/${id}/restore`)
161
+ .visible(async ({ user, record }) => {
162
+ if (!isTrashed(record, R))
163
+ return false;
164
+ return callPredicate(R.canRestore, user, record);
165
+ });
166
+ }
167
+ /**
168
+ * Plan #13 — Force-delete factory. POSTs to the resource's
169
+ * force-delete route, destructive-styled, with a stricter confirm
170
+ * prompt referencing permanence. Auto-hides on live (non-trashed)
171
+ * rows AND when `R.canForceDelete(user, record)` returns false.
172
+ */
173
+ export function forceDeleteAction(R, basePath, recordId) {
174
+ const id = recordId ?? ':id';
175
+ return Action.make('forceDelete')
176
+ .label('Delete forever')
177
+ .destructive()
178
+ .method('post')
179
+ .action(`${resourceBase(basePath, R)}/${id}/force-delete`)
180
+ .confirm(`Permanently delete this ${R.labelSingular.toLowerCase()}? This cannot be undone.`)
181
+ .visible(async ({ user, record }) => {
182
+ if (!isTrashed(record, R))
183
+ return false;
184
+ return callPredicate(R.canForceDelete, user, record);
185
+ });
186
+ }
187
+ /**
188
+ * Mark-as-read factory — POSTs to the panel's notification read
189
+ * endpoint for the given notification id. The endpoint
190
+ * (`${base}/_notifications/:id/read`) is mounted by
191
+ * `Pilotiq.databaseNotifications()`, so calling this without
192
+ * opting into the bell surface produces an Action whose POST 404s.
193
+ *
194
+ * `notificationId` is baked at config time. For row context where
195
+ * the id varies per row, omit it and the URL keeps the `:id`
196
+ * template; the renderer substitutes per-row at render time
197
+ * (parallel to `editAction`'s row form).
198
+ *
199
+ * No auto-visibility. Wrap in `.visible(({ record }) => !record.readAt)`
200
+ * to hide on already-read rows.
201
+ */
202
+ export function markAsReadAction(basePath, notificationId) {
203
+ const id = notificationId ?? ':id';
204
+ return Action.make('markAsRead')
205
+ .label('Mark as read')
206
+ .method('post')
207
+ .action(`${basePath}/_notifications/${id}/read`);
208
+ }
209
+ //# sourceMappingURL=crudFactories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crudFactories.js","sourceRoot":"","sources":["../../src/actions/crudFactories.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Shared helpers for the Action factory modules — `crudFactories.ts`,
3
+ * `bulkFactories.ts`, `relationFactories.ts`, `m2mFactories.ts`.
4
+ *
5
+ * Lives in its own file so the per-phase factory modules stay focused
6
+ * on their own factory bodies. Anything consumed by 2+ phase files
7
+ * lands here; phase-local helpers stay alongside their phase's
8
+ * factories.
9
+ *
10
+ * See `docs/plans/action-split.md` for the split plan.
11
+ */
12
+ import type { ResourceLike } from './Action.js';
13
+ import type { RelationManagerContext } from '../RelationManager.js';
14
+ /** Cluster-aware resource base path. Mirrors `clusterPaths.resourceBasePath`
15
+ * but uses the structural `ResourceLike` shape so `Action.ts` stays
16
+ * cycle-free against `Resource.ts`. */
17
+ export declare function resourceBase(basePath: string, R: ResourceLike): string;
18
+ /** Call a (possibly undefined) Resource predicate. When unset, the
19
+ * predicate is treated as "allowed" (returns true) so the factory
20
+ * doesn't hide actions on Resources that haven't opted into Plan #10. */
21
+ export declare function callPredicate(fn: ((user: unknown, record?: unknown) => boolean | Promise<boolean>) | undefined, user: unknown, record?: unknown): boolean | Promise<boolean>;
22
+ /** Read `record[R.deletedAtColumn ?? 'deletedAt']` and return true when
23
+ * the row is currently trashed (soft-deleted). Permissive on shape —
24
+ * bare `null` / `undefined` count as live; any other truthy value is
25
+ * trashed. */
26
+ export declare function isTrashed(record: unknown, R: ResourceLike): boolean;
27
+ /** True when a `RelationManagerContext.mode` denotes a pivot-mutation
28
+ * shape — i.e. a many-to-many relation. All three modes share the
29
+ * `attach` / `detach` / `sync` accessor surface (the rudder ORM stamps
30
+ * + filters the polymorphic discriminator transparently for the morph
31
+ * variants). The `relationCreate / Edit / Delete` factories auto-hide
32
+ * under any of these modes because per-pivot-row create / edit / delete
33
+ * is meaningless — users create the related record via its own Resource,
34
+ * then attach via `relationAttach`. */
35
+ export declare function isM2MMode(mode: RelationManagerContext['mode']): boolean;
36
+ /**
37
+ * Build the URL prefix for a relation factory action. Without
38
+ * a `chain` (depth-1 manager), this is the familiar
39
+ * `${base}/${parentSlug}/${parentId}/${relationship}`. With a chain
40
+ * (depth-2 nested manager), it threads the outer record + relationship
41
+ * between the parent slug and the leaf parent id:
42
+ *
43
+ * `${base}/${parentSlug}/${chain[0].recordId}/${chain[0].relationship}/${parentId}/${relationship}`
44
+ *
45
+ * Pure; takes a `RelationManagerContext` and emits a string. The leaf
46
+ * record id (and trailing `/edit`, `/delete`, etc.) gets appended by
47
+ * the caller.
48
+ */
49
+ export declare function relationUrlPrefix(ctx: RelationManagerContext): string;
50
+ /** Options bag for `buildReplica`. Optional fields explicitly accept
51
+ * `undefined` so call sites can pass `opts.excludeAttributes` through
52
+ * unconditionally under `exactOptionalPropertyTypes: true`. */
53
+ export interface BuildReplicaOptions {
54
+ /** Attribute keys to drop from the replicated payload IN ADDITION TO
55
+ * the model's primary key and soft-delete column. */
56
+ excludeAttributes?: readonly string[] | undefined;
57
+ /** Soft-delete column name on the source Resource. Defaults to
58
+ * `'deletedAt'`. Read separately from the model because the column
59
+ * lives on the Resource shape (`R.deletedAtColumn`) rather than on
60
+ * the model itself. */
61
+ deletedAtColumn?: string | undefined;
62
+ /** Force-pinned columns applied AFTER the strip and BEFORE the user
63
+ * `beforeReplicaSaved` mutator. Used by the relation replicate
64
+ * factories to re-stamp the parent attachment FK / morph columns
65
+ * so a tampered source row can't slip a different parent in. */
66
+ pin?: Record<string, unknown> | undefined;
67
+ /** Optional user mutator. Runs after the strip + pin. */
68
+ beforeReplicaSaved?: ((replica: Record<string, unknown>, source: unknown) => Record<string, unknown> | Promise<Record<string, unknown>>) | undefined;
69
+ }
70
+ /**
71
+ * Build a replica payload from a source record. Used by every replicate
72
+ * factory (`replicateAction / bulkReplicateAction / relationReplicateAction
73
+ * / relationBulkReplicateAction`).
74
+ *
75
+ * Strips the model's primary key (`model.primaryKey`, defaulting to
76
+ * `'id'`), the soft-delete column (defaulting to `'deletedAt'`), and any
77
+ * `excludeAttributes` keys. Applies `pin` columns (parent attachment
78
+ * for relation factories), then runs the optional `beforeReplicaSaved`
79
+ * user mutator. Returns the replica AND the resolved primary-key column
80
+ * name (callers need it to read `created[pkCol]` for redirect URLs).
81
+ *
82
+ * Does NOT call `model.create` — callers wrap their own create + error
83
+ * handling around the returned replica.
84
+ */
85
+ export declare function buildReplica(source: unknown, model: {
86
+ primaryKey?: string;
87
+ }, opts?: BuildReplicaOptions): Promise<{
88
+ replica: Record<string, unknown>;
89
+ pkCol: string;
90
+ }>;
91
+ /**
92
+ * Iterate `records`, run the policy probe in parallel up-front (only
93
+ * allowed rows enter the serial work loop), call `op(id, record)` per
94
+ * allowed row, swallow per-row throws (the aggregate notification shows
95
+ * the count succeeded). Returns the success count.
96
+ *
97
+ * Used by every bulk handler (`bulkDeleteAction / bulkRestoreAction /
98
+ * bulkForceDeleteAction / bulkReplicateAction / relationBulkReplicateAction
99
+ * / relationBulkDetachAction`-style pattern).
100
+ *
101
+ * Rows whose `record.id` coerces to an empty string are skipped without
102
+ * counting them as an attempt. The policy probe runs via `Promise.all`
103
+ * so backend round-trips parallelize, but the write loop stays serial
104
+ * (no transaction in v1 — concurrent writes would muddy failure
105
+ * semantics).
106
+ */
107
+ export declare function forEachAllowed(records: readonly unknown[], isAllowed: (record: unknown, index: number) => boolean | Promise<boolean>, op: (id: string, record: unknown, index: number) => Promise<void>): Promise<number>;
108
+ //# sourceMappingURL=factoryHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factoryHelpers.d.ts","sourceRoot":"","sources":["../../src/actions/factoryHelpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAEnE;;wCAEwC;AACxC,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAGtE;AAED;;yEAEyE;AACzE,wBAAgB,aAAa,CAC3B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,EACjF,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAG5B;AAED;;;eAGe;AACf,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CAKnE;AAED;;;;;;;wCAOwC;AACxC,wBAAgB,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,MAAM,CAAC,GAAG,OAAO,CAEvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,CAQrE;AAED;;gEAEgE;AAChE,MAAM,WAAW,mBAAmB;IAClC;0DACsD;IACtD,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACjD;;;4BAGwB;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC;;;qEAGiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzC,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,CAAC,CACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAG,OAAO,KACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;CAC7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,OAAO,EACf,KAAK,EAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/B,IAAI,GAAI,mBAAwB,GAC/B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAI,SAAS,OAAO,EAAE,EAC7B,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACzE,EAAE,EAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACvE,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Shared helpers for the Action factory modules — `crudFactories.ts`,
3
+ * `bulkFactories.ts`, `relationFactories.ts`, `m2mFactories.ts`.
4
+ *
5
+ * Lives in its own file so the per-phase factory modules stay focused
6
+ * on their own factory bodies. Anything consumed by 2+ phase files
7
+ * lands here; phase-local helpers stay alongside their phase's
8
+ * factories.
9
+ *
10
+ * See `docs/plans/action-split.md` for the split plan.
11
+ */
12
+ /** Cluster-aware resource base path. Mirrors `clusterPaths.resourceBasePath`
13
+ * but uses the structural `ResourceLike` shape so `Action.ts` stays
14
+ * cycle-free against `Resource.ts`. */
15
+ export function resourceBase(basePath, R) {
16
+ if (R.cluster)
17
+ return `${basePath}/${R.cluster.getSlug()}/${R.getSlug()}`;
18
+ return `${basePath}/${R.getSlug()}`;
19
+ }
20
+ /** Call a (possibly undefined) Resource predicate. When unset, the
21
+ * predicate is treated as "allowed" (returns true) so the factory
22
+ * doesn't hide actions on Resources that haven't opted into Plan #10. */
23
+ export function callPredicate(fn, user, record) {
24
+ if (!fn)
25
+ return true;
26
+ return fn(user, record);
27
+ }
28
+ /** Read `record[R.deletedAtColumn ?? 'deletedAt']` and return true when
29
+ * the row is currently trashed (soft-deleted). Permissive on shape —
30
+ * bare `null` / `undefined` count as live; any other truthy value is
31
+ * trashed. */
32
+ export function isTrashed(record, R) {
33
+ if (!record || typeof record !== 'object')
34
+ return false;
35
+ const col = R.deletedAtColumn ?? 'deletedAt';
36
+ const v = record[col];
37
+ return v !== null && v !== undefined;
38
+ }
39
+ /** True when a `RelationManagerContext.mode` denotes a pivot-mutation
40
+ * shape — i.e. a many-to-many relation. All three modes share the
41
+ * `attach` / `detach` / `sync` accessor surface (the rudder ORM stamps
42
+ * + filters the polymorphic discriminator transparently for the morph
43
+ * variants). The `relationCreate / Edit / Delete` factories auto-hide
44
+ * under any of these modes because per-pivot-row create / edit / delete
45
+ * is meaningless — users create the related record via its own Resource,
46
+ * then attach via `relationAttach`. */
47
+ export function isM2MMode(mode) {
48
+ return mode === 'belongsToMany' || mode === 'morphToMany' || mode === 'morphedByMany';
49
+ }
50
+ /**
51
+ * Build the URL prefix for a relation factory action. Without
52
+ * a `chain` (depth-1 manager), this is the familiar
53
+ * `${base}/${parentSlug}/${parentId}/${relationship}`. With a chain
54
+ * (depth-2 nested manager), it threads the outer record + relationship
55
+ * between the parent slug and the leaf parent id:
56
+ *
57
+ * `${base}/${parentSlug}/${chain[0].recordId}/${chain[0].relationship}/${parentId}/${relationship}`
58
+ *
59
+ * Pure; takes a `RelationManagerContext` and emits a string. The leaf
60
+ * record id (and trailing `/edit`, `/delete`, etc.) gets appended by
61
+ * the caller.
62
+ */
63
+ export function relationUrlPrefix(ctx) {
64
+ const head = `${ctx.basePath}/${ctx.parentSlug}`;
65
+ const chain = ctx.chain ?? [];
66
+ let mid = '';
67
+ for (const step of chain) {
68
+ mid += `/${step.recordId}/${step.relationship}`;
69
+ }
70
+ return `${head}${mid}/${ctx.parentId}/${ctx.relationship}`;
71
+ }
72
+ /**
73
+ * Build a replica payload from a source record. Used by every replicate
74
+ * factory (`replicateAction / bulkReplicateAction / relationReplicateAction
75
+ * / relationBulkReplicateAction`).
76
+ *
77
+ * Strips the model's primary key (`model.primaryKey`, defaulting to
78
+ * `'id'`), the soft-delete column (defaulting to `'deletedAt'`), and any
79
+ * `excludeAttributes` keys. Applies `pin` columns (parent attachment
80
+ * for relation factories), then runs the optional `beforeReplicaSaved`
81
+ * user mutator. Returns the replica AND the resolved primary-key column
82
+ * name (callers need it to read `created[pkCol]` for redirect URLs).
83
+ *
84
+ * Does NOT call `model.create` — callers wrap their own create + error
85
+ * handling around the returned replica.
86
+ */
87
+ export async function buildReplica(source, model, opts = {}) {
88
+ const pkCol = model.primaryKey ?? 'id';
89
+ const trashedCol = opts.deletedAtColumn ?? 'deletedAt';
90
+ const skip = new Set([pkCol, trashedCol, ...(opts.excludeAttributes ?? [])]);
91
+ let replica = {};
92
+ for (const [k, v] of Object.entries(source)) {
93
+ if (skip.has(k))
94
+ continue;
95
+ replica[k] = v;
96
+ }
97
+ if (opts.pin)
98
+ Object.assign(replica, opts.pin);
99
+ if (opts.beforeReplicaSaved) {
100
+ replica = await opts.beforeReplicaSaved(replica, source);
101
+ }
102
+ return { replica, pkCol };
103
+ }
104
+ /**
105
+ * Iterate `records`, run the policy probe in parallel up-front (only
106
+ * allowed rows enter the serial work loop), call `op(id, record)` per
107
+ * allowed row, swallow per-row throws (the aggregate notification shows
108
+ * the count succeeded). Returns the success count.
109
+ *
110
+ * Used by every bulk handler (`bulkDeleteAction / bulkRestoreAction /
111
+ * bulkForceDeleteAction / bulkReplicateAction / relationBulkReplicateAction
112
+ * / relationBulkDetachAction`-style pattern).
113
+ *
114
+ * Rows whose `record.id` coerces to an empty string are skipped without
115
+ * counting them as an attempt. The policy probe runs via `Promise.all`
116
+ * so backend round-trips parallelize, but the write loop stays serial
117
+ * (no transaction in v1 — concurrent writes would muddy failure
118
+ * semantics).
119
+ */
120
+ export async function forEachAllowed(records, isAllowed, op) {
121
+ const allowedFlags = await Promise.all(records.map((r, i) => isAllowed(r, i)));
122
+ let n = 0;
123
+ for (let i = 0; i < records.length; i++) {
124
+ if (!allowedFlags[i])
125
+ continue;
126
+ const record = records[i];
127
+ const id = String(record?.id ?? '');
128
+ if (!id)
129
+ continue;
130
+ try {
131
+ await op(id, record, i);
132
+ n++;
133
+ }
134
+ catch { /* skip — agg notify shows total */ }
135
+ }
136
+ return n;
137
+ }
138
+ //# sourceMappingURL=factoryHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factoryHelpers.js","sourceRoot":"","sources":["../../src/actions/factoryHelpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * M2M relation Action factories — `relationAttach` (header, modal-form
3
+ * picker → POST `_action/relationAttach`), `relationDetach` (row, direct
4
+ * POST to `_detach/:childId`), `relationBulkDetach` (bulk, handler-
5
+ * dispatched).
6
+ *
7
+ * Sibling of `relationCreate / Edit / Delete` for every M2M mode
8
+ * (`belongsToMany`, `morphToMany` (owning polymorphic side),
9
+ * `morphedByMany` (inverse polymorphic side)). All three modes share
10
+ * the same `attach` / `detach` / `sync` accessor surface — the rudder
11
+ * ORM stamps + filters the polymorphic discriminator on the morph
12
+ * variants automatically, so pilotiq's pivot factories are mode-agnostic
13
+ * beyond the visibility gate.
14
+ *
15
+ * All three auto-hide outside any M2M mode so dropping a factory into
16
+ * a non-M2M manager is a no-op (visible=false) instead of a confusing
17
+ * 404.
18
+ *
19
+ * The first and third route through the manager-scoped
20
+ * `_action/:actionName` endpoint (added in routes.ts) so handlers
21
+ * see `ctx.relation = { parent, parentId, relationship }`.
22
+ *
23
+ * See `docs/plans/action-split.md` for the split plan.
24
+ */
25
+ import { Action } from './Action.js';
26
+ import { type RelationManager, type RelationManagerContext } from '../RelationManager.js';
27
+ /** Header-placement attach factory — opens a modal with a SelectField
28
+ * listing related records that aren't already attached, and POSTs the
29
+ * selected id to the manager's `_action/relationAttach` endpoint.
30
+ *
31
+ * Visibility delegates to `M.canAttach(user, parentRecord)` AND
32
+ * guards against being dropped into a non-M2M manager. */
33
+ export declare function relationAttachAction(M: typeof RelationManager, ctx: RelationManagerContext): Action;
34
+ /** Row-placement detach factory — POSTs to
35
+ * `${base}/${parentSlug}/${parentId}/${relationship}/${recordId ?? ':id'}/_detach`,
36
+ * destructive style with a confirmation prompt that says "Detach"
37
+ * (not "Delete") so users understand the target record stays.
38
+ * Visibility delegates to `M.canDetach`. */
39
+ export declare function relationDetachAction(M: typeof RelationManager, ctx: RelationManagerContext, recordId?: string): Action;
40
+ /** Bulk-placement bulk-detach factory — handler-dispatched. Calls
41
+ * `parent.related(rel).detach(ids)` for the selected rows. Visibility
42
+ * delegates to `M.canAttach` (acts like a "manager admin" gate; we
43
+ * intentionally don't enforce per-row `canDetach` on the visibility
44
+ * side because the bulk button needs to be visible before the user
45
+ * has selected anything — per-row gating happens inside the handler). */
46
+ export declare function relationBulkDetachAction(M: typeof RelationManager, ctx: RelationManagerContext): Action;
47
+ //# sourceMappingURL=m2mFactories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"m2mFactories.d.ts","sourceRoot":"","sources":["../../src/actions/m2mFactories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,aAAa,CAAA;AACvD,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAA;AAsC9B;;;;;2DAK2D;AAC3D,wBAAgB,oBAAoB,CAClC,CAAC,EAAI,OAAO,eAAe,EAC3B,GAAG,EAAE,sBAAsB,GAC1B,MAAM,CA4CR;AAED;;;;6CAI6C;AAC7C,wBAAgB,oBAAoB,CAClC,CAAC,EAAS,OAAO,eAAe,EAChC,GAAG,EAAO,sBAAsB,EAChC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAaR;AAED;;;;;0EAK0E;AAC1E,wBAAgB,wBAAwB,CACtC,CAAC,EAAI,OAAO,eAAe,EAC3B,GAAG,EAAE,sBAAsB,GAC1B,MAAM,CAoCR"}