@antelopejs/interface-dms 0.10.4 → 0.13.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 (384) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +21 -10
  3. package/dist/attachments.d.ts +15 -2
  4. package/dist/attachments.js +14 -1
  5. package/dist/attachments.js.map +1 -1
  6. package/dist/auth/db/models/sessions.model.d.ts +7 -5
  7. package/dist/auth/db/models/sessions.model.js +2 -9
  8. package/dist/auth/db/models/sessions.model.js.map +1 -1
  9. package/dist/auth/db/models/userExternalIdentities.model.d.ts +7 -5
  10. package/dist/auth/db/models/users.model.d.ts +7 -5
  11. package/dist/auth/db/tables/users.table.d.ts +2 -2
  12. package/dist/auth/db/tables/users.table.js.map +1 -1
  13. package/dist/auth/index.d.ts +4 -4
  14. package/dist/auth/internal/jwt-auth-decorator.d.ts +1 -1
  15. package/dist/auth/internal/jwt-auth-decorator.js +6 -3
  16. package/dist/auth/internal/jwt-auth-decorator.js.map +1 -1
  17. package/dist/auth/internal/request-authenticators.d.ts +12 -0
  18. package/dist/auth/internal/request-authenticators.js +53 -10
  19. package/dist/auth/internal/request-authenticators.js.map +1 -1
  20. package/dist/base/activity-feed.d.ts +34 -32
  21. package/dist/base/activity-feed.js +2 -0
  22. package/dist/base/activity-feed.js.map +1 -1
  23. package/dist/base/banner.d.ts +12 -10
  24. package/dist/base/banner.js +2 -0
  25. package/dist/base/banner.js.map +1 -1
  26. package/dist/base/block-registry/internal/describe.js +4 -12
  27. package/dist/base/block-registry/internal/describe.js.map +1 -1
  28. package/dist/base/block-registry/internal/ui.js +1 -1
  29. package/dist/base/block-registry/internal/ui.js.map +1 -1
  30. package/dist/base/card.d.ts +11 -9
  31. package/dist/base/card.js +2 -0
  32. package/dist/base/card.js.map +1 -1
  33. package/dist/base/chart-card.d.ts +4 -2
  34. package/dist/base/chart-card.js +2 -0
  35. package/dist/base/chart-card.js.map +1 -1
  36. package/dist/base/chart-schemas.d.ts +148 -148
  37. package/dist/base/chart.d.ts +65 -0
  38. package/dist/base/chart.js +65 -0
  39. package/dist/base/chart.js.map +1 -1
  40. package/dist/base/code-block.d.ts +5 -3
  41. package/dist/base/code-block.js +2 -0
  42. package/dist/base/code-block.js.map +1 -1
  43. package/dist/base/custom.d.ts +5 -0
  44. package/dist/base/custom.js +5 -0
  45. package/dist/base/custom.js.map +1 -1
  46. package/dist/base/data-types/default/address.d.ts +5 -0
  47. package/dist/base/data-types/default/address.js +5 -0
  48. package/dist/base/data-types/default/address.js.map +1 -1
  49. package/dist/base/data-types/default/choices.d.ts +20 -0
  50. package/dist/base/data-types/default/choices.js +20 -0
  51. package/dist/base/data-types/default/choices.js.map +1 -1
  52. package/dist/base/data-types/default/files.d.ts +22 -5
  53. package/dist/base/data-types/default/files.js +20 -0
  54. package/dist/base/data-types/default/files.js.map +1 -1
  55. package/dist/base/data-types/default/numbers.d.ts +15 -0
  56. package/dist/base/data-types/default/numbers.js +25 -9
  57. package/dist/base/data-types/default/numbers.js.map +1 -1
  58. package/dist/base/data-types/default/relations.d.ts +10 -2
  59. package/dist/base/data-types/default/relations.js +9 -6
  60. package/dist/base/data-types/default/relations.js.map +1 -1
  61. package/dist/base/data-types/default/strings.d.ts +25 -0
  62. package/dist/base/data-types/default/strings.js +25 -0
  63. package/dist/base/data-types/default/strings.js.map +1 -1
  64. package/dist/base/data-types/default-types.d.ts +1 -1
  65. package/dist/base/data-types/field-types.d.ts +10 -0
  66. package/dist/base/data-types/field-types.js +10 -0
  67. package/dist/base/data-types/field-types.js.map +1 -1
  68. package/dist/base/data-types/internal/relation-endpoints.js +1 -0
  69. package/dist/base/data-types/internal/relation-endpoints.js.map +1 -1
  70. package/dist/base/data-types/status-type.d.ts +5 -0
  71. package/dist/base/data-types/status-type.js +5 -0
  72. package/dist/base/data-types/status-type.js.map +1 -1
  73. package/dist/base/display.d.ts +6 -6
  74. package/dist/base/empty-state.d.ts +15 -13
  75. package/dist/base/empty-state.js +2 -0
  76. package/dist/base/empty-state.js.map +1 -1
  77. package/dist/base/form-block-schema.d.ts +50 -50
  78. package/dist/base/form-schema.d.ts +2 -0
  79. package/dist/base/form-schema.js +2 -0
  80. package/dist/base/form-schema.js.map +1 -1
  81. package/dist/base/grid.d.ts +4 -0
  82. package/dist/base/grid.js +4 -0
  83. package/dist/base/grid.js.map +1 -1
  84. package/dist/base/guard.d.ts +30 -28
  85. package/dist/base/guard.js +2 -0
  86. package/dist/base/guard.js.map +1 -1
  87. package/dist/base/helpers/archive-mode-helpers.d.ts +1 -1
  88. package/dist/base/helpers/file-refs.js +15 -15
  89. package/dist/base/helpers/file-refs.js.map +1 -1
  90. package/dist/base/internal/form-schema-validation.js +7 -1
  91. package/dist/base/internal/form-schema-validation.js.map +1 -1
  92. package/dist/base/internal/realtime-topics.js.map +1 -1
  93. package/dist/base/internal/searchable.d.ts +2 -1
  94. package/dist/base/internal/searchable.js +1 -3
  95. package/dist/base/internal/searchable.js.map +1 -1
  96. package/dist/base/key-value-list.d.ts +21 -19
  97. package/dist/base/key-value-list.js +2 -0
  98. package/dist/base/key-value-list.js.map +1 -1
  99. package/dist/base/kpi-card.d.ts +4 -2
  100. package/dist/base/kpi-card.js +2 -0
  101. package/dist/base/kpi-card.js.map +1 -1
  102. package/dist/base/live-toggle.d.ts +2 -0
  103. package/dist/base/live-toggle.js +2 -0
  104. package/dist/base/live-toggle.js.map +1 -1
  105. package/dist/base/meter.d.ts +23 -21
  106. package/dist/base/meter.js +2 -0
  107. package/dist/base/meter.js.map +1 -1
  108. package/dist/base/nav-card-grid.d.ts +24 -19
  109. package/dist/base/nav-card-grid.js +5 -0
  110. package/dist/base/nav-card-grid.js.map +1 -1
  111. package/dist/base/page-toolbar.d.ts +2 -0
  112. package/dist/base/page-toolbar.js +2 -0
  113. package/dist/base/page-toolbar.js.map +1 -1
  114. package/dist/base/period-selector.d.ts +3 -1
  115. package/dist/base/period-selector.js +2 -0
  116. package/dist/base/period-selector.js.map +1 -1
  117. package/dist/base/placeholder.d.ts +2 -0
  118. package/dist/base/placeholder.js +2 -0
  119. package/dist/base/placeholder.js.map +1 -1
  120. package/dist/base/resource-form-schema.d.ts +2 -2
  121. package/dist/base/searchable.d.ts +3 -2
  122. package/dist/base/searchable.js +2 -2
  123. package/dist/base/searchable.js.map +1 -1
  124. package/dist/base/section.d.ts +6 -2
  125. package/dist/base/section.js +4 -0
  126. package/dist/base/section.js.map +1 -1
  127. package/dist/base/stack.d.ts +6 -0
  128. package/dist/base/stack.js +6 -0
  129. package/dist/base/stack.js.map +1 -1
  130. package/dist/base/stat-group.d.ts +16 -14
  131. package/dist/base/stat-group.js +2 -0
  132. package/dist/base/stat-group.js.map +1 -1
  133. package/dist/base/tab.d.ts +10 -8
  134. package/dist/base/tab.js +2 -0
  135. package/dist/base/tab.js.map +1 -1
  136. package/dist/base/table-view/column-display.d.ts +1 -1
  137. package/dist/base/table-view/column-display.js.map +1 -1
  138. package/dist/base/table-view/data-functions.d.ts +10 -4
  139. package/dist/base/table-view/data-functions.js.map +1 -1
  140. package/dist/base/table-view/factory.d.ts +5 -0
  141. package/dist/base/table-view/factory.js +8 -4
  142. package/dist/base/table-view/factory.js.map +1 -1
  143. package/dist/base/table-view/internal/auth.d.ts +17 -3
  144. package/dist/base/table-view/internal/auth.js +26 -5
  145. package/dist/base/table-view/internal/auth.js.map +1 -1
  146. package/dist/base/table-view/internal/column-conditions.d.ts +8 -1
  147. package/dist/base/table-view/internal/column-conditions.js +25 -13
  148. package/dist/base/table-view/internal/column-conditions.js.map +1 -1
  149. package/dist/base/table-view/internal/column-display.d.ts +1 -2
  150. package/dist/base/table-view/internal/column-display.js +3 -9
  151. package/dist/base/table-view/internal/column-display.js.map +1 -1
  152. package/dist/base/table-view/internal/factory-helpers.d.ts +1 -1
  153. package/dist/base/table-view/internal/factory-helpers.js +17 -14
  154. package/dist/base/table-view/internal/factory-helpers.js.map +1 -1
  155. package/dist/base/table-view/internal/factory-lifecycle-created.d.ts +2 -3
  156. package/dist/base/table-view/internal/factory-lifecycle-created.js +5 -5
  157. package/dist/base/table-view/internal/factory-lifecycle-created.js.map +1 -1
  158. package/dist/base/table-view/internal/factory-lifecycle-filter.d.ts +2 -2
  159. package/dist/base/table-view/internal/factory-private-actions.d.ts +2 -2
  160. package/dist/base/table-view/internal/files.d.ts +2 -1
  161. package/dist/base/table-view/internal/files.js +14 -5
  162. package/dist/base/table-view/internal/files.js.map +1 -1
  163. package/dist/base/table-view/internal/footer.d.ts +3 -3
  164. package/dist/base/table-view/internal/footer.js +16 -15
  165. package/dist/base/table-view/internal/footer.js.map +1 -1
  166. package/dist/base/table-view/internal/guards.d.ts +27 -5
  167. package/dist/base/table-view/internal/guards.js +133 -49
  168. package/dist/base/table-view/internal/guards.js.map +1 -1
  169. package/dist/base/table-view/internal/meta-helpers.d.ts +1 -1
  170. package/dist/base/table-view/internal/meta-helpers.js +3 -4
  171. package/dist/base/table-view/internal/meta-helpers.js.map +1 -1
  172. package/dist/base/table-view/internal/meta.js +2 -3
  173. package/dist/base/table-view/internal/meta.js.map +1 -1
  174. package/dist/base/table-view/internal/option-contract.d.ts +9 -1
  175. package/dist/base/table-view/internal/option-footer.d.ts +2 -2
  176. package/dist/base/table-view/internal/option-row-actions.d.ts +1 -1
  177. package/dist/base/table-view/internal/realtime.d.ts +52 -11
  178. package/dist/base/table-view/internal/realtime.js +23 -16
  179. package/dist/base/table-view/internal/realtime.js.map +1 -1
  180. package/dist/base/table-view/internal/resource-form.d.ts +1 -1
  181. package/dist/base/table-view/internal/resource-form.js +1 -1
  182. package/dist/base/table-view/internal/resource-form.js.map +1 -1
  183. package/dist/base/table-view/internal/row-actions-schema.d.ts +12 -12
  184. package/dist/base/table-view/internal/row-rule-shape.d.ts +11 -5
  185. package/dist/base/table-view/internal/row-rule-shape.js +60 -30
  186. package/dist/base/table-view/internal/row-rule-shape.js.map +1 -1
  187. package/dist/base/table-view/internal/row-rules.d.ts +28 -1
  188. package/dist/base/table-view/internal/row-rules.js +8 -19
  189. package/dist/base/table-view/internal/row-rules.js.map +1 -1
  190. package/dist/base/table-view/internal/tabs.d.ts +1 -1
  191. package/dist/base/table-view/internal/tabs.js +1 -4
  192. package/dist/base/table-view/internal/tabs.js.map +1 -1
  193. package/dist/base/table-view/internal/validation.d.ts +2 -2
  194. package/dist/base/table-view/internal/validation.js +7 -7
  195. package/dist/base/table-view/internal/validation.js.map +1 -1
  196. package/dist/base/table-view/meta.d.ts +7 -6
  197. package/dist/base/table-view/meta.js +12 -7
  198. package/dist/base/table-view/meta.js.map +1 -1
  199. package/dist/base/table-view/resource-form.d.ts +3 -1
  200. package/dist/base/table-view/resource-form.js +2 -0
  201. package/dist/base/table-view/resource-form.js.map +1 -1
  202. package/dist/base/table-view/routes.d.ts +73 -21
  203. package/dist/base/table-view/routes.js +13 -10
  204. package/dist/base/table-view/routes.js.map +1 -1
  205. package/dist/base/table-view/schema.d.ts +157 -152
  206. package/dist/base/table-view/schema.js +2 -1
  207. package/dist/base/table-view/schema.js.map +1 -1
  208. package/dist/base/table-view/source.js +4 -1
  209. package/dist/base/table-view/source.js.map +1 -1
  210. package/dist/base/table-view.d.ts +1 -1
  211. package/dist/base/table-view.js.map +1 -1
  212. package/dist/base/top-list-card.d.ts +35 -33
  213. package/dist/base/top-list-card.js +2 -0
  214. package/dist/base/top-list-card.js.map +1 -1
  215. package/dist/base/types/error.js +5 -2
  216. package/dist/base/types/error.js.map +1 -1
  217. package/dist/base/types/guards.d.ts +4 -4
  218. package/dist/base/types/json.d.ts +1 -10
  219. package/dist/base/types/row-action.d.ts +7 -7
  220. package/dist/component-options/confirm-dialog.d.ts +2 -0
  221. package/dist/component-options/confirm-dialog.js.map +1 -1
  222. package/dist/component-options/data-type.d.ts +2 -2
  223. package/dist/component-options/data-type.js +7 -7
  224. package/dist/component-options/data-type.js.map +1 -1
  225. package/dist/component-options/page-layout.d.ts +3 -2
  226. package/dist/component-options/page-layout.js.map +1 -1
  227. package/dist/component-options/row-action.d.ts +14 -9
  228. package/dist/component-slots.d.ts +11 -2
  229. package/dist/component-slots.js +1 -0
  230. package/dist/component-slots.js.map +1 -1
  231. package/dist/component.d.ts +7 -8
  232. package/dist/component.js +17 -25
  233. package/dist/component.js.map +1 -1
  234. package/dist/data-controllers/members.d.ts +11 -7
  235. package/dist/data-controllers/members.js +1 -1
  236. package/dist/data-controllers/members.js.map +1 -1
  237. package/dist/data-controllers/roles.d.ts +32 -10
  238. package/dist/db/internal/exportJobs.model.d.ts +7 -5
  239. package/dist/db/internal/inviteResolutions.model.d.ts +7 -5
  240. package/dist/db/internal/tenantLifecycle.model.d.ts +15 -7
  241. package/dist/db/internal/tenantLifecycle.model.js +16 -7
  242. package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
  243. package/dist/db/models/roles.model.d.ts +7 -5
  244. package/dist/db/models/tenantMembers.model.d.ts +7 -5
  245. package/dist/db/models/tenants.model.d.ts +7 -5
  246. package/dist/db/models/user_invites.model.d.ts +7 -5
  247. package/dist/guards.d.ts +1 -1
  248. package/dist/hooks.d.ts +1 -2
  249. package/dist/hooks.js +33 -26
  250. package/dist/hooks.js.map +1 -1
  251. package/dist/internal/attachments.d.ts +2 -2
  252. package/dist/internal/component-builder.js +2 -1
  253. package/dist/internal/component-builder.js.map +1 -1
  254. package/dist/internal/component-serialization.d.ts +2 -4
  255. package/dist/internal/component-serialization.js +4 -3
  256. package/dist/internal/component-serialization.js.map +1 -1
  257. package/dist/internal/component-slots.d.ts +19 -2
  258. package/dist/internal/component-slots.js +35 -12
  259. package/dist/internal/component-slots.js.map +1 -1
  260. package/dist/internal/component-watch-filter.d.ts +11 -0
  261. package/dist/internal/component-watch-filter.js +22 -0
  262. package/dist/internal/component-watch-filter.js.map +1 -0
  263. package/dist/internal/component-watches.js +0 -1
  264. package/dist/internal/component-watches.js.map +1 -1
  265. package/dist/internal/own-entry.d.ts +7 -0
  266. package/dist/internal/own-entry.js +13 -0
  267. package/dist/internal/own-entry.js.map +1 -0
  268. package/dist/internal/uploads.d.ts +30 -0
  269. package/dist/internal/uploads.js +19 -0
  270. package/dist/internal/uploads.js.map +1 -1
  271. package/dist/invite-extension-payloads.d.ts +14 -2
  272. package/dist/invite-extensions/internal/delivery.js +1 -2
  273. package/dist/invite-extensions/internal/delivery.js.map +1 -1
  274. package/dist/invite-extensions/internal/edit.d.ts +2 -1
  275. package/dist/invite-extensions/internal/edit.js +8 -9
  276. package/dist/invite-extensions/internal/edit.js.map +1 -1
  277. package/dist/invite-extensions/internal/form-slot.js +8 -15
  278. package/dist/invite-extensions/internal/form-slot.js.map +1 -1
  279. package/dist/invite-extensions/internal/payload-slices.d.ts +33 -3
  280. package/dist/invite-extensions/internal/payload-slices.js +84 -19
  281. package/dist/invite-extensions/internal/payload-slices.js.map +1 -1
  282. package/dist/invite-extensions/internal/types.d.ts +10 -1
  283. package/dist/invite-resolution.js +6 -4
  284. package/dist/invite-resolution.js.map +1 -1
  285. package/dist/json.d.ts +10 -0
  286. package/dist/json.js +3 -0
  287. package/dist/json.js.map +1 -0
  288. package/dist/layout-banners.d.ts +5 -2
  289. package/dist/layout-banners.js.map +1 -1
  290. package/dist/page/controllers.d.ts +2 -2
  291. package/dist/page/internal/extension-validation.js +3 -2
  292. package/dist/page/internal/extension-validation.js.map +1 -1
  293. package/dist/page/internal/metadata-layout.js +1 -1
  294. package/dist/page/internal/metadata-layout.js.map +1 -1
  295. package/dist/page/internal/metadata-publish.js +3 -2
  296. package/dist/page/internal/metadata-publish.js.map +1 -1
  297. package/dist/page/internal/metadata-registration.js +5 -4
  298. package/dist/page/internal/metadata-registration.js.map +1 -1
  299. package/dist/page/internal/metadata-upload-registration.d.ts +4 -2
  300. package/dist/page/internal/metadata-upload-registration.js +13 -4
  301. package/dist/page/internal/metadata-upload-registration.js.map +1 -1
  302. package/dist/page/internal/metadata-uploads.d.ts +5 -5
  303. package/dist/page/internal/metadata-uploads.js +4 -8
  304. package/dist/page/internal/metadata-uploads.js.map +1 -1
  305. package/dist/page/internal/page-record.d.ts +2 -3
  306. package/dist/page/internal/page-record.js +23 -16
  307. package/dist/page/internal/page-record.js.map +1 -1
  308. package/dist/page/layout-filter.js +17 -6
  309. package/dist/page/layout-filter.js.map +1 -1
  310. package/dist/page/metadata.js +5 -7
  311. package/dist/page/metadata.js.map +1 -1
  312. package/dist/request-tenant.d.ts +10 -4
  313. package/dist/request-tenant.js +16 -34
  314. package/dist/request-tenant.js.map +1 -1
  315. package/dist/tenant-export.d.ts +2 -1
  316. package/dist/tenant-lifecycle.d.ts +43 -4
  317. package/dist/tenant-lifecycle.js +97 -18
  318. package/dist/tenant-lifecycle.js.map +1 -1
  319. package/dist/types.d.ts +20 -0
  320. package/dist/uploads.d.ts +1 -1
  321. package/dist/uploads.js +39 -60
  322. package/dist/uploads.js.map +1 -1
  323. package/dist/utils/fire-and-forget.js.map +1 -1
  324. package/dist/utils/internal/decorated-class.d.ts +14 -0
  325. package/dist/utils/internal/decorated-class.js +37 -0
  326. package/dist/utils/internal/decorated-class.js.map +1 -0
  327. package/dist/utils/internal/type-check.d.ts +9 -0
  328. package/dist/utils/internal/type-check.js +13 -5
  329. package/dist/utils/internal/type-check.js.map +1 -1
  330. package/dist/utils/internal/value-parser.d.ts +1 -1
  331. package/dist/utils/internal/value-parser.js +22 -9
  332. package/dist/utils/internal/value-parser.js.map +1 -1
  333. package/dist/watch-actions.d.ts +1 -1
  334. package/docs/1.core/1.introduction.md +82 -77
  335. package/docs/1.core/10.layout-banners.md +57 -45
  336. package/docs/1.core/11.modules-and-dynamic-menus.md +178 -0
  337. package/docs/1.core/12.frontend-modules-and-request-helpers.md +155 -0
  338. package/docs/1.core/13.tenant-data-export.md +120 -0
  339. package/docs/1.core/2.pages-and-modules.md +140 -367
  340. package/docs/1.core/3.components.md +21 -22
  341. package/docs/1.core/4.permissions.md +92 -71
  342. package/docs/1.core/5.tenancy.md +150 -86
  343. package/docs/1.core/6.invites.md +90 -65
  344. package/docs/1.core/7.hooks.md +96 -166
  345. package/docs/1.core/8.realtime.md +44 -45
  346. package/docs/1.core/9.quick-actions.md +37 -30
  347. package/docs/2.auth/1.introduction.md +33 -35
  348. package/docs/2.auth/2.authentication.md +60 -38
  349. package/docs/2.auth/3.tokens-and-sessions.md +56 -55
  350. package/docs/2.auth/4.users.md +79 -51
  351. package/docs/2.auth/5.external-identities.md +25 -26
  352. package/docs/3.base/1.introduction.md +64 -60
  353. package/docs/3.base/10.display-blocks.md +15 -16
  354. package/docs/3.base/11.page-layouts.md +270 -0
  355. package/docs/3.base/12.table-row-actions.md +122 -0
  356. package/docs/3.base/13.table-filters-and-forms.md +104 -0
  357. package/docs/3.base/14.table-events-and-helpers.md +114 -0
  358. package/docs/3.base/15.table-sources-and-gates.md +24 -0
  359. package/docs/3.base/2.types.md +44 -41
  360. package/docs/3.base/3.forms.md +27 -28
  361. package/docs/3.base/4.tables.md +35 -368
  362. package/docs/3.base/5.charts-and-widgets.md +28 -29
  363. package/docs/3.base/6.layout.md +21 -270
  364. package/docs/3.base/8.data-types.md +39 -40
  365. package/docs/3.base/9.helpers.md +36 -38
  366. package/docs/4.notifications/1.introduction.md +22 -26
  367. package/docs/4.notifications/2.categories-and-subjects.md +58 -55
  368. package/docs/4.notifications/3.sending.md +72 -68
  369. package/docs/5.html-render/1.introduction.md +119 -81
  370. package/docs/5.html-render/2.built-in-emails.md +71 -51
  371. package/docs/index.md +18 -29
  372. package/docs/tsconfig.json +4 -0
  373. package/package.json +11 -11
  374. package/docs/images/emails-admin-invite.png +0 -0
  375. package/docs/images/emails-change-notice.png +0 -0
  376. package/docs/images/emails-change-verification.png +0 -0
  377. package/docs/images/emails-digest-logo-dark.png +0 -0
  378. package/docs/images/emails-digest-logo-light.png +0 -0
  379. package/docs/images/emails-digest.png +0 -0
  380. package/docs/images/emails-export-partial.png +0 -0
  381. package/docs/images/emails-export-ready.png +0 -0
  382. package/docs/images/emails-reset-password.png +0 -0
  383. package/docs/images/emails-two-factor.png +0 -0
  384. package/docs/images/emails-user-validation.png +0 -0
