@outfitter/contracts 0.4.0 → 0.4.2
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/README.md +18 -15
- package/dist/actions.d.ts +4 -4
- package/dist/actions.js +25 -6
- package/dist/adapters.d.ts +1 -1
- package/dist/assert/index.d.ts +2 -2
- package/dist/assert/index.js +28 -6
- package/dist/capabilities.d.ts +1 -1
- package/dist/capabilities.js +57 -8
- package/dist/context.d.ts +4 -4
- package/dist/envelope.d.ts +2 -2
- package/dist/envelope.js +49 -6
- package/dist/errors.d.ts +1 -1
- package/dist/handler.d.ts +3 -3
- package/dist/index.d.ts +17 -17
- package/dist/index.js +15 -153
- package/dist/logging.d.ts +1 -1
- package/dist/logging.js +11 -3
- package/dist/recovery.d.ts +2 -2
- package/dist/recovery.js +49 -6
- package/dist/redactor.d.ts +1 -1
- package/dist/resilience.d.ts +2 -2
- package/dist/resilience.js +76 -4
- package/dist/result/index.d.ts +2 -2
- package/dist/result/index.js +1 -16
- package/dist/result/utilities.d.ts +1 -1
- package/dist/result/utilities.js +29 -7
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +338 -3
- package/dist/serialization.d.ts +2 -2
- package/dist/shared/@outfitter/{contracts-ss9vjjft.d.ts → contracts-0akf2sm6.d.ts} +10 -10
- package/dist/shared/@outfitter/{contracts-25bkj17f.d.ts → contracts-1waabxbk.d.ts} +10 -10
- package/dist/shared/@outfitter/{contracts-j08e95jw.d.ts → contracts-31penhwa.d.ts} +1 -1
- package/dist/shared/@outfitter/{contracts-sf1z80yc.d.ts → contracts-56pcsavx.d.ts} +17 -17
- package/dist/shared/@outfitter/{contracts-bdwg55c5.d.ts → contracts-95cc3y06.d.ts} +13 -13
- package/dist/shared/@outfitter/{contracts-6j6z9dsd.d.ts → contracts-9wtm5nsw.d.ts} +1 -1
- package/dist/shared/@outfitter/{contracts-jggbn5tn.d.ts → contracts-e4m948m7.d.ts} +10 -10
- package/dist/shared/@outfitter/{contracts-evxky148.d.ts → contracts-k71jqd1m.d.ts} +1 -1
- package/dist/shared/@outfitter/{contracts-18vcxecr.d.ts → contracts-mmg0npfk.d.ts} +1 -1
- package/dist/validation.d.ts +2 -2
- package/dist/validation.js +36 -4
- package/package.json +26 -25
- package/dist/shared/@outfitter/contracts-0snpmkdt.js +0 -40
- package/dist/shared/@outfitter/contracts-37gpc56f.js +0 -1
- package/dist/shared/@outfitter/contracts-4zaj7ejb.js +0 -52
- package/dist/shared/@outfitter/contracts-btg89x4h.js +0 -53
- package/dist/shared/@outfitter/contracts-cp5c6dws.js +0 -32
- package/dist/shared/@outfitter/contracts-d0tq2adf.js +0 -60
- package/dist/shared/@outfitter/contracts-q0v44kef.js +0 -28
- package/dist/shared/@outfitter/contracts-r21yet6j.js +0 -80
- package/dist/shared/@outfitter/contracts-sm6vak1a.js +0 -14
- package/dist/shared/@outfitter/contracts-wfht4q2b.js +0 -341
- package/dist/shared/@outfitter/contracts-zx72gyh1.js +0 -32
- package/dist/shared/@outfitter/{contracts-r35bn9p6.d.ts → contracts-3gswmhb1.d.ts} +2 -2
- package/dist/shared/@outfitter/{contracts-e70qdasg.d.ts → contracts-9yd4vrjg.d.ts} +12 -12
- package/dist/shared/@outfitter/{contracts-93dx53mt.d.ts → contracts-c2cfj172.d.ts} +32 -32
- package/dist/shared/@outfitter/{contracts-2g8r01zf.d.ts → contracts-rwzqy9rn.d.ts} +10 -10
- package/dist/shared/@outfitter/{contracts-hbbxbwkt.d.ts → contracts-t79engf9.d.ts} +21 -21
- package/dist/shared/@outfitter/{contracts-bb4hjt8g.d.ts → contracts-y8f0m1ze.d.ts} +1 -1
package/dist/resilience.js
CHANGED
|
@@ -1,9 +1,81 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
TimeoutError
|
|
4
|
+
} from "./shared/@outfitter/contracts-phjhz5q3.js";
|
|
5
|
+
|
|
6
|
+
// packages/contracts/src/resilience.ts
|
|
7
|
+
import { Result } from "better-result";
|
|
8
|
+
function defaultIsRetryable(error) {
|
|
9
|
+
return error.category === "network" || error.category === "timeout" || error.category === "rate_limit";
|
|
10
|
+
}
|
|
11
|
+
function calculateDelay(attempt, initialDelayMs, maxDelayMs, backoffMultiplier, jitter) {
|
|
12
|
+
const baseDelay = initialDelayMs * backoffMultiplier ** (attempt - 1);
|
|
13
|
+
const cappedDelay = Math.min(baseDelay, maxDelayMs);
|
|
14
|
+
if (jitter) {
|
|
15
|
+
const jitterFactor = 0.5 + Math.random();
|
|
16
|
+
return Math.floor(cappedDelay * jitterFactor);
|
|
17
|
+
}
|
|
18
|
+
return cappedDelay;
|
|
19
|
+
}
|
|
20
|
+
function sleep(ms) {
|
|
21
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
22
|
+
}
|
|
23
|
+
async function retry(fn, options) {
|
|
24
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
25
|
+
const initialDelayMs = options?.initialDelayMs ?? 1000;
|
|
26
|
+
const maxDelayMs = options?.maxDelayMs ?? 30000;
|
|
27
|
+
const backoffMultiplier = options?.backoffMultiplier ?? 2;
|
|
28
|
+
const jitter = options?.jitter ?? true;
|
|
29
|
+
const isRetryable = options?.isRetryable ?? defaultIsRetryable;
|
|
30
|
+
const onRetry = options?.onRetry;
|
|
31
|
+
const signal = options?.signal;
|
|
32
|
+
let lastError;
|
|
33
|
+
let attempt = 0;
|
|
34
|
+
while (attempt < maxAttempts) {
|
|
35
|
+
attempt++;
|
|
36
|
+
if (signal?.aborted) {
|
|
37
|
+
return Result.err(lastError ?? new TimeoutError({
|
|
38
|
+
message: "Operation cancelled",
|
|
39
|
+
operation: "retry",
|
|
40
|
+
timeoutMs: 0
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
const result = await fn();
|
|
44
|
+
if (result.isOk()) {
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
lastError = result.error;
|
|
48
|
+
if (attempt >= maxAttempts || !isRetryable(lastError)) {
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
const delayMs = calculateDelay(attempt, initialDelayMs, maxDelayMs, backoffMultiplier, jitter);
|
|
52
|
+
if (onRetry) {
|
|
53
|
+
onRetry(attempt, lastError, delayMs);
|
|
54
|
+
}
|
|
55
|
+
await sleep(delayMs);
|
|
56
|
+
}
|
|
57
|
+
throw new Error("Unexpected: retry loop completed without returning a result");
|
|
58
|
+
}
|
|
59
|
+
async function withTimeout(fn, options) {
|
|
60
|
+
const { timeoutMs, operation = "operation" } = options;
|
|
61
|
+
let timeoutId;
|
|
62
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
63
|
+
timeoutId = setTimeout(() => {
|
|
64
|
+
resolve(Result.err(new TimeoutError({
|
|
65
|
+
message: `${operation} timed out after ${timeoutMs}ms`,
|
|
66
|
+
operation,
|
|
67
|
+
timeoutMs
|
|
68
|
+
})));
|
|
69
|
+
}, timeoutMs);
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
return await Promise.race([fn(), timeoutPromise]);
|
|
73
|
+
} finally {
|
|
74
|
+
if (timeoutId !== undefined) {
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
7
79
|
export {
|
|
8
80
|
withTimeout,
|
|
9
81
|
retry
|
package/dist/result/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../shared/@outfitter/contracts-qaccq0gf";
|
|
2
|
-
import { combine2, combine3, expect, orElse, unwrapOrElse } from "../shared/@outfitter/contracts-ar0etwtx";
|
|
1
|
+
import "../shared/@outfitter/contracts-qaccq0gf.js";
|
|
2
|
+
import { combine2, combine3, expect, orElse, unwrapOrElse } from "../shared/@outfitter/contracts-ar0etwtx.js";
|
|
3
3
|
export { unwrapOrElse, orElse, expect, combine3, combine2 };
|
package/dist/result/index.js
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import"../shared/@outfitter/contracts-37gpc56f.js";
|
|
3
|
-
import {
|
|
4
|
-
combine2,
|
|
5
|
-
combine3,
|
|
6
|
-
expect,
|
|
7
|
-
orElse,
|
|
8
|
-
unwrapOrElse
|
|
9
|
-
} from "../shared/@outfitter/contracts-zx72gyh1.js";
|
|
10
|
-
export {
|
|
11
|
-
unwrapOrElse,
|
|
12
|
-
orElse,
|
|
13
|
-
expect,
|
|
14
|
-
combine3,
|
|
15
|
-
combine2
|
|
16
|
-
};
|
|
1
|
+
export { combine2, combine3, expect, orElse, unwrapOrElse } from "./utilities.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { combine2, combine3, expect, orElse, unwrapOrElse } from "../shared/@outfitter/contracts-ar0etwtx";
|
|
1
|
+
import { combine2, combine3, expect, orElse, unwrapOrElse } from "../shared/@outfitter/contracts-ar0etwtx.js";
|
|
2
2
|
export { unwrapOrElse, orElse, expect, combine3, combine2 };
|
package/dist/result/utilities.js
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
// packages/contracts/src/result/utilities.ts
|
|
3
|
+
import { Result } from "better-result";
|
|
4
|
+
var unwrapOrElse = (result, defaultFn) => {
|
|
5
|
+
return result.isOk() ? result.value : defaultFn(result.error);
|
|
6
|
+
};
|
|
7
|
+
var orElse = (result, fallback) => {
|
|
8
|
+
return result.isOk() ? result : fallback;
|
|
9
|
+
};
|
|
10
|
+
var combine2 = (r1, r2) => {
|
|
11
|
+
if (r1.isErr())
|
|
12
|
+
return r1;
|
|
13
|
+
if (r2.isErr())
|
|
14
|
+
return r2;
|
|
15
|
+
return Result.ok([r1.value, r2.value]);
|
|
16
|
+
};
|
|
17
|
+
var combine3 = (r1, r2, r3) => {
|
|
18
|
+
if (r1.isErr())
|
|
19
|
+
return r1;
|
|
20
|
+
if (r2.isErr())
|
|
21
|
+
return r2;
|
|
22
|
+
if (r3.isErr())
|
|
23
|
+
return r3;
|
|
24
|
+
return Result.ok([r1.value, r2.value, r3.value]);
|
|
25
|
+
};
|
|
26
|
+
var expect = (result, message) => {
|
|
27
|
+
if (result.isOk())
|
|
28
|
+
return result.value;
|
|
29
|
+
throw new Error(`${message}: ${String(result.error)}`);
|
|
30
|
+
};
|
|
9
31
|
export {
|
|
10
32
|
unwrapOrElse,
|
|
11
33
|
orElse,
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { JsonSchema, zodToJsonSchema } from "./shared/@outfitter/contracts-
|
|
1
|
+
import { JsonSchema, zodToJsonSchema } from "./shared/@outfitter/contracts-t79engf9.js";
|
|
2
2
|
export { zodToJsonSchema, JsonSchema };
|
package/dist/schema.js
CHANGED
|
@@ -1,7 +1,342 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
// packages/contracts/src/schema.ts
|
|
3
|
+
function zodToJsonSchema(schema) {
|
|
4
|
+
return convertZodType(schema);
|
|
5
|
+
}
|
|
6
|
+
function getDef(schemaOrDef) {
|
|
7
|
+
if (!schemaOrDef) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (schemaOrDef._def) {
|
|
11
|
+
return schemaOrDef._def;
|
|
12
|
+
}
|
|
13
|
+
if (schemaOrDef.def) {
|
|
14
|
+
return schemaOrDef.def;
|
|
15
|
+
}
|
|
16
|
+
return schemaOrDef;
|
|
17
|
+
}
|
|
18
|
+
function getDescription(schema, def) {
|
|
19
|
+
if (typeof schema?.description === "string") {
|
|
20
|
+
return schema.description;
|
|
21
|
+
}
|
|
22
|
+
if (typeof def?.description === "string") {
|
|
23
|
+
return def.description;
|
|
24
|
+
}
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
function convertZodType(schema) {
|
|
28
|
+
const def = getDef(schema);
|
|
29
|
+
if (!def) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
const typeName = def.typeName ?? def.type;
|
|
33
|
+
let jsonSchema;
|
|
34
|
+
switch (typeName) {
|
|
35
|
+
case "ZodString":
|
|
36
|
+
case "string":
|
|
37
|
+
jsonSchema = convertString(def);
|
|
38
|
+
break;
|
|
39
|
+
case "ZodNumber":
|
|
40
|
+
case "number":
|
|
41
|
+
jsonSchema = convertNumber(def);
|
|
42
|
+
break;
|
|
43
|
+
case "ZodBoolean":
|
|
44
|
+
case "boolean":
|
|
45
|
+
jsonSchema = { type: "boolean" };
|
|
46
|
+
break;
|
|
47
|
+
case "ZodNull":
|
|
48
|
+
case "null":
|
|
49
|
+
jsonSchema = { type: "null" };
|
|
50
|
+
break;
|
|
51
|
+
case "ZodUndefined":
|
|
52
|
+
case "undefined":
|
|
53
|
+
jsonSchema = {};
|
|
54
|
+
break;
|
|
55
|
+
case "ZodArray":
|
|
56
|
+
case "array":
|
|
57
|
+
jsonSchema = convertArray(def);
|
|
58
|
+
break;
|
|
59
|
+
case "ZodObject":
|
|
60
|
+
case "object":
|
|
61
|
+
jsonSchema = convertObject(def);
|
|
62
|
+
break;
|
|
63
|
+
case "ZodOptional":
|
|
64
|
+
case "optional":
|
|
65
|
+
jsonSchema = convertZodType(def.innerType);
|
|
66
|
+
break;
|
|
67
|
+
case "ZodNullable":
|
|
68
|
+
case "nullable":
|
|
69
|
+
jsonSchema = {
|
|
70
|
+
anyOf: [convertZodType(def.innerType), { type: "null" }]
|
|
71
|
+
};
|
|
72
|
+
break;
|
|
73
|
+
case "ZodDefault":
|
|
74
|
+
case "default": {
|
|
75
|
+
const defaultValue = typeof def.defaultValue === "function" ? def.defaultValue() : def.defaultValue;
|
|
76
|
+
jsonSchema = {
|
|
77
|
+
...convertZodType(def.innerType),
|
|
78
|
+
default: defaultValue
|
|
79
|
+
};
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "ZodEnum":
|
|
83
|
+
case "enum": {
|
|
84
|
+
const values = def.values ?? Object.values(def.entries ?? {});
|
|
85
|
+
jsonSchema = {
|
|
86
|
+
type: "string",
|
|
87
|
+
enum: values
|
|
88
|
+
};
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case "ZodNativeEnum":
|
|
92
|
+
jsonSchema = {
|
|
93
|
+
enum: Object.values(def.values ?? def.entries ?? {})
|
|
94
|
+
};
|
|
95
|
+
break;
|
|
96
|
+
case "ZodLiteral":
|
|
97
|
+
case "literal": {
|
|
98
|
+
const literalValues = Array.isArray(def.values) ? def.values : [def.value].filter((value) => value !== undefined);
|
|
99
|
+
if (literalValues.length > 1) {
|
|
100
|
+
jsonSchema = {
|
|
101
|
+
enum: literalValues
|
|
102
|
+
};
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
jsonSchema = literalValues.length ? {
|
|
106
|
+
const: literalValues[0]
|
|
107
|
+
} : {};
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case "ZodUnion":
|
|
111
|
+
case "union":
|
|
112
|
+
jsonSchema = {
|
|
113
|
+
anyOf: def.options.map(convertZodType)
|
|
114
|
+
};
|
|
115
|
+
break;
|
|
116
|
+
case "ZodIntersection":
|
|
117
|
+
case "intersection":
|
|
118
|
+
jsonSchema = {
|
|
119
|
+
allOf: [convertZodType(def.left), convertZodType(def.right)]
|
|
120
|
+
};
|
|
121
|
+
break;
|
|
122
|
+
case "ZodRecord":
|
|
123
|
+
case "record":
|
|
124
|
+
jsonSchema = {
|
|
125
|
+
type: "object",
|
|
126
|
+
additionalProperties: def.valueType ? convertZodType(def.valueType) : {}
|
|
127
|
+
};
|
|
128
|
+
break;
|
|
129
|
+
case "ZodTuple":
|
|
130
|
+
case "tuple":
|
|
131
|
+
jsonSchema = {
|
|
132
|
+
type: "array",
|
|
133
|
+
items: def.items.map(convertZodType)
|
|
134
|
+
};
|
|
135
|
+
break;
|
|
136
|
+
case "ZodAny":
|
|
137
|
+
case "any":
|
|
138
|
+
jsonSchema = {};
|
|
139
|
+
break;
|
|
140
|
+
case "ZodUnknown":
|
|
141
|
+
case "unknown":
|
|
142
|
+
jsonSchema = {};
|
|
143
|
+
break;
|
|
144
|
+
case "ZodVoid":
|
|
145
|
+
case "void":
|
|
146
|
+
jsonSchema = {};
|
|
147
|
+
break;
|
|
148
|
+
case "ZodNever":
|
|
149
|
+
case "never":
|
|
150
|
+
jsonSchema = { not: {} };
|
|
151
|
+
break;
|
|
152
|
+
case "ZodEffects":
|
|
153
|
+
jsonSchema = convertZodType(def.schema);
|
|
154
|
+
break;
|
|
155
|
+
case "ZodPipeline":
|
|
156
|
+
case "pipe": {
|
|
157
|
+
const outputDef = getDef(def.out);
|
|
158
|
+
const outputType = outputDef?.typeName ?? outputDef?.type;
|
|
159
|
+
jsonSchema = outputType === "transform" ? convertZodType(def.in) : convertZodType(def.out);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
case "ZodLazy":
|
|
163
|
+
case "lazy":
|
|
164
|
+
jsonSchema = {};
|
|
165
|
+
break;
|
|
166
|
+
default:
|
|
167
|
+
jsonSchema = {};
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
const description = getDescription(schema, def);
|
|
171
|
+
if (description && !jsonSchema.description) {
|
|
172
|
+
jsonSchema.description = description;
|
|
173
|
+
}
|
|
174
|
+
return jsonSchema;
|
|
175
|
+
}
|
|
176
|
+
function convertString(def) {
|
|
177
|
+
const schema = { type: "string" };
|
|
178
|
+
if (def.checks) {
|
|
179
|
+
for (const check of def.checks) {
|
|
180
|
+
const normalizedCheck = check?._zod?.def ?? check?.def ?? check;
|
|
181
|
+
if (normalizedCheck?.kind) {
|
|
182
|
+
switch (normalizedCheck.kind) {
|
|
183
|
+
case "min":
|
|
184
|
+
schema.minLength = normalizedCheck.value;
|
|
185
|
+
break;
|
|
186
|
+
case "max":
|
|
187
|
+
schema.maxLength = normalizedCheck.value;
|
|
188
|
+
break;
|
|
189
|
+
case "length":
|
|
190
|
+
schema.minLength = normalizedCheck.value;
|
|
191
|
+
schema.maxLength = normalizedCheck.value;
|
|
192
|
+
break;
|
|
193
|
+
case "email":
|
|
194
|
+
schema.pattern = "^[^@]+@[^@]+\\.[^@]+$";
|
|
195
|
+
break;
|
|
196
|
+
case "url":
|
|
197
|
+
schema.pattern = "^https?://";
|
|
198
|
+
break;
|
|
199
|
+
case "uuid":
|
|
200
|
+
schema.pattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
|
|
201
|
+
break;
|
|
202
|
+
case "regex":
|
|
203
|
+
schema.pattern = normalizedCheck.regex?.source ?? normalizedCheck.pattern?.source ?? (typeof normalizedCheck.pattern === "string" ? normalizedCheck.pattern : undefined);
|
|
204
|
+
break;
|
|
205
|
+
default:
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (!normalizedCheck?.check) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
switch (normalizedCheck.check) {
|
|
214
|
+
case "min_length":
|
|
215
|
+
schema.minLength = normalizedCheck.minimum;
|
|
216
|
+
break;
|
|
217
|
+
case "max_length":
|
|
218
|
+
schema.maxLength = normalizedCheck.maximum;
|
|
219
|
+
break;
|
|
220
|
+
case "string_format":
|
|
221
|
+
if (normalizedCheck.pattern) {
|
|
222
|
+
schema.pattern = typeof normalizedCheck.pattern === "string" ? normalizedCheck.pattern : normalizedCheck.pattern.source;
|
|
223
|
+
}
|
|
224
|
+
if (normalizedCheck.format && normalizedCheck.format !== "regex") {
|
|
225
|
+
schema.format = normalizedCheck.format;
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
default:
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return schema;
|
|
234
|
+
}
|
|
235
|
+
function convertNumber(def) {
|
|
236
|
+
const schema = { type: "number" };
|
|
237
|
+
if (def.checks) {
|
|
238
|
+
for (const check of def.checks) {
|
|
239
|
+
const normalizedCheck = check?._zod?.def ?? check?.def ?? check;
|
|
240
|
+
if (normalizedCheck?.kind) {
|
|
241
|
+
switch (normalizedCheck.kind) {
|
|
242
|
+
case "min":
|
|
243
|
+
schema.minimum = normalizedCheck.value;
|
|
244
|
+
break;
|
|
245
|
+
case "max":
|
|
246
|
+
schema.maximum = normalizedCheck.value;
|
|
247
|
+
break;
|
|
248
|
+
case "int":
|
|
249
|
+
schema.type = "integer";
|
|
250
|
+
break;
|
|
251
|
+
default:
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (!normalizedCheck?.check) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
switch (normalizedCheck.check) {
|
|
260
|
+
case "greater_than":
|
|
261
|
+
if (normalizedCheck.inclusive) {
|
|
262
|
+
schema.minimum = normalizedCheck.value;
|
|
263
|
+
} else {
|
|
264
|
+
schema.exclusiveMinimum = normalizedCheck.value;
|
|
265
|
+
}
|
|
266
|
+
break;
|
|
267
|
+
case "less_than":
|
|
268
|
+
if (normalizedCheck.inclusive) {
|
|
269
|
+
schema.maximum = normalizedCheck.value;
|
|
270
|
+
} else {
|
|
271
|
+
schema.exclusiveMaximum = normalizedCheck.value;
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
case "number_format":
|
|
275
|
+
if (normalizedCheck.format === "int" || normalizedCheck.format === "safeint") {
|
|
276
|
+
schema.type = "integer";
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return schema;
|
|
285
|
+
}
|
|
286
|
+
function convertArray(def) {
|
|
287
|
+
const element = def.element ?? def.type;
|
|
288
|
+
const schema = {
|
|
289
|
+
type: "array",
|
|
290
|
+
items: element ? convertZodType(element) : {}
|
|
291
|
+
};
|
|
292
|
+
return schema;
|
|
293
|
+
}
|
|
294
|
+
function isFieldOptional(fieldDef) {
|
|
295
|
+
if (!(fieldDef?.typeName || fieldDef?.type)) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
const typeName = fieldDef.typeName ?? fieldDef.type;
|
|
299
|
+
if (typeName === "ZodOptional" || typeName === "ZodDefault" || typeName === "optional" || typeName === "default") {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (typeName === "ZodEffects") {
|
|
303
|
+
return isFieldOptional(getDef(fieldDef.schema));
|
|
304
|
+
}
|
|
305
|
+
if (typeName === "ZodPipeline" || typeName === "pipe") {
|
|
306
|
+
const inputOptional = isFieldOptional(getDef(fieldDef.in));
|
|
307
|
+
const outputDef = getDef(fieldDef.out);
|
|
308
|
+
const outputType = outputDef?.typeName ?? outputDef?.type;
|
|
309
|
+
if (outputType === "transform") {
|
|
310
|
+
return inputOptional;
|
|
311
|
+
}
|
|
312
|
+
const outputOptional = isFieldOptional(outputDef);
|
|
313
|
+
return inputOptional && outputOptional;
|
|
314
|
+
}
|
|
315
|
+
if (typeName === "ZodNullable" || typeName === "nullable") {
|
|
316
|
+
return isFieldOptional(getDef(fieldDef.innerType));
|
|
317
|
+
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
function convertObject(def) {
|
|
321
|
+
const properties = {};
|
|
322
|
+
const required = [];
|
|
323
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
324
|
+
for (const [key, value] of Object.entries(shape ?? {})) {
|
|
325
|
+
properties[key] = convertZodType(value);
|
|
326
|
+
const fieldDef = getDef(value);
|
|
327
|
+
if (!isFieldOptional(fieldDef)) {
|
|
328
|
+
required.push(key);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const schema = {
|
|
332
|
+
type: "object",
|
|
333
|
+
properties
|
|
334
|
+
};
|
|
335
|
+
if (required.length > 0) {
|
|
336
|
+
schema.required = required;
|
|
337
|
+
}
|
|
338
|
+
return schema;
|
|
339
|
+
}
|
|
5
340
|
export {
|
|
6
341
|
zodToJsonSchema
|
|
7
342
|
};
|
package/dist/serialization.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { SerializeErrorOptions, deserializeError, safeParse, safeStringify, serializeError } from "./shared/@outfitter/contracts-
|
|
2
|
-
import "./shared/@outfitter/contracts-
|
|
1
|
+
import { SerializeErrorOptions, deserializeError, safeParse, safeStringify, serializeError } from "./shared/@outfitter/contracts-31penhwa.js";
|
|
2
|
+
import "./shared/@outfitter/contracts-3gswmhb1.js";
|
|
3
3
|
export { serializeError, safeStringify, safeParse, deserializeError, SerializeErrorOptions };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { OutfitterError } from "./contracts-
|
|
2
|
-
import { Logger } from "./contracts-
|
|
1
|
+
import { OutfitterError } from "./contracts-3gswmhb1.js";
|
|
2
|
+
import { Logger } from "./contracts-rwzqy9rn.js";
|
|
3
3
|
import { Result } from "better-result";
|
|
4
4
|
/**
|
|
5
5
|
* Resolved configuration interface.
|
|
@@ -21,20 +21,20 @@ interface ResolvedConfig {
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
interface HandlerContext {
|
|
24
|
-
/** Abort signal for cancellation propagation */
|
|
25
|
-
signal?: AbortSignal;
|
|
26
|
-
/** Unique request identifier for tracing (UUIDv7) */
|
|
27
|
-
requestId: string;
|
|
28
|
-
/** Structured logger with automatic redaction */
|
|
29
|
-
logger: Logger;
|
|
30
24
|
/** Resolved configuration values */
|
|
31
25
|
config?: ResolvedConfig;
|
|
32
|
-
/** Workspace root path, if detected */
|
|
33
|
-
workspaceRoot?: string;
|
|
34
26
|
/** Current working directory */
|
|
35
27
|
cwd: string;
|
|
36
28
|
/** Environment variables (filtered, redacted) */
|
|
37
29
|
env: Record<string, string | undefined>;
|
|
30
|
+
/** Structured logger with automatic redaction */
|
|
31
|
+
logger: Logger;
|
|
32
|
+
/** Unique request identifier for tracing (UUIDv7) */
|
|
33
|
+
requestId: string;
|
|
34
|
+
/** Abort signal for cancellation propagation */
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
/** Workspace root path, if detected */
|
|
37
|
+
workspaceRoot?: string;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Handler - transport-agnostic domain logic unit.
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { HandlerContext, ResolvedConfig } from "./contracts-
|
|
2
|
-
import { Logger } from "./contracts-
|
|
1
|
+
import { HandlerContext, ResolvedConfig } from "./contracts-0akf2sm6.js";
|
|
2
|
+
import { Logger } from "./contracts-rwzqy9rn.js";
|
|
3
3
|
/**
|
|
4
4
|
* Options for creating a handler context.
|
|
5
5
|
*/
|
|
6
6
|
interface CreateContextOptions {
|
|
7
|
-
/** Logger instance (uses no-op logger if not provided) */
|
|
8
|
-
logger?: Logger;
|
|
9
7
|
/** Resolved configuration */
|
|
10
8
|
config?: ResolvedConfig;
|
|
11
|
-
/** Abort signal for cancellation */
|
|
12
|
-
signal?: AbortSignal;
|
|
13
|
-
/** Explicit request ID (generates UUIDv7 if not provided) */
|
|
14
|
-
requestId?: string;
|
|
15
|
-
/** Workspace root path */
|
|
16
|
-
workspaceRoot?: string;
|
|
17
9
|
/** Current working directory (defaults to process.cwd()) */
|
|
18
10
|
cwd?: string;
|
|
19
11
|
/** Environment variables to include */
|
|
20
12
|
env?: Record<string, string | undefined>;
|
|
13
|
+
/** Logger instance (uses no-op logger if not provided) */
|
|
14
|
+
logger?: Logger;
|
|
15
|
+
/** Explicit request ID (generates UUIDv7 if not provided) */
|
|
16
|
+
requestId?: string;
|
|
17
|
+
/** Abort signal for cancellation */
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
/** Workspace root path */
|
|
20
|
+
workspaceRoot?: string;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Create a HandlerContext for a new request.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Handler, SyncHandler } from "./contracts-
|
|
2
|
-
import { OutfitterError } from "./contracts-
|
|
1
|
+
import { Handler, SyncHandler } from "./contracts-0akf2sm6.js";
|
|
2
|
+
import { OutfitterError } from "./contracts-3gswmhb1.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
declare const ACTION_SURFACES: readonly ["cli", "mcp", "api", "server"];
|
|
5
5
|
type ActionSurface = (typeof ACTION_SURFACES)[number];
|
|
6
6
|
declare const DEFAULT_REGISTRY_SURFACES: readonly ActionSurface[];
|
|
7
7
|
interface ActionCliOption {
|
|
8
|
-
readonly flags: string;
|
|
9
|
-
readonly description: string;
|
|
10
8
|
readonly defaultValue?: string | boolean | string[];
|
|
9
|
+
readonly description: string;
|
|
10
|
+
readonly flags: string;
|
|
11
11
|
readonly required?: boolean;
|
|
12
12
|
}
|
|
13
13
|
interface ActionCliInputContext {
|
|
@@ -15,18 +15,18 @@ interface ActionCliInputContext {
|
|
|
15
15
|
readonly flags: Record<string, unknown>;
|
|
16
16
|
}
|
|
17
17
|
interface ActionCliSpec<TInput = unknown> {
|
|
18
|
-
readonly
|
|
18
|
+
readonly aliases?: readonly string[];
|
|
19
19
|
readonly command?: string;
|
|
20
20
|
readonly description?: string;
|
|
21
|
-
readonly
|
|
22
|
-
readonly options?: readonly ActionCliOption[];
|
|
21
|
+
readonly group?: string;
|
|
23
22
|
readonly mapInput?: (context: ActionCliInputContext) => TInput;
|
|
23
|
+
readonly options?: readonly ActionCliOption[];
|
|
24
24
|
}
|
|
25
25
|
interface ActionMcpSpec<TInput = unknown> {
|
|
26
|
-
readonly tool?: string;
|
|
27
|
-
readonly description?: string;
|
|
28
26
|
readonly deferLoading?: boolean;
|
|
27
|
+
readonly description?: string;
|
|
29
28
|
readonly mapInput?: (input: unknown) => TInput;
|
|
29
|
+
readonly tool?: string;
|
|
30
30
|
}
|
|
31
31
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
32
32
|
interface ActionApiSpec {
|
|
@@ -42,15 +42,15 @@ interface ActionSpec<
|
|
|
42
42
|
TOutput,
|
|
43
43
|
TError extends OutfitterError = OutfitterError
|
|
44
44
|
> {
|
|
45
|
-
readonly
|
|
45
|
+
readonly api?: ActionApiSpec;
|
|
46
|
+
readonly cli?: ActionCliSpec<TInput>;
|
|
46
47
|
readonly description?: string;
|
|
47
|
-
readonly surfaces?: readonly ActionSurface[];
|
|
48
|
-
readonly input: z.ZodType<TInput>;
|
|
49
|
-
readonly output?: z.ZodType<TOutput>;
|
|
50
48
|
readonly handler: Handler<TInput, TOutput, TError> | SyncHandler<TInput, TOutput, TError>;
|
|
51
|
-
readonly
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly input: z.ZodType<TInput>;
|
|
52
51
|
readonly mcp?: ActionMcpSpec<TInput>;
|
|
53
|
-
readonly
|
|
52
|
+
readonly output?: z.ZodType<TOutput>;
|
|
53
|
+
readonly surfaces?: readonly ActionSurface[];
|
|
54
54
|
readonly trpc?: ActionTrpcSpec;
|
|
55
55
|
}
|
|
56
56
|
type AnyActionSpec = ActionSpec<unknown, unknown, OutfitterError>;
|
|
@@ -60,9 +60,9 @@ interface ActionRegistry {
|
|
|
60
60
|
TOutput,
|
|
61
61
|
TError extends OutfitterError = OutfitterError
|
|
62
62
|
>(action: ActionSpec<TInput, TOutput, TError>): ActionRegistry;
|
|
63
|
-
list(): AnyActionSpec[];
|
|
64
|
-
get(id: string): AnyActionSpec | undefined;
|
|
65
63
|
forSurface(surface: ActionSurface): AnyActionSpec[];
|
|
64
|
+
get(id: string): AnyActionSpec | undefined;
|
|
65
|
+
list(): AnyActionSpec[];
|
|
66
66
|
}
|
|
67
67
|
declare function defineAction<
|
|
68
68
|
TInput,
|