@aphexcms/cms-core 9.5.2 → 9.7.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 (301) hide show
  1. package/dist/api/documents.d.ts +28 -0
  2. package/dist/api/documents.d.ts.map +1 -1
  3. package/dist/api/documents.js +18 -0
  4. package/dist/api/schemas/documents.d.ts +19 -0
  5. package/dist/api/schemas/documents.d.ts.map +1 -1
  6. package/dist/api/schemas/documents.js +18 -0
  7. package/dist/client/api.d.ts +2 -0
  8. package/dist/client/api.d.ts.map +1 -0
  9. package/dist/client/api.js +11 -0
  10. package/dist/client/ui.d.ts +25 -0
  11. package/dist/client/ui.d.ts.map +1 -0
  12. package/dist/client/ui.js +53 -0
  13. package/dist/components/admin/ActivityView.svelte +227 -0
  14. package/dist/components/admin/ActivityView.svelte.d.ts +4 -0
  15. package/dist/components/admin/ActivityView.svelte.d.ts.map +1 -0
  16. package/dist/components/admin/DocumentEditor.svelte +197 -11
  17. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  18. package/dist/components/admin/ScheduleDialog.svelte +174 -0
  19. package/dist/components/admin/ScheduleDialog.svelte.d.ts +20 -0
  20. package/dist/components/admin/ScheduleDialog.svelte.d.ts.map +1 -0
  21. package/dist/components/admin/fields/ArrayField.svelte +10 -2
  22. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
  23. package/dist/components/layout/OrganizationSwitcher.svelte +3 -3
  24. package/dist/components/layout/sidebar/NavUser.svelte +5 -5
  25. package/dist/db/interfaces/events.d.ts +55 -0
  26. package/dist/db/interfaces/events.d.ts.map +1 -0
  27. package/dist/db/interfaces/events.js +1 -0
  28. package/dist/db/interfaces/index.d.ts +10 -2
  29. package/dist/db/interfaces/index.d.ts.map +1 -1
  30. package/dist/db/interfaces/plugin-storage.d.ts +39 -0
  31. package/dist/db/interfaces/plugin-storage.d.ts.map +1 -0
  32. package/dist/db/interfaces/plugin-storage.js +1 -0
  33. package/dist/events/catalog.d.ts +8 -0
  34. package/dist/events/catalog.d.ts.map +1 -0
  35. package/dist/events/catalog.js +11 -0
  36. package/dist/events/consumer.d.ts +79 -0
  37. package/dist/events/consumer.d.ts.map +1 -0
  38. package/dist/events/consumer.js +76 -0
  39. package/dist/events/define-event.d.ts +17 -0
  40. package/dist/events/define-event.d.ts.map +1 -0
  41. package/dist/events/define-event.js +7 -0
  42. package/dist/events/emit.d.ts +11 -0
  43. package/dist/events/emit.d.ts.map +1 -0
  44. package/dist/events/emit.js +20 -0
  45. package/dist/events/index.d.ts +4 -0
  46. package/dist/events/index.d.ts.map +1 -0
  47. package/dist/events/index.js +3 -0
  48. package/dist/field-validation/rule.d.ts.map +1 -1
  49. package/dist/field-validation/rule.js +15 -0
  50. package/dist/field-validation/utils.d.ts.map +1 -1
  51. package/dist/field-validation/utils.js +7 -1
  52. package/dist/forms/define-form.d.ts +25 -0
  53. package/dist/forms/define-form.d.ts.map +1 -0
  54. package/dist/forms/define-form.js +22 -0
  55. package/dist/forms/index.d.ts +4 -0
  56. package/dist/forms/index.d.ts.map +1 -0
  57. package/dist/forms/index.js +5 -0
  58. package/dist/forms/types.d.ts +49 -0
  59. package/dist/forms/types.d.ts.map +1 -0
  60. package/dist/forms/types.js +1 -0
  61. package/dist/forms/validate.d.ts +9 -0
  62. package/dist/forms/validate.d.ts.map +1 -0
  63. package/dist/forms/validate.js +18 -0
  64. package/dist/hooks.d.ts.map +1 -1
  65. package/dist/hooks.js +15 -0
  66. package/dist/index.d.ts +2 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +6 -0
  69. package/dist/jobs/document-jobs.d.ts +27 -0
  70. package/dist/jobs/document-jobs.d.ts.map +1 -0
  71. package/dist/jobs/document-jobs.js +42 -0
  72. package/dist/jobs/embedded-runner.d.ts +25 -0
  73. package/dist/jobs/embedded-runner.d.ts.map +1 -0
  74. package/dist/jobs/embedded-runner.js +46 -0
  75. package/dist/jobs/index.d.ts +7 -0
  76. package/dist/jobs/index.d.ts.map +1 -0
  77. package/dist/jobs/index.js +8 -0
  78. package/dist/jobs/relay.d.ts +27 -0
  79. package/dist/jobs/relay.d.ts.map +1 -0
  80. package/dist/jobs/relay.js +60 -0
  81. package/dist/jobs/run-batch.d.ts +52 -0
  82. package/dist/jobs/run-batch.d.ts.map +1 -0
  83. package/dist/jobs/run-batch.js +61 -0
  84. package/dist/jobs/run-due-jobs.d.ts +30 -0
  85. package/dist/jobs/run-due-jobs.d.ts.map +1 -0
  86. package/dist/jobs/run-due-jobs.js +69 -0
  87. package/dist/jobs/types.d.ts +18 -0
  88. package/dist/jobs/types.d.ts.map +1 -0
  89. package/dist/jobs/types.js +1 -0
  90. package/dist/lib/api/documents.d.ts +28 -0
  91. package/dist/lib/api/documents.d.ts.map +1 -1
  92. package/dist/lib/api/documents.js +18 -0
  93. package/dist/lib/api/documents.js.map +1 -1
  94. package/dist/lib/api/schemas/documents.d.ts +19 -0
  95. package/dist/lib/api/schemas/documents.d.ts.map +1 -1
  96. package/dist/lib/api/schemas/documents.js +18 -0
  97. package/dist/lib/api/schemas/documents.js.map +1 -1
  98. package/dist/lib/client/api.d.ts +2 -0
  99. package/dist/lib/client/api.d.ts.map +1 -0
  100. package/dist/lib/client/api.js +12 -0
  101. package/dist/lib/client/api.js.map +1 -0
  102. package/dist/lib/client/ui.d.ts +25 -0
  103. package/dist/lib/client/ui.d.ts.map +1 -0
  104. package/dist/lib/client/ui.js +54 -0
  105. package/dist/lib/client/ui.js.map +1 -0
  106. package/dist/lib/db/interfaces/events.d.ts +55 -0
  107. package/dist/lib/db/interfaces/events.d.ts.map +1 -0
  108. package/dist/lib/db/interfaces/events.js +2 -0
  109. package/dist/lib/db/interfaces/events.js.map +1 -0
  110. package/dist/lib/db/interfaces/index.d.ts +10 -2
  111. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  112. package/dist/lib/db/interfaces/plugin-storage.d.ts +39 -0
  113. package/dist/lib/db/interfaces/plugin-storage.d.ts.map +1 -0
  114. package/dist/lib/db/interfaces/plugin-storage.js +2 -0
  115. package/dist/lib/db/interfaces/plugin-storage.js.map +1 -0
  116. package/dist/lib/events/catalog.d.ts +8 -0
  117. package/dist/lib/events/catalog.d.ts.map +1 -0
  118. package/dist/lib/events/catalog.js +12 -0
  119. package/dist/lib/events/catalog.js.map +1 -0
  120. package/dist/lib/events/consumer.d.ts +79 -0
  121. package/dist/lib/events/consumer.d.ts.map +1 -0
  122. package/dist/lib/events/consumer.js +77 -0
  123. package/dist/lib/events/consumer.js.map +1 -0
  124. package/dist/lib/events/define-event.d.ts +17 -0
  125. package/dist/lib/events/define-event.d.ts.map +1 -0
  126. package/dist/lib/events/define-event.js +8 -0
  127. package/dist/lib/events/define-event.js.map +1 -0
  128. package/dist/lib/events/emit.d.ts +11 -0
  129. package/dist/lib/events/emit.d.ts.map +1 -0
  130. package/dist/lib/events/emit.js +21 -0
  131. package/dist/lib/events/emit.js.map +1 -0
  132. package/dist/lib/events/index.d.ts +4 -0
  133. package/dist/lib/events/index.d.ts.map +1 -0
  134. package/dist/lib/events/index.js +4 -0
  135. package/dist/lib/events/index.js.map +1 -0
  136. package/dist/lib/field-validation/rule.d.ts.map +1 -1
  137. package/dist/lib/field-validation/rule.js +15 -0
  138. package/dist/lib/field-validation/rule.js.map +1 -1
  139. package/dist/lib/field-validation/utils.d.ts.map +1 -1
  140. package/dist/lib/field-validation/utils.js +7 -1
  141. package/dist/lib/field-validation/utils.js.map +1 -1
  142. package/dist/lib/forms/define-form.d.ts +25 -0
  143. package/dist/lib/forms/define-form.d.ts.map +1 -0
  144. package/dist/lib/forms/define-form.js +23 -0
  145. package/dist/lib/forms/define-form.js.map +1 -0
  146. package/dist/lib/forms/index.d.ts +4 -0
  147. package/dist/lib/forms/index.d.ts.map +1 -0
  148. package/dist/lib/forms/index.js +6 -0
  149. package/dist/lib/forms/index.js.map +1 -0
  150. package/dist/lib/forms/types.d.ts +49 -0
  151. package/dist/lib/forms/types.d.ts.map +1 -0
  152. package/dist/lib/forms/types.js +2 -0
  153. package/dist/lib/forms/types.js.map +1 -0
  154. package/dist/lib/forms/validate.d.ts +9 -0
  155. package/dist/lib/forms/validate.d.ts.map +1 -0
  156. package/dist/lib/forms/validate.js +19 -0
  157. package/dist/lib/forms/validate.js.map +1 -0
  158. package/dist/lib/hooks.d.ts.map +1 -1
  159. package/dist/lib/hooks.js +15 -0
  160. package/dist/lib/hooks.js.map +1 -1
  161. package/dist/lib/index.d.ts +2 -0
  162. package/dist/lib/index.d.ts.map +1 -1
  163. package/dist/lib/index.js +6 -0
  164. package/dist/lib/index.js.map +1 -1
  165. package/dist/lib/jobs/document-jobs.d.ts +27 -0
  166. package/dist/lib/jobs/document-jobs.d.ts.map +1 -0
  167. package/dist/lib/jobs/document-jobs.js +43 -0
  168. package/dist/lib/jobs/document-jobs.js.map +1 -0
  169. package/dist/lib/jobs/embedded-runner.d.ts +25 -0
  170. package/dist/lib/jobs/embedded-runner.d.ts.map +1 -0
  171. package/dist/lib/jobs/embedded-runner.js +47 -0
  172. package/dist/lib/jobs/embedded-runner.js.map +1 -0
  173. package/dist/lib/jobs/index.d.ts +7 -0
  174. package/dist/lib/jobs/index.d.ts.map +1 -0
  175. package/dist/lib/jobs/index.js +9 -0
  176. package/dist/lib/jobs/index.js.map +1 -0
  177. package/dist/lib/jobs/relay.d.ts +27 -0
  178. package/dist/lib/jobs/relay.d.ts.map +1 -0
  179. package/dist/lib/jobs/relay.js +61 -0
  180. package/dist/lib/jobs/relay.js.map +1 -0
  181. package/dist/lib/jobs/run-batch.d.ts +52 -0
  182. package/dist/lib/jobs/run-batch.d.ts.map +1 -0
  183. package/dist/lib/jobs/run-batch.js +62 -0
  184. package/dist/lib/jobs/run-batch.js.map +1 -0
  185. package/dist/lib/jobs/run-due-jobs.d.ts +30 -0
  186. package/dist/lib/jobs/run-due-jobs.d.ts.map +1 -0
  187. package/dist/lib/jobs/run-due-jobs.js +70 -0
  188. package/dist/lib/jobs/run-due-jobs.js.map +1 -0
  189. package/dist/lib/jobs/types.d.ts +18 -0
  190. package/dist/lib/jobs/types.d.ts.map +1 -0
  191. package/dist/lib/jobs/types.js +2 -0
  192. package/dist/lib/jobs/types.js.map +1 -0
  193. package/dist/lib/local-api/collection-api.d.ts +42 -0
  194. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  195. package/dist/lib/local-api/collection-api.js +200 -25
  196. package/dist/lib/local-api/collection-api.js.map +1 -1
  197. package/dist/lib/local-api/hooks.d.ts +7 -0
  198. package/dist/lib/local-api/hooks.d.ts.map +1 -0
  199. package/dist/lib/local-api/hooks.js +20 -0
  200. package/dist/lib/local-api/hooks.js.map +1 -0
  201. package/dist/lib/mcp/tools.js +1 -1
  202. package/dist/lib/mcp/tools.js.map +1 -1
  203. package/dist/lib/plugins/resolver.d.ts +12 -1
  204. package/dist/lib/plugins/resolver.d.ts.map +1 -1
  205. package/dist/lib/plugins/resolver.js +4 -1
  206. package/dist/lib/plugins/resolver.js.map +1 -1
  207. package/dist/lib/plugins/types.d.ts +47 -2
  208. package/dist/lib/plugins/types.d.ts.map +1 -1
  209. package/dist/lib/plugins/types.js.map +1 -1
  210. package/dist/lib/schema-utils/define-type.d.ts +32 -0
  211. package/dist/lib/schema-utils/define-type.d.ts.map +1 -0
  212. package/dist/lib/schema-utils/define-type.js +41 -0
  213. package/dist/lib/schema-utils/define-type.js.map +1 -0
  214. package/dist/lib/schema-utils/index.d.ts +1 -0
  215. package/dist/lib/schema-utils/index.d.ts.map +1 -1
  216. package/dist/lib/schema-utils/index.js +1 -0
  217. package/dist/lib/schema-utils/index.js.map +1 -1
  218. package/dist/lib/server/api/index.d.ts.map +1 -1
  219. package/dist/lib/server/api/index.js +8 -0
  220. package/dist/lib/server/api/index.js.map +1 -1
  221. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
  222. package/dist/lib/server/api/routes/documents-publish.js +110 -0
  223. package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
  224. package/dist/lib/server/api/routes/jobs.d.ts +4 -0
  225. package/dist/lib/server/api/routes/jobs.d.ts.map +1 -0
  226. package/dist/lib/server/api/routes/jobs.js +93 -0
  227. package/dist/lib/server/api/routes/jobs.js.map +1 -0
  228. package/dist/lib/server/api/routes/workers-run.d.ts +4 -0
  229. package/dist/lib/server/api/routes/workers-run.d.ts.map +1 -0
  230. package/dist/lib/server/api/routes/workers-run.js +41 -0
  231. package/dist/lib/server/api/routes/workers-run.js.map +1 -0
  232. package/dist/lib/server/index.d.ts +1 -0
  233. package/dist/lib/server/index.d.ts.map +1 -1
  234. package/dist/lib/server/index.js +2 -0
  235. package/dist/lib/server/index.js.map +1 -1
  236. package/dist/lib/services/version-service.d.ts +16 -0
  237. package/dist/lib/services/version-service.d.ts.map +1 -1
  238. package/dist/lib/services/version-service.js +72 -48
  239. package/dist/lib/services/version-service.js.map +1 -1
  240. package/dist/lib/types/config.d.ts +43 -0
  241. package/dist/lib/types/config.d.ts.map +1 -1
  242. package/dist/lib/types/events.d.ts +134 -0
  243. package/dist/lib/types/events.d.ts.map +1 -0
  244. package/dist/lib/types/events.js +4 -0
  245. package/dist/lib/types/events.js.map +1 -0
  246. package/dist/lib/types/index.d.ts +1 -0
  247. package/dist/lib/types/index.d.ts.map +1 -1
  248. package/dist/lib/types/index.js +1 -0
  249. package/dist/lib/types/index.js.map +1 -1
  250. package/dist/lib/types/schemas.d.ts +71 -0
  251. package/dist/lib/types/schemas.d.ts.map +1 -1
  252. package/dist/lib/utils/index.d.ts +1 -1
  253. package/dist/lib/utils/index.d.ts.map +1 -1
  254. package/dist/lib/utils/index.js.map +1 -1
  255. package/dist/local-api/collection-api.d.ts +42 -0
  256. package/dist/local-api/collection-api.d.ts.map +1 -1
  257. package/dist/local-api/collection-api.js +200 -25
  258. package/dist/local-api/hooks.d.ts +7 -0
  259. package/dist/local-api/hooks.d.ts.map +1 -0
  260. package/dist/local-api/hooks.js +19 -0
  261. package/dist/mcp/tools.js +1 -1
  262. package/dist/plugins/resolver.d.ts +12 -1
  263. package/dist/plugins/resolver.d.ts.map +1 -1
  264. package/dist/plugins/resolver.js +4 -1
  265. package/dist/plugins/types.d.ts +47 -2
  266. package/dist/plugins/types.d.ts.map +1 -1
  267. package/dist/schema-utils/define-type.d.ts +32 -0
  268. package/dist/schema-utils/define-type.d.ts.map +1 -0
  269. package/dist/schema-utils/define-type.js +40 -0
  270. package/dist/schema-utils/index.d.ts +1 -0
  271. package/dist/schema-utils/index.d.ts.map +1 -1
  272. package/dist/schema-utils/index.js +1 -0
  273. package/dist/server/api/index.d.ts.map +1 -1
  274. package/dist/server/api/index.js +8 -0
  275. package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
  276. package/dist/server/api/routes/documents-publish.js +110 -0
  277. package/dist/server/api/routes/jobs.d.ts +4 -0
  278. package/dist/server/api/routes/jobs.d.ts.map +1 -0
  279. package/dist/server/api/routes/jobs.js +92 -0
  280. package/dist/server/api/routes/workers-run.d.ts +4 -0
  281. package/dist/server/api/routes/workers-run.d.ts.map +1 -0
  282. package/dist/server/api/routes/workers-run.js +40 -0
  283. package/dist/server/index.d.ts +1 -0
  284. package/dist/server/index.d.ts.map +1 -1
  285. package/dist/server/index.js +2 -0
  286. package/dist/services/version-service.d.ts +16 -0
  287. package/dist/services/version-service.d.ts.map +1 -1
  288. package/dist/services/version-service.js +72 -48
  289. package/dist/types/config.d.ts +43 -0
  290. package/dist/types/config.d.ts.map +1 -1
  291. package/dist/types/events.d.ts +134 -0
  292. package/dist/types/events.d.ts.map +1 -0
  293. package/dist/types/events.js +3 -0
  294. package/dist/types/index.d.ts +1 -0
  295. package/dist/types/index.d.ts.map +1 -1
  296. package/dist/types/index.js +1 -0
  297. package/dist/types/schemas.d.ts +71 -0
  298. package/dist/types/schemas.d.ts.map +1 -1
  299. package/dist/utils/index.d.ts +1 -1
  300. package/dist/utils/index.d.ts.map +1 -1
  301. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ export {};