@@ -1,10 +1,9 @@
1
1
  ---
2
- title: "Data Types"
2
+ title: "Data types"
3
3
  description: "A data type is the single object that answers everything the DMS needs to know about one value: which input component edits it, which Zod schema validates it, which comparison modes its filter offers, and whether the…"
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Data Types
7
-
8
7
  ## Overview
9
8
 
10
9
  A data type is the single object that answers everything the DMS needs to know about one value: which input component edits it, which Zod schema validates it, which comparison modes its filter offers, and whether the field it sits on needs extra decorators. `FormField.type` and `ColumnOptions.type` both take one, which is why a form field and a table column of the same type behave identically.
@@ -20,11 +19,11 @@ import {
20
19
  } from "@antelopejs/interface-dms/base/data-types";
21
20
  ```
22
21
 
23
- The `data-types` subpath re-exports the built-in catalogues, so `DefaultDataTypes`, `DefaultDataCompareTypes` and `StatusType` are all reachable from it. They also have their own modules — `data-types/default-types`, `data-types/compare-types` and `data-types/status-type` — which is how much of the DMS imports them.
22
+ The `data-types` subpath re-exports the built-in catalogues, so `DefaultDataTypes`, `DefaultDataCompareTypes` and `StatusType` are all reachable from it. They also have their own modules, `data-types/default-types`, `data-types/compare-types` and `data-types/status-type`, and much of the DMS imports them from there.
24
23
 
25
- Note that the data types are **not** re-exported from the `base` barrel — always import them from the `data-types` subpath.
24
+ The `base` barrel does **not** re-export the data types. Import them from the `data-types` subpath.
26
25
 
27
- ## Use a Data Type
26
+ ## Use a data type
28
27
 
29
28
  Instantiate the type with its options and hand the instance to the field or the column.
30
29
 
@@ -57,9 +56,9 @@ const form = Form({
57
56
 
58
57
  An instance is reusable: the same object can back a form field and a table column, since it holds only its configuration.
59
58
 
60
- ## The DataType Contract
59
+ ## The `DataType` contract
61
60
 
62
- ```typescript
61
+ ```typescript fragment
63
62
  abstract class DataType {
64
63
  constructor(
65
64
  readonly compareModes: Class<DataCompareMode>[] = [],
@@ -89,9 +88,9 @@ abstract class DataType {
89
88
  | `describedInputComponent()` | The input as it is described where nothing is entered through it: a table column's type (its cells, cards and quick filters read the options) and a read-only form field. Defaults to `inputComponent()`; a type leaves out what only an editable control uses, as a relation leaves out its add form. |
90
89
  | `filterComponents()` | The filter inputs, keyed by compare-mode id with a mandatory `default`. Defaults to `{ default: defaultInputComponent() }`. |
91
90
  | `filter()` | Applies a filter for one compare mode. The base implementation looks the mode up in the compare-mode registry and delegates to it; a type overrides it when a mode needs different semantics. |
92
- | `decorateField()` | Optional. Called by the `@Column` decorator so the type can add further decorators to the field — this is how the relation types install their join. |
91
+ | `decorateField()` | Optional. Called by the `@Column` decorator so the type can add further decorators to the field. The relation types install their join this way. |
93
92
 
94
- ### Write a Custom Type
93
+ ### Write a custom type
95
94
 
96
95
  `StatusType` is the smallest complete example: a boolean rendered as an online/offline indicator whose labels and colours are configurable.
97
96
 
@@ -122,13 +121,13 @@ export class StatusType extends DataType {
122
121
  super(
123
122
  [DefaultDataCompareTypes.Is, DefaultDataCompareTypes.IsNot],
124
123
  DefaultDataCompareTypes.Is,
125
- options as Record<string, unknown>,
124
+ options,
126
125
  );
127
126
  }
128
127
 
129
128
  protected defaultInputComponent() {
130
129
  const component = FormComponents.InputCheckbox();
131
- component.options = this.options;
130
+ component.options = { label: this.options.onlineLabel };
132
131
  return component;
133
132
  }
134
133
 
@@ -138,32 +137,32 @@ export class StatusType extends DataType {
138
137
  }
139
138
  ```
