@voltro/cms 0.85.0 → 0.86.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 (80) hide show
  1. package/CHANGELOG.md +666 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -33
  3. package/dist/ContentForm.js +282 -0
  4. package/dist/RichDocumentEditor.js +550 -0
  5. package/dist/RichDocumentView.js +132 -0
  6. package/dist/RichTextSurface.js +135 -0
  7. package/dist/aiCandidates.js +199 -0
  8. package/dist/aiOperations.js +152 -0
  9. package/dist/audiences.js +31 -0
  10. package/dist/availability.js +121 -0
  11. package/dist/blueprint.js +166 -0
  12. package/dist/bulk.js +281 -0
  13. package/dist/cacheIdentity.js +152 -0
  14. package/dist/changes.js +90 -0
  15. package/dist/cmsContext.js +229 -0
  16. package/dist/collections.js +224 -0
  17. package/dist/consent.js +29 -0
  18. package/dist/contentType.js +191 -0
  19. package/dist/contentfulImport.js +162 -0
  20. package/dist/copies.js +89 -0
  21. package/dist/cutover.js +202 -0
  22. package/dist/deliveryChecks.js +138 -0
  23. package/dist/domains.js +145 -0
  24. package/dist/draftTexts.js +164 -0
  25. package/dist/duplicates.js +78 -0
  26. package/dist/edgePurge.js +69 -0
  27. package/dist/editHistory.js +113 -0
  28. package/dist/effectForm.js +11 -0
  29. package/dist/environments.js +109 -0
  30. package/dist/errors.js +67 -0
  31. package/dist/experiments.js +528 -0
  32. package/dist/exposure.js +28 -0
  33. package/dist/extensionManifest.js +81 -0
  34. package/dist/extensions.js +314 -0
  35. package/dist/fieldSchema.js +199 -0
  36. package/dist/formStrings.js +74 -0
  37. package/dist/glossary.js +73 -0
  38. package/dist/history.js +54 -0
  39. package/dist/htmlImport.js +297 -0
  40. package/dist/index.d.ts +11 -7
  41. package/dist/index.js +73 -6082
  42. package/dist/media.js +29 -0
  43. package/dist/metrics.js +46 -0
  44. package/dist/migration.js +193 -0
  45. package/dist/migrationStages.js +13 -0
  46. package/dist/presenceAnchors.js +68 -0
  47. package/dist/preview.js +31 -0
  48. package/dist/promotion.js +107 -0
  49. package/dist/quality.js +188 -0
  50. package/dist/recurrence.js +78 -0
  51. package/dist/redirects.js +99 -0
  52. package/dist/referenceGraph.js +223 -0
  53. package/dist/references.js +173 -0
  54. package/dist/release.js +205 -0
  55. package/dist/rest.js +52 -0
  56. package/dist/review.js +160 -0
  57. package/dist/richDocument.js +491 -0
  58. package/dist/richInline.js +100 -0
  59. package/dist/schedule.js +80 -0
  60. package/dist/search.js +148 -0
  61. package/dist/selectionIntent.js +164 -0
  62. package/dist/seo.js +31 -0
  63. package/dist/series.js +105 -0
  64. package/dist/share.js +112 -0
  65. package/dist/stewardship.js +146 -0
  66. package/dist/taxonomy.js +36 -0
  67. package/dist/team.js +103 -0
  68. package/dist/templates.js +106 -0
  69. package/dist/trackChanges.js +197 -0
  70. package/dist/translation.js +64 -0
  71. package/dist/tree.js +87 -0
  72. package/dist/usage.js +50 -0
  73. package/dist/validation.js +192 -0
  74. package/dist/visualEditing.js +60 -0
  75. package/dist/web.js +33 -2
  76. package/dist/workflow.js +322 -0
  77. package/dist/write.js +394 -0
  78. package/dist/xliff.js +325 -0
  79. package/package.json +5 -5
  80. package/dist/presenceAnchors-4iHAVQB3.js +0 -4367