@@ -7,6 +7,8 @@ import type { InstanceAdapter } from './instance.js';
7
7
  import type { RolesAdapter } from './role.js';
8
8
  import type { ReferenceAdapter } from './reference.js';
9
9
  import type { PluginSettingsAdapter } from './plugin-settings.js';
10
+ import type { EventJobAdapter } from './events.js';
11
+ import type { PluginStorageAdapter } from './plugin-storage.js';
10
12
  export type { DocumentAdapter, DocumentFilters, CreateDocumentData, UpdateDocumentData } from './document.js';
11
13
  export type { AssetAdapter, CreateAssetData, UpdateAssetData } from './asset.js';
12
14
  export type { UserProfileAdapter, NewUserProfileData } from './user.js';
@@ -16,11 +18,13 @@ export type { InstanceAdapter, InstanceSettings } from './instance.js';
16
18
  export type { RolesAdapter } from './role.js';
17
19
  export type { ReferenceAdapter, BackReferenceRow, BackReferenceLookup } from './reference.js';
18
20
  export type { PluginSettingsAdapter, PluginSettingsRow } from './plugin-settings.js';
21
+ export type { EventJobAdapter } from './events.js';
22
+ export type { PluginStorageAdapter, PluginStorageRecord, CreatePluginRecordInput, ListPluginRecordsOptions } from './plugin-storage.js';
19
23
  /**
20
24
  * Combined database adapter interface
21
25
  * Extends all entity-specific adapters for full database functionality
22
26
  */
