@sanity/workflow-engine 0.29.0 → 0.30.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.
- package/CHANGELOG.md +51 -0
- package/DATAMODEL.md +67 -22
- package/dist/_chunks-cjs/invariants.cjs +286 -87
- package/dist/_chunks-es/invariants.js +281 -88
- package/dist/define.d.cts +289 -276
- package/dist/define.d.ts +289 -276
- package/dist/index.cjs +1297 -914
- package/dist/index.d.cts +915 -1053
- package/dist/index.d.ts +915 -1053
- package/dist/index.js +1116 -749
- package/package.json +3 -3
|
@@ -55,79 +55,6 @@ function andConditions(parts) {
|
|
|
55
55
|
if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
class WorkflowError extends Error {
|
|
59
|
-
kind;
|
|
60
|
-
constructor(kind, message, options) {
|
|
61
|
-
super(message, options), this.kind = kind;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
class ContractViolationError extends WorkflowError {
|
|
66
|
-
constructor(message) {
|
|
67
|
-
super("contract-violation", message), this.name = "ContractViolationError";
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
class InstanceNotFoundError extends WorkflowError {
|
|
72
|
-
instanceId;
|
|
73
|
-
constructor(args) {
|
|
74
|
-
super("instance-not-found", `Workflow instance ${args.instanceId} not found${args.detail ? ` (${args.detail})` : ""}`),
|
|
75
|
-
this.name = "InstanceNotFoundError", this.instanceId = args.instanceId;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
class DefinitionNotFoundError extends WorkflowError {
|
|
80
|
-
definition;
|
|
81
|
-
version;
|
|
82
|
-
constructor(args) {
|
|
83
|
-
super("definition-not-found", args.version !== void 0 ? `Workflow definition ${args.definition} v${args.version} not deployed` : `Workflow definition ${args.definition} has no deployed versions`),
|
|
84
|
-
this.name = "DefinitionNotFoundError", this.definition = args.definition, args.version !== void 0 && (this.version = args.version);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
class SpawnContractsInvalidError extends WorkflowError {
|
|
89
|
-
issues;
|
|
90
|
-
constructor(args) {
|
|
91
|
-
super("spawn-contracts-invalid", args.message), this.name = "SpawnContractsInvalidError",
|
|
92
|
-
this.issues = args.issues;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
class DefinitionInUseError extends WorkflowError {
|
|
97
|
-
definition;
|
|
98
|
-
blockedBy;
|
|
99
|
-
constructor(args) {
|
|
100
|
-
super("definition-in-use", definitionInUseMessage(args.definition, args.blockedBy)),
|
|
101
|
-
this.name = "DefinitionInUseError", this.definition = args.definition, this.blockedBy = args.blockedBy;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function definitionInUseMessage(definition, blockedBy) {
|
|
106
|
-
if (blockedBy.reason === "non-terminal-instances") {
|
|
107
|
-
const head = blockedBy.instanceIds.slice(0, 3).join(", "), preview = blockedBy.instanceIds.length > 3 ? `${head}, …` : head;
|
|
108
|
-
return `Cannot delete ${definition}: ${blockedBy.instanceIds.length} non-terminal instance(s) exist (${preview}). Pass cascade to abort them first — instances are aborted in place, never deleted.`;
|
|
109
|
-
}
|
|
110
|
-
const names = blockedBy.referrers.map(r => `${r.definition} v${r.version}`).join(", ");
|
|
111
|
-
return `Cannot delete ${definition}: still spawn-referenced by deployed definition(s) ${names}. Delete or redeploy the referrer(s) first.`;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
class EffectNotFoundError extends WorkflowError {
|
|
115
|
-
instanceId;
|
|
116
|
-
effectKey;
|
|
117
|
-
settled;
|
|
118
|
-
constructor(args) {
|
|
119
|
-
super("effect-not-found", effectNotFoundMessage(args)), this.name = "EffectNotFoundError",
|
|
120
|
-
this.instanceId = args.instanceId, this.effectKey = args.effectKey, args.settled !== void 0 && (this.settled = args.settled);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function effectNotFoundMessage(args) {
|
|
125
|
-
const base = `Pending effect "${args.effectKey}" not found on instance ${args.instanceId}`;
|
|
126
|
-
if (args.settled === void 0) return base;
|
|
127
|
-
const cause = args.settled.detail !== void 0 ? ` (${args.settled.detail})` : "";
|
|
128
|
-
return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
58
|
const KNOWN_SCHEMES = /* @__PURE__ */ new Set([ "dataset", "canvas", "media-library", "dashboard" ]), KNOWN_SCHEMES_TEXT = [ ...KNOWN_SCHEMES ].join(", ");
|
|
132
59
|
|
|
133
60
|
class VersionSpecificDatasetGdrError extends Error {
|
|
@@ -343,6 +270,79 @@ function isGdr(value) {
|
|
|
343
270
|
return typeof value == "object" && value !== null && typeof value.id == "string" && typeof value.type == "string";
|
|
344
271
|
}
|
|
345
272
|
|
|
273
|
+
class WorkflowError extends Error {
|
|
274
|
+
kind;
|
|
275
|
+
constructor(kind, message, options) {
|
|
276
|
+
super(message, options), this.kind = kind;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
class ContractViolationError extends WorkflowError {
|
|
281
|
+
constructor(message) {
|
|
282
|
+
super("contract-violation", message), this.name = "ContractViolationError";
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
class InstanceNotFoundError extends WorkflowError {
|
|
287
|
+
instanceId;
|
|
288
|
+
constructor(args) {
|
|
289
|
+
super("instance-not-found", `Workflow instance ${args.instanceId} not found${args.detail ? ` (${args.detail})` : ""}`),
|
|
290
|
+
this.name = "InstanceNotFoundError", this.instanceId = args.instanceId;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
class DefinitionNotFoundError extends WorkflowError {
|
|
295
|
+
definition;
|
|
296
|
+
version;
|
|
297
|
+
constructor(args) {
|
|
298
|
+
super("definition-not-found", args.version !== void 0 ? `Workflow definition ${args.definition} v${args.version} not deployed` : `Workflow definition ${args.definition} has no deployed versions`),
|
|
299
|
+
this.name = "DefinitionNotFoundError", this.definition = args.definition, args.version !== void 0 && (this.version = args.version);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
class SpawnContractsInvalidError extends WorkflowError {
|
|
304
|
+
issues;
|
|
305
|
+
constructor(args) {
|
|
306
|
+
super("spawn-contracts-invalid", args.message), this.name = "SpawnContractsInvalidError",
|
|
307
|
+
this.issues = args.issues;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
class DefinitionInUseError extends WorkflowError {
|
|
312
|
+
definition;
|
|
313
|
+
blockedBy;
|
|
314
|
+
constructor(args) {
|
|
315
|
+
super("definition-in-use", definitionInUseMessage(args.definition, args.blockedBy)),
|
|
316
|
+
this.name = "DefinitionInUseError", this.definition = args.definition, this.blockedBy = args.blockedBy;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function definitionInUseMessage(definition, blockedBy) {
|
|
321
|
+
if (blockedBy.reason === "non-terminal-instances") {
|
|
322
|
+
const head = blockedBy.instanceIds.slice(0, 3).join(", "), preview = blockedBy.instanceIds.length > 3 ? `${head}, …` : head;
|
|
323
|
+
return `Cannot delete ${definition}: ${blockedBy.instanceIds.length} non-terminal instance(s) exist (${preview}). Pass cascade to abort them first — instances are aborted in place, never deleted.`;
|
|
324
|
+
}
|
|
325
|
+
const names = blockedBy.referrers.map(r => `${r.definition} v${r.version}`).join(", ");
|
|
326
|
+
return `Cannot delete ${definition}: still spawn-referenced by deployed definition(s) ${names}. Delete or redeploy the referrer(s) first.`;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
class EffectNotFoundError extends WorkflowError {
|
|
330
|
+
instanceId;
|
|
331
|
+
effectKey;
|
|
332
|
+
settled;
|
|
333
|
+
constructor(args) {
|
|
334
|
+
super("effect-not-found", effectNotFoundMessage(args)), this.name = "EffectNotFoundError",
|
|
335
|
+
this.instanceId = args.instanceId, this.effectKey = args.effectKey, args.settled !== void 0 && (this.settled = args.settled);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function effectNotFoundMessage(args) {
|
|
340
|
+
const base = `Pending effect "${args.effectKey}" not found on instance ${args.instanceId}`;
|
|
341
|
+
if (args.settled === void 0) return base;
|
|
342
|
+
const cause = args.settled.detail !== void 0 ? ` (${args.settled.detail})` : "";
|
|
343
|
+
return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
346
|
const LAKE_ID_SEGMENT_RE = /^[a-z0-9][a-z0-9-]*$/, LAKE_ID_SEGMENT_GLOSS = "ASCII lowercase + digits + dashes, no leading dash, no dots";
|
|
347
347
|
|
|
348
348
|
function validateTag(tag) {
|
|
@@ -668,6 +668,7 @@ function desugarFieldEntry({entry: entry, path: path, ctx: ctx}) {
|
|
|
668
668
|
options: entry.options,
|
|
669
669
|
validation: entry.validation,
|
|
670
670
|
types: entry.types,
|
|
671
|
+
roles: entry.roles,
|
|
671
672
|
fields: entry.fields,
|
|
672
673
|
of: entry.of
|
|
673
674
|
})
|
|
@@ -1289,10 +1290,18 @@ function refKindAcceptsTypes(kind) {
|
|
|
1289
1290
|
return isSingleDocRefKind(kind) || kind === "doc.refs";
|
|
1290
1291
|
}
|
|
1291
1292
|
|
|
1293
|
+
function assignmentKindAcceptsRoles(kind) {
|
|
1294
|
+
return kind === "assignee" || kind === "assignees";
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1292
1297
|
function isSingleDocRefEntry(entry) {
|
|
1293
1298
|
return isSingleDocRefKind(entry._type);
|
|
1294
1299
|
}
|
|
1295
1300
|
|
|
1301
|
+
function isAssignmentFieldEntry(entry) {
|
|
1302
|
+
return assignmentKindAcceptsRoles(entry._type);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1296
1305
|
function isTodoListItem(row) {
|
|
1297
1306
|
if (typeof row != "object" || row === null) return !1;
|
|
1298
1307
|
const candidate = row, status = candidate.status;
|
|
@@ -1601,6 +1610,10 @@ function lakePrincipalId(args) {
|
|
|
1601
1610
|
return args.localPrincipalId ?? args.actor.id;
|
|
1602
1611
|
}
|
|
1603
1612
|
|
|
1613
|
+
function isRecord(value) {
|
|
1614
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1604
1617
|
class FieldValueShapeError extends WorkflowError {
|
|
1605
1618
|
entryType;
|
|
1606
1619
|
entryName;
|
|
@@ -1697,9 +1710,16 @@ const fieldValueSchemas = {
|
|
|
1697
1710
|
query: v__namespace.any()
|
|
1698
1711
|
};
|
|
1699
1712
|
|
|
1700
|
-
function shapeValueSchema(
|
|
1701
|
-
|
|
1702
|
-
if (shape.type === "
|
|
1713
|
+
function shapeValueSchema(args) {
|
|
1714
|
+
const {shape: shape, leaf: leaf} = args;
|
|
1715
|
+
if (shape.type === "object") return objectSchema({
|
|
1716
|
+
fields: shape.fields ?? [],
|
|
1717
|
+
leaf: leaf
|
|
1718
|
+
});
|
|
1719
|
+
if (shape.type === "array") return v__namespace.array(objectSchema({
|
|
1720
|
+
fields: shape.of ?? [],
|
|
1721
|
+
leaf: leaf
|
|
1722
|
+
}));
|
|
1703
1723
|
const schema = leaf[shape.type] ?? v__namespace.any();
|
|
1704
1724
|
return constrainedScalarSchema({
|
|
1705
1725
|
schema: schema,
|
|
@@ -1750,19 +1770,31 @@ function constrainedScalarSchema(args) {
|
|
|
1750
1770
|
}) ?? [] ].join("; ")));
|
|
1751
1771
|
}
|
|
1752
1772
|
|
|
1753
|
-
function objectSchema(
|
|
1754
|
-
const entries = /* @__PURE__ */ Object.create(null);
|
|
1755
|
-
for (const f of fields) entries[f.name] = v__namespace.optional(shapeValueSchema(
|
|
1773
|
+
function objectSchema(args) {
|
|
1774
|
+
const {fields: fields, leaf: leaf} = args, entries = /* @__PURE__ */ Object.create(null);
|
|
1775
|
+
for (const f of fields) entries[f.name] = v__namespace.optional(shapeValueSchema({
|
|
1776
|
+
shape: f,
|
|
1777
|
+
leaf: leaf
|
|
1778
|
+
}));
|
|
1756
1779
|
return v__namespace.looseObject(entries);
|
|
1757
1780
|
}
|
|
1758
1781
|
|
|
1759
1782
|
function wholeValueSchema(args) {
|
|
1760
1783
|
const {entryType: entryType, shape: shape, leaf: leaf} = args;
|
|
1761
|
-
return entryType === "object" ? v__namespace.union([ v__namespace.null(), objectSchema(
|
|
1784
|
+
return entryType === "object" ? v__namespace.union([ v__namespace.null(), objectSchema({
|
|
1785
|
+
fields: shape.fields ?? [],
|
|
1786
|
+
leaf: leaf
|
|
1787
|
+
}) ]) : entryType === "array" ? v__namespace.array(objectSchema({
|
|
1788
|
+
fields: shape.of ?? [],
|
|
1789
|
+
leaf: leaf
|
|
1790
|
+
})) : leaf[entryType];
|
|
1762
1791
|
}
|
|
1763
1792
|
|
|
1764
1793
|
function appendItemSchema(entryType, shape) {
|
|
1765
|
-
if (entryType === "array") return objectSchema(
|
|
1794
|
+
if (entryType === "array") return objectSchema({
|
|
1795
|
+
fields: shape.of ?? [],
|
|
1796
|
+
leaf: valueSchemas
|
|
1797
|
+
});
|
|
1766
1798
|
if (entryType === "doc.refs") return GdrShape;
|
|
1767
1799
|
if (entryType === "assignees") return AssigneeWriteShape;
|
|
1768
1800
|
}
|
|
@@ -1814,7 +1846,7 @@ function checkValueAgainst(args, leaf) {
|
|
|
1814
1846
|
entryType: args.entryType,
|
|
1815
1847
|
validation: args.validation,
|
|
1816
1848
|
value: args.value
|
|
1817
|
-
});
|
|
1849
|
+
}) ?? assignmentValueIssues(args, result.output);
|
|
1818
1850
|
return postIssues !== void 0 ? {
|
|
1819
1851
|
issues: postIssues
|
|
1820
1852
|
} : {
|
|
@@ -1822,6 +1854,142 @@ function checkValueAgainst(args, leaf) {
|
|
|
1822
1854
|
};
|
|
1823
1855
|
}
|
|
1824
1856
|
|
|
1857
|
+
function assignmentIdentity(assignee) {
|
|
1858
|
+
return assignee.type === "user" ? `user:${assignee.id}` : `role:${assignee.role}`;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
function assignmentCandidate(value) {
|
|
1862
|
+
const parsed = v__namespace.safeParse(AssigneeShape, value);
|
|
1863
|
+
return parsed.success ? parsed.output : void 0;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
function assignmentValueIssues(args, value) {
|
|
1867
|
+
const retained = previousAssignmentIdentities(args), issues = [];
|
|
1868
|
+
return visitAssignmentEntries({
|
|
1869
|
+
entryType: args.entryType,
|
|
1870
|
+
value: value,
|
|
1871
|
+
roles: args.roles,
|
|
1872
|
+
fields: args.fields,
|
|
1873
|
+
of: args.of,
|
|
1874
|
+
path: "$"
|
|
1875
|
+
}, ({assignee: assignee, roles: roles, path: path}) => {
|
|
1876
|
+
consumeRetainedAssignment({
|
|
1877
|
+
retained: retained,
|
|
1878
|
+
path: path,
|
|
1879
|
+
identity: assignmentIdentity(assignee)
|
|
1880
|
+
}) || issues.push(...assignmentCandidateIssues({
|
|
1881
|
+
roles: roles,
|
|
1882
|
+
memberRoles: args.memberRoles,
|
|
1883
|
+
roleAliases: args.roleAliases
|
|
1884
|
+
}, assignee));
|
|
1885
|
+
}), issues.length === 0 ? void 0 : issues;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
function consumeRetainedAssignment(args) {
|
|
1889
|
+
const identities = args.retained.get(args.path), remaining = identities?.get(args.identity) ?? 0;
|
|
1890
|
+
return remaining === 0 || identities === void 0 ? !1 : (remaining === 1 ? identities.delete(args.identity) : identities.set(args.identity, remaining - 1),
|
|
1891
|
+
!0);
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
function previousAssignmentIdentities(args) {
|
|
1895
|
+
const retained = /* @__PURE__ */ new Map;
|
|
1896
|
+
if (args.previousValue === void 0 || args.entryType === "assignee") return retained;
|
|
1897
|
+
const schema = wholeValueSchema({
|
|
1898
|
+
entryType: args.entryType,
|
|
1899
|
+
shape: args,
|
|
1900
|
+
leaf: valueSchemas
|
|
1901
|
+
});
|
|
1902
|
+
if (schema === void 0) return retained;
|
|
1903
|
+
const previous = v__namespace.safeParse(schema, args.previousValue);
|
|
1904
|
+
return previous.success && visitAssignmentEntries({
|
|
1905
|
+
entryType: args.entryType,
|
|
1906
|
+
value: previous.output,
|
|
1907
|
+
roles: args.roles,
|
|
1908
|
+
fields: args.fields,
|
|
1909
|
+
of: args.of,
|
|
1910
|
+
path: "$"
|
|
1911
|
+
}, ({assignee: assignee, path: path}) => {
|
|
1912
|
+
const identities = retained.get(path) ?? /* @__PURE__ */ new Map, identity = assignmentIdentity(assignee);
|
|
1913
|
+
identities.set(identity, (identities.get(identity) ?? 0) + 1), retained.set(path, identities);
|
|
1914
|
+
}), retained;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
function visitAssignmentEntries(args, visit) {
|
|
1918
|
+
if (assignmentKindAcceptsRoles(args.entryType)) {
|
|
1919
|
+
visitAssignmentCandidates(args, visit);
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
if (args.entryType === "object") {
|
|
1923
|
+
visitAssignmentFields({
|
|
1924
|
+
fields: args.fields,
|
|
1925
|
+
value: args.value,
|
|
1926
|
+
path: args.path
|
|
1927
|
+
}, visit);
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
if (!(args.entryType !== "array" || !Array.isArray(args.value))) for (const row of args.value) visitAssignmentFields({
|
|
1931
|
+
fields: args.of,
|
|
1932
|
+
value: row,
|
|
1933
|
+
path: `${args.path}[]`
|
|
1934
|
+
}, visit);
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
function visitAssignmentCandidates(args, visit) {
|
|
1938
|
+
if (args.roles === void 0) return;
|
|
1939
|
+
const indexedValues = args.entryType === "assignees" && Array.isArray(args.value) ? args.value.map(value => ({
|
|
1940
|
+
value: value,
|
|
1941
|
+
path: args.path
|
|
1942
|
+
})) : [ {
|
|
1943
|
+
value: args.value,
|
|
1944
|
+
path: args.path
|
|
1945
|
+
} ];
|
|
1946
|
+
for (const {value: value, path: path} of indexedValues) {
|
|
1947
|
+
const assignee = assignmentCandidate(value);
|
|
1948
|
+
assignee !== void 0 && visit({
|
|
1949
|
+
assignee: assignee,
|
|
1950
|
+
roles: args.roles,
|
|
1951
|
+
path: path
|
|
1952
|
+
});
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
function visitAssignmentFields(args, visit) {
|
|
1957
|
+
if (!(args.fields === void 0 || !isRecord(args.value))) for (const field of args.fields) visitAssignmentShape({
|
|
1958
|
+
shape: field,
|
|
1959
|
+
value: args.value[field.name],
|
|
1960
|
+
path: `${args.path}.${field.name}`
|
|
1961
|
+
}, visit);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
function visitAssignmentShape(args, visit) {
|
|
1965
|
+
visitAssignmentEntries({
|
|
1966
|
+
entryType: args.shape.type,
|
|
1967
|
+
value: args.value,
|
|
1968
|
+
roles: args.shape.roles,
|
|
1969
|
+
fields: args.shape.fields,
|
|
1970
|
+
of: args.shape.of,
|
|
1971
|
+
path: args.path
|
|
1972
|
+
}, visit);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
function assignmentCandidateIssues(args, assignee) {
|
|
1976
|
+
if (assignee.type === "role") return collectiveRoleIssues(args, assignee.role);
|
|
1977
|
+
const held = args.memberRoles?.[assignee.id];
|
|
1978
|
+
return held === void 0 ? args.memberRoles === void 0 ? [] : [ `user "${assignee.id}" has no available project membership for role eligibility` ] : args.roles.some(required => actorFulfillsRole({
|
|
1979
|
+
actorRoles: held,
|
|
1980
|
+
required: required,
|
|
1981
|
+
aliases: args.roleAliases
|
|
1982
|
+
})) ? [] : [ `user "${assignee.id}" does not fulfill any eligible role: ${formatEligibleRoles(args.roles)}` ];
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
function collectiveRoleIssues(args, role) {
|
|
1986
|
+
return args.roles.includes(role) ? [] : [ `collective role "${role}" is not eligible — this entry accepts ${formatEligibleRoles(args.roles)}` ];
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
function formatEligibleRoles(roles) {
|
|
1990
|
+
return roles.map(role => `"${role}"`).join(", ");
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1825
1993
|
function issuesOf(check) {
|
|
1826
1994
|
return "issues" in check ? check.issues : void 0;
|
|
1827
1995
|
}
|
|
@@ -1881,6 +2049,20 @@ function validateFieldAppendItem(args) {
|
|
|
1881
2049
|
issues: formatIssues(result.issues),
|
|
1882
2050
|
mode: "item"
|
|
1883
2051
|
});
|
|
2052
|
+
const assignmentArgs = {
|
|
2053
|
+
entryType: appendAssignmentEntryType(args.entryType),
|
|
2054
|
+
value: result.output,
|
|
2055
|
+
roles: args.roles,
|
|
2056
|
+
fields: args.entryType === "array" ? args.of : void 0,
|
|
2057
|
+
memberRoles: args.memberRoles,
|
|
2058
|
+
roleAliases: args.roleAliases
|
|
2059
|
+
}, assignmentIssues = assignmentValueIssues(assignmentArgs, result.output);
|
|
2060
|
+
if (assignmentIssues !== void 0) throw new FieldValueShapeError({
|
|
2061
|
+
entryType: args.entryType,
|
|
2062
|
+
entryName: args.entryName,
|
|
2063
|
+
issues: assignmentIssues,
|
|
2064
|
+
mode: "item"
|
|
2065
|
+
});
|
|
1884
2066
|
const typeIssues = refTypeIssues({
|
|
1885
2067
|
entryType: args.entryType,
|
|
1886
2068
|
types: args.types,
|
|
@@ -1895,6 +2077,10 @@ function validateFieldAppendItem(args) {
|
|
|
1895
2077
|
return result.output;
|
|
1896
2078
|
}
|
|
1897
2079
|
|
|
2080
|
+
function appendAssignmentEntryType(entryType) {
|
|
2081
|
+
return entryType === "assignees" ? "assignee" : entryType === "array" ? "object" : entryType;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
1898
2084
|
function formatIssues(issues, formatMessage = issue => issue.message) {
|
|
1899
2085
|
const formatOne = (issue, prefix) => {
|
|
1900
2086
|
const keys = [ ...prefix, ...issue.path?.map(p => p.key) ?? [] ], sub = issue.issues?.filter(candidate => candidate.expected !== "null");
|
|
@@ -2087,16 +2273,17 @@ function compositeChecked(entries) {
|
|
|
2087
2273
|
return v__namespace.pipe(v__namespace.strictObject(entries), v__namespace.check(input => compositeShapeOk(input), issue => compositeShapeMessage(issue.input)), v__namespace.check(input => duplicateSubfieldName(input) === void 0, issue => `duplicate sub-field name "${duplicateSubfieldName(issue.input)}" — sub-field names must be unique within \`fields\` / \`of\``));
|
|
2088
2274
|
}
|
|
2089
2275
|
|
|
2090
|
-
const FieldShapeSchema = v__namespace.lazy(() => v__namespace.pipe(compositeChecked({
|
|
2276
|
+
const AssignmentRolesSchema = v__namespace.pipe(v__namespace.array(NonEmpty), v__namespace.minLength(1, "declare at least one eligible role, or omit `roles`")), FieldShapeSchema = v__namespace.lazy(() => v__namespace.pipe(compositeChecked({
|
|
2091
2277
|
type: FieldValueKindSchema,
|
|
2092
2278
|
name: FieldEntryName,
|
|
2093
2279
|
title: v__namespace.optional(v__namespace.string()),
|
|
2094
2280
|
description: v__namespace.optional(v__namespace.string()),
|
|
2095
2281
|
options: v__namespace.optional(ChoiceOptionsSchema),
|
|
2096
2282
|
validation: v__namespace.optional(ScalarValidationSchema),
|
|
2283
|
+
roles: v__namespace.optional(AssignmentRolesSchema),
|
|
2097
2284
|
fields: v__namespace.optional(v__namespace.array(FieldShapeSchema)),
|
|
2098
2285
|
of: v__namespace.optional(v__namespace.array(FieldShapeSchema))
|
|
2099
|
-
}), choiceOptionsCheck(), scalarValidationCheck())), StoredEditableSchema = v__namespace.union([ v__namespace.literal(!0), NonEmpty ]), AuthoringEditableSchema = v__namespace.union([ v__namespace.literal(!0), v__namespace.array(NonEmpty), NonEmpty ]);
|
|
2286
|
+
}), choiceOptionsCheck(), scalarValidationCheck(), assignmentRolesCheck())), StoredEditableSchema = v__namespace.union([ v__namespace.literal(!0), NonEmpty ]), AuthoringEditableSchema = v__namespace.union([ v__namespace.literal(!0), v__namespace.array(NonEmpty), NonEmpty ]);
|
|
2100
2287
|
|
|
2101
2288
|
function fieldBase(editable, group) {
|
|
2102
2289
|
return {
|
|
@@ -2117,6 +2304,7 @@ function fieldEntryFields({editable: editable, group: group, kind: kind = FieldK
|
|
|
2117
2304
|
options: v__namespace.optional(ChoiceOptionsSchema),
|
|
2118
2305
|
validation: v__namespace.optional(ScalarValidationSchema),
|
|
2119
2306
|
types: v__namespace.optional(v__namespace.pipe(v__namespace.array(NonEmpty), v__namespace.minLength(1, "declare at least one accepted type, or omit `types` to accept any"))),
|
|
2307
|
+
roles: v__namespace.optional(AssignmentRolesSchema),
|
|
2120
2308
|
fields: v__namespace.optional(v__namespace.array(FieldShapeSchema)),
|
|
2121
2309
|
of: v__namespace.optional(v__namespace.array(FieldShapeSchema))
|
|
2122
2310
|
};
|
|
@@ -2130,7 +2318,8 @@ function literalSeedIssues(entry) {
|
|
|
2130
2318
|
fields: entry.fields,
|
|
2131
2319
|
of: entry.of,
|
|
2132
2320
|
options: entry.options,
|
|
2133
|
-
validation: entry.validation
|
|
2321
|
+
validation: entry.validation,
|
|
2322
|
+
roles: entry.roles
|
|
2134
2323
|
});
|
|
2135
2324
|
}
|
|
2136
2325
|
|
|
@@ -2142,6 +2331,10 @@ function refTypesCheck() {
|
|
|
2142
2331
|
return v__namespace.check(entry => entry.types === void 0 || refKindAcceptsTypes(entry.type), issue => `\`types\` is only valid on \`doc.ref\` / \`doc.refs\` / \`subject\` entries, not "${issue.input.type}"`);
|
|
2143
2332
|
}
|
|
2144
2333
|
|
|
2334
|
+
function assignmentRolesCheck() {
|
|
2335
|
+
return v__namespace.check(entry => entry.roles === void 0 || assignmentKindAcceptsRoles(entry.type), issue => `\`roles\` is only valid on \`assignee\` / \`assignees\` entries, not "${issue.input.type}"`);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2145
2338
|
function choiceOptionsCheck() {
|
|
2146
2339
|
return v__namespace.check(entry => checkChoiceList({
|
|
2147
2340
|
entryType: entry.type,
|
|
@@ -2176,11 +2369,11 @@ function scalarValidationDeclarationIssues(entry) {
|
|
|
2176
2369
|
const FieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
|
|
2177
2370
|
editable: StoredEditableSchema,
|
|
2178
2371
|
group: StoredGroupMembershipSchema
|
|
2179
|
-
})), refTypesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), RawAuthoringFieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
|
|
2372
|
+
})), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), RawAuthoringFieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
|
|
2180
2373
|
editable: AuthoringEditableSchema,
|
|
2181
2374
|
group: AuthoringGroupMembershipSchema,
|
|
2182
2375
|
kind: AuthoringRawFieldKindSchema
|
|
2183
|
-
})), refTypesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), ClaimFieldSchema = pinned()(v__namespace.strictObject({
|
|
2376
|
+
})), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), ClaimFieldSchema = pinned()(v__namespace.strictObject({
|
|
2184
2377
|
type: v__namespace.literal("claim"),
|
|
2185
2378
|
name: FieldEntryName,
|
|
2186
2379
|
title: v__namespace.optional(v__namespace.string()),
|
|
@@ -3948,6 +4141,8 @@ exports.actorFulfillsRole = actorFulfillsRole;
|
|
|
3948
4141
|
|
|
3949
4142
|
exports.andConditions = andConditions;
|
|
3950
4143
|
|
|
4144
|
+
exports.assignmentKindAcceptsRoles = assignmentKindAcceptsRoles;
|
|
4145
|
+
|
|
3951
4146
|
exports.checkWorkflowInvariants = checkWorkflowInvariants;
|
|
3952
4147
|
|
|
3953
4148
|
exports.choiceValueIssues = choiceValueIssues;
|
|
@@ -4012,6 +4207,8 @@ exports.groupMembershipNames = groupMembershipNames;
|
|
|
4012
4207
|
|
|
4013
4208
|
exports.isAlwaysArrayFieldKind = isAlwaysArrayFieldKind;
|
|
4014
4209
|
|
|
4210
|
+
exports.isAssignmentFieldEntry = isAssignmentFieldEntry;
|
|
4211
|
+
|
|
4015
4212
|
exports.isBareSeedId = isBareSeedId;
|
|
4016
4213
|
|
|
4017
4214
|
exports.isCascadeFired = isCascadeFired;
|
|
@@ -4028,6 +4225,8 @@ exports.isNotesEntry = isNotesEntry;
|
|
|
4028
4225
|
|
|
4029
4226
|
exports.isParseableInstant = isParseableInstant;
|
|
4030
4227
|
|
|
4228
|
+
exports.isRecord = isRecord;
|
|
4229
|
+
|
|
4031
4230
|
exports.isSingleDocRefEntry = isSingleDocRefEntry;
|
|
4032
4231
|
|
|
4033
4232
|
exports.isSingleDocRefKind = isSingleDocRefKind;
|