@@ -0,0 +1,322 @@
1
+ import { asTyped as e } from "./effectForm.js";
2
+ import { ContentNotFound as t } from "./errors.js";
3
+ import { and as n, eq as r, id as i, json as a, table as o, text as s, timestamp as c } from "@voltro/database";
4
+ import { tenant as l } from "@voltro/plugin-multitenancy/mixin";
5
+ //#region src/workflow.ts
6
+ var u = "cms_workflow_instances", d = "cms_workflow_decisions", f = (e) => {
7
+ if (!/^[a-z][a-zA-Z0-9]*$/.test(e.id)) throw Error(`defineReviewWorkflow('${e.id}'): the id must be camelCase letters and digits.`);
8
+ if (!Number.isInteger(e.version) || e.version < 1) throw Error(`defineReviewWorkflow('${e.id}'): version is a whole number from 1.`);
9
+ if (e.steps.length === 0) throw Error(`defineReviewWorkflow('${e.id}'): name at least one step.`);
10
+ let t = /* @__PURE__ */ new Set();
11
+ for (let n of e.steps) {
12
+ if (!/^[a-z][a-zA-Z0-9]*$/.test(n.id) || t.has(n.id)) throw Error(`defineReviewWorkflow('${e.id}'): step '${n.id}' must be a unique camelCase id.`);
13
+ t.add(n.id);
14
+ }
15
+ for (let n of e.steps) for (let r of n.after ?? []) if (!t.has(r)) throw Error(`defineReviewWorkflow('${e.id}'): step '${n.id}' waits for unknown step '${r}'.`);
16
+ let n = new Map(e.steps.map((e) => [e.id, e.after ?? []])), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (t) => {
17
+ if (!i.has(t)) {
18
+ if (r.has(t)) throw Error(`defineReviewWorkflow('${e.id}'): steps wait for each other in a cycle at '${t}'.`);
19
+ r.add(t);
20
+ for (let e of n.get(t) ?? []) a(e);
21
+ r.delete(t), i.add(t);
22
+ }
23
+ };
24
+ for (let t of e.steps) a(t.id);
25
+ return e;
26
+ }, p = o(u, {
27
+ id: i({ prefix: "cwfi" }),
28
+ contentType: s().maxLength(64),
29
+ variantId: s().maxLength(64),
30
+ documentId: s().maxLength(64),
31
+ site: s().maxLength(64),
32
+ environment: s().maxLength(64),
33
+ locale: s().maxLength(64),
34
+ revisionId: s().maxLength(64),
35
+ workflowId: s().maxLength(64),
36
+ workflowVersion: s().maxLength(16),
37
+ steps: a(),
38
+ status: s().oneOf([
39
+ "open",
40
+ "approved",
41
+ "changesRequested",
42
+ "superseded"
43
+ ]),
44
+ requestedBy: s().maxLength(64),
45
+ requestedAt: c(),
46
+ closedAt: c().nullable()
47
+ }).with(l()).index("cms_workflow_instances_by_variant", ["contentType", "variantId"]), m = o(d, {
48
+ id: i({ prefix: "cwfd" }),
49
+ instanceId: s().maxLength(64),
50
+ stepId: s().maxLength(64),
51
+ action: s().oneOf([
52
+ "approved",
53
+ "changesRequested",
54
+ "delegated",
55
+ "suggested"
56
+ ]),
57
+ actorId: s().maxLength(64),
58
+ delegateTo: s().maxLength(64).nullable(),
59
+ candidateId: s().maxLength(64).nullable(),
60
+ evidence: s().nullable(),
61
+ note: s().nullable(),
62
+ decidedAt: c()
63
+ }).with(l()).index("cms_workflow_decisions_by_instance", ["instanceId"]), h = (e) => e instanceof Date ? e : new Date(String(e)), g = (e) => typeof e == "string" && e !== "" ? e : null, _ = (e) => [
64
+ r("site", e.site),
65
+ r("environment", e.environment),
66
+ r("locale", e.locale)
67
+ ], v = async (e, i, a, o, s, c, l = /* @__PURE__ */ new Date()) => {
68
+ let [d] = await e.query({
69
+ table: `${i.name}_drafts`,
70
+ predicate: n(r("id", o), ..._(s)),
71
+ order: [],
72
+ take: 1,
73
+ skip: void 0,
74
+ projection: void 0
75
+ });
76
+ if (d === void 0) throw new t({
77
+ contentType: i.name,
78
+ id: o,
79
+ stage: "draft"
80
+ });
81
+ await e.updateMany(u, {
82
+ status: "superseded",
83
+ closedAt: l
84
+ }, { where: n(r("contentType", i.name), r("variantId", o), r("status", "open")) });
85
+ let f = a.steps.map((e) => ({
86
+ id: e.id,
87
+ label: e.label,
88
+ approverScope: e.approverScope,
89
+ after: [...e.after ?? []],
90
+ applies: e.when === void 0 || e.when(d),
91
+ slaHours: e.slaHours ?? null,
92
+ evidence: e.evidence === !0
93
+ })), p = await e.insert(u, {
94
+ contentType: i.name,
95
+ variantId: o,
96
+ documentId: d.documentId,
97
+ ...s,
98
+ revisionId: String(d.revisionId),
99
+ workflowId: a.id,
100
+ workflowVersion: String(a.version),
101
+ steps: f,
102
+ status: "open",
103
+ requestedBy: c.actorId,
104
+ requestedAt: l,
105
+ closedAt: null,
106
+ ...d.tenantId !== void 0 && d.tenantId !== null ? { tenantId: d.tenantId } : {}
107
+ });
108
+ return {
109
+ id: String(p.id),
110
+ revisionId: String(d.revisionId)
111
+ };
112
+ }, y = (e, t, n) => {
113
+ let r = t.map((e) => ({
114
+ stepId: String(e.stepId),
115
+ action: String(e.action),
116
+ actorId: String(e.actorId),
117
+ delegateTo: g(e.delegateTo),
118
+ candidateId: g(e.candidateId),
119
+ evidence: g(e.evidence),
120
+ note: g(e.note),
121
+ decidedAt: h(e.decidedAt)
122
+ })).sort((e, t) => e.decidedAt.getTime() - t.decidedAt.getTime()), i = e.steps ?? [], a = h(e.requestedAt), o = /* @__PURE__ */ new Map();
123
+ for (let e of r) e.action === "approved" && o.set(e.stepId, e.decidedAt);
124
+ let s = new Map(i.map((e) => [e.id, e.applies])), c = (e) => s.get(e) === !1 ? a : o.get(e) ?? null, l = i.map((e) => {
125
+ let t = r.filter((t) => t.stepId === e.id), i = [...t].reverse().find((e) => e.action === "approved" || e.action === "changesRequested"), o = [...t].reverse().find((e) => e.action === "delegated"), s = e.after.map(c), l = s.some((e) => e === null) ? null : new Date(Math.max(a.getTime(), ...s.map((e) => e.getTime()))), u = e.applies ? i?.action === "approved" ? "approved" : i?.action === "changesRequested" ? "changesRequested" : l === null ? "waiting" : "open" : "notApplicable", d = l !== null && e.slaHours !== null ? new Date(l.getTime() + e.slaHours * 36e5) : null;
126
+ return {
127
+ ...e,
128
+ status: u,
129
+ openedAt: l,
130
+ dueAt: d,
131
+ overdue: u === "open" && d !== null && n.getTime() > d.getTime(),
132
+ delegateTo: o?.delegateTo ?? null,
133
+ decidedBy: i?.actorId ?? null,
134
+ evidenceGiven: i?.action === "approved" ? i.evidence : null
135
+ };
136
+ });
137
+ return {
138
+ id: String(e.id),
139
+ contentType: String(e.contentType),
140
+ variantId: String(e.variantId),
141
+ revisionId: String(e.revisionId),
142
+ workflowId: String(e.workflowId),
143
+ workflowVersion: Number(e.workflowVersion),
144
+ status: e.status,
145
+ requestedBy: String(e.requestedBy),
146
+ requestedAt: a,
147
+ steps: l,
148
+ decisions: r
149
+ };
150
+ }, b = async (e, t) => (await e.query({
151
+ table: u,
152
+ predicate: r("id", t),
153
+ order: [],
154
+ take: 1,
155
+ skip: void 0,
156
+ projection: void 0
157
+ }))[0], x = (e, t) => e.query({
158
+ table: d,
159
+ predicate: r("instanceId", t),
160
+ order: [],
161
+ take: void 0,
162
+ skip: void 0,
163
+ projection: void 0
164
+ }), S = async (e, t, n = /* @__PURE__ */ new Date()) => {
165
+ let r = await b(e, t);
166
+ return r === void 0 ? null : y(r, await x(e, t), n);
167
+ }, C = async (e, t, i, a = /* @__PURE__ */ new Date()) => {
168
+ let o = await e.query({
169
+ table: u,
170
+ predicate: n(r("contentType", t.name), r("variantId", i)),
171
+ order: [{
172
+ column: "requestedAt",
173
+ direction: "desc"
174
+ }],
175
+ take: 1,
176
+ skip: void 0,
177
+ projection: void 0
178
+ });
179
+ return o[0] === void 0 ? null : y(o[0], await x(e, String(o[0].id)), a);
180
+ }, w = async (e, t, n, i, a) => {
181
+ let o = await b(e, t);
182
+ if (o === void 0) return {
183
+ ok: !1,
184
+ reason: "notFound"
185
+ };
186
+ let s = y(o, await x(e, t), a);
187
+ if (s.status !== "open") return {
188
+ ok: !1,
189
+ reason: "closed"
190
+ };
191
+ let [c] = await e.query({
192
+ table: `${s.contentType}_drafts`,
193
+ predicate: r("id", s.variantId),
194
+ order: [],
195
+ take: 1,
196
+ skip: void 0,
197
+ projection: ["revisionId"]
198
+ });
199
+ if (c === void 0) return {
200
+ ok: !1,
201
+ reason: "notFound"
202
+ };
203
+ if (c.revisionId !== s.revisionId) return {
204
+ ok: !1,
205
+ reason: "revisionMoved"
206
+ };
207
+ let l = s.steps.find((e) => e.id === n);
208
+ return l === void 0 ? {
209
+ ok: !1,
210
+ reason: "unknownStep"
211
+ } : l.status === "notApplicable" ? {
212
+ ok: !1,
213
+ reason: "notApplicable"
214
+ } : l.status === "waiting" ? {
215
+ ok: !1,
216
+ reason: "waiting"
217
+ } : l.status === "open" ? i.actorId === s.requestedBy ? {
218
+ ok: !1,
219
+ reason: "selfApproval"
220
+ } : (l.delegateTo === null ? i.scopes.has(l.approverScope) : l.delegateTo === i.actorId) ? {
221
+ ok: !0,
222
+ instance: s,
223
+ step: l
224
+ } : {
225
+ ok: !1,
226
+ reason: "notAllowed"
227
+ } : {
228
+ ok: !1,
229
+ reason: "decided"
230
+ };
231
+ }, T = async (e, t, n, r, i, a = /* @__PURE__ */ new Date()) => {
232
+ let o = await w(e, t, n, r, a);
233
+ if (!o.ok) return o;
234
+ let s = i.evidence?.trim() ?? "", c = i.note?.trim() ?? "";
235
+ if (i.action === "approve" && o.step.evidence && s === "") return {
236
+ ok: !1,
237
+ reason: "noEvidence"
238
+ };
239
+ if (i.action === "requestChanges" && c === "") return {
240
+ ok: !1,
241
+ reason: "noNote"
242
+ };
243
+ await e.insert(d, {
244
+ instanceId: t,
245
+ stepId: n,
246
+ action: i.action === "approve" ? "approved" : "changesRequested",
247
+ actorId: r.actorId,
248
+ delegateTo: null,
249
+ candidateId: null,
250
+ evidence: s === "" ? null : s.slice(0, 1e3),
251
+ note: c === "" ? null : c.slice(0, 1e3),
252
+ decidedAt: a,
253
+ ...E(await b(e, t))
254
+ });
255
+ let l = y(await b(e, t), await x(e, t), a), f = l.steps.some((e) => e.status === "changesRequested") ? "changesRequested" : l.steps.every((e) => e.status === "approved" || e.status === "notApplicable") ? "approved" : "open";
256
+ return f !== "open" && await e.update(u, t, {
257
+ status: f,
258
+ closedAt: a
259
+ }), {
260
+ ok: !0,
261
+ instanceStatus: f
262
+ };
263
+ }, E = (e) => e?.tenantId !== void 0 && e.tenantId !== null ? { tenantId: e.tenantId } : {}, D = async (e, t, n, r, i, a = /* @__PURE__ */ new Date()) => {
264
+ let o = await w(e, t, n, r, a);
265
+ return o.ok ? i === r.actorId || i === o.instance.requestedBy ? {
266
+ ok: !1,
267
+ reason: "selfDelegation"
268
+ } : (await e.insert(d, {
269
+ instanceId: t,
270
+ stepId: n,
271
+ action: "delegated",
272
+ actorId: r.actorId,
273
+ delegateTo: i,
274
+ candidateId: null,
275
+ evidence: null,
276
+ note: null,
277
+ decidedAt: a,
278
+ ...E(await b(e, t))
279
+ }), { ok: !0 }) : o;
280
+ }, O = async (e, t, n, r, i, a = /* @__PURE__ */ new Date()) => {
281
+ let o = await w(e, t, n, r, a);
282
+ if (!o.ok) return o;
283
+ let s = i.note?.trim() ?? "";
284
+ return await e.insert(d, {
285
+ instanceId: t,
286
+ stepId: n,
287
+ action: "suggested",
288
+ actorId: r.actorId,
289
+ delegateTo: null,
290
+ candidateId: i.candidateId,
291
+ evidence: null,
292
+ note: s === "" ? null : s.slice(0, 1e3),
293
+ decidedAt: a,
294
+ ...E(await b(e, t))
295
+ }), { ok: !0 };
296
+ }, k = async (e, t, n) => {
297
+ let i = await e.query({
298
+ table: u,
299
+ predicate: r("status", "open"),
300
+ order: [],
301
+ take: 500,
302
+ skip: void 0,
303
+ projection: void 0
304
+ }), a = [];
305
+ for (let r of i) {
306
+ let i = y(r, await x(e, String(r.id)), n);
307
+ for (let e of i.steps) e.status === "open" && e.dueAt !== null && e.dueAt.getTime() > t.getTime() && e.dueAt.getTime() <= n.getTime() && a.push({
308
+ instance: i,
309
+ step: e
310
+ });
311
+ }
312
+ return a;
313
+ }, A = async (e, t, i, a) => (await e.query({
314
+ table: u,
315
+ predicate: n(r("contentType", t.name), r("variantId", i), r("revisionId", a), r("status", "approved")),
316
+ order: [],
317
+ take: 1,
318
+ skip: void 0,
319
+ projection: ["id"]
320
+ })).length > 0, j = (...n) => e(() => v(...n), t), M = (...t) => e(() => T(...t)), N = (...t) => e(() => D(...t)), P = (...t) => e(() => S(...t)), F = (...t) => e(() => C(...t)), I = (...t) => e(() => O(...t)), L = (...t) => e(() => k(...t)), R = (...t) => e(() => A(...t));
321
+ //#endregion
322
+ export { d as CMS_WORKFLOW_DECISIONS_TABLE, u as CMS_WORKFLOW_INSTANCES_TABLE, A as approvedByWorkflow, R as approvedByWorkflowEffect, m as cmsWorkflowDecisionsTable, p as cmsWorkflowInstancesTable, T as decideStep, M as decideStepEffect, f as defineReviewWorkflow, D as delegateStep, N as delegateStepEffect, C as latestWorkflow, F as latestWorkflowEffect, k as overdueSteps, L as overdueStepsEffect, v as startWorkflow, j as startWorkflowEffect, O as suggestOnStep, I as suggestOnStepEffect, S as workflowState, P as workflowStateEffect };