@prenta/core 8.9.2 → 8.10.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 (290) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/dist/actions.d.ts +25 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +51 -4
  5. package/dist/actions.js.map +1 -1
  6. package/dist/ai/batch-links.d.ts +105 -0
  7. package/dist/ai/batch-links.d.ts.map +1 -0
  8. package/dist/ai/batch-links.js +667 -0
  9. package/dist/ai/batch-links.js.map +1 -0
  10. package/dist/ai/batch-list.d.ts +127 -4
  11. package/dist/ai/batch-list.d.ts.map +1 -1
  12. package/dist/ai/batch-list.js +250 -14
  13. package/dist/ai/batch-list.js.map +1 -1
  14. package/dist/ai/providers/http.d.ts +4 -0
  15. package/dist/ai/providers/http.d.ts.map +1 -1
  16. package/dist/ai/providers/http.js +9 -8
  17. package/dist/ai/providers/http.js.map +1 -1
  18. package/dist/ai/tasks/editor-text.d.ts +39 -0
  19. package/dist/ai/tasks/editor-text.d.ts.map +1 -0
  20. package/dist/ai/tasks/editor-text.js +45 -0
  21. package/dist/ai/tasks/editor-text.js.map +1 -0
  22. package/dist/ai/tasks/link-embeddings.d.ts +22 -0
  23. package/dist/ai/tasks/link-embeddings.d.ts.map +1 -1
  24. package/dist/ai/tasks/link-embeddings.js +24 -10
  25. package/dist/ai/tasks/link-embeddings.js.map +1 -1
  26. package/dist/ai/usage.d.ts +7 -0
  27. package/dist/ai/usage.d.ts.map +1 -1
  28. package/dist/ai/usage.js +11 -0
  29. package/dist/ai/usage.js.map +1 -1
  30. package/dist/api/guarded-db.d.ts +6 -0
  31. package/dist/api/guarded-db.d.ts.map +1 -1
  32. package/dist/api/guarded-db.js +13 -1
  33. package/dist/api/guarded-db.js.map +1 -1
  34. package/dist/api/handlers.d.ts.map +1 -1
  35. package/dist/api/handlers.js +2 -0
  36. package/dist/api/handlers.js.map +1 -1
  37. package/dist/api/openapi.d.ts.map +1 -1
  38. package/dist/api/openapi.js +47 -0
  39. package/dist/api/openapi.js.map +1 -1
  40. package/dist/api/route-helpers/forms.d.ts.map +1 -1
  41. package/dist/api/route-helpers/forms.js +7 -1
  42. package/dist/api/route-helpers/forms.js.map +1 -1
  43. package/dist/api/routes/ai-authoring.d.ts.map +1 -1
  44. package/dist/api/routes/ai-authoring.js +1 -0
  45. package/dist/api/routes/ai-authoring.js.map +1 -1
  46. package/dist/api/routes/ai-seo.d.ts.map +1 -1
  47. package/dist/api/routes/ai-seo.js +20 -18
  48. package/dist/api/routes/ai-seo.js.map +1 -1
  49. package/dist/api/routes/media.d.ts.map +1 -1
  50. package/dist/api/routes/media.js +3 -1
  51. package/dist/api/routes/media.js.map +1 -1
  52. package/dist/api/routes/scheduling.d.ts.map +1 -1
  53. package/dist/api/routes/scheduling.js +33 -2
  54. package/dist/api/routes/scheduling.js.map +1 -1
  55. package/dist/appearance/color.d.ts +17 -0
  56. package/dist/appearance/color.d.ts.map +1 -1
  57. package/dist/appearance/color.js +162 -1
  58. package/dist/appearance/color.js.map +1 -1
  59. package/dist/appearance/index.d.ts +3 -3
  60. package/dist/appearance/index.d.ts.map +1 -1
  61. package/dist/appearance/index.js +2 -2
  62. package/dist/appearance/index.js.map +1 -1
  63. package/dist/appearance/resolve.d.ts.map +1 -1
  64. package/dist/appearance/resolve.js +4 -2
  65. package/dist/appearance/resolve.js.map +1 -1
  66. package/dist/appearance/theme-tokens.d.ts +60 -11
  67. package/dist/appearance/theme-tokens.d.ts.map +1 -1
  68. package/dist/appearance/theme-tokens.js +184 -175
  69. package/dist/appearance/theme-tokens.js.map +1 -1
  70. package/dist/appearance/types.d.ts +16 -2
  71. package/dist/appearance/types.d.ts.map +1 -1
  72. package/dist/astro-site.d.ts +1 -11
  73. package/dist/astro-site.d.ts.map +1 -1
  74. package/dist/astro-site.js +4 -0
  75. package/dist/astro-site.js.map +1 -1
  76. package/dist/auth/team.d.ts +1 -0
  77. package/dist/auth/team.d.ts.map +1 -1
  78. package/dist/auth/team.js +1 -1
  79. package/dist/auth/team.js.map +1 -1
  80. package/dist/cache/http.d.ts +20 -0
  81. package/dist/cache/http.d.ts.map +1 -1
  82. package/dist/cache/http.js +42 -0
  83. package/dist/cache/http.js.map +1 -1
  84. package/dist/chrome/announcement.d.ts +30 -0
  85. package/dist/chrome/announcement.d.ts.map +1 -0
  86. package/dist/chrome/announcement.js +190 -0
  87. package/dist/chrome/announcement.js.map +1 -0
  88. package/dist/chrome/codegen.d.ts +17 -0
  89. package/dist/chrome/codegen.d.ts.map +1 -0
  90. package/dist/chrome/codegen.js +96 -0
  91. package/dist/chrome/codegen.js.map +1 -0
  92. package/dist/chrome/contract.d.ts +142 -0
  93. package/dist/chrome/contract.d.ts.map +1 -0
  94. package/dist/chrome/contract.js +2 -0
  95. package/dist/chrome/contract.js.map +1 -0
  96. package/dist/chrome/memory-store.d.ts +15 -0
  97. package/dist/chrome/memory-store.d.ts.map +1 -0
  98. package/dist/chrome/memory-store.js +54 -0
  99. package/dist/chrome/memory-store.js.map +1 -0
  100. package/dist/chrome/parse.d.ts +36 -0
  101. package/dist/chrome/parse.d.ts.map +1 -0
  102. package/dist/chrome/parse.js +277 -0
  103. package/dist/chrome/parse.js.map +1 -0
  104. package/dist/chrome/prisma-store.d.ts +11 -0
  105. package/dist/chrome/prisma-store.d.ts.map +1 -0
  106. package/dist/chrome/prisma-store.js +48 -0
  107. package/dist/chrome/prisma-store.js.map +1 -0
  108. package/dist/chrome/public.d.ts +22 -0
  109. package/dist/chrome/public.d.ts.map +1 -0
  110. package/dist/chrome/public.js +181 -0
  111. package/dist/chrome/public.js.map +1 -0
  112. package/dist/chrome/resolve.d.ts +36 -0
  113. package/dist/chrome/resolve.d.ts.map +1 -0
  114. package/dist/chrome/resolve.js +165 -0
  115. package/dist/chrome/resolve.js.map +1 -0
  116. package/dist/chrome/revalidate.d.ts +9 -0
  117. package/dist/chrome/revalidate.d.ts.map +1 -0
  118. package/dist/chrome/revalidate.js +51 -0
  119. package/dist/chrome/revalidate.js.map +1 -0
  120. package/dist/chrome/routes.d.ts +14 -0
  121. package/dist/chrome/routes.d.ts.map +1 -0
  122. package/dist/chrome/routes.js +306 -0
  123. package/dist/chrome/routes.js.map +1 -0
  124. package/dist/chrome/schema.d.ts +231 -0
  125. package/dist/chrome/schema.d.ts.map +1 -0
  126. package/dist/chrome/schema.js +73 -0
  127. package/dist/chrome/schema.js.map +1 -0
  128. package/dist/chrome/service.d.ts +76 -0
  129. package/dist/chrome/service.d.ts.map +1 -0
  130. package/dist/chrome/service.js +286 -0
  131. package/dist/chrome/service.js.map +1 -0
  132. package/dist/chrome/settings.d.ts +14 -0
  133. package/dist/chrome/settings.d.ts.map +1 -0
  134. package/dist/chrome/settings.js +142 -0
  135. package/dist/chrome/settings.js.map +1 -0
  136. package/dist/chrome/store.d.ts +48 -0
  137. package/dist/chrome/store.d.ts.map +1 -0
  138. package/dist/chrome/store.js +26 -0
  139. package/dist/chrome/store.js.map +1 -0
  140. package/dist/chrome/values.d.ts +98 -0
  141. package/dist/chrome/values.d.ts.map +1 -0
  142. package/dist/chrome/values.js +491 -0
  143. package/dist/chrome/values.js.map +1 -0
  144. package/dist/config/define.d.ts +2 -0
  145. package/dist/config/define.d.ts.map +1 -1
  146. package/dist/config/define.js +2 -0
  147. package/dist/config/define.js.map +1 -1
  148. package/dist/db/model-types.d.ts +62 -0
  149. package/dist/db/model-types.d.ts.map +1 -1
  150. package/dist/forms/attribution-settings.d.ts +23 -0
  151. package/dist/forms/attribution-settings.d.ts.map +1 -0
  152. package/dist/forms/attribution-settings.js +42 -0
  153. package/dist/forms/attribution-settings.js.map +1 -0
  154. package/dist/forms/attribution.d.ts +5 -1
  155. package/dist/forms/attribution.d.ts.map +1 -1
  156. package/dist/forms/attribution.js +6 -4
  157. package/dist/forms/attribution.js.map +1 -1
  158. package/dist/forms/client-validation.d.ts.map +1 -1
  159. package/dist/forms/client-validation.js +3 -0
  160. package/dist/forms/client-validation.js.map +1 -1
  161. package/dist/forms/form-model.d.ts +109 -0
  162. package/dist/forms/form-model.d.ts.map +1 -0
  163. package/dist/forms/form-model.js +192 -0
  164. package/dist/forms/form-model.js.map +1 -0
  165. package/dist/forms/index.d.ts +2 -2
  166. package/dist/forms/index.d.ts.map +1 -1
  167. package/dist/forms/index.js +1 -1
  168. package/dist/forms/index.js.map +1 -1
  169. package/dist/forms/service.d.ts +19 -1
  170. package/dist/forms/service.d.ts.map +1 -1
  171. package/dist/forms/service.js +152 -0
  172. package/dist/forms/service.js.map +1 -1
  173. package/dist/forms/spam.d.ts +0 -12
  174. package/dist/forms/spam.d.ts.map +1 -1
  175. package/dist/forms/spam.js +30 -0
  176. package/dist/forms/spam.js.map +1 -1
  177. package/dist/forms/submission.d.ts +7 -0
  178. package/dist/forms/submission.d.ts.map +1 -1
  179. package/dist/forms/submission.js +33 -0
  180. package/dist/forms/submission.js.map +1 -1
  181. package/dist/forms/types.d.ts +26 -1
  182. package/dist/forms/types.d.ts.map +1 -1
  183. package/dist/forms/types.js +9 -1
  184. package/dist/forms/types.js.map +1 -1
  185. package/dist/generated/browser.d.ts +35 -3
  186. package/dist/generated/client.d.ts +35 -3
  187. package/dist/generated/internal/class.d.ts +44 -0
  188. package/dist/generated/internal/class.js +4 -4
  189. package/dist/generated/internal/prismaNamespace.d.ts +403 -1
  190. package/dist/generated/internal/prismaNamespace.js +95 -1
  191. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +102 -0
  192. package/dist/generated/internal/prismaNamespaceBrowser.js +95 -1
  193. package/dist/generated/models/ChromeRegion.d.ts +1203 -0
  194. package/dist/generated/models/ChromeRegion.js +1 -0
  195. package/dist/generated/models/Job.d.ts +732 -5
  196. package/dist/generated/models/JobEvent.d.ts +1339 -0
  197. package/dist/generated/models/JobEvent.js +1 -0
  198. package/dist/generated/models/JobReviewItem.d.ts +1470 -0
  199. package/dist/generated/models/JobReviewItem.js +1 -0
  200. package/dist/generated/models/SystemSetting.d.ts +952 -0
  201. package/dist/generated/models/SystemSetting.js +1 -0
  202. package/dist/generated/models.d.ts +4 -0
  203. package/dist/index.d.ts +12 -5
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +8 -3
  206. package/dist/index.js.map +1 -1
  207. package/dist/jobs/batch-ai.d.ts +53 -0
  208. package/dist/jobs/batch-ai.d.ts.map +1 -0
  209. package/dist/jobs/batch-ai.js +314 -0
  210. package/dist/jobs/batch-ai.js.map +1 -0
  211. package/dist/jobs/contract.d.ts +186 -0
  212. package/dist/jobs/contract.d.ts.map +1 -0
  213. package/dist/jobs/contract.js +2 -0
  214. package/dist/jobs/contract.js.map +1 -0
  215. package/dist/jobs/error-text.d.ts +23 -0
  216. package/dist/jobs/error-text.d.ts.map +1 -0
  217. package/dist/jobs/error-text.js +110 -0
  218. package/dist/jobs/error-text.js.map +1 -0
  219. package/dist/jobs/handlers.d.ts.map +1 -1
  220. package/dist/jobs/handlers.js +48 -7
  221. package/dist/jobs/handlers.js.map +1 -1
  222. package/dist/jobs/memory-store.d.ts +26 -2
  223. package/dist/jobs/memory-store.d.ts.map +1 -1
  224. package/dist/jobs/memory-store.js +157 -3
  225. package/dist/jobs/memory-store.js.map +1 -1
  226. package/dist/jobs/outcomes.d.ts +46 -0
  227. package/dist/jobs/outcomes.d.ts.map +1 -0
  228. package/dist/jobs/outcomes.js +251 -0
  229. package/dist/jobs/outcomes.js.map +1 -0
  230. package/dist/jobs/prisma-store.d.ts +14 -2
  231. package/dist/jobs/prisma-store.d.ts.map +1 -1
  232. package/dist/jobs/prisma-store.js +257 -15
  233. package/dist/jobs/prisma-store.js.map +1 -1
  234. package/dist/jobs/queue.d.ts +62 -2
  235. package/dist/jobs/queue.d.ts.map +1 -1
  236. package/dist/jobs/queue.js +412 -36
  237. package/dist/jobs/queue.js.map +1 -1
  238. package/dist/jobs/retention.d.ts +11 -0
  239. package/dist/jobs/retention.d.ts.map +1 -0
  240. package/dist/jobs/retention.js +18 -0
  241. package/dist/jobs/retention.js.map +1 -0
  242. package/dist/jobs/review.d.ts +111 -0
  243. package/dist/jobs/review.d.ts.map +1 -0
  244. package/dist/jobs/review.js +461 -0
  245. package/dist/jobs/review.js.map +1 -0
  246. package/dist/jobs/routes.d.ts.map +1 -1
  247. package/dist/jobs/routes.js +491 -16
  248. package/dist/jobs/routes.js.map +1 -1
  249. package/dist/jobs/serialize.d.ts +40 -0
  250. package/dist/jobs/serialize.d.ts.map +1 -0
  251. package/dist/jobs/serialize.js +270 -0
  252. package/dist/jobs/serialize.js.map +1 -0
  253. package/dist/jobs/types.d.ts +141 -2
  254. package/dist/jobs/types.d.ts.map +1 -1
  255. package/dist/jobs/worker-status.d.ts +27 -0
  256. package/dist/jobs/worker-status.d.ts.map +1 -0
  257. package/dist/jobs/worker-status.js +66 -0
  258. package/dist/jobs/worker-status.js.map +1 -0
  259. package/dist/media/optimize.d.ts.map +1 -1
  260. package/dist/media/optimize.js +4 -2
  261. package/dist/media/optimize.js.map +1 -1
  262. package/dist/next-site.d.ts +1 -0
  263. package/dist/next-site.d.ts.map +1 -1
  264. package/dist/next-site.js +3 -0
  265. package/dist/next-site.js.map +1 -1
  266. package/dist/seo/audit-runner.d.ts.map +1 -1
  267. package/dist/seo/audit-runner.js +23 -2
  268. package/dist/seo/audit-runner.js.map +1 -1
  269. package/dist/seo/issue-fix-link-insert.d.ts +11 -0
  270. package/dist/seo/issue-fix-link-insert.d.ts.map +1 -1
  271. package/dist/seo/issue-fix-link-insert.js +122 -8
  272. package/dist/seo/issue-fix-link-insert.js.map +1 -1
  273. package/dist/server-site.d.ts.map +1 -1
  274. package/dist/server-site.js +15 -0
  275. package/dist/server-site.js.map +1 -1
  276. package/dist/site.d.ts +8 -0
  277. package/dist/site.d.ts.map +1 -1
  278. package/dist/site.js +6 -0
  279. package/dist/site.js.map +1 -1
  280. package/dist/webhooks/index.d.ts +3 -1
  281. package/dist/webhooks/index.d.ts.map +1 -1
  282. package/dist/webhooks/index.js.map +1 -1
  283. package/package.json +6 -1
  284. package/prisma/migrations/0025_job_cancel_review/down.sql +60 -0
  285. package/prisma/migrations/0025_job_cancel_review/migration.sql +56 -0
  286. package/prisma/migrations/0026_job_creator_system_settings/down.sql +30 -0
  287. package/prisma/migrations/0026_job_creator_system_settings/migration.sql +14 -0
  288. package/prisma/migrations/0027_chrome_regions/down.sql +24 -0
  289. package/prisma/migrations/0027_chrome_regions/migration.sql +16 -0
  290. package/prisma/schema.prisma +105 -15
