@apifuse/provider-sdk 2.2.0-beta.37 → 2.2.0-beta.39
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 +8 -0
- package/dist/declaration-validation.d.ts +9 -0
- package/dist/declaration-validation.js +51 -3
- package/dist/define.d.ts +2 -2
- package/dist/define.js +37 -22
- package/dist/health-scenario.d.ts +1842 -0
- package/dist/health-scenario.js +624 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/provider.d.ts +3 -0
- package/dist/provider.js +1 -0
- package/dist/runtime/executor.d.ts +2 -2
- package/dist/runtime/executor.js +3 -1
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +41 -1
- package/dist/runtime/proxy-telemetry.js +59 -56
- package/dist/server/index.d.ts +2 -0
- package/dist/server/serve-implementation.d.ts +3 -1
- package/dist/server/serve-implementation.js +81 -30
- package/dist/server/types.d.ts +4 -4
- package/dist/types.d.ts +10 -8
- package/package.json +1 -1
- package/src/declaration-validation.ts +71 -7
- package/src/define.ts +61 -38
- package/src/health-scenario.ts +875 -0
- package/src/index.ts +78 -0
- package/src/provider.ts +75 -0
- package/src/runtime/executor.ts +11 -6
- package/src/runtime/instrumentation.ts +5 -2
- package/src/runtime/proxy-telemetry.ts +100 -99
- package/src/server/index.ts +8 -0
- package/src/server/serve-implementation.ts +90 -8
- package/src/types.ts +11 -8
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const finiteInt = (min, max) => {
|
|
3
|
+
const schema = z.number().finite().int().min(min);
|
|
4
|
+
return max === undefined ? schema : schema.max(max);
|
|
5
|
+
};
|
|
6
|
+
const nonEmptyArray = (schema) => z
|
|
7
|
+
.array(schema)
|
|
8
|
+
.min(1)
|
|
9
|
+
.transform((value) => value);
|
|
10
|
+
const jsonValueSchema = z.lazy(() => z.union([
|
|
11
|
+
z.null(),
|
|
12
|
+
z.boolean(),
|
|
13
|
+
z.number().finite(),
|
|
14
|
+
z.string(),
|
|
15
|
+
z.array(jsonValueSchema),
|
|
16
|
+
z.record(z.string(), jsonValueSchema),
|
|
17
|
+
]));
|
|
18
|
+
const pathPartSchema = z.union([z.string().min(1), finiteInt(0, 10_000)]);
|
|
19
|
+
const propertyNameSchema = z
|
|
20
|
+
.string()
|
|
21
|
+
.min(1)
|
|
22
|
+
.superRefine((value, ctx) => {
|
|
23
|
+
if (new TextEncoder().encode(value).byteLength > 128)
|
|
24
|
+
ctx.addIssue({ code: "custom", message: "property name exceeds 128 UTF-8 bytes" });
|
|
25
|
+
});
|
|
26
|
+
const pathSegmentSchema = z.union([
|
|
27
|
+
z.object({ kind: z.literal("property"), name: propertyNameSchema }).strict(),
|
|
28
|
+
z.object({ kind: z.literal("index"), index: finiteInt(0, 10_000) }).strict(),
|
|
29
|
+
]);
|
|
30
|
+
export const BoundedJsonPathSchema = z
|
|
31
|
+
.object({ root: z.literal("$"), segments: z.array(pathSegmentSchema).max(12) })
|
|
32
|
+
.strict();
|
|
33
|
+
const valueTypeSchema = z.enum([
|
|
34
|
+
"null",
|
|
35
|
+
"boolean",
|
|
36
|
+
"number",
|
|
37
|
+
"string",
|
|
38
|
+
"object",
|
|
39
|
+
"array",
|
|
40
|
+
"json",
|
|
41
|
+
"established_connection",
|
|
42
|
+
]);
|
|
43
|
+
export const ValueTypeSchema = valueTypeSchema;
|
|
44
|
+
const stepReferenceSchema = z
|
|
45
|
+
.object({
|
|
46
|
+
namespace: z.literal("steps"),
|
|
47
|
+
binding: z.string().min(1),
|
|
48
|
+
path: z.array(pathPartSchema).min(1).max(12),
|
|
49
|
+
})
|
|
50
|
+
.strict();
|
|
51
|
+
export const StepReferenceSchema = stepReferenceSchema;
|
|
52
|
+
const credentialReferenceSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
namespace: z.literal("credentials"),
|
|
55
|
+
alias: z.string().min(1),
|
|
56
|
+
field: z.literal("connection"),
|
|
57
|
+
})
|
|
58
|
+
.strict();
|
|
59
|
+
const attemptReferenceSchema = z
|
|
60
|
+
.object({
|
|
61
|
+
namespace: z.literal("attempt"),
|
|
62
|
+
field: z.enum([
|
|
63
|
+
"id",
|
|
64
|
+
"external_ref",
|
|
65
|
+
"provider_id",
|
|
66
|
+
"scenario_id",
|
|
67
|
+
"started_at",
|
|
68
|
+
"deadline_at",
|
|
69
|
+
]),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
const candidateReferenceSchema = z
|
|
73
|
+
.object({
|
|
74
|
+
namespace: z.literal("candidate"),
|
|
75
|
+
binding: z.string().min(1),
|
|
76
|
+
path: z.union([
|
|
77
|
+
z.tuple([z.literal("item")]).rest(pathPartSchema),
|
|
78
|
+
z.tuple([z.literal("result")]).rest(pathPartSchema),
|
|
79
|
+
]),
|
|
80
|
+
})
|
|
81
|
+
.strict();
|
|
82
|
+
const referenceSchema = z.discriminatedUnion("namespace", [
|
|
83
|
+
stepReferenceSchema,
|
|
84
|
+
credentialReferenceSchema,
|
|
85
|
+
attemptReferenceSchema,
|
|
86
|
+
candidateReferenceSchema,
|
|
87
|
+
]);
|
|
88
|
+
export const ReferenceSchema = referenceSchema;
|
|
89
|
+
const relativeDateNodeSchema = z
|
|
90
|
+
.object({
|
|
91
|
+
relativeDate: z
|
|
92
|
+
.object({
|
|
93
|
+
anchor: z.literal("operation_started_at"),
|
|
94
|
+
offsetDays: finiteInt(1, 365),
|
|
95
|
+
timeZone: z.literal("Asia/Seoul"),
|
|
96
|
+
format: z.enum(["YYYY-MM-DD", "YYYYMMDD"]),
|
|
97
|
+
})
|
|
98
|
+
.strict(),
|
|
99
|
+
})
|
|
100
|
+
.strict();
|
|
101
|
+
export const RelativeDateNodeSchema = relativeDateNodeSchema;
|
|
102
|
+
const referenceNodeSchema = z.object({ ref: referenceSchema }).strict();
|
|
103
|
+
// Reserved template keys may only occur in their exact, single-key node forms.
|
|
104
|
+
const templateRecordSchema = z
|
|
105
|
+
.record(z.string(), z.lazy(() => jsonTemplateSchema))
|
|
106
|
+
.superRefine((value, ctx) => {
|
|
107
|
+
if (Object.hasOwn(value, "ref") || Object.hasOwn(value, "relativeDate"))
|
|
108
|
+
ctx.addIssue({ code: "custom", message: "reserved template keys require a sole-key node" });
|
|
109
|
+
});
|
|
110
|
+
const jsonTemplateSchema = z.lazy(() => z.union([
|
|
111
|
+
z.null(),
|
|
112
|
+
z.boolean(),
|
|
113
|
+
z.number().finite(),
|
|
114
|
+
z.string(),
|
|
115
|
+
referenceNodeSchema,
|
|
116
|
+
relativeDateNodeSchema,
|
|
117
|
+
z.array(jsonTemplateSchema),
|
|
118
|
+
templateRecordSchema,
|
|
119
|
+
]));
|
|
120
|
+
export const JsonTemplateSchema = jsonTemplateSchema;
|
|
121
|
+
function containsNestedRegexQuantifier(pattern) {
|
|
122
|
+
const groups = [];
|
|
123
|
+
let escaped = false;
|
|
124
|
+
let inClass = false;
|
|
125
|
+
let closedQuantified = false;
|
|
126
|
+
for (let i = 0; i < pattern.length; i += 1) {
|
|
127
|
+
const c = pattern[i];
|
|
128
|
+
if (escaped) {
|
|
129
|
+
escaped = false;
|
|
130
|
+
closedQuantified = false;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (c === "\\") {
|
|
134
|
+
escaped = true;
|
|
135
|
+
closedQuantified = false;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (c === "[" && !inClass) {
|
|
139
|
+
inClass = true;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (c === "]" && inClass) {
|
|
143
|
+
inClass = false;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (inClass)
|
|
147
|
+
continue;
|
|
148
|
+
if (c === "(") {
|
|
149
|
+
groups.push(false);
|
|
150
|
+
closedQuantified = false;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (c === ")") {
|
|
154
|
+
closedQuantified = groups.pop() ?? false;
|
|
155
|
+
if (closedQuantified && groups.length > 0)
|
|
156
|
+
groups[groups.length - 1] = true;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const brace = c === "{" && /^\{\d+(?:,\d*)?\}/.test(pattern.slice(i));
|
|
160
|
+
if (c === "*" || c === "+" || brace || (c === "?" && pattern[i - 1] !== "(")) {
|
|
161
|
+
if (closedQuantified)
|
|
162
|
+
return true;
|
|
163
|
+
if (groups.length > 0)
|
|
164
|
+
groups[groups.length - 1] = true;
|
|
165
|
+
}
|
|
166
|
+
closedQuantified = false;
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
export const SafeRegexSchema = z
|
|
171
|
+
.object({ engine: z.literal("re2"), pattern: z.string().max(256), flags: z.enum(["", "i"]) })
|
|
172
|
+
.strict()
|
|
173
|
+
.superRefine((value, ctx) => {
|
|
174
|
+
if (/\\[1-9kg]/.test(value.pattern))
|
|
175
|
+
ctx.addIssue({ code: "custom", path: ["pattern"], message: "backreferences are not supported by RE2" });
|
|
176
|
+
if (/\(\?/.test(value.pattern))
|
|
177
|
+
ctx.addIssue({ code: "custom", path: ["pattern"], message: "extended groups are not supported by RE2" });
|
|
178
|
+
if (containsNestedRegexQuantifier(value.pattern))
|
|
179
|
+
ctx.addIssue({ code: "custom", path: ["pattern"], message: "nested regex quantifiers are not permitted" });
|
|
180
|
+
try {
|
|
181
|
+
new RegExp(value.pattern, value.flags);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
ctx.addIssue({ code: "custom", path: ["pattern"], message: "pattern must be valid regular-expression syntax" });
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
const operandLiteralSchema = jsonValueSchema.superRefine((value, ctx) => {
|
|
188
|
+
if (value !== null &&
|
|
189
|
+
typeof value === "object" &&
|
|
190
|
+
!Array.isArray(value) &&
|
|
191
|
+
Object.hasOwn(value, "ref"))
|
|
192
|
+
ctx.addIssue({
|
|
193
|
+
code: "custom",
|
|
194
|
+
message: 'the object key "ref" is reserved for a validated reference',
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
const operandSchema = z.union([operandLiteralSchema, referenceNodeSchema]);
|
|
198
|
+
export const OperandSchema = operandSchema;
|
|
199
|
+
const predicateSchema = z.union([
|
|
200
|
+
z
|
|
201
|
+
.object({
|
|
202
|
+
kind: z.literal("predicate"),
|
|
203
|
+
operator: z.enum(["exists", "not_exists", "non_empty", "is_true"]),
|
|
204
|
+
actual: operandSchema,
|
|
205
|
+
})
|
|
206
|
+
.strict(),
|
|
207
|
+
z
|
|
208
|
+
.object({
|
|
209
|
+
kind: z.literal("predicate"),
|
|
210
|
+
operator: z.enum(["equals", "not_equals", "contains"]),
|
|
211
|
+
actual: operandSchema,
|
|
212
|
+
expected: operandSchema,
|
|
213
|
+
})
|
|
214
|
+
.strict(),
|
|
215
|
+
z
|
|
216
|
+
.object({
|
|
217
|
+
kind: z.literal("predicate"),
|
|
218
|
+
operator: z.literal("matches"),
|
|
219
|
+
actual: operandSchema,
|
|
220
|
+
pattern: SafeRegexSchema,
|
|
221
|
+
})
|
|
222
|
+
.strict(),
|
|
223
|
+
z
|
|
224
|
+
.object({
|
|
225
|
+
kind: z.literal("predicate"),
|
|
226
|
+
operator: z.enum(["number_gt", "number_gte", "number_lt", "number_lte"]),
|
|
227
|
+
actual: operandSchema,
|
|
228
|
+
expected: operandSchema,
|
|
229
|
+
})
|
|
230
|
+
.strict(),
|
|
231
|
+
z
|
|
232
|
+
.object({
|
|
233
|
+
kind: z.literal("predicate"),
|
|
234
|
+
operator: z.enum(["array_length_eq", "array_length_gte", "array_length_lte"]),
|
|
235
|
+
actual: operandSchema,
|
|
236
|
+
expected: z.number().finite().int().nonnegative(),
|
|
237
|
+
})
|
|
238
|
+
.strict(),
|
|
239
|
+
z
|
|
240
|
+
.object({
|
|
241
|
+
kind: z.literal("predicate"),
|
|
242
|
+
operator: z.literal("status_2xx"),
|
|
243
|
+
actual: operandSchema,
|
|
244
|
+
})
|
|
245
|
+
.strict(),
|
|
246
|
+
z
|
|
247
|
+
.object({
|
|
248
|
+
kind: z.literal("predicate"),
|
|
249
|
+
operator: z.literal("type_is"),
|
|
250
|
+
actual: operandSchema,
|
|
251
|
+
expected: z.enum(["null", "boolean", "number", "string", "object", "array"]),
|
|
252
|
+
})
|
|
253
|
+
.strict(),
|
|
254
|
+
]);
|
|
255
|
+
export const AssertionPredicateSchema = predicateSchema;
|
|
256
|
+
const scopedItemReferenceSchema = z
|
|
257
|
+
.object({
|
|
258
|
+
namespace: z.literal("item"),
|
|
259
|
+
binding: z.string().min(1),
|
|
260
|
+
path: z.array(pathPartSchema).max(12),
|
|
261
|
+
})
|
|
262
|
+
.strict();
|
|
263
|
+
export const ScopedItemReferenceSchema = scopedItemReferenceSchema;
|
|
264
|
+
const scopedOperandSchema = z.union([
|
|
265
|
+
operandLiteralSchema,
|
|
266
|
+
z.object({ ref: scopedItemReferenceSchema }).strict(),
|
|
267
|
+
referenceNodeSchema,
|
|
268
|
+
]);
|
|
269
|
+
export const ScopedOperandSchema = scopedOperandSchema;
|
|
270
|
+
const scopedPredicateSchema = z.union([
|
|
271
|
+
z
|
|
272
|
+
.object({
|
|
273
|
+
kind: z.literal("predicate"),
|
|
274
|
+
operator: z.enum(["exists", "not_exists", "non_empty", "is_true"]),
|
|
275
|
+
actual: scopedOperandSchema,
|
|
276
|
+
})
|
|
277
|
+
.strict(),
|
|
278
|
+
z
|
|
279
|
+
.object({
|
|
280
|
+
kind: z.literal("predicate"),
|
|
281
|
+
operator: z.enum(["equals", "not_equals", "contains"]),
|
|
282
|
+
actual: scopedOperandSchema,
|
|
283
|
+
expected: scopedOperandSchema,
|
|
284
|
+
})
|
|
285
|
+
.strict(),
|
|
286
|
+
z
|
|
287
|
+
.object({
|
|
288
|
+
kind: z.literal("predicate"),
|
|
289
|
+
operator: z.literal("matches"),
|
|
290
|
+
actual: scopedOperandSchema,
|
|
291
|
+
pattern: SafeRegexSchema,
|
|
292
|
+
})
|
|
293
|
+
.strict(),
|
|
294
|
+
z
|
|
295
|
+
.object({
|
|
296
|
+
kind: z.literal("predicate"),
|
|
297
|
+
operator: z.enum(["number_gt", "number_gte", "number_lt", "number_lte"]),
|
|
298
|
+
actual: scopedOperandSchema,
|
|
299
|
+
expected: scopedOperandSchema,
|
|
300
|
+
})
|
|
301
|
+
.strict(),
|
|
302
|
+
z
|
|
303
|
+
.object({
|
|
304
|
+
kind: z.literal("predicate"),
|
|
305
|
+
operator: z.enum(["array_length_eq", "array_length_gte", "array_length_lte"]),
|
|
306
|
+
actual: scopedOperandSchema,
|
|
307
|
+
expected: z.number().finite().int().nonnegative(),
|
|
308
|
+
})
|
|
309
|
+
.strict(),
|
|
310
|
+
z
|
|
311
|
+
.object({
|
|
312
|
+
kind: z.literal("predicate"),
|
|
313
|
+
operator: z.literal("status_2xx"),
|
|
314
|
+
actual: scopedOperandSchema,
|
|
315
|
+
})
|
|
316
|
+
.strict(),
|
|
317
|
+
z
|
|
318
|
+
.object({
|
|
319
|
+
kind: z.literal("predicate"),
|
|
320
|
+
operator: z.literal("type_is"),
|
|
321
|
+
actual: scopedOperandSchema,
|
|
322
|
+
expected: z.enum(["null", "boolean", "number", "string", "object", "array"]),
|
|
323
|
+
})
|
|
324
|
+
.strict(),
|
|
325
|
+
]);
|
|
326
|
+
export const ScopedAssertionPredicateSchema = scopedPredicateSchema;
|
|
327
|
+
const scopedExpressionSchema = z.lazy(() => z.union([
|
|
328
|
+
z.object({ kind: z.literal("all"), clauses: nonEmptyArray(scopedExpressionSchema) }).strict(),
|
|
329
|
+
z.object({ kind: z.literal("any"), clauses: nonEmptyArray(scopedExpressionSchema) }).strict(),
|
|
330
|
+
z.object({ kind: z.literal("not"), clause: scopedExpressionSchema }).strict(),
|
|
331
|
+
scopedPredicateSchema,
|
|
332
|
+
]));
|
|
333
|
+
export const ScopedAssertionExpressionSchema = scopedExpressionSchema;
|
|
334
|
+
const quantifierSchema = z
|
|
335
|
+
.object({
|
|
336
|
+
kind: z.literal("quantifier"),
|
|
337
|
+
quantifier: z.enum(["every", "any"]),
|
|
338
|
+
items: z.object({ ref: z.union([stepReferenceSchema, candidateReferenceSchema]) }).strict(),
|
|
339
|
+
itemBinding: z.string().min(1),
|
|
340
|
+
maxItems: finiteInt(1, 100),
|
|
341
|
+
clause: scopedExpressionSchema,
|
|
342
|
+
})
|
|
343
|
+
.strict();
|
|
344
|
+
export const QuantifierSchema = quantifierSchema;
|
|
345
|
+
const expressionSchema = z.lazy(() => z.union([
|
|
346
|
+
z.object({ kind: z.literal("all"), clauses: nonEmptyArray(expressionSchema) }).strict(),
|
|
347
|
+
z.object({ kind: z.literal("any"), clauses: nonEmptyArray(expressionSchema) }).strict(),
|
|
348
|
+
z.object({ kind: z.literal("not"), clause: expressionSchema }).strict(),
|
|
349
|
+
predicateSchema,
|
|
350
|
+
quantifierSchema,
|
|
351
|
+
]));
|
|
352
|
+
export const AssertionExpressionSchema = expressionSchema;
|
|
353
|
+
const retryPolicySchema = z
|
|
354
|
+
.object({
|
|
355
|
+
maxAttempts: finiteInt(1, 3),
|
|
356
|
+
retryOn: nonEmptyArray(z.enum(["transport_error", "timeout", "http_429", "http_5xx"])),
|
|
357
|
+
backoff: z.union([
|
|
358
|
+
z
|
|
359
|
+
.object({ kind: z.literal("fixed"), delayMs: z.number().finite().int().nonnegative() })
|
|
360
|
+
.strict(),
|
|
361
|
+
z
|
|
362
|
+
.object({
|
|
363
|
+
kind: z.literal("exponential"),
|
|
364
|
+
initialDelayMs: z.number().finite().int().nonnegative(),
|
|
365
|
+
maxDelayMs: z.number().finite().int().nonnegative(),
|
|
366
|
+
})
|
|
367
|
+
.strict(),
|
|
368
|
+
]),
|
|
369
|
+
attemptTimeoutMs: finiteInt(1, 600_000).optional(),
|
|
370
|
+
})
|
|
371
|
+
.strict();
|
|
372
|
+
export const RetryPolicySchema = retryPolicySchema;
|
|
373
|
+
const candidatePolicySchema = z
|
|
374
|
+
.object({
|
|
375
|
+
items: stepReferenceSchema,
|
|
376
|
+
itemBinding: z.string().min(1),
|
|
377
|
+
itemType: z.enum(["string", "number", "object"]),
|
|
378
|
+
maxAttempts: finiteInt(1, 10),
|
|
379
|
+
accept: expressionSchema,
|
|
380
|
+
})
|
|
381
|
+
.strict();
|
|
382
|
+
export const CandidatePolicySchema = candidatePolicySchema;
|
|
383
|
+
const candidateBlockSchema = z
|
|
384
|
+
.object({
|
|
385
|
+
scope: z.literal("step_block"),
|
|
386
|
+
items: stepReferenceSchema,
|
|
387
|
+
itemBinding: z.string().min(1),
|
|
388
|
+
itemType: z.enum(["string", "number", "object"]),
|
|
389
|
+
members: z
|
|
390
|
+
.array(z.string().min(1))
|
|
391
|
+
.min(2)
|
|
392
|
+
.max(16)
|
|
393
|
+
.transform((value) => value),
|
|
394
|
+
maxAttempts: finiteInt(1, 10),
|
|
395
|
+
accept: expressionSchema,
|
|
396
|
+
})
|
|
397
|
+
.strict();
|
|
398
|
+
export const CandidateBlockSchema = candidateBlockSchema;
|
|
399
|
+
const journalPolicySchema = z
|
|
400
|
+
.object({
|
|
401
|
+
kind: z.literal("side_effect_barrier"),
|
|
402
|
+
version: z.literal(1),
|
|
403
|
+
key: referenceSchema,
|
|
404
|
+
before: z.literal("required"),
|
|
405
|
+
after: z.literal("required"),
|
|
406
|
+
replay: z.literal("deny_after_started"),
|
|
407
|
+
})
|
|
408
|
+
.strict();
|
|
409
|
+
export const JournalPolicySchema = journalPolicySchema;
|
|
410
|
+
const stepBaseSchema = z
|
|
411
|
+
.object({
|
|
412
|
+
id: z.string().min(1),
|
|
413
|
+
result: z.string().min(1),
|
|
414
|
+
timeoutMs: finiteInt(1, 600_000).optional(),
|
|
415
|
+
})
|
|
416
|
+
.strict();
|
|
417
|
+
const attributionSchema = z
|
|
418
|
+
.object({
|
|
419
|
+
operationId: z.string().min(1),
|
|
420
|
+
status: z.literal("degraded"),
|
|
421
|
+
reasonCode: z.literal("expected_absence"),
|
|
422
|
+
reasonKey: z.string().min(1),
|
|
423
|
+
})
|
|
424
|
+
.strict();
|
|
425
|
+
const findFirstSchema = z
|
|
426
|
+
.object({
|
|
427
|
+
kind: z.literal("find_first"),
|
|
428
|
+
itemBinding: z.string().min(1),
|
|
429
|
+
predicate: scopedExpressionSchema,
|
|
430
|
+
maxScan: finiteInt(1, 100),
|
|
431
|
+
})
|
|
432
|
+
.strict();
|
|
433
|
+
export const FindFirstSchema = findFirstSchema;
|
|
434
|
+
const operationStepSchema = stepBaseSchema
|
|
435
|
+
.extend({
|
|
436
|
+
kind: z.literal("operation"),
|
|
437
|
+
operationId: z.string().min(1),
|
|
438
|
+
inputTemplate: jsonTemplateSchema,
|
|
439
|
+
connection: credentialReferenceSchema.optional(),
|
|
440
|
+
retry: retryPolicySchema.optional(),
|
|
441
|
+
candidate: z.union([candidatePolicySchema, candidateBlockSchema]).optional(),
|
|
442
|
+
journal: journalPolicySchema.optional(),
|
|
443
|
+
})
|
|
444
|
+
.strict();
|
|
445
|
+
const extractStepSchema = stepBaseSchema
|
|
446
|
+
.extend({
|
|
447
|
+
kind: z.literal("extract"),
|
|
448
|
+
from: stepReferenceSchema,
|
|
449
|
+
selector: z.union([BoundedJsonPathSchema, findFirstSchema]),
|
|
450
|
+
valueType: valueTypeSchema,
|
|
451
|
+
required: z.boolean(),
|
|
452
|
+
})
|
|
453
|
+
.strict();
|
|
454
|
+
const assertStepSchema = stepBaseSchema
|
|
455
|
+
.extend({
|
|
456
|
+
kind: z.literal("assert"),
|
|
457
|
+
coversOperations: nonEmptyArray(z.string().min(1)),
|
|
458
|
+
expression: expressionSchema,
|
|
459
|
+
})
|
|
460
|
+
.strict();
|
|
461
|
+
const guardStepSchema = stepBaseSchema
|
|
462
|
+
.extend({
|
|
463
|
+
kind: z.literal("guard"),
|
|
464
|
+
condition: expressionSchema,
|
|
465
|
+
onFail: z
|
|
466
|
+
.object({ attribute: nonEmptyArray(attributionSchema), stop: z.literal("scenario") })
|
|
467
|
+
.strict(),
|
|
468
|
+
})
|
|
469
|
+
.strict();
|
|
470
|
+
export const HealthStepSchema = z.discriminatedUnion("kind", [
|
|
471
|
+
operationStepSchema,
|
|
472
|
+
extractStepSchema,
|
|
473
|
+
assertStepSchema,
|
|
474
|
+
guardStepSchema,
|
|
475
|
+
]);
|
|
476
|
+
export const OperationStepSchema = operationStepSchema;
|
|
477
|
+
export const ExtractStepSchema = extractStepSchema;
|
|
478
|
+
export const AssertStepSchema = assertStepSchema;
|
|
479
|
+
export const GuardStepSchema = guardStepSchema;
|
|
480
|
+
const manualTriggerSchema = z.union([
|
|
481
|
+
z.object({ enabled: z.literal(false), reasonKey: z.string().min(1) }).strict(),
|
|
482
|
+
z
|
|
483
|
+
.object({
|
|
484
|
+
enabled: z.literal(true),
|
|
485
|
+
requiresAcknowledgement: z.boolean(),
|
|
486
|
+
risk: z.enum(["read_only", "writes_external_state"]),
|
|
487
|
+
minManualIntervalMs: finiteInt(1000, 86_400_000),
|
|
488
|
+
publicRationaleKey: z.string().min(1),
|
|
489
|
+
})
|
|
490
|
+
.strict(),
|
|
491
|
+
]);
|
|
492
|
+
export const ManualTriggerPolicySchema = manualTriggerSchema;
|
|
493
|
+
const credentialRefDeclarationSchema = z
|
|
494
|
+
.object({ alias: z.string().min(1), kind: z.literal("connection") })
|
|
495
|
+
.strict();
|
|
496
|
+
export const CredentialRefDeclarationSchema = credentialRefDeclarationSchema;
|
|
497
|
+
export const HealthScenarioSchema = z
|
|
498
|
+
.object({
|
|
499
|
+
scenarioVersion: z.literal(2),
|
|
500
|
+
id: z.string().min(1),
|
|
501
|
+
display: z
|
|
502
|
+
.object({ titleKey: z.string().min(1), descriptionKey: z.string().min(1).optional() })
|
|
503
|
+
.strict(),
|
|
504
|
+
schedule: z
|
|
505
|
+
.object({
|
|
506
|
+
kind: z.literal("interval"),
|
|
507
|
+
intervalMs: finiteInt(30_000, 604_800_000),
|
|
508
|
+
jitterMs: finiteInt(0),
|
|
509
|
+
})
|
|
510
|
+
.strict(),
|
|
511
|
+
timeoutMs: finiteInt(1000, 600_000),
|
|
512
|
+
cooldownMs: finiteInt(0, 86_400_000).optional(),
|
|
513
|
+
manualTrigger: manualTriggerSchema.optional(),
|
|
514
|
+
coversOperations: nonEmptyArray(z.string().min(1)),
|
|
515
|
+
credentialRefs: z.array(credentialRefDeclarationSchema),
|
|
516
|
+
steps: z
|
|
517
|
+
.array(HealthStepSchema)
|
|
518
|
+
.min(1)
|
|
519
|
+
.max(64)
|
|
520
|
+
.transform((value) => value),
|
|
521
|
+
})
|
|
522
|
+
.strict()
|
|
523
|
+
.superRefine((value, ctx) => {
|
|
524
|
+
if (value.schedule.jitterMs > value.schedule.intervalMs)
|
|
525
|
+
ctx.addIssue({
|
|
526
|
+
code: "custom",
|
|
527
|
+
path: ["schedule", "jitterMs"],
|
|
528
|
+
message: "jitterMs must not exceed intervalMs",
|
|
529
|
+
});
|
|
530
|
+
if (value.timeoutMs > value.schedule.intervalMs)
|
|
531
|
+
ctx.addIssue({
|
|
532
|
+
code: "custom",
|
|
533
|
+
path: ["timeoutMs"],
|
|
534
|
+
message: "timeoutMs must not exceed intervalMs",
|
|
535
|
+
});
|
|
536
|
+
const ids = new Set();
|
|
537
|
+
const bindings = new Set();
|
|
538
|
+
for (const [index, step] of value.steps.entries()) {
|
|
539
|
+
if (ids.has(step.id))
|
|
540
|
+
ctx.addIssue({
|
|
541
|
+
code: "custom",
|
|
542
|
+
path: ["steps", index, "id"],
|
|
543
|
+
message: `duplicate step ${step.id}`,
|
|
544
|
+
});
|
|
545
|
+
ids.add(step.id);
|
|
546
|
+
if (bindings.has(step.result))
|
|
547
|
+
ctx.addIssue({
|
|
548
|
+
code: "custom",
|
|
549
|
+
path: ["steps", index, "result"],
|
|
550
|
+
message: `duplicate result binding ${step.result}`,
|
|
551
|
+
});
|
|
552
|
+
bindings.add(step.result);
|
|
553
|
+
if (step.timeoutMs !== undefined && step.timeoutMs > value.timeoutMs)
|
|
554
|
+
ctx.addIssue({
|
|
555
|
+
code: "custom",
|
|
556
|
+
path: ["steps", index, "timeoutMs"],
|
|
557
|
+
message: "step timeout must not exceed the scenario timeout",
|
|
558
|
+
});
|
|
559
|
+
if (step.kind === "operation" &&
|
|
560
|
+
step.retry?.retryOn.includes("timeout") &&
|
|
561
|
+
step.retry.attemptTimeoutMs === undefined)
|
|
562
|
+
ctx.addIssue({
|
|
563
|
+
code: "custom",
|
|
564
|
+
path: ["steps", index, "retry", "attemptTimeoutMs"],
|
|
565
|
+
message: "timeout retry requires attemptTimeoutMs",
|
|
566
|
+
});
|
|
567
|
+
const expression = step.kind === "assert"
|
|
568
|
+
? step.expression
|
|
569
|
+
: step.kind === "guard"
|
|
570
|
+
? step.condition
|
|
571
|
+
: step.kind === "operation" && step.candidate
|
|
572
|
+
? step.candidate.accept
|
|
573
|
+
: undefined;
|
|
574
|
+
if (expression)
|
|
575
|
+
walkExpression(expression, ctx, ["steps", index], 0, { count: 0 }, true);
|
|
576
|
+
if (step.kind === "extract" && "kind" in step.selector && step.selector.kind === "find_first")
|
|
577
|
+
walkExpression(step.selector.predicate, ctx, ["steps", index, "selector", "predicate"], 0, { count: 0 }, false, step.selector.itemBinding);
|
|
578
|
+
}
|
|
579
|
+
try {
|
|
580
|
+
const serialized = JSON.stringify(value);
|
|
581
|
+
if (new TextEncoder().encode(serialized).byteLength > 128 * 1024)
|
|
582
|
+
ctx.addIssue({ code: "custom", path: [], message: "serialized scenario exceeds 128 KiB" });
|
|
583
|
+
}
|
|
584
|
+
catch {
|
|
585
|
+
ctx.addIssue({ code: "custom", path: [], message: "scenario must be JSON-serializable" });
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
function walkExpression(expression, ctx, path, depth, leaves, allowQuantifier, scopedBinding) {
|
|
589
|
+
if (depth > 8) {
|
|
590
|
+
ctx.addIssue({ code: "custom", path, message: "expression depth exceeds 8" });
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
if (expression.kind === "quantifier") {
|
|
594
|
+
if (!allowQuantifier) {
|
|
595
|
+
ctx.addIssue({ code: "custom", path, message: "quantifiers may not be nested" });
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
if (expression.itemBinding === scopedBinding) {
|
|
599
|
+
ctx.addIssue({
|
|
600
|
+
code: "custom",
|
|
601
|
+
path: [...path, "itemBinding"],
|
|
602
|
+
message: "item binding is invalid or shadows an enclosing binding",
|
|
603
|
+
});
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
walkExpression(expression.clause, ctx, [...path, "clause"], depth + 1, leaves, false, expression.itemBinding);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
if (expression.kind === "all" || expression.kind === "any") {
|
|
610
|
+
for (const [index, clause] of expression.clauses.entries())
|
|
611
|
+
walkExpression(clause, ctx, [...path, "clauses", index], depth + 1, leaves, allowQuantifier, scopedBinding);
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
if (expression.kind === "not") {
|
|
615
|
+
walkExpression(expression.clause, ctx, [...path, "clause"], depth + 1, leaves, allowQuantifier, scopedBinding);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
leaves.count += 1;
|
|
619
|
+
if (leaves.count > 64)
|
|
620
|
+
ctx.addIssue({ code: "custom", path, message: "expression contains more than 64 leaves" });
|
|
621
|
+
}
|
|
622
|
+
export function defineHealthScenario(input) {
|
|
623
|
+
return HealthScenarioSchema.parse(input);
|
|
624
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export * from "./auth.js";
|
|
2
2
|
export * from "./ceremonies/index.js";
|
|
3
3
|
export * from "./choice-token.js";
|
|
4
|
-
export type { ApiFuseConfig, BrowserConfig, ProxyProtocol, ProxyResolutionOptions, ProxyResolutionSource, ProxyVendorName, ResolvedProxyConfig, SessionConfig, } from "./config/loader.js";
|
|
4
|
+
export type { ApiFuseConfig, BrowserConfig, ProxyCacheStatus, ProxyProtocol, ProxyResolutionOptions, ProxyResolutionSource, ProxyUserAgentSource, ProxyVendorName, ResolvedProxyConfig, SessionConfig, SmartproxyAllocatorBodyClass, } from "./config/loader.js";
|
|
5
5
|
export { defineConfig, loadApiFuseConfig, resolveProxy } from "./config/loader.js";
|
|
6
6
|
export { canonicalJson, digestProviderContract, extractProviderContract, type JsonPrimitive, type JsonValue, PROVIDER_CONTRACT_SCHEMA_VERSION, type ProviderContractOperation, type ProviderContractSnapshot, } from "./contract.js";
|
|
7
7
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, defineStreamOperation, every, type AuthStartNoInputGuard, type ProviderBuilder, type ProviderContextOf, type ProviderDeclaration, } from "./define.js";
|
|
8
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
9
|
+
export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
|
|
8
10
|
export type { DevServerOptions } from "./dev.js";
|
|
9
11
|
export { createDevServer, startDevServer } from "./dev.js";
|
|
10
12
|
export * from "./errors.js";
|
|
@@ -29,6 +31,7 @@ export { generateInsights } from "./runtime/insights.js";
|
|
|
29
31
|
export { type InstrumentationOptions, type InstrumentedProviderContext, wrapWithInstrumentation, } from "./runtime/instrumentation.js";
|
|
30
32
|
export type { PrevalidateResult } from "./runtime/prevalidate.js";
|
|
31
33
|
export { getProviderBaseUrl } from "./runtime/provider.js";
|
|
34
|
+
export type { ProxyTelemetryLogPayload } from "./runtime/proxy-telemetry.js";
|
|
32
35
|
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./runtime/resolver-config.js";
|
|
33
36
|
export { createUnsupportedResolverClient } from "./runtime/resolver-shared.js";
|
|
34
37
|
export type { ResolverRuntimeOptions } from "./runtime/resolver.js";
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./choice-token.js";
|
|
|
5
5
|
export { defineConfig, loadApiFuseConfig, resolveProxy } from "./config/loader.js";
|
|
6
6
|
export { canonicalJson, digestProviderContract, extractProviderContract, PROVIDER_CONTRACT_SCHEMA_VERSION, } from "./contract.js";
|
|
7
7
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, defineStreamOperation, every, } from "./define.js";
|
|
8
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
8
9
|
export { createDevServer, startDevServer } from "./dev.js";
|
|
9
10
|
export * from "./errors.js";
|
|
10
11
|
export * from "./observability.js";
|
package/dist/provider.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export { createFormCeremony } from "./ceremonies/index.js";
|
|
|
4
4
|
export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, type ProviderChoiceTokenErrorReason, type ProviderChoiceTokenPayload, parseProviderChoiceToken, } from "./choice-token.js";
|
|
5
5
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
|
|
6
6
|
export type { ProviderBuilder, ProviderContextOf, ProviderDeclaration, } from "./define.js";
|
|
7
|
+
export type { JsonPrimitive, JsonValue } from "./contract-json.js";
|
|
8
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
9
|
+
export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
|
|
7
10
|
export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
8
11
|
export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
|
|
9
12
|
export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
|
package/dist/provider.js
CHANGED
|
@@ -2,6 +2,7 @@ export { AuthAbortError, credentialsAuthChallenge, createAuthFlowHelpers, define
|
|
|
2
2
|
export { createFormCeremony } from "./ceremonies/index.js";
|
|
3
3
|
export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, parseProviderChoiceToken, } from "./choice-token.js";
|
|
4
4
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
|
|
5
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
5
6
|
export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
6
7
|
export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
|
|
7
8
|
export { createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
|