@outfitter/contracts 0.4.1 → 0.5.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/README.md +18 -15
- package/dist/actions.d.ts +8 -3
- package/dist/actions.js +25 -6
- package/dist/assert/index.d.ts +7 -3
- package/dist/assert/index.js +59 -6
- package/dist/capabilities.js +57 -8
- package/dist/context.d.ts +8 -3
- package/dist/context.js +1 -1
- package/dist/envelope.d.ts +6 -2
- package/dist/envelope.js +49 -7
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +7 -1
- package/dist/from-fetch.d.ts +7 -0
- package/dist/from-fetch.js +110 -0
- package/dist/handler.d.ts +7 -2
- package/dist/hints.d.ts +2 -0
- package/dist/index.d.ts +25 -14
- package/dist/index.js +17 -153
- package/dist/internal/error-base.d.ts +2 -0
- package/dist/internal/error-base.js +31 -0
- package/dist/internal/error-operational.d.ts +3 -0
- package/dist/internal/error-operational.js +125 -0
- package/dist/internal/error-serialization.d.ts +7 -0
- package/dist/{shared/@outfitter/contracts-3wj7xghe.js → internal/error-serialization.js} +28 -67
- package/dist/internal/error-taxonomy.d.ts +2 -0
- package/dist/internal/error-taxonomy.js +21 -0
- package/dist/internal/error-validation.d.ts +3 -0
- package/dist/internal/error-validation.js +121 -0
- package/dist/internal/safe-json.d.ts +7 -0
- package/dist/internal/safe-json.js +66 -0
- package/dist/internal/schema-converters.d.ts +26 -0
- package/dist/internal/schema-converters.js +12 -0
- package/dist/internal/schema-primitives.d.ts +10 -0
- package/dist/internal/schema-primitives.js +9 -0
- package/dist/internal/schema-types.d.ts +2 -0
- package/dist/internal/schema-types.js +9 -0
- package/dist/logging.js +11 -3
- package/dist/recovery.d.ts +6 -2
- package/dist/recovery.js +49 -6
- package/dist/resilience.d.ts +6 -2
- package/dist/resilience.js +80 -4
- package/dist/result/index.js +1 -16
- package/dist/result/utilities.js +29 -7
- package/dist/schema.d.ts +2 -1
- package/dist/schema.js +165 -2
- package/dist/serialization.d.ts +8 -2
- package/dist/serialization.js +1 -3
- package/dist/shared/@outfitter/{contracts-k71jqd1m.d.ts → contracts-10p5q75w.d.ts} +1 -1
- package/dist/shared/@outfitter/contracts-1zzcpfyg.d.ts +40 -0
- package/dist/shared/@outfitter/contracts-3f5k5tg5.d.ts +28 -0
- package/dist/shared/@outfitter/contracts-3qmyq81n.d.ts +78 -0
- package/dist/shared/@outfitter/contracts-3re9d4bp.js +114 -0
- package/dist/shared/@outfitter/contracts-735ecmbq.d.ts +107 -0
- package/dist/shared/@outfitter/contracts-7a0xmwbg.d.ts +11 -0
- package/dist/shared/@outfitter/contracts-8cmkh2db.d.ts +31 -0
- package/dist/shared/@outfitter/{contracts-agmt8915.js → contracts-c3qfce25.js} +3 -0
- package/dist/shared/@outfitter/{contracts-1waabxbk.d.ts → contracts-drwd9ywk.d.ts} +4 -1
- package/dist/shared/@outfitter/{contracts-0snpmkdt.js → contracts-hgh47193.js} +10 -4
- package/dist/shared/@outfitter/contracts-hrepwwne.js +62 -0
- package/dist/shared/@outfitter/contracts-jtn6b927.js +18 -0
- package/dist/shared/@outfitter/contracts-jtt6dnmg.js +2 -0
- package/dist/shared/@outfitter/contracts-jyhqr766.js +25 -0
- package/dist/shared/@outfitter/contracts-mehpmvwp.d.ts +164 -0
- package/dist/shared/@outfitter/contracts-msxdg52h.d.ts +125 -0
- package/dist/shared/@outfitter/{contracts-95cc3y06.d.ts → contracts-mt027fqj.d.ts} +2 -1
- package/dist/shared/@outfitter/contracts-njb2art4.d.ts +174 -0
- package/dist/shared/@outfitter/contracts-p77yjs4g.d.ts +46 -0
- package/dist/shared/@outfitter/contracts-qpbv29bg.d.ts +59 -0
- package/dist/shared/@outfitter/contracts-sawwfgb5.js +111 -0
- package/dist/shared/@outfitter/{contracts-e4m948m7.d.ts → contracts-t4txv24h.d.ts} +2 -1
- package/dist/shared/@outfitter/contracts-vbgt9rfn.d.ts +74 -0
- package/dist/shared/@outfitter/{contracts-56pcsavx.d.ts → contracts-vhajx4gg.d.ts} +8 -2
- package/dist/shared/@outfitter/contracts-vhr2ep6b.js +3 -0
- package/dist/shared/@outfitter/contracts-w7nvcwrp.d.ts +44 -0
- package/dist/shared/@outfitter/contracts-x0ppyt7e.d.ts +76 -0
- package/dist/shared/@outfitter/{contracts-0akf2sm6.d.ts → contracts-zma4mscd.d.ts} +16 -1
- package/dist/shared/@outfitter/contracts-zsgxsa91.d.ts +84 -0
- package/dist/stream.d.ts +2 -0
- package/dist/stream.js +1 -0
- package/dist/validation.d.ts +7 -3
- package/dist/validation.js +6 -2
- package/dist/wrap-error.d.ts +7 -0
- package/dist/wrap-error.js +71 -0
- package/package.json +44 -20
- package/dist/shared/@outfitter/contracts-31penhwa.d.ts +0 -81
- package/dist/shared/@outfitter/contracts-3gswmhb1.d.ts +0 -446
- package/dist/shared/@outfitter/contracts-4zaj7ejb.js +0 -52
- package/dist/shared/@outfitter/contracts-85nd53s9.js +0 -53
- package/dist/shared/@outfitter/contracts-9wtm5nsw.d.ts +0 -42
- package/dist/shared/@outfitter/contracts-cp5c6dws.js +0 -32
- package/dist/shared/@outfitter/contracts-d0tq2adf.js +0 -60
- package/dist/shared/@outfitter/contracts-mmg0npfk.d.ts +0 -30
- package/dist/shared/@outfitter/contracts-phjhz5q3.js +0 -293
- 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-t79engf9.d.ts +0 -60
- package/dist/shared/@outfitter/contracts-wfht4q2b.js +0 -341
- package/dist/shared/@outfitter/contracts-zx72gyh1.js +0 -32
- /package/dist/{shared/@outfitter/contracts-37gpc56f.js → hints.js} +0 -0
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
import { TaggedErrorClass } from "better-result";
|
|
2
|
-
/**
|
|
3
|
-
* Error categories for classification, exit codes, and HTTP status mapping.
|
|
4
|
-
*
|
|
5
|
-
* Used for:
|
|
6
|
-
* - CLI exit code determination
|
|
7
|
-
* - HTTP status code mapping
|
|
8
|
-
* - Error grouping in logs and metrics
|
|
9
|
-
* - Client retry decisions (transient vs permanent)
|
|
10
|
-
*/
|
|
11
|
-
type ErrorCategory = "validation" | "not_found" | "conflict" | "permission" | "timeout" | "rate_limit" | "network" | "internal" | "auth" | "cancelled";
|
|
12
|
-
/**
|
|
13
|
-
* Maps error category to CLI exit code.
|
|
14
|
-
* Non-zero exit indicates error; specific values for script automation.
|
|
15
|
-
*/
|
|
16
|
-
declare const exitCodeMap: Record<ErrorCategory, number>;
|
|
17
|
-
/**
|
|
18
|
-
* Maps error category to HTTP status code.
|
|
19
|
-
* Used by MCP servers and API responses.
|
|
20
|
-
*/
|
|
21
|
-
declare const statusCodeMap: Record<ErrorCategory, number>;
|
|
22
|
-
/**
|
|
23
|
-
* Numeric error codes for granular error identification.
|
|
24
|
-
*
|
|
25
|
-
* Ranges by category:
|
|
26
|
-
* - validation: 1000-1999
|
|
27
|
-
* - not_found: 2000-2999
|
|
28
|
-
* - conflict: 3000-3999
|
|
29
|
-
* - permission: 4000-4999
|
|
30
|
-
* - timeout: 5000-5999
|
|
31
|
-
* - rate_limit: 6000-6999
|
|
32
|
-
* - network: 7000-7999
|
|
33
|
-
* - internal: 8000-8999
|
|
34
|
-
* - auth: 9000-9999
|
|
35
|
-
* - cancelled: 10000-10999
|
|
36
|
-
*/
|
|
37
|
-
declare const ERROR_CODES: {
|
|
38
|
-
readonly validation: {
|
|
39
|
-
readonly FIELD_REQUIRED: 1001;
|
|
40
|
-
readonly INVALID_FORMAT: 1002;
|
|
41
|
-
readonly OUT_OF_RANGE: 1003;
|
|
42
|
-
readonly TYPE_MISMATCH: 1004;
|
|
43
|
-
readonly AMBIGUOUS_MATCH: 1005;
|
|
44
|
-
};
|
|
45
|
-
readonly not_found: {
|
|
46
|
-
readonly RESOURCE_NOT_FOUND: 2001;
|
|
47
|
-
readonly FILE_NOT_FOUND: 2002;
|
|
48
|
-
};
|
|
49
|
-
readonly conflict: {
|
|
50
|
-
readonly ALREADY_EXISTS: 3001;
|
|
51
|
-
readonly VERSION_MISMATCH: 3002;
|
|
52
|
-
};
|
|
53
|
-
readonly permission: {
|
|
54
|
-
readonly FORBIDDEN: 4001;
|
|
55
|
-
readonly INSUFFICIENT_RIGHTS: 4002;
|
|
56
|
-
};
|
|
57
|
-
readonly timeout: {
|
|
58
|
-
readonly OPERATION_TIMEOUT: 5001;
|
|
59
|
-
readonly CONNECTION_TIMEOUT: 5002;
|
|
60
|
-
};
|
|
61
|
-
readonly rate_limit: {
|
|
62
|
-
readonly QUOTA_EXCEEDED: 6001;
|
|
63
|
-
readonly THROTTLED: 6002;
|
|
64
|
-
};
|
|
65
|
-
readonly network: {
|
|
66
|
-
readonly CONNECTION_REFUSED: 7001;
|
|
67
|
-
readonly DNS_FAILED: 7002;
|
|
68
|
-
};
|
|
69
|
-
readonly internal: {
|
|
70
|
-
readonly UNEXPECTED_STATE: 8001;
|
|
71
|
-
readonly ASSERTION_FAILED: 8002;
|
|
72
|
-
};
|
|
73
|
-
readonly auth: {
|
|
74
|
-
readonly INVALID_TOKEN: 9001;
|
|
75
|
-
readonly EXPIRED_TOKEN: 9002;
|
|
76
|
-
};
|
|
77
|
-
readonly cancelled: {
|
|
78
|
-
readonly USER_CANCELLED: 10_001;
|
|
79
|
-
readonly SIGNAL_RECEIVED: 10_002;
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Union type of all numeric error codes.
|
|
84
|
-
* Useful for type-safe error code handling.
|
|
85
|
-
*/
|
|
86
|
-
type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES][keyof (typeof ERROR_CODES)[keyof typeof ERROR_CODES]];
|
|
87
|
-
/**
|
|
88
|
-
* Serialized error format for JSON transport.
|
|
89
|
-
*/
|
|
90
|
-
interface SerializedError {
|
|
91
|
-
_tag: string;
|
|
92
|
-
category: ErrorCategory;
|
|
93
|
-
context?: Record<string, unknown>;
|
|
94
|
-
message: string;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Base interface for OutfitterError properties.
|
|
98
|
-
* All concrete error classes must include these fields.
|
|
99
|
-
*/
|
|
100
|
-
interface KitErrorProps {
|
|
101
|
-
category: ErrorCategory;
|
|
102
|
-
context?: Record<string, unknown>;
|
|
103
|
-
message: string;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Get CLI exit code for an error category.
|
|
107
|
-
*/
|
|
108
|
-
declare function getExitCode(category: ErrorCategory): number;
|
|
109
|
-
/**
|
|
110
|
-
* Get HTTP status code for an error category.
|
|
111
|
-
*/
|
|
112
|
-
declare function getStatusCode(category: ErrorCategory): number;
|
|
113
|
-
declare const ValidationErrorBase: TaggedErrorClass<"ValidationError", {
|
|
114
|
-
message: string;
|
|
115
|
-
field?: string;
|
|
116
|
-
context?: Record<string, unknown>;
|
|
117
|
-
}>;
|
|
118
|
-
declare const AmbiguousErrorBase: TaggedErrorClass<"AmbiguousError", {
|
|
119
|
-
message: string;
|
|
120
|
-
candidates: string[];
|
|
121
|
-
context?: Record<string, unknown>;
|
|
122
|
-
}>;
|
|
123
|
-
declare const AssertionErrorBase: TaggedErrorClass<"AssertionError", {
|
|
124
|
-
message: string;
|
|
125
|
-
}>;
|
|
126
|
-
declare const NotFoundErrorBase: TaggedErrorClass<"NotFoundError", {
|
|
127
|
-
message: string;
|
|
128
|
-
resourceType: string;
|
|
129
|
-
resourceId: string;
|
|
130
|
-
context?: Record<string, unknown>;
|
|
131
|
-
}>;
|
|
132
|
-
declare const AlreadyExistsErrorBase: TaggedErrorClass<"AlreadyExistsError", {
|
|
133
|
-
message: string;
|
|
134
|
-
resourceType: string;
|
|
135
|
-
resourceId: string;
|
|
136
|
-
context?: Record<string, unknown>;
|
|
137
|
-
}>;
|
|
138
|
-
declare const ConflictErrorBase: TaggedErrorClass<"ConflictError", {
|
|
139
|
-
message: string;
|
|
140
|
-
context?: Record<string, unknown>;
|
|
141
|
-
}>;
|
|
142
|
-
declare const PermissionErrorBase: TaggedErrorClass<"PermissionError", {
|
|
143
|
-
message: string;
|
|
144
|
-
context?: Record<string, unknown>;
|
|
145
|
-
}>;
|
|
146
|
-
declare const TimeoutErrorBase: TaggedErrorClass<"TimeoutError", {
|
|
147
|
-
message: string;
|
|
148
|
-
operation: string;
|
|
149
|
-
timeoutMs: number;
|
|
150
|
-
}>;
|
|
151
|
-
declare const RateLimitErrorBase: TaggedErrorClass<"RateLimitError", {
|
|
152
|
-
message: string;
|
|
153
|
-
retryAfterSeconds?: number;
|
|
154
|
-
}>;
|
|
155
|
-
declare const NetworkErrorBase: TaggedErrorClass<"NetworkError", {
|
|
156
|
-
message: string;
|
|
157
|
-
context?: Record<string, unknown>;
|
|
158
|
-
}>;
|
|
159
|
-
declare const InternalErrorBase: TaggedErrorClass<"InternalError", {
|
|
160
|
-
message: string;
|
|
161
|
-
context?: Record<string, unknown>;
|
|
162
|
-
}>;
|
|
163
|
-
declare const AuthErrorBase: TaggedErrorClass<"AuthError", {
|
|
164
|
-
message: string;
|
|
165
|
-
reason?: "missing" | "invalid" | "expired";
|
|
166
|
-
}>;
|
|
167
|
-
declare const CancelledErrorBase: TaggedErrorClass<"CancelledError", {
|
|
168
|
-
message: string;
|
|
169
|
-
}>;
|
|
170
|
-
/**
|
|
171
|
-
* Input validation failed.
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* ```typescript
|
|
175
|
-
* new ValidationError({ message: "Email format invalid", field: "email" });
|
|
176
|
-
* new ValidationError({
|
|
177
|
-
* message: "Value out of range",
|
|
178
|
-
* field: "age",
|
|
179
|
-
* context: { min: 0, max: 150, received: -1 },
|
|
180
|
-
* });
|
|
181
|
-
* ```
|
|
182
|
-
*/
|
|
183
|
-
declare class ValidationError extends ValidationErrorBase {
|
|
184
|
-
readonly category: "validation";
|
|
185
|
-
/** Create a ValidationError with auto-generated message from field name. */
|
|
186
|
-
static create(field: string, reason: string, context?: Record<string, unknown>): ValidationError;
|
|
187
|
-
/**
|
|
188
|
-
* Create a freeform ValidationError without a specific field.
|
|
189
|
-
*
|
|
190
|
-
* Use when the validation failure applies to the input as a whole
|
|
191
|
-
* rather than a single field (e.g., "Invalid pipeline configuration").
|
|
192
|
-
*
|
|
193
|
-
* @param message - Human-readable validation error message
|
|
194
|
-
* @param context - Optional structured context for debugging
|
|
195
|
-
*/
|
|
196
|
-
static fromMessage(message: string, context?: Record<string, unknown>): ValidationError;
|
|
197
|
-
exitCode(): number;
|
|
198
|
-
statusCode(): number;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Multiple matches found — user must disambiguate.
|
|
202
|
-
*
|
|
203
|
-
* Used in search/resolution systems where partial input matches
|
|
204
|
-
* multiple candidates. Carries the candidate list so transport
|
|
205
|
-
* layers can prompt disambiguation.
|
|
206
|
-
*
|
|
207
|
-
* @example
|
|
208
|
-
* ```typescript
|
|
209
|
-
* new AmbiguousError({
|
|
210
|
-
* message: "Multiple headings match 'Intro'",
|
|
211
|
-
* candidates: ["Introduction", "Intro to APIs"],
|
|
212
|
-
* });
|
|
213
|
-
* AmbiguousError.create("heading", ["Introduction", "Intro to APIs"]);
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
216
|
-
declare class AmbiguousError extends AmbiguousErrorBase {
|
|
217
|
-
readonly category: "validation";
|
|
218
|
-
/** Create an AmbiguousError with auto-generated message. */
|
|
219
|
-
static create(what: string, candidates: string[], context?: Record<string, unknown>): AmbiguousError;
|
|
220
|
-
exitCode(): number;
|
|
221
|
-
statusCode(): number;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Assertion failed (invariant violation).
|
|
225
|
-
*
|
|
226
|
-
* Used by assertion utilities that return Result types instead of throwing.
|
|
227
|
-
* AssertionError indicates a programming bug — an invariant that should
|
|
228
|
-
* never be violated was broken. These are internal errors, not user input
|
|
229
|
-
* validation failures.
|
|
230
|
-
*
|
|
231
|
-
* **Category rationale**: Uses `internal` (not `validation`) because:
|
|
232
|
-
* - Assertions check **invariants** (programmer assumptions), not user input
|
|
233
|
-
* - A failed assertion means "this should be impossible if the code is correct"
|
|
234
|
-
* - User-facing validation uses {@link ValidationError} with helpful field info
|
|
235
|
-
* - HTTP 500 is correct: this is a server bug, not a client mistake
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```typescript
|
|
239
|
-
* // In domain logic after validation has passed
|
|
240
|
-
* const result = assertDefined(cachedValue, "Cache should always have value after init");
|
|
241
|
-
* if (result.isErr()) {
|
|
242
|
-
* return result; // Propagate as internal error
|
|
243
|
-
* }
|
|
244
|
-
* ```
|
|
245
|
-
*
|
|
246
|
-
* @see ValidationError - For user input validation failures (HTTP 400)
|
|
247
|
-
*/
|
|
248
|
-
declare class AssertionError extends AssertionErrorBase {
|
|
249
|
-
readonly category: "internal";
|
|
250
|
-
exitCode(): number;
|
|
251
|
-
statusCode(): number;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Requested resource not found.
|
|
255
|
-
*
|
|
256
|
-
* @example
|
|
257
|
-
* ```typescript
|
|
258
|
-
* new NotFoundError({ message: "note not found: abc123", resourceType: "note", resourceId: "abc123" });
|
|
259
|
-
* new NotFoundError({
|
|
260
|
-
* message: "Heading not found",
|
|
261
|
-
* resourceType: "heading",
|
|
262
|
-
* resourceId: "h:Intro",
|
|
263
|
-
* context: { availableHeadings: ["Introduction", "Getting Started"] },
|
|
264
|
-
* });
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
declare class NotFoundError extends NotFoundErrorBase {
|
|
268
|
-
readonly category: "not_found";
|
|
269
|
-
/** Create a NotFoundError with auto-generated message. */
|
|
270
|
-
static create(resourceType: string, resourceId: string, context?: Record<string, unknown>): NotFoundError;
|
|
271
|
-
exitCode(): number;
|
|
272
|
-
statusCode(): number;
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Resource already exists — the inverse of {@link NotFoundError}.
|
|
276
|
-
*
|
|
277
|
-
* Use when a create/write operation fails because the target resource
|
|
278
|
-
* is already present. Carries `resourceType` and `resourceId` to identify
|
|
279
|
-
* what already exists, mirroring {@link NotFoundError}'s structure.
|
|
280
|
-
*
|
|
281
|
-
* Maps to HTTP 409 (Conflict) and exit code 3.
|
|
282
|
-
*
|
|
283
|
-
* @example
|
|
284
|
-
* ```typescript
|
|
285
|
-
* new AlreadyExistsError({
|
|
286
|
-
* message: "File already exists: notes/meeting.md",
|
|
287
|
-
* resourceType: "file",
|
|
288
|
-
* resourceId: "notes/meeting.md",
|
|
289
|
-
* });
|
|
290
|
-
* AlreadyExistsError.create("file", "notes/meeting.md");
|
|
291
|
-
* ```
|
|
292
|
-
*
|
|
293
|
-
* @see ConflictError - For general state conflicts (version mismatch, concurrent modification)
|
|
294
|
-
* @see NotFoundError - The inverse: resource does not exist
|
|
295
|
-
*/
|
|
296
|
-
declare class AlreadyExistsError extends AlreadyExistsErrorBase {
|
|
297
|
-
readonly category: "conflict";
|
|
298
|
-
/** Create an AlreadyExistsError with auto-generated message. */
|
|
299
|
-
static create(resourceType: string, resourceId: string, context?: Record<string, unknown>): AlreadyExistsError;
|
|
300
|
-
exitCode(): number;
|
|
301
|
-
statusCode(): number;
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* State conflict (version mismatch, concurrent modification).
|
|
305
|
-
*
|
|
306
|
-
* Use for general conflicts that don't fit {@link AlreadyExistsError}:
|
|
307
|
-
* optimistic locking failures, concurrent writes, ETag mismatches,
|
|
308
|
-
* or any case where the operation can't proceed due to state divergence.
|
|
309
|
-
*
|
|
310
|
-
* Maps to HTTP 409 (Conflict) and exit code 3.
|
|
311
|
-
*
|
|
312
|
-
* **Choosing the right conflict error:**
|
|
313
|
-
* - Resource already exists? Use {@link AlreadyExistsError}
|
|
314
|
-
* - Version/ETag mismatch? Use {@link ConflictError}
|
|
315
|
-
* - Concurrent modification detected? Use {@link ConflictError}
|
|
316
|
-
*
|
|
317
|
-
* @example
|
|
318
|
-
* ```typescript
|
|
319
|
-
* new ConflictError({ message: "Resource was modified by another process" });
|
|
320
|
-
* ConflictError.create("ETag mismatch: expected abc, got def");
|
|
321
|
-
* ```
|
|
322
|
-
*
|
|
323
|
-
* @see AlreadyExistsError - For "resource already exists" specifically
|
|
324
|
-
*/
|
|
325
|
-
declare class ConflictError extends ConflictErrorBase {
|
|
326
|
-
readonly category: "conflict";
|
|
327
|
-
/** Create a ConflictError with optional context. */
|
|
328
|
-
static create(message: string, context?: Record<string, unknown>): ConflictError;
|
|
329
|
-
exitCode(): number;
|
|
330
|
-
statusCode(): number;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Authorization denied.
|
|
334
|
-
*
|
|
335
|
-
* @example
|
|
336
|
-
* ```typescript
|
|
337
|
-
* new PermissionError({ message: "Cannot delete read-only resource" });
|
|
338
|
-
* ```
|
|
339
|
-
*/
|
|
340
|
-
declare class PermissionError extends PermissionErrorBase {
|
|
341
|
-
readonly category: "permission";
|
|
342
|
-
/** Create a PermissionError with optional context. */
|
|
343
|
-
static create(message: string, context?: Record<string, unknown>): PermissionError;
|
|
344
|
-
exitCode(): number;
|
|
345
|
-
statusCode(): number;
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Operation timed out.
|
|
349
|
-
*
|
|
350
|
-
* @example
|
|
351
|
-
* ```typescript
|
|
352
|
-
* new TimeoutError({ message: "Database query timed out after 5000ms", operation: "Database query", timeoutMs: 5000 });
|
|
353
|
-
* ```
|
|
354
|
-
*/
|
|
355
|
-
declare class TimeoutError extends TimeoutErrorBase {
|
|
356
|
-
readonly category: "timeout";
|
|
357
|
-
/** Create a TimeoutError with auto-generated message. */
|
|
358
|
-
static create(operation: string, timeoutMs: number): TimeoutError;
|
|
359
|
-
exitCode(): number;
|
|
360
|
-
statusCode(): number;
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* Rate limit exceeded.
|
|
364
|
-
*
|
|
365
|
-
* @example
|
|
366
|
-
* ```typescript
|
|
367
|
-
* new RateLimitError({ message: "Rate limit exceeded, retry after 60s", retryAfterSeconds: 60 });
|
|
368
|
-
* ```
|
|
369
|
-
*/
|
|
370
|
-
declare class RateLimitError extends RateLimitErrorBase {
|
|
371
|
-
readonly category: "rate_limit";
|
|
372
|
-
/** Create a RateLimitError with optional retry hint. */
|
|
373
|
-
static create(message: string, retryAfterSeconds?: number): RateLimitError;
|
|
374
|
-
exitCode(): number;
|
|
375
|
-
statusCode(): number;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Network/transport failure.
|
|
379
|
-
*
|
|
380
|
-
* @example
|
|
381
|
-
* ```typescript
|
|
382
|
-
* new NetworkError({ message: "Connection refused to api.example.com" });
|
|
383
|
-
* ```
|
|
384
|
-
*/
|
|
385
|
-
declare class NetworkError extends NetworkErrorBase {
|
|
386
|
-
readonly category: "network";
|
|
387
|
-
/** Create a NetworkError with optional context. */
|
|
388
|
-
static create(message: string, context?: Record<string, unknown>): NetworkError;
|
|
389
|
-
exitCode(): number;
|
|
390
|
-
statusCode(): number;
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Unexpected internal error.
|
|
394
|
-
*
|
|
395
|
-
* @example
|
|
396
|
-
* ```typescript
|
|
397
|
-
* new InternalError({ message: "Unexpected state in processor" });
|
|
398
|
-
* ```
|
|
399
|
-
*/
|
|
400
|
-
declare class InternalError extends InternalErrorBase {
|
|
401
|
-
readonly category: "internal";
|
|
402
|
-
/** Create an InternalError with optional context. */
|
|
403
|
-
static create(message: string, context?: Record<string, unknown>): InternalError;
|
|
404
|
-
exitCode(): number;
|
|
405
|
-
statusCode(): number;
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Authentication failed (missing or invalid credentials).
|
|
409
|
-
*
|
|
410
|
-
* @example
|
|
411
|
-
* ```typescript
|
|
412
|
-
* new AuthError({ message: "Invalid API key", reason: "invalid" });
|
|
413
|
-
* ```
|
|
414
|
-
*/
|
|
415
|
-
declare class AuthError extends AuthErrorBase {
|
|
416
|
-
readonly category: "auth";
|
|
417
|
-
/** Create an AuthError with optional reason. */
|
|
418
|
-
static create(message: string, reason?: "missing" | "invalid" | "expired"): AuthError;
|
|
419
|
-
exitCode(): number;
|
|
420
|
-
statusCode(): number;
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Operation cancelled by user or signal.
|
|
424
|
-
*
|
|
425
|
-
* @example
|
|
426
|
-
* ```typescript
|
|
427
|
-
* new CancelledError({ message: "Operation cancelled by user" });
|
|
428
|
-
* ```
|
|
429
|
-
*/
|
|
430
|
-
declare class CancelledError extends CancelledErrorBase {
|
|
431
|
-
readonly category: "cancelled";
|
|
432
|
-
/** Create a CancelledError. */
|
|
433
|
-
static create(message: string): CancelledError;
|
|
434
|
-
exitCode(): number;
|
|
435
|
-
statusCode(): number;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Union type of all concrete error class instances.
|
|
439
|
-
*/
|
|
440
|
-
type AnyKitError = InstanceType<typeof ValidationError> | InstanceType<typeof AmbiguousError> | InstanceType<typeof AssertionError> | InstanceType<typeof NotFoundError> | InstanceType<typeof AlreadyExistsError> | InstanceType<typeof ConflictError> | InstanceType<typeof PermissionError> | InstanceType<typeof TimeoutError> | InstanceType<typeof RateLimitError> | InstanceType<typeof NetworkError> | InstanceType<typeof InternalError> | InstanceType<typeof AuthError> | InstanceType<typeof CancelledError>;
|
|
441
|
-
/**
|
|
442
|
-
* Type alias for backwards compatibility with handler signatures.
|
|
443
|
-
* Use AnyKitError for the union type.
|
|
444
|
-
*/
|
|
445
|
-
type OutfitterError = AnyKitError;
|
|
446
|
-
export { ErrorCategory, exitCodeMap, statusCodeMap, ERROR_CODES, ErrorCode, SerializedError, KitErrorProps, getExitCode, getStatusCode, ValidationError, AmbiguousError, AssertionError, NotFoundError, AlreadyExistsError, ConflictError, PermissionError, TimeoutError, RateLimitError, NetworkError, InternalError, AuthError, CancelledError, AnyKitError, OutfitterError };
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// packages/contracts/src/recovery.ts
|
|
3
|
-
var RECOVERABLE_CATEGORIES = [
|
|
4
|
-
"network",
|
|
5
|
-
"timeout",
|
|
6
|
-
"rate_limit",
|
|
7
|
-
"conflict"
|
|
8
|
-
];
|
|
9
|
-
var RETRYABLE_CATEGORIES = ["network", "timeout"];
|
|
10
|
-
var isRecoverable = (error) => {
|
|
11
|
-
return RECOVERABLE_CATEGORIES.includes(error.category);
|
|
12
|
-
};
|
|
13
|
-
var isRetryable = (error) => {
|
|
14
|
-
return RETRYABLE_CATEGORIES.includes(error.category);
|
|
15
|
-
};
|
|
16
|
-
var getBackoffDelay = (attempt, options = {}) => {
|
|
17
|
-
const {
|
|
18
|
-
baseDelayMs = 100,
|
|
19
|
-
maxDelayMs = 30000,
|
|
20
|
-
strategy = "exponential",
|
|
21
|
-
useJitter = true
|
|
22
|
-
} = options;
|
|
23
|
-
let delay;
|
|
24
|
-
switch (strategy) {
|
|
25
|
-
case "constant": {
|
|
26
|
-
delay = baseDelayMs;
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
case "linear": {
|
|
30
|
-
delay = baseDelayMs * (attempt + 1);
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
default: {
|
|
34
|
-
delay = baseDelayMs * 2 ** attempt;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
delay = Math.min(delay, maxDelayMs);
|
|
38
|
-
if (useJitter) {
|
|
39
|
-
const jitterFactor = 0.1;
|
|
40
|
-
const jitter = delay * jitterFactor * (Math.random() * 2 - 1);
|
|
41
|
-
delay = Math.round(delay + jitter);
|
|
42
|
-
}
|
|
43
|
-
return Math.min(delay, maxDelayMs);
|
|
44
|
-
};
|
|
45
|
-
var shouldRetry = (error, attempt, maxAttempts = 3) => {
|
|
46
|
-
if (attempt >= maxAttempts) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
return isRetryable(error);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export { isRecoverable, isRetryable, getBackoffDelay, shouldRetry };
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
serializeError
|
|
4
|
-
} from "./contracts-3wj7xghe.js";
|
|
5
|
-
import {
|
|
6
|
-
statusCodeMap
|
|
7
|
-
} from "./contracts-phjhz5q3.js";
|
|
8
|
-
import {
|
|
9
|
-
generateRequestId
|
|
10
|
-
} from "./contracts-agmt8915.js";
|
|
11
|
-
|
|
12
|
-
// packages/contracts/src/envelope.ts
|
|
13
|
-
function buildMeta(overrides) {
|
|
14
|
-
const meta = {
|
|
15
|
-
requestId: overrides?.requestId ?? generateRequestId(),
|
|
16
|
-
timestamp: new Date().toISOString()
|
|
17
|
-
};
|
|
18
|
-
if (overrides?.durationMs !== undefined) {
|
|
19
|
-
meta.durationMs = overrides.durationMs;
|
|
20
|
-
}
|
|
21
|
-
return meta;
|
|
22
|
-
}
|
|
23
|
-
function toEnvelope(result, meta) {
|
|
24
|
-
const envelopeMeta = buildMeta(meta);
|
|
25
|
-
if (result.isOk()) {
|
|
26
|
-
return {
|
|
27
|
-
ok: true,
|
|
28
|
-
data: result.value,
|
|
29
|
-
meta: envelopeMeta
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
ok: false,
|
|
34
|
-
error: serializeError(result.error),
|
|
35
|
-
meta: envelopeMeta
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function toHttpResponse(result) {
|
|
39
|
-
const envelope = toEnvelope(result);
|
|
40
|
-
if (envelope.ok) {
|
|
41
|
-
return {
|
|
42
|
-
status: 200,
|
|
43
|
-
body: envelope
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
const status = statusCodeMap[envelope.error.category];
|
|
47
|
-
return {
|
|
48
|
-
status,
|
|
49
|
-
body: envelope
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { toEnvelope, toHttpResponse };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { ValidationError } from "./contracts-3gswmhb1.js";
|
|
2
|
-
import { Result } from "better-result";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
/**
|
|
5
|
-
* Create a validator function from a Zod schema.
|
|
6
|
-
*
|
|
7
|
-
* @typeParam T - The validated output type
|
|
8
|
-
* @param schema - Zod schema to validate against
|
|
9
|
-
* @returns A function that validates input and returns Result
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const NoteSchema = z.object({
|
|
14
|
-
* id: z.string().uuid(),
|
|
15
|
-
* title: z.string().min(1),
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* const validateNote = createValidator(NoteSchema);
|
|
19
|
-
* const result = validateNote(input); // Result<Note, ValidationError>
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
declare function createValidator<T>(schema: z.ZodType<T>): (input: unknown) => Result<T, ValidationError>;
|
|
23
|
-
/**
|
|
24
|
-
* Validate input against a Zod schema.
|
|
25
|
-
*
|
|
26
|
-
* Standardized wrapper for Zod schemas that returns Result instead of throwing.
|
|
27
|
-
*
|
|
28
|
-
* @typeParam T - The validated output type
|
|
29
|
-
* @param schema - Zod schema to validate against
|
|
30
|
-
* @param input - Unknown input to validate
|
|
31
|
-
* @returns Result with validated data or ValidationError
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```typescript
|
|
35
|
-
* const result = validateInput(NoteSchema, userInput);
|
|
36
|
-
* if (result.isErr()) {
|
|
37
|
-
* console.error(result.unwrapErr().message);
|
|
38
|
-
* }
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
declare function validateInput<T>(schema: z.ZodType<T>, input: unknown): Result<T, ValidationError>;
|
|
42
|
-
export { createValidator, validateInput };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
AssertionError
|
|
4
|
-
} from "./contracts-phjhz5q3.js";
|
|
5
|
-
|
|
6
|
-
// packages/contracts/src/assert/index.ts
|
|
7
|
-
import { Result } from "better-result";
|
|
8
|
-
var isNonEmptyArray = (arr) => {
|
|
9
|
-
return arr.length > 0;
|
|
10
|
-
};
|
|
11
|
-
var assertDefined = (value, message) => {
|
|
12
|
-
if (value === null || value === undefined) {
|
|
13
|
-
return Result.err(new AssertionError({ message: message ?? "Value is null or undefined" }));
|
|
14
|
-
}
|
|
15
|
-
return Result.ok(value);
|
|
16
|
-
};
|
|
17
|
-
var assertNonEmpty = (arr, message) => {
|
|
18
|
-
if (arr.length === 0) {
|
|
19
|
-
return Result.err(new AssertionError({ message: message ?? "Array is empty" }));
|
|
20
|
-
}
|
|
21
|
-
return Result.ok(arr);
|
|
22
|
-
};
|
|
23
|
-
function assertMatches(value, predicate, message) {
|
|
24
|
-
if (!predicate(value)) {
|
|
25
|
-
return Result.err(new AssertionError({
|
|
26
|
-
message: message ?? "Value does not match predicate"
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
return Result.ok(value);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { isNonEmptyArray, assertDefined, assertNonEmpty, assertMatches };
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// packages/contracts/src/capabilities.ts
|
|
3
|
-
var CAPABILITY_SURFACES = ["cli", "mcp", "api", "server"];
|
|
4
|
-
var DEFAULT_ACTION_SURFACES = ["cli", "mcp"];
|
|
5
|
-
function capability(surfaces = DEFAULT_ACTION_SURFACES, notes) {
|
|
6
|
-
return notes ? { surfaces, notes } : { surfaces };
|
|
7
|
-
}
|
|
8
|
-
function capabilityAll(notes) {
|
|
9
|
-
return capability(CAPABILITY_SURFACES, notes);
|
|
10
|
-
}
|
|
11
|
-
var ACTION_CAPABILITIES = {
|
|
12
|
-
navigate: capability(),
|
|
13
|
-
back: capability(),
|
|
14
|
-
forward: capability(),
|
|
15
|
-
reload: capability(),
|
|
16
|
-
tab: capability(),
|
|
17
|
-
tabs: capability(),
|
|
18
|
-
newTab: capability(),
|
|
19
|
-
closeTab: capability(),
|
|
20
|
-
click: capability(),
|
|
21
|
-
type: capability(),
|
|
22
|
-
select: capability(),
|
|
23
|
-
hover: capability(),
|
|
24
|
-
focus: capability(["mcp"]),
|
|
25
|
-
scroll: capability(),
|
|
26
|
-
press: capability(),
|
|
27
|
-
fill: capability(),
|
|
28
|
-
find: capability(),
|
|
29
|
-
check: capability(),
|
|
30
|
-
uncheck: capability(),
|
|
31
|
-
upload: capability(),
|
|
32
|
-
download: capability(["server"], "Server-only for now"),
|
|
33
|
-
dialog: capability(),
|
|
34
|
-
waitFor: capability(["mcp"]),
|
|
35
|
-
waitForNavigation: capability(["mcp"]),
|
|
36
|
-
wait: capability(["mcp"]),
|
|
37
|
-
snap: capability(),
|
|
38
|
-
screenshot: capability(),
|
|
39
|
-
html: capability(["mcp"]),
|
|
40
|
-
text: capability(["mcp"]),
|
|
41
|
-
marker: capability(),
|
|
42
|
-
markers: capability(),
|
|
43
|
-
markerGet: capability(),
|
|
44
|
-
markerRead: capability(["mcp"]),
|
|
45
|
-
markerCompare: capability(),
|
|
46
|
-
markerDelete: capability(),
|
|
47
|
-
markerResolve: capability(["cli"], "CLI-only for now"),
|
|
48
|
-
viewport: capability(),
|
|
49
|
-
colorScheme: capability(),
|
|
50
|
-
mode: capability(["mcp"]),
|
|
51
|
-
evaluate: capability(["mcp"]),
|
|
52
|
-
session: capability(),
|
|
53
|
-
sessions: capability(["mcp"]),
|
|
54
|
-
steps: capability()
|
|
55
|
-
};
|
|
56
|
-
function getActionsForSurface(surface) {
|
|
57
|
-
return Object.entries(ACTION_CAPABILITIES).filter(([, capability2]) => capability2.surfaces.includes(surface)).map(([action]) => action);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export { CAPABILITY_SURFACES, DEFAULT_ACTION_SURFACES, capability, capabilityAll, ACTION_CAPABILITIES, getActionsForSurface };
|