23
- export interface DatabaseAdapter extends DocumentAdapter, AssetAdapter, UserProfileAdapter, SchemaAdapter, OrganizationAdapter, InstanceAdapter, RolesAdapter, ReferenceAdapter, PluginSettingsAdapter {
27
+ export interface DatabaseAdapter extends DocumentAdapter, AssetAdapter, UserProfileAdapter, SchemaAdapter, OrganizationAdapter, InstanceAdapter, RolesAdapter, ReferenceAdapter, PluginSettingsAdapter, EventJobAdapter, PluginStorageAdapter {
24
28
  connect?(): Promise<void>;
25
29
  disconnect?(): Promise<void>;
26
30
  isHealthy(): Promise<boolean>;
@@ -46,8 +50,12 @@ export interface DatabaseAdapter extends DocumentAdapter, AssetAdapter, UserProf
46
50
  * Execute multiple adapter operations in a single atomic transaction.
47
51
  * The callback receives a transactional version of the adapter — all operations
48
52
  * within it share the same DB transaction and commit/rollback together.
53
+ *
54
+ * Required: every first-party adapter implements this. It is the outbox seam —
55
+ * emitting a domain event (`appendEvent`) alongside a state change in one callback
56
+ * is what makes event emission atomic with the write that caused it.
49
57
  */
50
- withTransaction?<T>(fn: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
58
+ withTransaction<T>(fn: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
51
59
  }
52
60
  /**
53
61
  * Database provider factory interface
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG/D,YAAY,EACX,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAElF;;;GAGG;AACH,MAAM,WAAW,eAChB,SACC,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,qBAAqB;IAEtB,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAG7B,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAG9B;;OAEG;IACH,aAAa,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7E;;OAEG;IACH,qBAAqB,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvE;;OAEG;IACH,kBAAkB,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAExC;;;;OAIG;IACH,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9E;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,IAAI,eAAe,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACnB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,eAAe;IACpE,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjD,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { Page } from '../../types/events.js';
2
+ /** A stored plugin record — arbitrary JSON data under a `(plugin, collection)` namespace. */
3
+ export interface PluginStorageRecord {
4
+ id: string;
5
+ organizationId: string;
6
+ /** Owning plugin namespace, e.g. `'forms'`. Package-namespace it to avoid collisions. */
7
+ plugin: string;
8
+ /** Sub-namespace within the plugin, e.g. a form's id `'contact'`. */
9
+ collection: string;
10
+ /** Arbitrary JSON payload the plugin defines. */
11
+ data: Record<string, unknown>;
12
+ createdAt: Date;
13
+ }
14
+ /** Input to persist a record. `id` may be supplied so it can match a related event's id. */
15
+ export interface CreatePluginRecordInput {
16
+ id?: string;
17
+ organizationId: string;
18
+ plugin: string;
19
+ collection: string;
20
+ data: Record<string, unknown>;
21
+ }
22
+ /** Query for a plugin's records (newest first). */
23
+ export interface ListPluginRecordsOptions {
24
+ organizationId: string;
25
+ plugin: string;
26
+ /** Filter to one collection within the plugin. */
27
+ collection?: string;
28
+ limit?: number;
29
+ offset?: number;
30
+ }
31
+ export interface PluginStorageAdapter {
32
+ /** Persist a record. Call on the tx handle to commit it atomically with `appendEvent`. */
33
+ createPluginRecord(input: CreatePluginRecordInput): Promise<PluginStorageRecord>;
34
+ /** Read one record by id (org-scoped) — e.g. a consumer resolving an event's record id. */
35
+ getPluginRecord(organizationId: string, id: string): Promise<PluginStorageRecord | null>;
36
+ /** List a plugin's records (optionally one collection), newest first. */
37
+ listPluginRecords(options: ListPluginRecordsOptions): Promise<Page<PluginStorageRecord>>;
38
+ }
39
+ //# sourceMappingURL=plugin-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-storage.d.ts","sourceRoot":"","sources":["../../../src/lib/db/interfaces/plugin-storage.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE/C,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,IAAI,CAAC;CAChB;AAED,4FAA4F;AAC5F,MAAM,WAAW,uBAAuB;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,mDAAmD;AACnD,MAAM,WAAW,wBAAwB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACpC,0FAA0F;IAC1F,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjF,2FAA2F;IAC3F,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACzF,yEAAyE;IACzE,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;CACzF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ /** Emitted after a document's draft is copied to published, inside the publish transaction. */
3
+ export declare const documentPublished: import("./define-event.js").EventDefinition<"document.published", z.ZodObject<{
4
+ documentId: z.ZodString;
5
+ documentType: z.ZodString;
6
+ publishedHash: z.ZodNullable<z.ZodString>;
7
+ }, z.core.$strip>>;
8
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/lib/events/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB;;;;kBAO7B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ import { defineEvent } from './define-event.js';
3
+ // Built-in event catalog. The payload carries identifiers + intentional metadata only —
4
+ // never secrets or full document copies (the log is not a content mirror). `organizationId`
5
+ // and `createdBy` are columns on the row, so they're not repeated in the payload.
6
+ /** Emitted after a document's draft is copied to published, inside the publish transaction. */
7
+ export const documentPublished = defineEvent('document.published', z.object({
8
+ documentId: z.string(),
9
+ documentType: z.string(),
10
+ publishedHash: z.string().nullable()
11
+ }));
@@ -0,0 +1,79 @@
1
+ import type { DatabaseAdapter } from '../db/interfaces/index.js';
2
+ import type { EmailAdapter } from '../email/interfaces/email.js';
3
+ import type { Logger } from '../utils/logger.js';
4
+ import type { JobHandler } from '../jobs/types.js';
5
+ /**
6
+ * The event as a consumer sees it — the immutable fields of the `cms_domain_events` row that
7
+ * triggered this delivery. `id` is the event's id (stable across retries of the same
8
+ * delivery), so a consumer can dedupe on it if its side effect isn't naturally idempotent.
9
+ */
10
+ export interface ConsumedEvent {
11
+ id: string;
12
+ type: string;
13
+ organizationId: string;
14
+ payload: Record<string, unknown>;
15
+ correlationId: string | null;
16
+ causationId: string | null;
17
+ createdBy: string | null;
18
+ createdAt: Date;
19
+ }
20
+ /**
21
+ * Reads a plugin's resolved, **decrypted** per-org settings — bound to the triggering event's
22
+ * organization, so a consumer can pull its own config (connection details, `secret` fields like
23
+ * API keys) without threading org ids around. `pluginId` is the settings declaration's id (the
24
+ * plugin's package name); an author reading their own plugin's settings passes their own id.
25
+ * The `.get(orgId, pluginId)` on the host's PluginSettingsService satisfies this structurally.
26
+ */
27
+ export interface PluginSettingsReader {
28
+ get(organizationId: string, pluginId: string): Promise<Record<string, unknown>>;
29
+ }
30
+ /** The consumer-facing settings accessor — already scoped to the event's org. */
31
+ export interface ConsumerSettingsReader {
32
+ /** Decrypted settings for `pluginId` in the event's organization ({} if never configured). */
33
+ get(pluginId: string): Promise<Record<string, unknown>>;
34
+ }
35
+ /** What an event-consumer handler receives. `databaseAdapter` is the live adapter (org-scoped calls take an org id). */
36
+ export interface EventConsumerContext {
37
+ event: ConsumedEvent;
38
+ databaseAdapter: DatabaseAdapter;
39
+ logger: Logger;
40
+ /** Read this plugin's own decrypted settings for the event's org (e.g. a webhook URL secret). */
41
+ settings: ConsumerSettingsReader;
42
+ /**
43
+ * The configured email adapter, or `null` when the app has no email configured. A consumer that
44
+ * sends notifications (e.g. a form's "new submission" email) must handle `null` — treat it as
45
+ * "email disabled" and skip, never throw, so a missing key doesn't dead-letter the delivery.
46
+ */
47
+ emailAdapter: EmailAdapter | null;
48
+ }
49
+ /** Runtime services the consumer wrapper injects into each delivery's context. */
50
+ export interface ConsumerHandlerDeps {
51
+ pluginSettingsService: PluginSettingsReader;
52
+ /** The app's email adapter (or `null` if email isn't configured). Passed straight to the consumer. */
53
+ emailAdapter?: EmailAdapter | null;
54
+ }
55
+ /**
56
+ * Runs when a subscribed event fires. Resolve to ack the delivery; throw to retry it (with
57
+ * backoff, until the delivery job's attempts are exhausted, then dead-letter). MUST be
58
+ * idempotent: at-least-once delivery means it can run more than once for the same event.
59
+ */
60
+ export type EventConsumerHandler = (ctx: EventConsumerContext) => Promise<void>;
61
+ /**
62
+ * Reserved job-type prefix for consumer deliveries. Namespaced so a delivery job can never
63
+ * collide with a document job or a plugin's own `aphex/job/handler` type. The relay enqueues
64
+ * `consumerJobType(id)`; the resolver registers the matching handler under the same key.
65
+ */
66
+ export declare const CONSUMER_JOB_PREFIX = "aphex/consumer:";
67
+ /** The delivery job type for a consumer id. */
68
+ export declare function consumerJobType(consumerId: string): string;
69
+ /** Build the delivery job payload for an event (the relay's side of the envelope). */
70
+ export declare function toDeliveryPayload(event: ConsumedEvent): Record<string, unknown>;
71
+ /**
72
+ * Adapt an `EventConsumerHandler` into a `JobHandler`. The runner calls the returned function
73
+ * with a claimed delivery job; it reconstructs the `ConsumedEvent` from the job payload, binds
74
+ * a settings reader to the event's org, and invokes the consumer. Throwing propagates to the
75
+ * runner as a retryable failure. `deps` is injected by the runner (`runJobsBatch`), which is
76
+ * where the live services live — the resolver only knows which consumers exist, not how to run them.
77
+ */
78
+ export declare function toConsumerJobHandler(handler: EventConsumerHandler, deps: ConsumerHandlerDeps): JobHandler;
79
+ //# sourceMappingURL=consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/lib/events/consumer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChF;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACtC,8FAA8F;IAC9F,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACxD;AAED,wHAAwH;AACxH,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,aAAa,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;;;OAIG;IACH,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CAClC;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IACnC,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,sGAAsG;IACtG,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqBD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/E;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,mBAAmB,GACvB,UAAU,CAcZ"}
@@ -0,0 +1,76 @@
1
+ // Event consumers — the "react to a fact" surface. A consumer subscribes to one or more
2
+ // domain-event types and runs when they fire. It is NOT called inline at emit time: the
3
+ // relay turns each event into a durable delivery *job* (one per subscribed consumer), and
4
+ // the ordinary job runner executes it — so a consumer inherits retries, backoff, and
5
+ // dead-lettering for free, and a slow/failing consumer never blocks the write that emitted
6
+ // the event.
7
+ //
8
+ // This module is the bridge between the two halves: `EventConsumerHandler` is what a plugin
9
+ // author writes; `toConsumerJobHandler` adapts it to a `JobHandler` the runner understands,
10
+ // and `consumerJobType` is the reserved job-type namespace the relay enqueues under.
11
+ import { z } from 'zod';
12
+ /**
13
+ * Reserved job-type prefix for consumer deliveries. Namespaced so a delivery job can never
14
+ * collide with a document job or a plugin's own `aphex/job/handler` type. The relay enqueues
15
+ * `consumerJobType(id)`; the resolver registers the matching handler under the same key.
16
+ */
17
+ export const CONSUMER_JOB_PREFIX = 'aphex/consumer:';
18
+ /** The delivery job type for a consumer id. */
19
+ export function consumerJobType(consumerId) {
20
+ return `${CONSUMER_JOB_PREFIX}${consumerId}`;
21
+ }
22
+ /**
23
+ * The delivery job's payload envelope. The relay serializes the triggering event into this
24
+ * shape; `toConsumerJobHandler` parses it back out — parsing (not casting) so a malformed
25
+ * payload fails loudly at the handler boundary rather than reaching consumer code as `any`.
26
+ * `createdAt` crosses the DB as a JSON string and is coerced back to a `Date`.
27
+ */
28
+ const deliveryEnvelope = z.object({
29
+ event: z.object({
30
+ id: z.string(),
31
+ type: z.string(),
32
+ organizationId: z.string(),
33
+ payload: z.record(z.string(), z.unknown()).default({}),
34
+ correlationId: z.string().nullable().default(null),
35
+ causationId: z.string().nullable().default(null),
36
+ createdBy: z.string().nullable().default(null),
37
+ createdAt: z.coerce.date()
38
+ })
39
+ });
40
+ /** Build the delivery job payload for an event (the relay's side of the envelope). */
41
+ export function toDeliveryPayload(event) {
42
+ return {
43
+ event: {
44
+ id: event.id,
45
+ type: event.type,
46
+ organizationId: event.organizationId,
47
+ payload: event.payload,
48
+ correlationId: event.correlationId,
49
+ causationId: event.causationId,
50
+ createdBy: event.createdBy,
51
+ createdAt: event.createdAt.toISOString()
52
+ }
53
+ };
54
+ }
55
+ /**
56
+ * Adapt an `EventConsumerHandler` into a `JobHandler`. The runner calls the returned function
57
+ * with a claimed delivery job; it reconstructs the `ConsumedEvent` from the job payload, binds
58
+ * a settings reader to the event's org, and invokes the consumer. Throwing propagates to the
59
+ * runner as a retryable failure. `deps` is injected by the runner (`runJobsBatch`), which is
60
+ * where the live services live — the resolver only knows which consumers exist, not how to run them.
61
+ */
62
+ export function toConsumerJobHandler(handler, deps) {
63
+ return async ({ job, databaseAdapter, logger }) => {
64
+ const { event } = deliveryEnvelope.parse(job.payload);
65
+ const settings = {
66
+ get: (pluginId) => deps.pluginSettingsService.get(event.organizationId, pluginId)
67
+ };
68
+ await handler({
69
+ event,
70
+ databaseAdapter,
71
+ logger,
72
+ settings,
73
+ emailAdapter: deps.emailAdapter ?? null
74
+ });
75
+ };
76
+ }
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A typed domain-event definition: a stable `type` name paired with a zod schema for
4
+ * its payload. Mirrors the API-contract pattern (`api/schemas/*`) — one source of truth
5
+ * for the payload shape, with an inferred TS type. Emitters call `parse` so a malformed
6
+ * payload fails loudly at the write site rather than rotting in the log.
7
+ */
8
+ export interface EventDefinition<TName extends string, TSchema extends z.ZodTypeAny> {
9
+ type: TName;
10
+ schema: TSchema;
11
+ /** Validate + narrow an unknown payload to the event's payload type. Throws on mismatch. */
12
+ parse(payload: unknown): z.infer<TSchema>;
13
+ }
14
+ /** The payload type of an event definition. */
15
+ export type EventPayload<D> = D extends EventDefinition<string, infer S> ? z.infer<S> : never;
16
+ export declare function defineEvent<TName extends string, TSchema extends z.ZodTypeAny>(type: TName, schema: TSchema): EventDefinition<TName, TSchema>;
17
+ //# sourceMappingURL=define-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-event.d.ts","sourceRoot":"","sources":["../../src/lib/events/define-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,eAAe,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,UAAU;IAClF,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,4FAA4F;IAC5F,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;CAC1C;AAED,+CAA+C;AAC/C,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;AAE9F,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,UAAU,EAC7E,IAAI,EAAE,KAAK,EACX,MAAM,EAAE,OAAO,GACb,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAMjC"}
@@ -0,0 +1,7 @@
1
+ export function defineEvent(type, schema) {
2
+ return {
3
+ type,
4
+ schema,
5
+ parse: (payload) => schema.parse(payload)
6
+ };
7
+ }
@@ -0,0 +1,11 @@
1
+ import type { DatabaseAdapter } from '../db/interfaces/index.js';
2
+ import type { Document } from '../types/document.js';
3
+ /**
4
+ * Emit `document.published` (and its outbox row) for a freshly published document. MUST be
5
+ * called on a TRANSACTION handle (from `withTransaction`) so the event commits atomically with
6
+ * the publish it describes — the transactional-outbox guarantee. Shared by every publish path,
7
+ * versioned and non-versioned alike, so the fact fires whenever a publish happens regardless of
8
+ * whether a version snapshot was taken.
9
+ */
10
+ export declare function emitDocumentPublished(tx: DatabaseAdapter, organizationId: string, doc: Document): Promise<void>;
11
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/lib/events/emit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,eAAe,EACnB,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,QAAQ,GACX,OAAO,CAAC,IAAI,CAAC,CAWf"}
@@ -0,0 +1,20 @@
1
+ import { documentPublished } from './catalog.js';
2
+ /**
3
+ * Emit `document.published` (and its outbox row) for a freshly published document. MUST be
4
+ * called on a TRANSACTION handle (from `withTransaction`) so the event commits atomically with
5
+ * the publish it describes — the transactional-outbox guarantee. Shared by every publish path,
6
+ * versioned and non-versioned alike, so the fact fires whenever a publish happens regardless of
7
+ * whether a version snapshot was taken.
8
+ */
9
+ export async function emitDocumentPublished(tx, organizationId, doc) {
10
+ await tx.appendEvent({
11
+ organizationId,
12
+ type: documentPublished.type,
13
+ payload: documentPublished.parse({
14
+ documentId: doc.id,
15
+ documentType: doc.type,
16
+ publishedHash: doc.publishedHash ?? null
17
+ }),
18
+ createdBy: doc.updatedBy
19
+ });
20
+ }
@@ -0,0 +1,4 @@
1
+ export * from './define-event.js';
2
+ export * from './catalog.js';
3
+ export * from './consumer.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './define-event.js';
2
+ export * from './catalog.js';
3
+ export * from './consumer.js';
@@ -1 +1 @@
1
- {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/rule.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAEjC,QAAQ,CAAC,EAAE,GAAG,CAAC;IAEf,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC3C,CACC,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,iBAAiB,GACxB,gBAAgB,EAAE,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,cAAc;IAC9B,gBAAgB,EAAE,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACxB;AAED,qBAAa,IAAI;IAChB,OAAO,CAAC,SAAS,CAAkB;IAEnC,OAAO,CAAC,MAAM,CAAmE;IACjF,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B,MAAM,CAAC,SAAS,SAA4B;IAE5C,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAO5D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAIrD,QAAQ,IAAI,IAAI;IAMhB,QAAQ,IAAI,IAAI;IAMhB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI;IAMhD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI;IAMhD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM1C,MAAM,IAAI,IAAI;IAMd,KAAK,IAAI,IAAI;IAMb,GAAG,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAMnE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3C,QAAQ,IAAI,IAAI;IAMhB,QAAQ,IAAI,IAAI;IAMhB,OAAO,IAAI,IAAI;IAMf,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM/C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM5C,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAOxD,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI;IAMjD,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO7B,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO/B,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO5B,KAAK,IAAI,IAAI;IASP,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAwC9E,YAAY;IAgO1B,UAAU,IAAI,OAAO;IAKrB,OAAO,CAAC,sBAAsB;CAkB9B"}
1
+ {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/rule.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAEjC,QAAQ,CAAC,EAAE,GAAG,CAAC;IAEf,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC3C,CACC,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,iBAAiB,GACxB,gBAAgB,EAAE,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,cAAc;IAC9B,gBAAgB,EAAE,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACxB;AAED,qBAAa,IAAI;IAChB,OAAO,CAAC,SAAS,CAAkB;IAEnC,OAAO,CAAC,MAAM,CAAmE;IACjF,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B,MAAM,CAAC,SAAS,SAA4B;IAE5C,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAO5D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAIrD,QAAQ,IAAI,IAAI;IAMhB,QAAQ,IAAI,IAAI;IAMhB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI;IAMhD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,IAAI;IAMhD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM1C,MAAM,IAAI,IAAI;IAMd,KAAK,IAAI,IAAI;IAMb,GAAG,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAMnE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3C,QAAQ,IAAI,IAAI;IAMhB,QAAQ,IAAI,IAAI;IAMhB,OAAO,IAAI,IAAI;IAMf,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM/C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM5C,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAM3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAOxD,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI;IAMjD,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO7B,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO/B,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO5B,KAAK,IAAI,IAAI;IASP,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAwC9E,YAAY;IAuO1B,UAAU,IAAI,OAAO;IAKrB,OAAO,CAAC,sBAAsB;CAkB9B"}
@@ -4,6 +4,15 @@ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
4
4
  import { cmsLogger } from '../utils/logger.js';
5
5
  // Enable strict parsing
6
6
  dayjs.extend(customParseFormat);
7
+ // A canonical ISO-8601 datetime (what `new Date().toISOString()` and most APIs produce) is a
8
+ // valid datetime regardless of a field's display format. The strict format check below is meant
9
+ // for admin-typed input (`YYYY-MM-DD HH:mm`); machine-stamped values — e.g. a `beforeValidate`
10
+ // hook doing `toISOString()` — arrive as ISO-8601 and must also pass. Date + time, optional
11
+ // seconds/fractional seconds, optional `Z` or numeric offset.
12
+ const ISO_8601_DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?$/;
13
+ function isIso8601DateTime(value) {
14
+ return ISO_8601_DATETIME.test(value) && !Number.isNaN(Date.parse(value));
15
+ }
7
16
  export class Rule {
8
17
  _required = false;
9
18
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -325,6 +334,12 @@ export class Rule {
325
334
  if (typeof value === 'string') {
326
335
  const format = rule.constraint || 'YYYY-MM-DD HH:mm';
327
336
  cmsLogger.debug('[Rule.validate] DATETIME validation', { value, format });
337
+ // A canonical ISO-8601 timestamp (machine-stamped: hooks, APIs) is always valid,
338
+ // independent of the field's admin display format.
339
+ if (isIso8601DateTime(value)) {
340
+ cmsLogger.debug('[Rule.validate] DATETIME validation PASSED (ISO-8601)');
341
+ break;
342
+ }
328
343
  // Parse with strict mode
329
344
  const parsed = dayjs(value, format, true);
330
345
  cmsLogger.debug('[Rule.validate] DATETIME parsed', {
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKxD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAUrD;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmC9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAClC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,GAAG,EACV,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC,CA6ID;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAO/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC,wBAAwB,CAAC,CAqDnC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/field-validation/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKxD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAUrD;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmC9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAClC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,GAAG,EACV,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC,CA6ID;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAO/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACzC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,OAAO,GAAE,GAAQ,GACf,OAAO,CAAC,wBAAwB,CAAC,CA2DnC"}
@@ -239,7 +239,13 @@ export async function validateDocumentData(schema, data, context = {}) {
239
239
  type: field.type,
240
240
  value
241
241
  });
242
- const result = await validateField(field, value, { ...context, ...dataForValidation });
242
+ // Build the document context here from the data we're already validating —
243
+ // no need for callers to pass it. Cross-field validators read it via
244
+ // `Rule.custom((v, { document }) => ...)`, matching ValidationContext.
245
+ const result = await validateField(field, value, {
246
+ ...context,
247
+ document: dataForValidation
248
+ });
243
249
  cmsLogger.debug('[validateDocumentData]', `Field "${field.name}" validation result`, {
244
250
  isValid: result.isValid,
245
251
  errors: result.errors
@@ -0,0 +1,25 @@
1
+ import type { Field } from '../types/schemas.js';
2
+ import type { FormDefinition } from './types.js';
3
+ /**
4
+ * Define a form whose submission type is inferred from its own fields.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * export const contactForm = defineForm({
9
+ * id: 'contact',
10
+ * title: 'Contact us',
11
+ * fields: [
12
+ * { name: 'name', type: 'string', title: 'Name', validation: (R) => R.required() },
13
+ * { name: 'email', type: 'string', title: 'Email', validation: (R) => R.required().email() },
14
+ * { name: 'message', type: 'text', title: 'Message', validation: (R) => R.required() }
15
+ * ]
16
+ * });
17
+ *
18
+ * type ContactSubmission = InferForm<typeof contactForm>;
19
+ * // { name?: string; email?: string; message?: string }
20
+ * ```
21
+ */
22
+ export declare function defineForm<const F extends readonly Field[]>(form: Omit<FormDefinition, 'fields'> & {
23
+ fields: F;
24
+ }): FormDefinition<F>;
25
+ //# sourceMappingURL=define-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-form.d.ts","sourceRoot":"","sources":["../../src/lib/forms/define-form.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,KAAK,EAAE,EAC1D,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,CAAC,CAAA;CAAE,GAClD,cAAc,CAAC,CAAC,CAAC,CAEnB"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Define a form whose submission type is inferred from its own fields.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * export const contactForm = defineForm({
7
+ * id: 'contact',
8
+ * title: 'Contact us',
9
+ * fields: [
10
+ * { name: 'name', type: 'string', title: 'Name', validation: (R) => R.required() },
11
+ * { name: 'email', type: 'string', title: 'Email', validation: (R) => R.required().email() },
12
+ * { name: 'message', type: 'text', title: 'Message', validation: (R) => R.required() }
13
+ * ]
14
+ * });
15
+ *
16
+ * type ContactSubmission = InferForm<typeof contactForm>;
17
+ * // { name?: string; email?: string; message?: string }
18
+ * ```
19
+ */
20
+ export function defineForm(form) {
21
+ return form;
22
+ }
@@ -0,0 +1,4 @@
1
+ export * from './types.js';
2
+ export * from './define-form.js';
3
+ export * from './validate.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/forms/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ // Forms primitives — developer-owned form definitions with compile-time inference and
2
+ // runtime validation reuse. Plain TS (no Svelte), safe in the root barrel.
3
+ export * from './types.js';
4
+ export * from './define-form.js';
5
+ export * from './validate.js';
@@ -0,0 +1,49 @@
1
+ import type { Field, InferFields } from '../types/schemas.js';
2
+ /**
3
+ * A developer-authored form. `id` is the stable public key (submission endpoint + event
4
+ * payload); `fields` is an ordinary CMS field array, so a text field, an email (a `string`
5
+ * with an email `Rule`), a number, a boolean, etc. all just work.
6
+ *
7
+ * The type parameter preserves the exact field literals when built via `defineForm`, which is
8
+ * what lets `InferForm<typeof form>` recover the submission shape with no generated types.
9
+ */
10
+ export interface FormDefinition<F extends readonly Field[] = readonly Field[]> {
11
+ /** Stable public id — the submission key and the `form.submitted` payload's `formId`. */
12
+ id: string;
13
+ title: string;
14
+ /** The form's fields, reusing the CMS field DSL. */
15
+ fields: F;
16
+ /** Optional message a client can show after a successful submit. */
17
+ successMessage?: string;
18
+ /**
19
+ * Optional input transform, run on the raw submission BEFORE validation — the one thing
20
+ * validation can't do (it judges, never mutates): `trim()` strings, lowercase an email, coerce
21
+ * shapes. Return the transformed data. This is the forms-native equivalent of a schema's
22
+ * `beforeValidate` hook — a form isn't a document, so it owns its own input shaping here rather
23
+ * than borrowing the document-hook machinery. Rejection (required, format) still belongs in a
24
+ * field's `validation` Rule; side effects (notify) belong in a `form.submitted` consumer.
25
+ */
26
+ transform?: (data: Record<string, unknown>) => Record<string, unknown>;
27
+ /**
28
+ * Where a "new submission" notification is sent. One address or several. Kept next to the form
29
+ * definition so the routing decision lives with the form, not in a global env var — different
30
+ * forms notify different inboxes. Omit to store-only (no notification); a notification consumer
31
+ * skips forms without it. The email itself is sent out of band by a `form.submitted` consumer,
32
+ * never in the submit path.
33
+ */
34
+ notifyEmail?: string | string[];
35
+ /**
36
+ * Persist submissions to `cms_plugin_storage` (under `plugin:'forms', collection:id`). Default
37
+ * `true`. Set `false` for a
38
+ * "just email me" form — the `form.submitted` event still fires (so notification consumers
39
+ * run), but nothing is stored. Matches the real split where some forms only notify.
40
+ */
41
+ store?: boolean;
42
+ }
43
+ /**
44
+ * The typed shape of a form's submission data, inferred from its fields. Values are
45
+ * `T | undefined` (a submission may omit optional fields); required-ness is enforced at
46
+ * runtime by validation, exactly as in the rest of the CMS.
47
+ */
48
+ export type InferForm<D> = D extends FormDefinition<infer F> ? InferFields<F> : never;
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/forms/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,SAAS,KAAK,EAAE,GAAG,SAAS,KAAK,EAAE;IAC5E,yFAAyF;IACzF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,EAAE,CAAC,CAAC;IACV,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvE;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { FormDefinition } from './types.js';
2
+ import { type DocumentValidationResult } from '../field-validation/utils.js';
3
+ /**
4
+ * Validate raw submission data against a form's fields. Returns the standard
5
+ * `DocumentValidationResult` (`isValid`, field-keyed `errors`, `normalizedData`) — the core
6
+ * submit path rejects on `!isValid` and stores/emits from `normalizedData`.
7
+ */
8
+ export declare function validateFormData(form: FormDefinition, data: Record<string, unknown>): Promise<DocumentValidationResult>;
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/lib/forms/validate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAwB,KAAK,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAYhG;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAAC,wBAAwB,CAAC,CAEnC"}
@@ -0,0 +1,18 @@
1
+ import { validateDocumentData } from '../field-validation/utils.js';
2
+ /** Adapt a form to a schema-like object so the field validator can run against it. */
3
+ function formToSchema(form) {
4
+ return {
5
+ type: 'object',
6
+ name: form.id,
7
+ title: form.title,
8
+ fields: [...form.fields]
9
+ };
10
+ }
11
+ /**
12
+ * Validate raw submission data against a form's fields. Returns the standard
13
+ * `DocumentValidationResult` (`isValid`, field-keyed `errors`, `normalizedData`) — the core
14
+ * submit path rejects on `!isValid` and stores/emits from `normalizedData`.
15
+ */
16
+ export function validateFormData(form, data) {
17
+ return validateDocumentData(formToSchema(form), data);
18
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/lib/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAO7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAa,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAIN,KAAK,QAAQ,EACb,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,eAAe,CAAC;IACjC,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,uEAAuE;IACvE,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,sFAAsF;IACtF,YAAY,EAAE,YAAY,CAAC;CAC3B;AAmCD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAGrE;AAgBD,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAmMvD"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/lib/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAO7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAa,SAAS,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAIN,KAAK,QAAQ,EACb,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,eAAe,CAAC;IACjC,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,uEAAuE;IACvE,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,sFAAsF;IACtF,YAAY,EAAE,YAAY,CAAC;CAC3B;AAsCD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAGrE;AAgBD,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CA+MvD"}