140
139
 
141
- Three pieces make it a type: the `@RegisterDataType("status")` decorator puts it in the registry under an id, the `super()` call declares the compare modes and stores the options, and the two abstract members supply the input and the schema. `StatusType` itself is exported by the `data-types` subpath and is one of the three column types a kanban board can group by — see [Tables](/docs/interfaces/base/tables).
140
+ Three pieces make it a type: the `@RegisterDataType("status")` decorator puts it in the registry under an id, the `super()` call declares the compare modes and stores the options, and the two abstract members supply the input and the schema. `StatusType` itself is exported by the `data-types` subpath and is one of the three column types a kanban board can group by. See [Tables](/docs/interfaces/base/tables).
142
141
 
143
- ## The Registry
142
+ ## The registry
144
143
 
145
- ### RegisterDataType
144
+ ### `RegisterDataType`
146
145
 
147
- ```typescript
146
+ ```typescript fragment
148
147
  const RegisterDataType: (id: string) => ClassDecorator<Class<DataType>>;
149
148
  ```
150
149
 
151
- Registers the decorated class under `id`, in both directions: `CreateDataType` looks up the class by id, and `getDataTypeId` recovers the id from an instance. An id must be unique — registering twice under the same string replaces the earlier class.
150
+ Registers the decorated class under `id`, in both directions: `CreateDataType` looks up the class by id, and `getDataTypeId` recovers the id from an instance. An id must be unique. Registering twice under the same string replaces the earlier class.
152
151
 
153
- ### RegisterDataCompareMode
152
+ ### `RegisterDataCompareMode`
154
153
 
155
- ```typescript
154
+ ```typescript fragment
156
155
  const RegisterDataCompareMode: (
157
156
  id: string,
158
157
  noInput?: boolean,
159
158
  ) => ClassDecorator<Class<DataCompareMode>>;
160
159
  ```
