@plitzi/sdk-shared 0.35.5 → 0.35.7
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
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @plitzi/sdk-shared
|
|
2
2
|
|
|
3
|
+
## 0.35.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- An SMTP failure says which credential it was, and a credential's values can be replaced from the builder.
|
|
8
|
+
|
|
9
|
+
- **`email.send` names the credential it could not send through:** `Could not send through the SMTP credential
|
|
10
|
+
"ceniza-smtp": its SMTP host is on a private network…`. The host used to be in the sentence, and a run's trace
|
|
11
|
+
redacts every value of a credential it resolved, so the message read `The SMTP host "«redacted»"…`.
|
|
12
|
+
- **Credentials can be edited in the builder.** A pencil on each row opens the form with the name and the provider
|
|
13
|
+
fixed and nothing it holds shown: every value is entered again, and saving replaces all of them. SMTP credentials
|
|
14
|
+
are also labelled in the list.
|
|
15
|
+
|
|
16
|
+
## 0.35.6
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- A failed server action can give back what it already did.
|
|
21
|
+
|
|
22
|
+
- **`flow.onFailure` ("On Failure") marks where the undo begins.** A run that reaches it has succeeded and ends there.
|
|
23
|
+
A run whose step failed jumps to it and runs the steps after it, in order, each still asking its own `when` — the
|
|
24
|
+
failure may have come before the thing to undo was ever done — with `{{ failure.step }}` and `{{ failure.message }}`
|
|
25
|
+
in scope. The run still ends failed, with the failure it had; an undo step that fails too is added to it.
|
|
26
|
+
- **The undo runs on its own clock and budget:** 5 seconds (or the run's own timeout if shorter) and its own outbound
|
|
27
|
+
request budget, because the run's may be exactly what ran out, and a caller closing the connection does not stop it.
|
|
28
|
+
A run that hit its deadline is undone too.
|
|
29
|
+
- **`defineAction` writes it from `onFailure: [...]`**, after the answer. `validateActionDocument` refuses an output
|
|
30
|
+
step or a second handler after one, warns about a handler with nothing to undo or nothing that undoes, and reserves
|
|
31
|
+
`failure` as a step id. `FAILURE_HANDLER_TASK` is exported from `@plitzi/sdk-shared/actions`.
|
|
32
|
+
|
|
3
33
|
## 0.35.5
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The step that marks where a server action's undo begins.
|
|
3
|
+
*
|
|
4
|
+
* Steps after it run only when a step before it failed, so an action can give back what it already did — seats it took,
|
|
5
|
+
* a row it wrote — instead of leaving it behind a failure. Named once because four places read it: the runner that jumps
|
|
6
|
+
* to it, the validator that checks where it sits, the authoring API that writes it and the task catalog that offers it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const FAILURE_HANDLER_TASK = "flow.onFailure";
|
package/dist/actions/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { cronMatches, isKnownTimeZone, parseCron, zonedClock } from './cron';
|
|
2
|
+
export { FAILURE_HANDLER_TASK } from './failureHandler';
|
|
2
3
|
export { triggerAccess, triggerCacheMs, triggerHasStaleVerify, triggerInput, triggerVerify } from './triggerParams';
|
|
3
4
|
export { actionName, actionTriggers, isActionEnabled } from './triggers';
|
|
4
5
|
export { validateActionDocument } from './validateDocument';
|
package/dist/actions/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cronMatches as e, isKnownTimeZone as t, parseCron as n, zonedClock as r } from "./cron.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { FAILURE_HANDLER_TASK as i } from "./failureHandler.mjs";
|
|
3
|
+
import { triggerAccess as a, triggerCacheMs as o, triggerHasStaleVerify as s, triggerInput as c, triggerVerify as l } from "./triggerParams.mjs";
|
|
4
|
+
import { actionName as u, actionTriggers as d, isActionEnabled as f } from "./triggers.mjs";
|
|
5
|
+
import { validateActionDocument as p } from "./validateDocument.mjs";
|
|
6
|
+
import { SMTP_CREDENTIAL_KEYS as m, isSingleEmailAddress as h, readSmtpCredential as g } from "./smtp.mjs";
|
|
7
|
+
export { i as FAILURE_HANDLER_TASK, m as SMTP_CREDENTIAL_KEYS, u as actionName, d as actionTriggers, e as cronMatches, f as isActionEnabled, t as isKnownTimeZone, h as isSingleEmailAddress, n as parseCron, g as readSmtpCredential, a as triggerAccess, o as triggerCacheMs, s as triggerHasStaleVerify, c as triggerInput, l as triggerVerify, p as validateActionDocument, r as zonedClock };
|
|
@@ -1,41 +1,43 @@
|
|
|
1
1
|
import { isKnownTimeZone as e, parseCron as t } from "./cron.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { FAILURE_HANDLER_TASK as n } from "./failureHandler.mjs";
|
|
3
|
+
import { triggerAccess as r, triggerHasStaleVerify as i, triggerVerify as a } from "./triggerParams.mjs";
|
|
3
4
|
//#region src/actions/validateDocument.ts
|
|
4
|
-
var
|
|
5
|
+
var o = [
|
|
5
6
|
"text",
|
|
6
7
|
"number",
|
|
7
8
|
"boolean",
|
|
8
9
|
"date",
|
|
9
10
|
"json",
|
|
10
11
|
"file"
|
|
11
|
-
],
|
|
12
|
+
], s = [
|
|
12
13
|
"public",
|
|
13
14
|
"session",
|
|
14
15
|
"role"
|
|
15
|
-
],
|
|
16
|
+
], c = [
|
|
16
17
|
"call",
|
|
17
18
|
"webhook",
|
|
18
19
|
"schedule",
|
|
19
20
|
"render",
|
|
20
21
|
"custom"
|
|
21
|
-
],
|
|
22
|
+
], l = ["sha256", "sha1"], u = /* @__PURE__ */ new Set([
|
|
22
23
|
"input",
|
|
23
24
|
"user",
|
|
24
25
|
"spaceId",
|
|
25
26
|
"environment",
|
|
26
27
|
"trigger",
|
|
27
28
|
"runId",
|
|
28
|
-
"now"
|
|
29
|
-
|
|
29
|
+
"now",
|
|
30
|
+
"failure"
|
|
31
|
+
]), d = /^[a-z][a-zA-Z0-9]*\.[a-z][a-zA-Z0-9]*$/, f = (e) => typeof e == "object" && !!e && !Array.isArray(e), p = (e) => typeof e == "string" && e.trim() !== "", m = (e) => {
|
|
30
32
|
try {
|
|
31
33
|
let t = JSON.parse(e);
|
|
32
|
-
return
|
|
34
|
+
return f(t) ? t : void 0;
|
|
33
35
|
} catch {
|
|
34
36
|
return;
|
|
35
37
|
}
|
|
36
|
-
},
|
|
38
|
+
}, h = (e, t, n) => {
|
|
37
39
|
if (e !== void 0) {
|
|
38
|
-
if (!
|
|
40
|
+
if (!f(e)) {
|
|
39
41
|
n.push({
|
|
40
42
|
path: t,
|
|
41
43
|
message: "must be an object of field definitions"
|
|
@@ -43,215 +45,245 @@ var a = [
|
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
45
47
|
Object.entries(e).forEach(([e, r]) => {
|
|
46
|
-
if (!
|
|
48
|
+
if (!f(r) || !p(r.type)) {
|
|
47
49
|
n.push({
|
|
48
50
|
path: `${t}.${e}`,
|
|
49
51
|
message: "must declare a type"
|
|
50
52
|
});
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
|
-
|
|
55
|
+
o.includes(r.type) || n.push({
|
|
54
56
|
path: `${t}.${e}.type`,
|
|
55
57
|
message: `unknown field type "${r.type}"`,
|
|
56
|
-
hint: `one of ${
|
|
58
|
+
hint: `one of ${o.join(", ")}`
|
|
57
59
|
});
|
|
58
60
|
});
|
|
59
61
|
}
|
|
60
|
-
},
|
|
61
|
-
let g = `nodes.${
|
|
62
|
-
if (!
|
|
62
|
+
}, g = (n, o, u, d) => {
|
|
63
|
+
let g = `nodes.${n}`, _ = o.action;
|
|
64
|
+
if (!p(_) || !c.includes(_)) {
|
|
63
65
|
u.push({
|
|
64
66
|
path: `${g}.action`,
|
|
65
67
|
message: `"${String(_)}" is not a way an action can be started`,
|
|
66
|
-
hint: `one of ${
|
|
68
|
+
hint: `one of ${c.join(", ")}`
|
|
67
69
|
});
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
|
-
let v =
|
|
71
|
-
if (
|
|
72
|
-
let e =
|
|
72
|
+
let v = f(o.params) ? o.params : {};
|
|
73
|
+
if (p(v.input)) {
|
|
74
|
+
let e = m(v.input);
|
|
73
75
|
e === void 0 ? u.push({
|
|
74
76
|
path: `${g}.params.input`,
|
|
75
77
|
message: "is not valid JSON"
|
|
76
|
-
}) :
|
|
78
|
+
}) : h(e, `${g}.params.input`, u);
|
|
77
79
|
}
|
|
78
80
|
if (_ !== "schedule") {
|
|
79
|
-
if (!
|
|
81
|
+
if (!p(v.access) || !s.includes(v.access)) u.push({
|
|
80
82
|
path: `${g}.params.access`,
|
|
81
83
|
message: "must say who may start a run this way",
|
|
82
|
-
hint: `one of ${
|
|
84
|
+
hint: `one of ${s.join(", ")}`
|
|
83
85
|
});
|
|
84
86
|
else if (v.access === "role") {
|
|
85
|
-
let e =
|
|
87
|
+
let e = r(v);
|
|
86
88
|
e?.mode === "role" && e.permissions.length === 0 && u.push({
|
|
87
89
|
path: `${g}.params.permissions`,
|
|
88
90
|
message: "role access must name at least one permission"
|
|
89
91
|
});
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
|
-
if (_ === "schedule" && (
|
|
94
|
+
if (_ === "schedule" && (p(v.cron) ? t(v.cron) || u.push({
|
|
93
95
|
path: `${g}.params.cron`,
|
|
94
96
|
message: `"${v.cron}" is not an expression this server can read, so it would never fire`,
|
|
95
97
|
hint: "five fields — minute hour day-of-month month day-of-week — with *, lists, ranges and steps"
|
|
96
98
|
}) : u.push({
|
|
97
99
|
path: `${g}.params.cron`,
|
|
98
100
|
message: "a scheduled trigger needs a cron expression"
|
|
99
|
-
}),
|
|
101
|
+
}), p(v.timezone) && !e(v.timezone) && u.push({
|
|
100
102
|
path: `${g}.params.timezone`,
|
|
101
103
|
message: `"${v.timezone}" is not a time zone this server knows, so the schedule would never fire`,
|
|
102
104
|
hint: "an IANA name like America/Santiago or Europe/Madrid — leave it empty for UTC"
|
|
103
|
-
})),
|
|
105
|
+
})), p(v.cacheSeconds)) {
|
|
104
106
|
let e = Number.parseFloat(v.cacheSeconds);
|
|
105
107
|
!Number.isFinite(e) || e < 0 ? u.push({
|
|
106
108
|
path: `${g}.params.cacheSeconds`,
|
|
107
109
|
message: "must be a number of seconds, or left empty"
|
|
108
|
-
}) : _ !== "render" &&
|
|
110
|
+
}) : _ !== "render" && d.push({
|
|
109
111
|
path: `${g}.params.cacheSeconds`,
|
|
110
112
|
message: `a "${_}" trigger is never answered from a cache`,
|
|
111
113
|
hint: "reuse only applies to a render, where the same page is built for one visitor after another"
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
|
-
_ === "custom" && !
|
|
116
|
+
_ === "custom" && !p(v.name) && u.push({
|
|
115
117
|
path: `${g}.params.name`,
|
|
116
118
|
message: "a custom trigger needs a name to be mounted under"
|
|
117
|
-
}), _ === "webhook" && (
|
|
119
|
+
}), _ === "webhook" && (i(v) && u.push({
|
|
118
120
|
path: `${g}.params.signatureCredential`,
|
|
119
121
|
message: "this signature check is in a format nothing reads any more, so the webhook is unverified",
|
|
120
122
|
hint: "name the credential holding the signing secret in \"Signing secret\", and its header beside it"
|
|
121
|
-
}),
|
|
123
|
+
}), a(v) || d.push({
|
|
122
124
|
path: `${g}.params.signatureCredential`,
|
|
123
125
|
message: "this webhook accepts unsigned requests",
|
|
124
126
|
hint: "name the credential holding the signing secret, and only the sender you expect can start a run"
|
|
125
|
-
}),
|
|
127
|
+
}), p(v.signatureAlgorithm) && !l.includes(v.signatureAlgorithm) && d.push({
|
|
126
128
|
path: `${g}.params.signatureAlgorithm`,
|
|
127
129
|
message: `"${v.signatureAlgorithm}" is not an algorithm this server signs with, so sha256 is used`,
|
|
128
|
-
hint: `one of ${
|
|
129
|
-
}),
|
|
130
|
+
hint: `one of ${l.join(", ")}`
|
|
131
|
+
}), p(v.signatureToleranceSeconds) && !p(v.signatureTimestampHeader) && d.push({
|
|
130
132
|
path: `${g}.params.signatureToleranceSeconds`,
|
|
131
133
|
message: "a tolerance with no timestamp header expires nothing",
|
|
132
134
|
hint: "name the header the sender puts the signing time in, or drop the tolerance"
|
|
133
|
-
})), _ === "call" && v.access === "public" &&
|
|
135
|
+
})), _ === "call" && v.access === "public" && d.push({
|
|
134
136
|
path: `${g}.params.access`,
|
|
135
137
|
message: "anyone can run this action, including signed-out visitors",
|
|
136
138
|
hint: "use session access unless the page needs it before anyone signs in"
|
|
137
139
|
});
|
|
138
|
-
},
|
|
139
|
-
if (!
|
|
140
|
-
|
|
140
|
+
}, _ = (e, t, r, i) => {
|
|
141
|
+
if (!f(e)) {
|
|
142
|
+
r.push({
|
|
141
143
|
path: "nodes",
|
|
142
144
|
message: "must be an object of steps"
|
|
143
145
|
});
|
|
144
146
|
return;
|
|
145
147
|
}
|
|
146
|
-
let
|
|
147
|
-
|
|
148
|
+
let a = Object.entries(e), o = a.filter(([, e]) => f(e) && e.type === "trigger");
|
|
149
|
+
o.length === 0 && r.push({
|
|
148
150
|
path: "nodes",
|
|
149
151
|
message: "this action has no way in",
|
|
150
152
|
hint: "add a trigger step — call, webhook, schedule, render or custom"
|
|
151
153
|
});
|
|
152
|
-
let
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}),
|
|
156
|
-
e.length > 1 &&
|
|
154
|
+
let s = /* @__PURE__ */ new Map();
|
|
155
|
+
o.forEach(([e, t]) => {
|
|
156
|
+
p(t.action) && s.set(t.action, [...s.get(t.action) ?? [], e]);
|
|
157
|
+
}), s.forEach((e, t) => {
|
|
158
|
+
e.length > 1 && r.push({
|
|
157
159
|
path: `nodes.${e[1]}`,
|
|
158
160
|
message: `this action has ${e.length} "${t}" triggers`,
|
|
159
161
|
hint: "one step per way in — a second flow starts from a different kind of trigger"
|
|
160
162
|
});
|
|
161
|
-
}),
|
|
163
|
+
}), a.forEach(([t, n]) => {
|
|
162
164
|
let a = `nodes.${t}`;
|
|
163
|
-
if (!
|
|
164
|
-
|
|
165
|
+
if (!f(n)) {
|
|
166
|
+
r.push({
|
|
165
167
|
path: a,
|
|
166
168
|
message: "must be an object"
|
|
167
169
|
});
|
|
168
170
|
return;
|
|
169
171
|
}
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
+
if (n.type === "trigger") {
|
|
173
|
+
g(t, n, r, i);
|
|
172
174
|
return;
|
|
173
175
|
}
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
+
if (n.type !== "task") {
|
|
177
|
+
r.push({
|
|
176
178
|
path: `${a}.type`,
|
|
177
|
-
message: `"${String(
|
|
179
|
+
message: `"${String(n.type)}" steps run in the browser and cannot run on the server`,
|
|
178
180
|
hint: "a server action is made of task steps"
|
|
179
181
|
});
|
|
180
182
|
return;
|
|
181
183
|
}
|
|
182
|
-
if (!
|
|
183
|
-
|
|
184
|
+
if (!p(n.action) || !d.test(n.action)) {
|
|
185
|
+
r.push({
|
|
184
186
|
path: `${a}.action`,
|
|
185
187
|
message: "must name a task as <namespace>.<action>",
|
|
186
188
|
hint: "for example flow.output or http.request"
|
|
187
189
|
});
|
|
188
190
|
return;
|
|
189
191
|
}
|
|
190
|
-
|
|
192
|
+
p(n.afterNode) && !Object.hasOwn(e, n.afterNode) && r.push({
|
|
191
193
|
path: `${a}.afterNode`,
|
|
192
|
-
message: `points at "${
|
|
194
|
+
message: `points at "${n.afterNode}", which is not a step here`
|
|
193
195
|
});
|
|
194
|
-
}),
|
|
195
|
-
|
|
196
|
+
}), a.forEach(([e]) => {
|
|
197
|
+
u.has(e) && r.push({
|
|
196
198
|
path: `nodes.${e}`,
|
|
197
199
|
message: `"${e}" is what the run itself publishes in the flow scope, so a step may not take the name`,
|
|
198
200
|
hint: `rename the step — every later step reads {{ ${e} }} expecting the run's own value`
|
|
199
201
|
});
|
|
200
202
|
});
|
|
201
|
-
let
|
|
202
|
-
|
|
203
|
-
let n = /* @__PURE__ */ new Set(), r = t;
|
|
204
|
-
for (;
|
|
205
|
-
if (n.has(
|
|
206
|
-
|
|
203
|
+
let c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set(), m = [];
|
|
204
|
+
o.forEach(([t]) => {
|
|
205
|
+
let n = /* @__PURE__ */ new Set(), r = [], i = t;
|
|
206
|
+
for (; i;) {
|
|
207
|
+
if (n.has(i)) {
|
|
208
|
+
l.add(i);
|
|
207
209
|
break;
|
|
208
210
|
}
|
|
209
|
-
n.add(r),
|
|
210
|
-
let t = e[
|
|
211
|
-
|
|
211
|
+
n.add(i), r.push(i), c.add(i);
|
|
212
|
+
let t = e[i];
|
|
213
|
+
i = p(t?.afterNode) ? t.afterNode : "";
|
|
212
214
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
+
m.push(r);
|
|
216
|
+
}), l.forEach((e) => {
|
|
217
|
+
r.push({
|
|
215
218
|
path: `nodes.${e}`,
|
|
216
219
|
message: "this step is reached again by its own chain, so the flow never ends",
|
|
217
220
|
hint: "break the `afterNode` chain that comes back to it"
|
|
218
221
|
});
|
|
219
|
-
}),
|
|
220
|
-
|
|
222
|
+
}), a.forEach(([e]) => {
|
|
223
|
+
c.has(e) || i.push({
|
|
221
224
|
path: `nodes.${e}`,
|
|
222
225
|
message: "no trigger reaches this step, so it never runs",
|
|
223
226
|
hint: "chain it with `afterNode` from a trigger, or delete it"
|
|
224
227
|
});
|
|
225
228
|
});
|
|
226
|
-
let
|
|
227
|
-
for (let [t, n] of
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
let h = (t) => e[t]?.action, _ = a.filter(([, e]) => f(e) && e.action === "flow.output");
|
|
230
|
+
for (let [t, n] of _) {
|
|
231
|
+
let r = p(n.afterNode) && h(n.afterNode) === "flow.onFailure";
|
|
232
|
+
p(n.afterNode) && Object.hasOwn(e, n.afterNode) && !r && i.push({
|
|
233
|
+
path: `nodes.${t}.afterNode`,
|
|
234
|
+
message: "the output step is not the last one, so the steps after it run for nothing",
|
|
235
|
+
hint: "move flow.output to the end of the flow"
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
let v = /* @__PURE__ */ new Set(), y = (e, t) => {
|
|
239
|
+
v.has(`${t.path}|${t.message}`) || (v.add(`${t.path}|${t.message}`), e.push(t));
|
|
240
|
+
};
|
|
241
|
+
m.forEach((e) => {
|
|
242
|
+
let t = e.findIndex((e) => h(e) === n);
|
|
243
|
+
if (t === -1) return;
|
|
244
|
+
let a = e[t];
|
|
245
|
+
t === 1 && y(i, {
|
|
246
|
+
path: `nodes.${a}`,
|
|
247
|
+
message: "nothing runs before this step, so nothing can fail and the steps after it never run",
|
|
248
|
+
hint: "put On Failure after the steps whose work it undoes"
|
|
249
|
+
}), t === e.length - 1 && y(i, {
|
|
250
|
+
path: `nodes.${a}`,
|
|
251
|
+
message: "nothing follows this step, so a failed run undoes nothing",
|
|
252
|
+
hint: "add the steps that give back what the flow already did"
|
|
253
|
+
}), e.slice(t + 1).forEach((e) => {
|
|
254
|
+
h(e) === "flow.onFailure" && y(r, {
|
|
255
|
+
path: `nodes.${e}`,
|
|
256
|
+
message: "a flow has one place its undo begins, and this is a second one",
|
|
257
|
+
hint: "keep one On Failure step and put every undo step after it"
|
|
258
|
+
}), h(e) === "flow.output" && y(r, {
|
|
259
|
+
path: `nodes.${e}`,
|
|
260
|
+
message: "an output step after On Failure answers a run that has already failed",
|
|
261
|
+
hint: "move flow.output before On Failure"
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
}), _.length === 0 && f(t) && Object.keys(t).length > 0 && i.push({
|
|
233
265
|
path: "nodes",
|
|
234
266
|
message: "this action is expected to answer values but no step names any",
|
|
235
267
|
hint: "add a flow.output step at the end naming what the caller should get"
|
|
236
268
|
});
|
|
237
|
-
},
|
|
269
|
+
}, v = /\{\{\s*credential\./, y = (e, t) => {
|
|
238
270
|
Object.entries(e).forEach(([e, n]) => {
|
|
239
|
-
if (!
|
|
240
|
-
let r =
|
|
271
|
+
if (!f(n) || !f(n.params)) return;
|
|
272
|
+
let r = p(n.params.credential) ? n.params.credential : "";
|
|
241
273
|
Object.entries(n.params).forEach(([n, i]) => {
|
|
242
|
-
typeof i == "string" &&
|
|
274
|
+
typeof i == "string" && v.test(i) && r === "" && t.push({
|
|
243
275
|
path: `nodes.${e}.params.${n}`,
|
|
244
276
|
message: "this step reads a credential it did not ask for, so the token resolves to nothing",
|
|
245
277
|
hint: "set the step’s `credential` to the identifier it should use"
|
|
246
278
|
});
|
|
247
279
|
});
|
|
248
280
|
});
|
|
249
|
-
},
|
|
281
|
+
}, b = (e) => {
|
|
250
282
|
let t = [], n = [];
|
|
251
|
-
return
|
|
283
|
+
return f(e) ? (p(e.name) || t.push({
|
|
252
284
|
path: "name",
|
|
253
285
|
message: "must have a name"
|
|
254
|
-
}),
|
|
286
|
+
}), h(e.output, "output", t), _(e.nodes, e.output, t, n), y(f(e.nodes) ? e.nodes : {}, n), {
|
|
255
287
|
valid: t.length === 0,
|
|
256
288
|
errors: t,
|
|
257
289
|
warnings: n
|
|
@@ -265,4 +297,4 @@ var a = [
|
|
|
265
297
|
};
|
|
266
298
|
};
|
|
267
299
|
//#endregion
|
|
268
|
-
export {
|
|
300
|
+
export { b as validateActionDocument };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-shared",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.7",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
"types": "./dist/actions/cron.d.ts",
|
|
23
23
|
"import": "./dist/actions/cron.mjs"
|
|
24
24
|
},
|
|
25
|
+
"./actions/failureHandler": {
|
|
26
|
+
"types": "./dist/actions/failureHandler.d.ts",
|
|
27
|
+
"import": "./dist/actions/failureHandler.mjs"
|
|
28
|
+
},
|
|
25
29
|
"./actions/index": {
|
|
26
30
|
"types": "./dist/actions/index.d.ts",
|
|
27
31
|
"import": "./dist/actions/index.mjs"
|