@@ -0,0 +1,192 @@
1
+ export function migrateFormSettings(input) {
2
+ const notifications = [];
3
+ if ((input.recipients?.length ?? 0) > 0) {
4
+ notifications.push({ kind: 'admin', to: input.recipients });
5
+ }
6
+ if (input.autoresponder) {
7
+ notifications.push({
8
+ kind: 'autoresponder',
9
+ subject: input.autoresponder.subject,
10
+ body: input.autoresponder.body,
11
+ });
12
+ }
13
+ return {
14
+ notifications,
15
+ confirmations: [{ message: input.successMessage, redirectUrl: input.redirectUrl }],
16
+ fields: (input.fields ?? []).map((field) => ({ width: 'full', ...field })),
17
+ };
18
+ }
19
+ export function downgradeFormSettings(input) {
20
+ const admin = input.notifications.find((item) => item.kind === 'admin');
21
+ const auto = input.notifications.find((item) => item.kind === 'autoresponder');
22
+ const confirmation = input.confirmations[0];
23
+ return {
24
+ recipients: admin?.to,
25
+ autoresponder: auto ? { enabled: true, subject: auto.subject, body: auto.body } : null,
26
+ successMessage: confirmation?.message,
27
+ redirectUrl: confirmation?.redirectUrl,
28
+ fields: input.fields.map((field) => {
29
+ const next = { ...field };
30
+ delete next.width;
31
+ return next;
32
+ }),
33
+ };
34
+ }
35
+ const FREE_EMAIL_DOMAINS = new Set([
36
+ 'gmail.com',
37
+ 'googlemail.com',
38
+ 'yahoo.com',
39
+ 'hotmail.com',
40
+ 'outlook.com',
41
+ 'live.com',
42
+ 'icloud.com',
43
+ 'aol.com',
44
+ ]);
45
+ function normalizeDomain(value) {
46
+ return value
47
+ .trim()
48
+ .toLowerCase()
49
+ .replace(/^https?:\/\//, '')
50
+ .replace(/^www\./, '')
51
+ .split('/')[0];
52
+ }
53
+ export function isFreeEmailDomain(email) {
54
+ const domain = email.split('@')[1]?.toLowerCase() ?? '';
55
+ return FREE_EMAIL_DOMAINS.has(domain);
56
+ }
57
+ export function termMatches(text, term) {
58
+ const value = term.value.trim().toLowerCase();
59
+ if (!value)
60
+ return false;
61
+ if (term.kind === 'domain')
62
+ return normalizeDomain(text) === normalizeDomain(value);
63
+ if (term.kind === 'contains')
64
+ return text.toLowerCase().includes(value);
65
+ const pattern = new RegExp(`(?<![\\p{L}\\p{N}_])${escapeRegExp(value)}(?![\\p{L}\\p{N}_])`, 'u');
66
+ return pattern.test(text.toLowerCase());
67
+ }
68
+ function escapeRegExp(value) {
69
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
70
+ }
71
+ /**
72
+ * `entryCount` is only consulted when the form has an `entryLimit`; callers
73
+ * that skip it get the schedule check alone.
74
+ */
75
+ export function formIsClosed(availability, now, entryCount) {
76
+ if (!availability)
77
+ return false;
78
+ if (availability.closed)
79
+ return true;
80
+ if (availability.opensAt && now < new Date(availability.opensAt))
81
+ return true;
82
+ if (availability.closesAt && now >= new Date(availability.closesAt))
83
+ return true;
84
+ if (typeof availability.entryLimit === 'number' &&
85
+ typeof entryCount === 'number' &&
86
+ entryCount >= availability.entryLimit) {
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ export function stepValues(fields, values, step) {
92
+ const errors = fields.filter((field) => field.step === step && field.required && !(values[field.key] ?? '').trim());
93
+ return { ok: errors.length === 0, values: { ...values } };
94
+ }
95
+ function displayFieldTypes() {
96
+ return new Set(['divider', 'heading', 'content', 'pagebreak', 'richtext']);
97
+ }
98
+ export function valuesForEntry(fields, values) {
99
+ const hidden = displayFieldTypes();
100
+ const data = {};
101
+ for (const field of fields) {
102
+ if (hidden.has(field.type))
103
+ continue;
104
+ if (field.key in values)
105
+ data[field.key] = values[field.key];
106
+ }
107
+ return data;
108
+ }
109
+ export function convertPartial(existingId, nextId) {
110
+ if (existingId)
111
+ return { id: existingId, created: false };
112
+ return { id: nextId, created: true };
113
+ }
114
+ export function webhookEntryPayload(entry) {
115
+ return { data: entry.data };
116
+ }
117
+ export function mineCount(entries, userId) {
118
+ return entries.filter((entry) => entry.assigneeId === userId && entry.status !== 'won' && entry.status !== 'lost').length;
119
+ }
120
+ export function planRetention(rows, policy, alreadyDeleted = new Set()) {
121
+ const due = rows.filter((row) => {
122
+ if (alreadyDeleted.has(row.id))
123
+ return false;
124
+ if (row.kind === 'entry' && row.starred)
125
+ return false;
126
+ if (row.kind === 'entry')
127
+ return row.ageDays >= policy.entryDays;
128
+ if (row.kind === 'spam')
129
+ return row.ageDays >= policy.spamDays;
130
+ if (row.kind === 'archived')
131
+ return row.ageDays >= policy.archivedDays;
132
+ if (row.kind === 'delivery')
133
+ return row.ageDays >= policy.deliveryDays;
134
+ return row.ageDays >= policy.partialDays;
135
+ });
136
+ return {
137
+ entries: due.filter((row) => row.kind === 'entry').length,
138
+ spam: due.filter((row) => row.kind === 'spam').length,
139
+ archived: due.filter((row) => row.kind === 'archived').length,
140
+ deliveries: due.filter((row) => row.kind === 'delivery').length,
141
+ files: policy.deleteFiles ? due.filter((row) => row.hasFile).length : 0,
142
+ ids: due.map((row) => row.id),
143
+ };
144
+ }
145
+ const BOUNCE_EXPLANATIONS = {
146
+ '5.1.1': 'The recipient address does not exist.',
147
+ '5.2.2': 'The recipient mailbox is full.',
148
+ '4.2.2': 'The mailbox is full, so delivery was delayed.',
149
+ };
150
+ export function explainDelivery(code) {
151
+ return {
152
+ code,
153
+ explanation: BOUNCE_EXPLANATIONS[code] ?? 'The provider rejected the message.',
154
+ timeline: ['queued', 'attempted', code.startsWith('4') ? 'deferred' : 'bounced'],
155
+ };
156
+ }
157
+ export function resendDelivery(previous) {
158
+ return { submissionId: previous.submissionId, attempt: previous.attempt + 1 };
159
+ }
160
+ export function shouldReviewSpamWithAi(earlierMatched) {
161
+ return !earlierMatched;
162
+ }
163
+ export function aiSpamTimeoutResult() {
164
+ return 'clean';
165
+ }
166
+ export function interpolateSmartTags(template, values) {
167
+ return template.replace(/\{\{?\s*([a-z0-9_]+)\s*\}?\}/gi, (match, key) => {
168
+ if (!(key in values))
169
+ return match;
170
+ return values[key] ?? '';
171
+ });
172
+ }
173
+ export function fieldKeyFromLabel(label, locked, current) {
174
+ if (locked)
175
+ return current;
176
+ const slug = label
177
+ .toLowerCase()
178
+ .replace(/[^a-z0-9]+/g, '_')
179
+ .replace(/^_+|_+$/g, '');
180
+ return slug || 'field';
181
+ }
182
+ export function insertFieldBelow(fields, field, selectedId) {
183
+ if (!selectedId)
184
+ return [...fields, field];
185
+ const index = fields.findIndex((item) => item.id === selectedId);
186
+ if (index < 0)
187
+ return [...fields, field];
188
+ const next = [...fields];
189
+ next.splice(index + 1, 0, field);
190
+ return next;
191
+ }
192
+ //# sourceMappingURL=form-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-model.js","sourceRoot":"","sources":["../../src/forms/form-model.ts"],"names":[],"mappings":"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"}
@@ -3,13 +3,13 @@ export type { AttributionData, AttributionChannel, AttributionClickIds, Attribut
3
3
  export { trackFormStart, trackFormSubmit, trackFormError, pushDataLayerEvent, getDefaultConfirmation, getDefaultAnalyticsConfig, } from './analytics.js';
4
4
  export type { FormAnalyticsConfig, FormConfirmation } from './analytics.js';
5
5
  export { INPUT_FIELD_TYPES, NON_INPUT_FIELD_TYPES } from './types.js';
6
- export type { FormFieldType, PiiClassification, FormFieldOption, FieldValidationRules, ConditionalOperator, ConditionalRule, ConditionalLogic, FieldWidth, FormField, FormSchemaVersion, FormWebhookConfig, FormWebhookEvent, FormNotificationSettings, SpamProtectionStrategy, FormSpamSettings, FormEmbedSettings, FormStatus, FormDefinition, SpamStatus, FormSubmissionFile, FormSubmission, FetchFormsParams, FetchFormEntriesParams, FormStats, FormsSidebarCount, EntryCounts, } from './types.js';
6
+ export type { FormFieldType, PiiClassification, FormFieldOption, FieldValidationRules, ConditionalOperator, ConditionalRule, ConditionalLogic, FieldWidth, FormField, FormSchemaVersion, FormWebhookConfig, FormWebhookEvent, FormNotificationSettings, SpamProtectionStrategy, FormSpamSettings, FormEmbedSettings, FormAvailability, FormStatus, FormDefinition, SpamStatus, FormSubmissionFile, FormSubmission, FetchFormsParams, FetchFormEntriesParams, FormStats, FormsSidebarCount, EntryCounts, } from './types.js';
7
7
  export * from './service.js';
8
8
  export * from './entries.js';
9
9
  export { validateAndNormalizeSubmission, type FieldError, type SubmissionValidationResult, } from './validation.js';
10
10
  export { scoreSubmissionSpam, type SpamScoreInput, type SpamScoreResult } from './spam.js';
11
11
  export { validateSubmissionFiles, persistSubmissionFiles, FORM_UPLOAD_ALLOWED_MIME_TYPES, DEFAULT_MAX_FILE_BYTES, type IncomingFile, type ValidateFilesResult, } from './files.js';
12
- export { processSubmission, buildPublicForm, runSubmissionSideEffects, SubmissionValidationError, type SubmissionContext, type SubmissionResult, type SubmissionConfirmation, type SubmissionSideEffectInput, type PublicForm, type PublicFormField, } from './submission.js';
12
+ export { processSubmission, buildPublicForm, runSubmissionSideEffects, FormClosedError, SubmissionValidationError, type SubmissionContext, type SubmissionResult, type SubmissionConfirmation, type SubmissionSideEffectInput, type PublicForm, type PublicFormField, } from './submission.js';
13
13
  export { buildWebMcpFormMeta, attachWebMcpToPublicForm, slugToWebMcpToolName, isWebMcpEnabledForForms, type WebMcpFormMeta, type BuildWebMcpFormMetaOptions, } from './webmcp.js';
14
14
  export { renderPublicFormHtml, type RenderPublicFormHtmlOptions } from './public-html.js';
15
15
  export { collectFormSlugsFromSections, prefetchPublicForms } from './prefetch.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,GACd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAE3E,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AACrE,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAE5B,OAAO,EACL,8BAA8B,EAC9B,KAAK,UAAU,EACf,KAAK,0BAA0B,GAChC,MAAM,iBAAiB,CAAA;AAIxB,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AAC1F,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,0BAA0B,GAChC,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,kBAAkB,CAAA;AAEzF,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEjF,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAA"}
@@ -8,7 +8,7 @@ export { validateAndNormalizeSubmission, } from './validation.js';
8
8
  // `@prenta/core/forms/client` for public-site form components.
9
9
  export { scoreSubmissionSpam } from './spam.js';
10
10
  export { validateSubmissionFiles, persistSubmissionFiles, FORM_UPLOAD_ALLOWED_MIME_TYPES, DEFAULT_MAX_FILE_BYTES, } from './files.js';
11
- export { processSubmission, buildPublicForm, runSubmissionSideEffects, SubmissionValidationError, } from './submission.js';
11
+ export { processSubmission, buildPublicForm, runSubmissionSideEffects, FormClosedError, SubmissionValidationError, } from './submission.js';
12
12
  export { buildWebMcpFormMeta, attachWebMcpToPublicForm, slugToWebMcpToolName, isWebMcpEnabledForForms, } from './webmcp.js';
13
13
  export { renderPublicFormHtml } from './public-html.js';
14
14
  export { collectFormSlugsFromSections, prefetchPublicForms } from './prefetch.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AASzB,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AA8BrE,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAE5B,OAAO,EACL,8BAA8B,GAG/B,MAAM,iBAAiB,CAAA;AACxB,4EAA4E;AAC5E,+DAA+D;AAE/D,OAAO,EAAE,mBAAmB,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,GAGvB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,yBAAyB,GAO1B,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,GAGxB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,oBAAoB,EAAoC,MAAM,kBAAkB,CAAA;AAEzF,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEjF,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,GAI7B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,GAOlB,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,GAKpB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AASzB,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AA+BrE,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAE5B,OAAO,EACL,8BAA8B,GAG/B,MAAM,iBAAiB,CAAA;AACxB,4EAA4E;AAC5E,+DAA+D;AAE/D,OAAO,EAAE,mBAAmB,EAA6C,MAAM,WAAW,CAAA;AAC1F,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,GAGvB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,yBAAyB,GAO1B,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,GAGxB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,oBAAoB,EAAoC,MAAM,kBAAkB,CAAA;AAEzF,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAEjF,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,GAI7B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,GAOlB,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,GAKpB,MAAM,eAAe,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { type ActionContext } from '../actions.js';
2
- import { type FetchFormsParams, type FormDefinition, type FormEmbedSettings, type FormField, type FormNotificationSettings, type FormSchemaVersion, type FormSpamSettings, type FormStats, type FormStatus, type FormsSidebarCount } from './types.js';
2
+ import { type FetchFormsParams, type FormAvailability, type FormDefinition, type FormEmbedSettings, type FormField, type FormNotificationSettings, type FormSchemaVersion, type FormSpamSettings, type FormStats, type FormStatus, type FormsSidebarCount } from './types.js';
3
3
  import type { FormAnalyticsConfig } from './analytics.js';
4
4
  /**
5
5
  * Coerce an untrusted value into a clean `FormAnalyticsConfig`, or `undefined`
@@ -8,6 +8,21 @@ import type { FormAnalyticsConfig } from './analytics.js';
8
8
  * ever persisted or exposed on the public schema.
9
9
  */
10
10
  export declare function normalizeAnalyticsConfig(value: unknown): FormAnalyticsConfig | undefined;
11
+ /**
12
+ * Coerce an untrusted value into a clean `FormAvailability`, or `undefined`
13
+ * when it holds nothing usable. Like `normalizeAnalyticsConfig`, this runs on
14
+ * read (legacy documents have no `availability`, and a malformed one must
15
+ * never throw) and on write, so only known keys are persisted. Timestamps are
16
+ * stored as canonical ISO strings.
17
+ */
18
+ export declare function normalizeFormAvailability(value: unknown): FormAvailability | undefined;
19
+ /**
20
+ * Validate an `availability` value from an API body. `null` clears it, and so
21
+ * does `null` on a single date; `''` is rejected like any other non-ISO value.
22
+ * Unknown keys are rejected rather than normalized away, so a client sending
23
+ * the kit's `FormAccess` shape gets an error instead of a silent no-op.
24
+ */
25
+ export declare function validateFormAvailability(value: unknown): string[];
11
26
  /** Parse a raw `forms` document row into the typed `FormDefinition` shape. */
12
27
  export declare function parseFormDefinition(doc: any): FormDefinition;
13
28
  export interface SchemaValidationResult {
@@ -38,6 +53,7 @@ export interface CreateFormInput {
38
53
  notificationSettings?: FormNotificationSettings;
39
54
  embedSettings?: FormEmbedSettings;
40
55
  spamSettings?: FormSpamSettings;
56
+ availability?: FormAvailability | null;
41
57
  successMessage?: string;
42
58
  redirectUrl?: string;
43
59
  analytics?: FormAnalyticsConfig;
@@ -51,6 +67,8 @@ export interface UpdateFormInput {
51
67
  redirectUrl?: string;
52
68
  spamSettings?: FormSpamSettings;
53
69
  embedSettings?: FormEmbedSettings;
70
+ /** Replaces the stored value; `null` clears it. */
71
+ availability?: FormAvailability | null;
54
72
  analytics?: FormAnalyticsConfig;
55
73
  }
56
74
  export declare function updateForm(ctx: ActionContext, id: string, patch: UpdateFormInput): Promise<FormDefinition>;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/forms/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/forms/service.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkD,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlG,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EAEd,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAoCzD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,GAAG,SAAS,CA8BxF;AA8CD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAatF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAkCjE;AAiBD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,CA2B5D;AAID,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,sBAAsB,CAqD1E;AA2DD,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAG3F;AA0ED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAsB,SAAS,CAAC,MAAM,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6CvF;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAe5E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAKhF;AAeD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,oBAAoB,CAAC,EAAE,wBAAwB,CAAA;IAC/C,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACtC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,mBAAmB,CAAA;CAChC;AAWD,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,cAAc,CAAC,CAmDzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC,mDAAmD;IACnD,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACtC,SAAS,CAAC,EAAE,mBAAmB,CAAA;CAChC;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,cAAc,CAAC,CA4CzB;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAwB3F;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAef;AAID,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,SAAS,EAAE,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAyB/D;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CAKjG;AAcD,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAI3F;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,wBAAwB,CAAC,GACvC,OAAO,CAAC,wBAAwB,CAAC,CAenC;AAED,6EAA6E;AAC7E,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,wBAAwB,CAAC,CAEnC;AAED,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAI7E;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAID,wBAAsB,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC,CAsBvD;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAe1E;AAID,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,MAAM,EAAE,MAAM,EAAE,CAAA;gBACJ,MAAM,EAAE,MAAM,EAAE;CAK7B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,eAAe,EAAE,MAAM,CAAA;gBACX,eAAe,EAAE,MAAM;CAKpC"}
@@ -80,6 +80,130 @@ export function normalizeAnalyticsConfig(value) {
80
80
  out.customParameters = cleanParams;
81
81
  return out;
82
82
  }
83
+ /**
84
+ * Lenient, for READ: anything `Date` can parse becomes a canonical ISO string,
85
+ * so legacy values never throw. Writes are checked with `isIsoDateTime` first.
86
+ */
87
+ function toIsoTimestamp(value) {
88
+ if (typeof value !== 'string' || !value.trim())
89
+ return null;
90
+ const date = new Date(value.trim());
91
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
92
+ }
93
+ /**
94
+ * ISO 8601 date-time: `YYYY-MM-DDThh:mm`, then optional seconds and fraction,
95
+ * then an optional `Z` or `±hh:mm` offset. Date-only values are rejected: the
96
+ * contract's `opens`/`closes` are date-times.
97
+ */
98
+ const ISO_DATE_TIME = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minute>\d{2})(?::(?<second>\d{2})(?:\.\d{1,9})?)?(?:Z|[+-](?<offsetHour>\d{2}):(?<offsetMinute>\d{2}))?$/;
99
+ /**
100
+ * Strict, for WRITE. `new Date()` alone accepts "1" or "11/01/2026" and rolls
101
+ * "2026-02-30" over into March, so the calendar fields are checked too. A value
102
+ * without an offset is read in the server's time zone.
103
+ */
104
+ function isIsoDateTime(value) {
105
+ if (typeof value !== 'string')
106
+ return false;
107
+ const groups = ISO_DATE_TIME.exec(value)?.groups;
108
+ if (!groups)
109
+ return false;
110
+ const part = (key) => Number(groups[key] ?? 0);
111
+ const calendar = new Date(0);
112
+ calendar.setUTCFullYear(part('year'), part('month') - 1, part('day'));
113
+ if (calendar.getUTCMonth() !== part('month') - 1 || calendar.getUTCDate() !== part('day')) {
114
+ return false;
115
+ }
116
+ if (part('hour') > 23 || part('minute') > 59 || part('second') > 59)
117
+ return false;
118
+ if (part('offsetHour') > 23 || part('offsetMinute') > 59)
119
+ return false;
120
+ return !Number.isNaN(Date.parse(value));
121
+ }
122
+ function isEntryLimit(value) {
123
+ return typeof value === 'number' && Number.isInteger(value) && value >= 1;
124
+ }
125
+ const AVAILABILITY_KEYS = new Set(['closed', 'opensAt', 'closesAt', 'entryLimit', 'closedMessage']);
126
+ /**
127
+ * Coerce an untrusted value into a clean `FormAvailability`, or `undefined`
128
+ * when it holds nothing usable. Like `normalizeAnalyticsConfig`, this runs on
129
+ * read (legacy documents have no `availability`, and a malformed one must
130
+ * never throw) and on write, so only known keys are persisted. Timestamps are
131
+ * stored as canonical ISO strings.
132
+ */
133
+ export function normalizeFormAvailability(value) {
134
+ const raw = asRecord(value);
135
+ const out = {};
136
+ if (raw.closed === true)
137
+ out.closed = true;
138
+ const opensAt = toIsoTimestamp(raw.opensAt);
139
+ if (opensAt)
140
+ out.opensAt = opensAt;
141
+ const closesAt = toIsoTimestamp(raw.closesAt);
142
+ if (closesAt)
143
+ out.closesAt = closesAt;
144
+ if (isEntryLimit(raw.entryLimit))
145
+ out.entryLimit = raw.entryLimit;
146
+ if (typeof raw.closedMessage === 'string' && raw.closedMessage.trim()) {
147
+ out.closedMessage = raw.closedMessage.trim();
148
+ }
149
+ return Object.keys(out).length > 0 ? out : undefined;
150
+ }
151
+ /**
152
+ * Validate an `availability` value from an API body. `null` clears it, and so
153
+ * does `null` on a single date; `''` is rejected like any other non-ISO value.
154
+ * Unknown keys are rejected rather than normalized away, so a client sending
155
+ * the kit's `FormAccess` shape gets an error instead of a silent no-op.
156
+ */
157
+ export function validateFormAvailability(value) {
158
+ if (value === null)
159
+ return [];
160
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
161
+ return ['Availability must be an object or null.'];
162
+ }
163
+ const raw = value;
164
+ const errors = [];
165
+ for (const key of Object.keys(raw)) {
166
+ if (!AVAILABILITY_KEYS.has(key))
167
+ errors.push(`Unknown availability setting "${key}".`);
168
+ }
169
+ if (raw.closed != null && typeof raw.closed !== 'boolean') {
170
+ errors.push('Availability "closed" must be true or false.');
171
+ }
172
+ for (const key of ['opensAt', 'closesAt']) {
173
+ if (raw[key] != null && !isIsoDateTime(raw[key])) {
174
+ errors.push(`Availability "${key}" must be an ISO 8601 date-time (e.g. 2026-11-01T09:00:00Z) or null.`);
175
+ }
176
+ }
177
+ if (raw.entryLimit != null && !isEntryLimit(raw.entryLimit)) {
178
+ errors.push('Availability "entryLimit" must be a whole number of at least 1.');
179
+ }
180
+ if (raw.closedMessage != null && typeof raw.closedMessage !== 'string') {
181
+ errors.push('Availability "closedMessage" must be a string.');
182
+ }
183
+ if (isIsoDateTime(raw.opensAt) &&
184
+ isIsoDateTime(raw.closesAt) &&
185
+ Date.parse(raw.closesAt) <= Date.parse(raw.opensAt)) {
186
+ errors.push('Availability "closesAt" must be after "opensAt".');
187
+ }
188
+ return errors;
189
+ }
190
+ /**
191
+ * The source's availability, made safe to write onto a duplicate. Every
192
+ * setting is copied, but stored data predates write validation: a legacy
193
+ * window that closes before it opens is dropped (the copy starts as a draft,
194
+ * so nothing goes live with it) instead of failing the duplicate.
195
+ */
196
+ function availabilityForCopy(value) {
197
+ const copy = normalizeFormAvailability(value);
198
+ if (!copy)
199
+ return null;
200
+ if (validateFormAvailability(copy).length === 0)
201
+ return copy;
202
+ const unscheduled = normalizeFormAvailability({ ...copy, opensAt: null, closesAt: null });
203
+ if (!unscheduled || validateFormAvailability(unscheduled).length > 0)
204
+ return null;
205
+ return unscheduled;
206
+ }
83
207
  /** Parse a raw `forms` document row into the typed `FormDefinition` shape. */
84
208
  export function parseFormDefinition(doc) {
85
209
  const data = asRecord(doc?.data);
@@ -98,6 +222,7 @@ export function parseFormDefinition(doc) {
98
222
  : undefined,
99
223
  embedSettings: data.embedSettings ? data.embedSettings : undefined,
100
224
  spamSettings: data.spamSettings ? data.spamSettings : undefined,
225
+ availability: normalizeFormAvailability(data.availability),
101
226
  successMessage: typeof data.successMessage === 'string' ? data.successMessage : undefined,
102
227
  redirectUrl: typeof data.redirectUrl === 'string' ? data.redirectUrl : undefined,
103
228
  analytics: normalizeAnalyticsConfig(data.analytics),
@@ -144,6 +269,20 @@ export function validateFormSchema(fields) {
144
269
  (!Array.isArray(raw.options) || raw.options.length === 0)) {
145
270
  errors.push(`Field "${key ?? ''}" of type ${raw.type} requires at least one option.`);
146
271
  }
272
+ const rules = [
273
+ ...(raw?.conditionalLogic?.show ?? []),
274
+ ...(raw?.conditionalLogic?.require ?? []),
275
+ ];
276
+ const index = fields.indexOf(raw);
277
+ for (const rule of rules) {
278
+ if (rule.fieldKey === key) {
279
+ errors.push(`Field "${key ?? ''}" cannot reference itself.`);
280
+ }
281
+ const target = fields.findIndex((field) => field.key === rule.fieldKey);
282
+ if (target > index) {
283
+ errors.push(`Field "${key ?? ''}" cannot reference a later field.`);
284
+ }
285
+ }
147
286
  }
148
287
  return { valid: errors.length === 0, errors };
149
288
  }
@@ -354,6 +493,11 @@ export async function createForm(ctx, input) {
354
493
  if (!validation.valid) {
355
494
  throw new FormValidationError(validation.errors);
356
495
  }
496
+ if (input.availability !== undefined) {
497
+ const availabilityErrors = validateFormAvailability(input.availability);
498
+ if (availabilityErrors.length > 0)
499
+ throw new FormValidationError(availabilityErrors);
500
+ }
357
501
  let slug = input.slug?.trim() ? slugify(input.slug) : slugify(input.name);
358
502
  if (!slug)
359
503
  slug = `form-${Date.now()}`;
@@ -369,6 +513,7 @@ export async function createForm(ctx, input) {
369
513
  notificationSettings: input.notificationSettings ?? { enabled: false, recipients: [] },
370
514
  embedSettings: input.embedSettings ?? {},
371
515
  spamSettings: input.spamSettings ?? {},
516
+ availability: normalizeFormAvailability(input.availability) ?? null,
372
517
  successMessage: input.successMessage ?? getPrentaConfig()?.forms?.defaultSuccessMessage,
373
518
  redirectUrl: input.redirectUrl,
374
519
  analytics: normalizeAnalyticsConfig(input.analytics) ?? { enabled: false },
@@ -406,6 +551,12 @@ export async function updateForm(ctx, id, patch) {
406
551
  data.spamSettings = patch.spamSettings;
407
552
  if (patch.embedSettings !== undefined)
408
553
  data.embedSettings = patch.embedSettings;
554
+ if (patch.availability !== undefined) {
555
+ const availabilityErrors = validateFormAvailability(patch.availability);
556
+ if (availabilityErrors.length > 0)
557
+ throw new FormValidationError(availabilityErrors);
558
+ data.availability = normalizeFormAvailability(patch.availability) ?? null;
559
+ }
409
560
  if (patch.analytics !== undefined) {
410
561
  data.analytics = normalizeAnalyticsConfig(patch.analytics) ?? { enabled: false };
411
562
  }
@@ -450,6 +601,7 @@ export async function duplicateForm(ctx, id) {
450
601
  notificationSettings: source.notificationSettings,
451
602
  embedSettings: {},
452
603
  spamSettings: source.spamSettings,
604
+ availability: availabilityForCopy(source.availability),
453
605
  successMessage: source.successMessage,
454
606
  redirectUrl: source.redirectUrl,
455
607
  analytics: source.analytics,