161
160
 
162
- Registers a compare mode. The decorator instantiates the class immediately and keeps that single instance, so a compare mode is stateless. `noInput` marks a mode that needs no value from the viewer — `serializeType` replaces its filter component with the literal `"noInput"`.
161
+ Registers a compare mode. The decorator instantiates the class immediately and keeps that single instance, so a compare mode is stateless. `noInput` marks a mode that needs no value from the viewer. `serializeType` replaces its filter component with the literal `"noInput"`.
163
162
 
164
163
  `DataCompareMode` is the interface a mode implements:
165
164
 
166
- ```typescript
165
+ ```typescript fragment
167
166
  interface DataCompareMode {
168
167
  filter(
169
168
  context: RequestContext,
@@ -177,17 +176,17 @@ interface DataCompareMode {
177
176
 
178
177
  `proxy` is the database value proxy for the field being filtered and `row` the proxy for the whole row, both from `@antelopejs/interface-database`, so a mode builds a database-side predicate rather than filtering in memory.
179
178
 
180
- ### CreateDataType
179
+ ### `CreateDataType`
181
180
 
182
- ```typescript
181
+ ```typescript fragment
183
182
  function CreateDataType(id: string, options?: unknown): DataType;
184
183
  ```
185
184
 
186
- Instantiates a registered type by id, forwarding `options` to its constructor. It asserts on an unknown id with the message `Unknown type <id>`. Use it when the type is chosen at runtime — from configuration, or from a description produced by another module — rather than written in the source.
185
+ Instantiates a registered type by id, forwarding `options` to its constructor. It asserts on an unknown id with the message `Unknown type <id>`. Use it when the type is chosen at runtime, from configuration or from a description another module produced, rather than written in the source.
187
186
 
188
- ### getDataTypeId
187
+ ### `getDataTypeId`
189
188
 
190
- ```typescript
189
+ ```typescript fragment
191
190
  function getDataTypeId(instance: DataType): string | undefined;
192
191
  ```
193
192
 
@@ -195,7 +194,7 @@ Returns the id an instance's class was registered under, or `undefined` when the
195
194
 
196
195
  ## Serialization
197
196
 
198
- ```typescript
197
+ ```typescript fragment
199
198
  function serializeType(instance?: DataType): DataTypeSerialized | undefined;
200
199
  ```
201
200
 
@@ -211,9 +210,9 @@ function serializeType(instance?: DataType): DataTypeSerialized | undefined;
211
210
  | `filterComponents` | `Record<string, FilterComponent>` | Filter inputs by mode id, from `filterComponents()`, with every `noInput` mode's entry replaced by the literal `"noInput"`. |
212
211
  | `inputComponent` | `ComponentInfoSerialized` | The input the column's cells and quick filters read the options of, from `describedInputComponent()`. |
213
212
 
214
- `FilterComponent` is `ComponentInfoSerialized | "noInput"`. The value-level counterpart, `ComponentOrNoInput`, is described in [Shared Types](/docs/interfaces/base/types).
213
+ `FilterComponent` is `ComponentInfoSerialized | "noInput"`. The value-level counterpart, `ComponentOrNoInput`, is described in [Shared types](/docs/interfaces/base/types).
215
214
 
216
- ## Compare Modes
215
+ ## Compare modes
217
216
 
218
217
  `DefaultDataCompareTypes` holds the built-in modes. Each entry is a class; you reference the class in a type's `compareModes`, and the string id is what appears in a serialized type and in a filter query.
219
218
 
@@ -238,7 +237,7 @@ The ordering modes and `is_between` send a date value to the value proxy as epoc
238
237
 
239
238
  `IsEmpty` and `IsNotEmpty` are the two registered with `noInput`. `Include`, `Exclude` and `ArrayContainsString` read a `null` or missing list as an empty one, so a row saved without a value never fails the query: it is left out by `include` and `array_contains_string`, and kept by `exclude`. The namespace also exports `escapeRegex(str: string): string`, the helper the substring modes use to make a viewer-supplied value safe inside a pattern.
240
239
 
241
- ## The Default Types
240
+ ## The default types
242
241
 
243
242
  `DefaultDataTypes` is the built-in catalogue. Every class takes its options object as its only constructor argument, and most of them accept a `fallback` string used in place of an empty value.
244
243
 
@@ -264,7 +263,7 @@ The ordering modes and `is_between` send a date value to the value proxy as epoc
264
263
  | `FileType` | `file` | none | file upload |
265
264
  | `ImageType` | `image` | none | image upload |
266
265
 
267
- ### Scalar Types
266
+ ### Scalar types
268
267
 
269
268
  | Options interface | Fields |
270
269
  | --- | --- |
@@ -293,13 +292,13 @@ Notes on the ones whose behaviour is not obvious from the options:
293
292
  - `PercentageType` is a `NumberType` whose options default to `min: 0`, `max: 1` and `step: 0.01`; the stored value is a fraction while the input works in whole percent.
294
293
  - `PhoneType` only validates the E.164 pattern when `requiredPrefix` is set; otherwise any string passes.
295
294
  - `ColorType` validates a six-digit `#RRGGBB` string.
296
- - `StringTimeType` validates a **number** — a time of day expressed as a number, bounded by `min` and `max`.
295
+ - `StringTimeType` validates a **number**: a time of day expressed as a number, bounded by `min` and `max`.
297
296
 
298
297
  ### Relations
299
298
 
300
- `RelationType<T>` points a field at another data controller. Its input is a searchable picker whose `searchUrl` is the target controller's `select` endpoint, and — unless `filterOnly` is set — its `decorateField` installs a data-api `Foreign` join so list rows carry the resolved related row instead of the raw foreign key.
299
+ `RelationType<T>` points a field at another data controller. Its input is a searchable picker whose `searchUrl` is the target controller's `select` endpoint. Unless `filterOnly` is set, its `decorateField` installs a data-api `Foreign` join so list rows carry the resolved related row instead of the raw foreign key.
301
300
 
302
- ```typescript
301
+ ```typescript fragment
303
302
  import { DefaultDataTypes } from "@antelopejs/interface-dms/base/data-types";
304
303
  import { Column } from "@antelopejs/interface-dms/base/table-view";
305
304
 
@@ -329,9 +328,9 @@ declare customerId: string;
329
328
 
330
329
  With `filterBy`, the picker sends the table filter syntax to the `select` endpoint (`filter_<field>=is:<value>`), which honors only the filters the target controller declares. It searches again when `from` changes and clears a pick made for its previous value; the pair a record loaded with is kept, and while `from` is empty every row is offered. It narrows what is offered only: a rule that must hold on save belongs to the module's routes.
331
330
 
332
- When the target controller exposes a `new` endpoint and has form fields, the picker of an editable form field also carries an inline "add" form built from the target's `new` fields, plus the permission id of the target's `add` action. That form is the bulk of the component — the target's fields, its validation schema, its own relations' add forms — so a table column's type, its filter and a read-only field leave it out: they read the related rows through the `select` route, and a filter only picks among them.
331
+ When the target controller exposes a `new` endpoint and has form fields, the picker of an editable form field also carries an inline "add" form built from the target's `new` fields, plus the permission id of the target's `add` action. That form (the target's fields, its validation schema, its own relations' add forms) is the bulk of the component, so a table column's type, its filter and a read-only field leave it out: they read the related rows through the `select` route, and a filter only picks among them.
333
332
 
334
- `CascaderRelationType<T>` is the same idea for a self-referencing table: the target's `select` endpoint returns a flat list, and the widget rebuilds the tree client-side. Its cell and its field name the picked row by its path, read by `?ids=` for the picked rows and then each level of their ancestors. Its `keyMapping` is required and adds `parent` — the field pointing at the parent row, which must itself carry `@Select()` — alongside the required `label` and `value`. It adds `maxDepth` and `leafOnly` to the relation options, and supports the same `filterOnly` behaviour. In a table cell it shows the path of the picked node ("Electronics / Audio"); a `multiple` one shows a badge per picked node, named by its own label with its path on hover, and folds those past three into `+N`.
333
+ `CascaderRelationType<T>` is the same idea for a self-referencing table: the target's `select` endpoint returns a flat list, and the widget rebuilds the tree client-side. Its cell and its field name the picked row by its path, read by `?ids=` for the picked rows and then each level of their ancestors. Its `keyMapping` is required and adds `parent`, the field pointing at the parent row, which must itself carry `@Select()`, alongside the required `label` and `value`. It adds `maxDepth` and `leafOnly` to the relation options, and supports the same `filterOnly` behaviour. In a table cell it shows the path of the picked node ("Electronics / Audio"); a `multiple` one shows a badge per picked node, named by its own label with its path on hover, and folds those past three into `+N`.
335
334
 
336
335
  ### Address
337
336
 
@@ -358,14 +357,14 @@ The type's options are `placeholder` (one string per address component), `autoco
358
357
  | `limit` | `number` | Maximum number of suggestions. Defaults to `5`. |
359
358
  | `placeholder` | `string` | Search field placeholder. |
360
359
 
361
- ### Files and Images
360
+ ### Files and images
362
361
 
363
362
  `FileTypeOptions` has `multiple?`, `constraints?: UploadConstraints`, `path?`, `storage?` and `fallback?`. `ImageTypeOptions` has `multiple?`, `max?`, `constraints?`, `path?`, `storage?` and `resize?`, the `FormComponents.ImageResizeOptions` the input applies client-side before uploading ([Forms](/docs/interfaces/base/forms)). Both accept `attachmentField?` for a stable native field identity and `visibility?: "private" | "public"`, defaulting to private. `constraints` is the `UploadConstraints` type from `@antelopejs/interface-file-storage`; `storage` names the storage backend and `path` the prefix uploads land under.
364
363
 
365
- A file value is the resource key as a string. Metadata-based validation checks configured constraints, matching `allowedMimetypes` patterns including the `type/*` form. A native field's save integration also validates upload provenance and canonical metadata before persistence. Existing unclassified legacy values may be retained, but cannot be introduced as new native attachments or read through the native metadata endpoint. A storage outage propagates as a server error rather than becoming a field validation error. An image value is an `ImageValue` — `{ key: string; alt?: string; principal?: boolean }` — and `ImageType` defaults `allowedMimetypes` to `["image/*"]`, caps the array at `max` when `multiple` is set, and rejects a list with more than one `principal` image.
364
+ A file value is the resource key as a string. Metadata-based validation checks configured constraints, matching `allowedMimetypes` patterns including the `type/*` form. A native field's save integration also validates upload provenance and canonical metadata before persistence. Existing unclassified legacy values may be retained, but cannot be introduced as new native attachments or read through the native metadata endpoint. A storage outage propagates as a server error rather than becoming a field validation error. An image value is an `ImageValue`, `{ key: string; alt?: string; principal?: boolean }`, and `ImageType` defaults `allowedMimetypes` to `["image/*"]`, caps the array at `max` when `multiple` is set, and rejects a list with more than one `principal` image.
366
365
 
367
366
  Both types enable the table view's native file handling: authorized saves promote staging keys, and successful edits or deletes clean removed native references. Failed saves retain promoted objects; cleanup is not reference-counted across records. See [File storage](/docs/components/file-storage) for authorization, visibility, retries, and custom save routes, and [Helpers](/docs/interfaces/base/helpers) for comparing references within records.
368
367
 
369
- ## Next Steps
368
+ ## Next steps
370
369
 
371
- - [Helpers](/docs/interfaces/base/helpers) - Search, export jobs, file references and the archive-mode defaults.
370
+ - [Helpers](/docs/interfaces/base/helpers): Search, export jobs, file references and the archive-mode defaults.
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  title: "Helpers"
3
3
  description: "A few small surfaces sit beside the components and support them: the `@Searchable` decorator that tells a list route which columns free-text search covers, the export-job runner behind every long download, the…"
4
+ mode: reference
4
5
  ---
5
6
 
6
- # Helpers
7
-
8
7
  ## Overview
9
8
 
10
- A few small surfaces sit beside the components and support them: the `@Searchable` decorator that tells a list route which columns free-text search covers, the export-job runner behind every long download, the tenant-export archive built on top of it, and two helper modules — file references and archive-mode defaults — that the table view uses internally and that are available when you build equivalent routes yourself.
9
+ A few small surfaces sit beside the components and support them: the `@Searchable` decorator that tells a list route which columns free-text search covers, the export-job runner behind every long download, the tenant-export archive built on top of it, and two helper modules, file references and archive-mode defaults, that the table view uses internally and that are available when you build equivalent routes yourself.
11
10
 
12
11
  ```typescript
13
12
  import { Searchable, SearchableMeta } from "@antelopejs/interface-dms/base/searchable";
@@ -19,11 +18,11 @@ import { startTenantExportJob } from "@antelopejs/interface-dms/base/tenant-expo
19
18
 
20
19
  `Searchable`, `SearchableMeta` and everything in `export-jobs` and `tenant-export-archive` are also exported from the package root, `@antelopejs/interface-dms/base`. The two `helpers/*` modules are not in that barrel and are imported from their own subpath.
21
20
 
22
- ## Make Columns Searchable
21
+ ## Make columns searchable
23
22
 
24
23
  `@Searchable(compareMode?)` is a property decorator on a data controller field. It records the field, and the compare mode used to match it, on the controller's `SearchableMeta`. The list route reads that record when the request carries a `search` query parameter and ORs one condition per recorded field into the query. A field does not have to be `filterable` to be searched: it is matched with its data-api filter when it has one, and otherwise with the filter of its `@Column` type. A controller with no searchable field ignores the parameter.
25
24
 
26
- ```typescript
25
+ ```typescript fragment
27
26
  import { Listable } from "@antelopejs/interface-data-api/metadata";
28
27
  import { DefaultDataTypes } from "@antelopejs/interface-dms/base/data-types";
29
28
  import { Searchable } from "@antelopejs/interface-dms/base/searchable";
@@ -50,9 +49,9 @@ export class customerDataAPI extends DataController(/* … */) {
50
49
  | --- | --- |
51
50
  | `compareMode` | Id of a registered `DataCompareMode` used to match this field. Defaults to `"contains"`. |
52
51
 
53
- The id is the one the mode was registered under with `@RegisterDataCompareMode` — `"contains"`, `"is"`, `"array_contains_string"` and the rest of the catalogue are listed in [Data Types](/docs/interfaces/base/data-types).
52
+ The id is the one the mode was registered under with `@RegisterDataCompareMode`. `"contains"`, `"is"`, `"array_contains_string"` and the rest of the catalog are listed in [Data types](/docs/interfaces/base/data-types).
54
53
 
55
- ### SearchableMeta
54
+ ### `SearchableMeta`
56
55
 
57
56
  `SearchableMeta` is the metadata object the decorator writes to. Read it with `GetMetadata(controller, SearchableMeta)` from `@antelopejs/interface-core`.
58
57
 
@@ -62,7 +61,7 @@ The id is the one the mode was registered under with `@RegisterDataCompareMode`
62
61
  | `setSearchableField(key, compareMode)` | Records one field. Called by the decorator. |
63
62
  | `getSearchableFields()` | Returns the same record. |
64
63
 
65
- ## Run an Export Job
64
+ ## Run an export job
66
65
 
67
66
  `runExportJob` starts a background job, hands you a ticket immediately, and leaves the generation running. The pattern is three routes: one that starts the job, one that reports its progress, one that streams the finished file. The table view's export action is built on exactly these three, and any route of your own can reuse them.
68
67
 
@@ -133,9 +132,9 @@ export class ReportPage extends PageController("report", {
133
132
  }
134
133
  ```
135
134
 
136
- ### RunExportJobOptions
135
+ ### `RunExportJobOptions`
137
136
 
138
- ```typescript
137
+ ```typescript fragment
139
138
  function runExportJob<TContext = unknown>(
140
139
  opts: RunExportJobOptions<TContext>,
141
140
  ): Promise<ExportJobTicket>;
@@ -172,7 +171,7 @@ interface ExportJobFailure {
172
171
  }
173
172
  ```
174
173
 
175
- The summary is stored on the job and surfaced on its status, so a consumer can tell a complete export from one that succeeded with holes. `source` names the part that failed — a contributing module id, typically.
174
+ The summary is stored on the job and surfaced on its status, so a consumer can tell a complete export from one that succeeded with holes. `source` names the part that failed, usually a contributing module id.
176
175
 
177
176
  By default a job is deleted once it has been downloaded. Set `retainUntilExpiry` for a scope whose jobs outlive their first download: one that surfaces a job history, or one whose result is reached through a delivered link.
178
177
 
@@ -182,7 +181,7 @@ By default a job is deleted once it has been downloaded. Set `retainUntilExpiry`
182
181
  | `extension` | `string` | Echo of the requested extension. |
183
182
  | `filename` | `string` | Echo of the requested base name. |
184
183
 
185
- ### ExportJobGenerateContext
184
+ ### `ExportJobGenerateContext`
186
185
 
187
186
  | Field | Type | Description |
188
187
  | --- | --- | --- |
@@ -190,12 +189,12 @@ By default a job is deleted once it has been downloaded. Set `retainUntilExpiry`
190
189
  | `tenantId` | `string` | Tenant the job belongs to. |
191
190
  | `localPath` | `string` | Path your generator writes the file to. |
192
191
  | `context` | `TContext` | The payload passed as `context` to `runExportJob`. |
193
- | `reportProgress` | `(progress: number) => Promise<void>` | Records progress. The value is floored and clamped to `0`–`99`; repeating the last value writes nothing. Throws once the job is aborted. |
192
+ | `reportProgress` | `(progress: number) => Promise<void>` | Records progress. The value is floored and clamped to `0` through `99`; repeating the last value writes nothing. Throws once the job is aborted. |
194
193
  | `signal` | `AbortSignal` | Aborted when the job exceeds `maxExecutionTimeMs`. |
195
194
 
196
- ### Status and Download
195
+ ### Status and download
197
196
 
198
- ```typescript
197
+ ```typescript fragment
199
198
  function getExportJobStatus<TContext = unknown>(
200
199
  ctx: RequestContext,
201
200
  user: User,
@@ -211,19 +210,19 @@ function downloadExportJob<TContext = unknown>(
211
210
  ): Promise<void>;
212
211
  ```
213
212
 
214
- `ExportJobStatus` carries `status: ExportStatus`, `progress: number`, and the optional `error`, `filename`, `extension`, `result` and `expiresAt`. `ExportStatus` is the `pending` / `completed` / `failed` enum from [Shared Types](/docs/interfaces/base/types). `result` is the `ExportJobResultSummary` the generator returned, present once the job completed; `expiresAt` is when the sweep will drop the record and its stored file.
213
+ `ExportJobStatus` carries `status: ExportStatus`, `progress: number`, and the optional `error`, `filename`, `extension`, `result` and `expiresAt`. `ExportStatus` is the `pending` / `completed` / `failed` enum from [Shared types](/docs/interfaces/base/types). `result` is the `ExportJobResultSummary` the generator returned, present once the job completed; `expiresAt` is when the sweep will drop the record and its stored file.
215
214
 
216
- `getExportJobExpiry(record)` computes that moment from a record directly — `updatedAt` plus `EXPORT_TTL_MS`, which is one day.
215
+ `getExportJobExpiry(record)` computes that moment from a record directly: `updatedAt` plus `EXPORT_TTL_MS`, which is one day.
217
216
 
218
- `downloadExportJob` requires a completed job with a stored result — anything else fails with `400` or `500`. It sets `Content-Disposition` (with a filename built by `buildExportFilename`), `Content-Length` when the size is known, and `Access-Control-Expose-Headers`, then pipes the stored object to the response. The function returns as soon as the pipe is set up rather than awaiting it; once the response stream closes, the stored object and the job record are both deleted.
217
+ `downloadExportJob` requires a completed job with a stored result. Anything else fails with `400` or `500`. It sets `Content-Disposition` (with a filename built by `buildExportFilename`), `Content-Length` when the size is known, and `Access-Control-Expose-Headers`, then pipes the stored object to the response. The function returns as soon as the pipe is set up rather than awaiting it; once the response stream closes, the stored object and the job record are both deleted.
219
218
 
220
219
  `loadExportJobForUser(ctx, user, jobId, access?)` is the shared step underneath both: it resolves the tenant, loads the record, runs the access checks, and returns the model, the record and the parsed context. Use it when you need the record itself rather than its status.
221
220
 
222
- `downloadExportJob` deletes the stored object and the job record once the response stream closes — unless the job was started with `retainUntilExpiry`, in which case both survive until the sweep.
221
+ `downloadExportJob` deletes the stored object and the job record once the response stream closes, unless the job was started with `retainUntilExpiry`, in which case both survive until the sweep.
223
222
 
224
- ### List a Caller's Jobs
223
+ ### List a caller's jobs
225
224
 
226
- ```typescript
225
+ ```typescript fragment
227
226
  function listExportJobs(
228
227
  ctx: RequestContext,
229
228
  user: User,
@@ -231,11 +230,11 @@ function listExportJobs(
231
230
  ): Promise<ExportJobSummary[]>;
232
231
  ```
233
232
 
234
- Returns the caller's own jobs, most recent first — the history a scope such as a tenant data export surfaces next to its request action. `ListExportJobsOptions` narrows it: `scope` restricts to one scope, `limit` caps the count and defaults to 20.
233
+ Returns the caller's own jobs, most recent first: the history a scope such as a tenant data export surfaces next to its request action. `ListExportJobsOptions` narrows it: `scope` restricts to one scope, `limit` caps the count and defaults to 20.
235
234
 
236
235
  `ExportJobSummary` extends `ExportJobStatus` with `jobId`, `scope` and `createdAt`. Listing is scoped to the caller, so it needs no access options: another user's jobs are never returned.
237
236
 
238
- ### Access Checks
237
+ ### Access checks
239
238
 
240
239
  | Option | Type | Description |
241
240
  | --- | --- | --- |
@@ -244,19 +243,18 @@ Returns the caller's own jobs, most recent first — the history a scope such as
244
243
 
245
244
  `ExportJobOwnership<TContext>` carries only `isOwnedBy`; `ExportJobAccessOptions<TContext>` extends it with `scope`. The job's `userId` is always compared against the caller regardless of what you pass, and every failed check answers `403`.
246
245
 
247
- ### Formats and Delivery
246
+ ### Formats and delivery
248
247
 
249
248
  An export format is an `Exporter`, and a delivery mode is a `Deliverer`. Both are looked up by id.
250
249
 
251
250
  ```typescript
252
251
  import {
253
- DEFAULT_DELIVERY,
254
252
  DEFAULT_EXPORT_FORMAT,
255
- getDeliverer,
256
253
  getExporter,
257
254
  } from "@antelopejs/interface-dms/base/export-jobs";
258
255
 
259
- const exporter = getExporter(DEFAULT_EXPORT_FORMAT); // "csv"
256
+ const localPath = "/tmp/export.csv";
257
+ const exporter = await getExporter(DEFAULT_EXPORT_FORMAT); // "csv"
260
258
  const writer = exporter.createWriter(localPath);
261
259
  writer.writeHeaders(["id", "name"]);
262
260
  writer.appendRow(["id", "name"], { id: "1", name: "Ada" });
@@ -269,8 +267,8 @@ writer.close();
269
267
  | `ExportWriter` | `{ writeHeaders(headers), appendRow(headers, row), close() }` | Incremental writer for one file. |
270
268
  | `Deliverer` | `{ validate?(options: ExportJobDeliveryOptions): void; deliver(exportRecord, resultPath): Promise<void> }` | One delivery mode. `validate` runs when the job is created, so an unusable delivery fails fast rather than after generation. |
271
269
  | `ExportJobDeliveryOptions` | `{ delivery: string; deliveryPath?: string }` | What `validate` is given. |
272
- | `getExporter(format)` | `Exporter` | Throws `400` for an unknown format. |
273
- | `getDeliverer(delivery)` | `Deliverer` | Throws `400` for an unknown delivery mode. |
270
+ | `getExporter(format)` | `Promise<Exporter>` | Resolves to the format's exporter. Rejects with `400` for an unknown format. |
271
+ | `getDeliverer(delivery)` | `Promise<Deliverer>` | Resolves to the delivery mode's deliverer. Rejects with `400` for an unknown delivery mode. |
274
272
  | `DEFAULT_EXPORT_FORMAT` | `"csv"` | The format `csv` writes a BOM-prefixed comma-separated file; array values are joined with `;` and dates written as ISO strings. |
275
273
  | `DEFAULT_DELIVERY` | `"download"` | Keeps the result in storage for the download route. |
276
274
  | `EMAIL_DELIVERY` | `"email"` | Mails the recipient a link instead. Requires `deliveryPath`: the link is that path with `?exportJob=<jobId>` appended. |
@@ -279,7 +277,7 @@ writer.close();
279
277
 
280
278
  `buildExportFilename(base, extension)` produces the name sent to the browser: the base and an ISO timestamp, both stripped of anything outside `[a-zA-Z0-9._-]`, joined by `-` and suffixed with the extension.
281
279
 
282
- ### Storage and Maintenance
280
+ ### Storage and maintenance
283
281
 
284
282
  | Function | Signature | Description |
285
283
  | --- | --- | --- |
@@ -290,7 +288,7 @@ writer.close();
290
288
  | `sweepStaleExportsAllTenants` | `(ttlMs) => Promise<void>` | Deletes every job whose `updatedAt` is older than `ttlMs`, in every tenant, along with its stored file. |
291
289
  | `deleteAllExportsForTenant` | `(tenantId) => Promise<void>` | Deletes every job of one tenant and its stored files. |
292
290
 
293
- ## Export a Tenant's Data
291
+ ## Export a tenant's data
294
292
 
295
293
  `startTenantExportJob` runs the tenant data export as a background job: it asks every registered contributor for its slice, assembles the answers into one ZIP, and hands you the same ticket `runExportJob` does.
296
294
 
@@ -334,17 +332,17 @@ export class ExportsPage extends PageController("exports", {
334
332
  }
335
333
  ```
336
334
 
337
- `StartTenantExportJobOptions` is `ctx`, `user`, `scope`, `filename`, and the optional `delivery`, `deliveryPath` and `maxExecutionTimeMs` — the same fields `runExportJob` takes, minus the ones the archive fixes itself: the extension is `TENANT_EXPORT_EXTENSION` (`"zip"`), the content type `TENANT_EXPORT_CONTENT_TYPE` (`"application/zip"`), and `retainUntilExpiry` is always on, since the archive is reachable from a delivered link and from the job history long after the first download.
335
+ `StartTenantExportJobOptions` is `ctx`, `user`, `scope`, `filename`, and the optional `delivery`, `deliveryPath` and `maxExecutionTimeMs`: the same fields `runExportJob` takes, minus the ones the archive fixes itself: the extension is `TENANT_EXPORT_EXTENSION` (`"zip"`), the content type `TENANT_EXPORT_CONTENT_TYPE` (`"application/zip"`), and `retainUntilExpiry` is always on, since the archive is reachable from a delivered link and from the job history long after the first download.
338
336
 
339
337
  `buildTenantExportArchive(options)` is the step underneath, for a caller that runs the archive outside a job. Its `BuildTenantExportArchiveOptions` are `tenantId`, the `localPath` to write the ZIP to, an `AbortSignal`, and an optional `reportProgress`; it resolves to the `ExportJobResultSummary` describing which contributors failed.
340
338
 
341
339
  Contributing to the archive is the other side of this: a module registers a handler on the `TENANT_DATA_EXPORT` hook of the [Core](/docs/interfaces/core/introduction) domain, and that hook's page covers the archive sink, the manifest and what a failing contributor does to the result.
342
340
 
343
- ## Track File References
341
+ ## Track file references
344
342
 
345
343
  A `file` or `image` column stores keys into file storage, not the bytes. The helpers in `helpers/file-refs` compare or remap references in the supplied records. They do not authorize access, validate upload provenance, or determine whether another record still references an object. Use the [native save integration](/docs/components/file-storage#custom-save-routes) for promotion and cleanup in custom write routes.
346
344
 
347
- ```typescript
345
+ ```typescript fragment
348
346
  import {
349
347
  collectFileRefs,
350
348
  dedupeRefs,
@@ -379,7 +377,7 @@ The three functions that inspect columns take the column map first. An entry onl
379
377
 
380
378
  `FileRef` is `{ key: string; storage?: string }`. The `storage` is read from the data type's `storage` option when it declares one, and left undefined otherwise, so a ref always carries the storage its key belongs to.
381
379
 
382
- ## Archive-Mode Defaults
380
+ ## Archive mode defaults
383
381
 
384
382
  `applyArchiveModeDefaultRules(rowActions, archiveField)` derives the row-action rules that make archive mode coherent: archived rows offer restore and delete, live rows offer edit, duplicate and archive. `TableView` calls it for you when `archiveMode` is set; call it directly only when you assemble `TableViewRowActionOptions` yourself.
385
383
 
@@ -401,7 +399,7 @@ const rowActions = applyArchiveModeDefaultRules(
401
399
  | `restore` | `{ field: archiveField, equals: true }` |
402
400
  | `delete` | `{ field: archiveField, equals: true }` |
403
401
 
404
- The function returns a new options object and never rewrites a decision you made explicitly:
402
+ The function returns a new options object; it skips only actions you turned off:
405
403
 
406
404
  | Value you passed | Result |
407
405
  | --- | --- |
@@ -409,6 +407,6 @@ The function returns a new options object and never rewrites a decision you made
409
407
  | `true` | `{ isEnabled: true, rule: <default> }` |
410
408
  | `false`, or a config with `isEnabled: false` | Left as is; no rule added. |
411
409
  | A config without a `rule` | The config, plus the default rule. |
412
- | A config with a `rule` | Left as is. |
410
+ | A config with a `rule` | The config, with its rule ANDed with the default rule. |
413
411
 
414
- Passing `undefined` as `rowActions` yields an object carrying only the five defaults. The rule shapes themselves are documented in [Shared Types](/docs/interfaces/base/types), and how the table view consumes them in [Tables](/docs/interfaces/base/tables).
412
+ Passing `undefined` as `rowActions` yields an object carrying only the five defaults. The rule shapes themselves are documented in [Shared types](/docs/interfaces/base/types), and how the table view consumes them in [Tables](/docs/interfaces/base/tables).
@@ -1,41 +1,38 @@
1
1
  ---
2
2
  title: "Introduction"
3
3
  description: "How backend code puts a message in a user's notification list: categories, subjects and sending."
4
+ mode: explanation
4
5
  ---
5
6
 
6
- # Introduction
7
+ The `notifications` domain of `@antelopejs/interface-dms` is how backend code puts a message in a user's notification list. It has two halves. You declare a taxonomy once, and you use a builder every time you send.
7
8
 
8
- ## Overview
9
+ The taxonomy is two levels deep. A **category** groups related notifications. A **subject** sits under a category and names one kind of message. Every notification is filed under a subject. Users choose what they receive per subject in their notification settings, so the subject you pick decides how the user sees the message grouped and whether the DMS delivers it at all.
9
10
 
10
- The `notifications` domain of `@antelopejs/interface-dms` is how backend code puts a message in a user's notification list. It has two halves: a taxonomy you declare once, and a builder you use every time you send.
11
+ You declare both levels at import time, with `NotificationCategory()` first and then the `NotificationSubject()` calls under it. Sending is a chain of calls. `Notification()` opens a builder, the setters fill in the icon, title, description and subject, and `.build()` returns an immutable `SendableNotification`. You dispatch that to one user, a list of users, the holders of a set of roles, or every user.
11
12
 
12
- The taxonomy is two levels deep. A **category** groups related notifications, a **subject** sits under a category and names one kind of message, and every notification is filed under a subject. Users manage what they receive per subject from their notification settings, so the subject you pick decides how the message is grouped for the user and whether it is delivered at all.
13
+ The [Read notifications](/docs/auth-and-tenancy/authentication#read-notifications) walkthrough shows the open notification bell with one unread message, and describes how a click marks a message read and how a new message reaches every open session of its recipient. The [Notification preferences](/docs/auth-and-tenancy/authentication#notification-preferences) walkthrough shows the System category expanded to its subjects.
13
14
 
14
- Both levels are declared at import time: `NotificationCategory()` first, then the `NotificationSubject()` calls that sit under it. Sending is a fluent chain: `Notification()` opens a builder, the setters fill in the icon, title, description and subject, and `.build()` returns an immutable `SendableNotification` you dispatch to one user, a list of users, the holders of a set of roles, or everyone.
15
+ ## What the domain gives you
15
16
 
16
- See the [notification bell before and after reading](/docs/auth-and-tenancy/authentication#read-notifications) and the [category and subject preferences](/docs/auth-and-tenancy/authentication#notification-preferences) for real dashboard examples. The demonstration sends to one disposable account and checks a second session of that account; it does not broadcast or send email.
17
-
18
- ## Key Features
19
-
20
- - **Two-level taxonomy** — Categories group subjects, and subjects classify notifications; the `categoryId:subjectId` pair is the key a user's preferences are stored under.
21
- - **Declarative registration** — `NotificationCategory()` and `NotificationSubject()` register at import time and return plain info objects you keep as constants and pass around.
22
- - **Built-in system subjects** — `GeneralSubject`, `SecuritySubject`, `AccountSubject`, `CollaborationSubject` and `AutomationSubject` cover the common platform messages without declaring anything.
23
- - **Type-checked builder** — The builder tracks which fields have been supplied in its type parameter, so `.build()` does not compile until icon, title, description and subject are all set.
24
- - **Four dispatch targets** — Send to one user, a list of users, every user holding at least one of a set of roles, or every user.
25
- - **Shared or individual read state** — A multi-recipient send can give each recipient their own read state, or group the copies so one recipient reading it clears it for all of them.
26
- - **Preference-aware delivery** — Sends are silently skipped for users who turned the subject off, and `togglePermission` marks the subjects users may not turn off.
17
+ - **A two-level taxonomy.** Categories group subjects, and subjects classify notifications. The DMS stores a user's preferences under the `categoryId:subjectId` pair.
18
+ - **Declarative registration.** `NotificationCategory()` and `NotificationSubject()` register at import time and return plain info objects that you keep as constants and pass around.
19
+ - **Built-in system subjects.** `GeneralSubject`, `SecuritySubject`, `AccountSubject`, `CollaborationSubject` and `AutomationSubject` cover the common platform messages, so you declare nothing for them.
20
+ - **A type-checked builder.** The builder tracks the fields you have supplied in its type parameter, so `.build()` does not compile until the icon, the title, the description and the subject are all set.
21
+ - **Four dispatch targets.** You send to one user, to a list of users, to every user holding at least one of a set of roles, or to every user.
22
+ - **Shared or individual read state.** A multi-recipient send can give each recipient their own read state. It can also group the copies, so that one recipient reading the notification marks it read for all of them.
23
+ - **Preference-aware delivery.** The DMS skips a send without an error for a user who turned the subject off. `togglePermission` marks the subjects that users may not turn off.
27
24
 
28
25
  ## Dependencies
29
26
 
30
- This interface relies on the following AntelopeJS packages:
27
+ This interface relies on the following AntelopeJS package:
31
28
 
32
- - [@antelopejs/interface-core](https://github.com/AntelopeJS/interface-core) - Interface function and registration proxies used to reach the DMS implementation.
29
+ - [`@antelopejs/interface-core`](https://github.com/AntelopeJS/interface-core) provides the interface functions and registration proxies that reach the DMS implementation.
33
30
 
34
- The implementation lives in the DMS module, so the interface only works in a project that loads `@antelopejs/dms`. Sending to users and roles uses the DMS user and role identifiers described in the DMS auth and tenancy guide.
31
+ The implementation lives in the DMS module, so the interface only works in a project that loads `@antelopejs/dms`. Sending to users and roles uses the DMS user and role identifiers that the DMS auth and tenancy guide describes.
35
32
 
36
- ## Quick Start
33
+ ## A first notification
37
34
 
38
- The following example declares a category with one subject and sends a notification against it.
35
+ The following example declares a category with one subject and sends a notification under it.
39
36
 
40
37
  ```typescript
41
38
  import {
@@ -44,7 +41,6 @@ import {
44
41
  NotificationSubject,
45
42
  } from "@antelopejs/interface-dms/notifications";
46
43
 
47
- // Declared at import time — the category first, then its subjects
48
44
  export const shopCategory = NotificationCategory("shop", {
49
45
  labelKey: "shop.notifications.categories.shop",
50
46
  descriptionKey: "shop.notifications.categories.shop_desc",
@@ -73,9 +69,9 @@ export async function notifyOrderShipped(
73
69
  }
74
70
  ```
75
71
 
76
- The user sees the notification in the dashboard, and finds an `orders` toggle under a `shop` group in their notification settings.
72
+ The category comes first in the file because the DMS refuses a subject whose category it has not registered yet. The user sees the notification in the dashboard, and finds an `orders` switch under a `shop` group in their notification settings.
77
73
 
78
- ## Documentation Sections
74
+ ## Pages in this section
79
75
 
80
- - [Categories and Subjects](/docs/interfaces/notifications/categories-and-subjects) - Declare categories and subjects, control what users may toggle, and use the built-in system subjects
81
- - [Sending Notifications](/docs/interfaces/notifications/sending) - Build a notification, dispatch it to users, roles or everyone, and understand what gates delivery
76
+ - [Categories and subjects](/docs/interfaces/notifications/categories-and-subjects) covers declaring categories and subjects, controlling what users may turn off, and the built-in system subjects.
77
+ - [Sending notifications](/docs/interfaces/notifications/sending) covers building a notification, dispatching it to users, roles or everyone, and the rules that decide delivery.