@outfitter/contracts 0.4.2 → 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/dist/actions.d.ts +8 -3
- package/dist/assert/index.d.ts +7 -3
- package/dist/assert/index.js +32 -1
- package/dist/context.d.ts +8 -3
- package/dist/context.js +1 -1
- package/dist/envelope.d.ts +6 -2
- package/dist/envelope.js +5 -6
- 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/hints.js +1 -0
- package/dist/index.d.ts +24 -13
- package/dist/index.js +5 -3
- 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-5k6q4n48.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/recovery.d.ts +6 -2
- package/dist/resilience.d.ts +6 -2
- package/dist/resilience.js +6 -2
- package/dist/schema.d.ts +2 -1
- package/dist/schema.js +15 -187
- 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-hgh47193.js +46 -0
- 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 +8 -36
- package/dist/wrap-error.d.ts +7 -0
- package/dist/wrap-error.js +71 -0
- package/package.json +41 -17
- 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-9wtm5nsw.d.ts +0 -42
- package/dist/shared/@outfitter/contracts-mmg0npfk.d.ts +0 -30
- package/dist/shared/@outfitter/contracts-phjhz5q3.js +0 -293
- package/dist/shared/@outfitter/contracts-t79engf9.d.ts +0 -60
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { TaggedErrorClass } from "better-result";
|
|
2
|
+
declare const ValidationErrorBase: TaggedErrorClass<"ValidationError", {
|
|
3
|
+
message: string;
|
|
4
|
+
field?: string;
|
|
5
|
+
context?: Record<string, unknown>;
|
|
6
|
+
}>;
|
|
7
|
+
declare const AmbiguousErrorBase: TaggedErrorClass<"AmbiguousError", {
|
|
8
|
+
message: string;
|
|
9
|
+
candidates: string[];
|
|
10
|
+
context?: Record<string, unknown>;
|
|
11
|
+
}>;
|
|
12
|
+
declare const AssertionErrorBase: TaggedErrorClass<"AssertionError", {
|
|
13
|
+
message: string;
|
|
14
|
+
}>;
|
|
15
|
+
declare const NotFoundErrorBase: TaggedErrorClass<"NotFoundError", {
|
|
16
|
+
message: string;
|
|
17
|
+
resourceType: string;
|
|
18
|
+
resourceId: string;
|
|
19
|
+
context?: Record<string, unknown>;
|
|
20
|
+
}>;
|
|
21
|
+
declare const AlreadyExistsErrorBase: TaggedErrorClass<"AlreadyExistsError", {
|
|
22
|
+
message: string;
|
|
23
|
+
resourceType: string;
|
|
24
|
+
resourceId: string;
|
|
25
|
+
context?: Record<string, unknown>;
|
|
26
|
+
}>;
|
|
27
|
+
declare const ConflictErrorBase: TaggedErrorClass<"ConflictError", {
|
|
28
|
+
message: string;
|
|
29
|
+
context?: Record<string, unknown>;
|
|
30
|
+
}>;
|
|
31
|
+
declare const PermissionErrorBase: TaggedErrorClass<"PermissionError", {
|
|
32
|
+
message: string;
|
|
33
|
+
context?: Record<string, unknown>;
|
|
34
|
+
}>;
|
|
35
|
+
declare const TimeoutErrorBase: TaggedErrorClass<"TimeoutError", {
|
|
36
|
+
message: string;
|
|
37
|
+
operation: string;
|
|
38
|
+
timeoutMs: number;
|
|
39
|
+
}>;
|
|
40
|
+
declare const RateLimitErrorBase: TaggedErrorClass<"RateLimitError", {
|
|
41
|
+
message: string;
|
|
42
|
+
retryAfterSeconds?: number;
|
|
43
|
+
}>;
|
|
44
|
+
declare const NetworkErrorBase: TaggedErrorClass<"NetworkError", {
|
|
45
|
+
message: string;
|
|
46
|
+
context?: Record<string, unknown>;
|
|
47
|
+
}>;
|
|
48
|
+
declare const InternalErrorBase: TaggedErrorClass<"InternalError", {
|
|
49
|
+
message: string;
|
|
50
|
+
context?: Record<string, unknown>;
|
|
51
|
+
}>;
|
|
52
|
+
declare const AuthErrorBase: TaggedErrorClass<"AuthError", {
|
|
53
|
+
message: string;
|
|
54
|
+
reason?: "missing" | "invalid" | "expired";
|
|
55
|
+
}>;
|
|
56
|
+
declare const CancelledErrorBase: TaggedErrorClass<"CancelledError", {
|
|
57
|
+
message: string;
|
|
58
|
+
}>;
|
|
59
|
+
export { ValidationErrorBase, AmbiguousErrorBase, AssertionErrorBase, NotFoundErrorBase, AlreadyExistsErrorBase, ConflictErrorBase, PermissionErrorBase, TimeoutErrorBase, RateLimitErrorBase, NetworkErrorBase, InternalErrorBase, AuthErrorBase, CancelledErrorBase };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/contracts/src/internal/error-taxonomy.ts
|
|
3
|
+
var exitCodeMap = {
|
|
4
|
+
validation: 1,
|
|
5
|
+
not_found: 2,
|
|
6
|
+
conflict: 3,
|
|
7
|
+
permission: 4,
|
|
8
|
+
timeout: 5,
|
|
9
|
+
rate_limit: 6,
|
|
10
|
+
network: 7,
|
|
11
|
+
internal: 8,
|
|
12
|
+
auth: 9,
|
|
13
|
+
cancelled: 130
|
|
14
|
+
};
|
|
15
|
+
var statusCodeMap = {
|
|
16
|
+
validation: 400,
|
|
17
|
+
not_found: 404,
|
|
18
|
+
conflict: 409,
|
|
19
|
+
permission: 403,
|
|
20
|
+
timeout: 504,
|
|
21
|
+
rate_limit: 429,
|
|
22
|
+
network: 502,
|
|
23
|
+
internal: 500,
|
|
24
|
+
auth: 401,
|
|
25
|
+
cancelled: 499
|
|
26
|
+
};
|
|
27
|
+
var jsonRpcCodeMap = {
|
|
28
|
+
validation: -32602,
|
|
29
|
+
not_found: -32007,
|
|
30
|
+
internal: -32603,
|
|
31
|
+
auth: -32000,
|
|
32
|
+
timeout: -32001,
|
|
33
|
+
conflict: -32002,
|
|
34
|
+
permission: -32003,
|
|
35
|
+
rate_limit: -32004,
|
|
36
|
+
network: -32005,
|
|
37
|
+
cancelled: -32006
|
|
38
|
+
};
|
|
39
|
+
var retryableMap = {
|
|
40
|
+
validation: false,
|
|
41
|
+
not_found: false,
|
|
42
|
+
conflict: false,
|
|
43
|
+
permission: false,
|
|
44
|
+
timeout: true,
|
|
45
|
+
rate_limit: true,
|
|
46
|
+
network: true,
|
|
47
|
+
internal: false,
|
|
48
|
+
auth: false,
|
|
49
|
+
cancelled: false
|
|
50
|
+
};
|
|
51
|
+
function errorCategoryMeta(category) {
|
|
52
|
+
return {
|
|
53
|
+
exitCode: exitCodeMap[category],
|
|
54
|
+
statusCode: statusCodeMap[category],
|
|
55
|
+
jsonRpcCode: jsonRpcCodeMap[category],
|
|
56
|
+
retryable: retryableMap[category]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
var ERROR_CODES = {
|
|
60
|
+
validation: {
|
|
61
|
+
FIELD_REQUIRED: 1001,
|
|
62
|
+
INVALID_FORMAT: 1002,
|
|
63
|
+
OUT_OF_RANGE: 1003,
|
|
64
|
+
TYPE_MISMATCH: 1004,
|
|
65
|
+
AMBIGUOUS_MATCH: 1005
|
|
66
|
+
},
|
|
67
|
+
not_found: {
|
|
68
|
+
RESOURCE_NOT_FOUND: 2001,
|
|
69
|
+
FILE_NOT_FOUND: 2002
|
|
70
|
+
},
|
|
71
|
+
conflict: {
|
|
72
|
+
ALREADY_EXISTS: 3001,
|
|
73
|
+
VERSION_MISMATCH: 3002
|
|
74
|
+
},
|
|
75
|
+
permission: {
|
|
76
|
+
FORBIDDEN: 4001,
|
|
77
|
+
INSUFFICIENT_RIGHTS: 4002
|
|
78
|
+
},
|
|
79
|
+
timeout: {
|
|
80
|
+
OPERATION_TIMEOUT: 5001,
|
|
81
|
+
CONNECTION_TIMEOUT: 5002
|
|
82
|
+
},
|
|
83
|
+
rate_limit: {
|
|
84
|
+
QUOTA_EXCEEDED: 6001,
|
|
85
|
+
THROTTLED: 6002
|
|
86
|
+
},
|
|
87
|
+
network: {
|
|
88
|
+
CONNECTION_REFUSED: 7001,
|
|
89
|
+
DNS_FAILED: 7002
|
|
90
|
+
},
|
|
91
|
+
internal: {
|
|
92
|
+
UNEXPECTED_STATE: 8001,
|
|
93
|
+
ASSERTION_FAILED: 8002
|
|
94
|
+
},
|
|
95
|
+
auth: {
|
|
96
|
+
INVALID_TOKEN: 9001,
|
|
97
|
+
EXPIRED_TOKEN: 9002
|
|
98
|
+
},
|
|
99
|
+
cancelled: {
|
|
100
|
+
USER_CANCELLED: 10001,
|
|
101
|
+
SIGNAL_RECEIVED: 10002
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
function getExitCode(category) {
|
|
105
|
+
return exitCodeMap[category];
|
|
106
|
+
}
|
|
107
|
+
function getStatusCode(category) {
|
|
108
|
+
return statusCodeMap[category];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { exitCodeMap, statusCodeMap, jsonRpcCodeMap, retryableMap, errorCategoryMeta, ERROR_CODES, getExitCode, getStatusCode };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { OutfitterError
|
|
1
|
+
import { OutfitterError } from "./contracts-7a0xmwbg.js";
|
|
2
|
+
import { SerializedError } from "./contracts-njb2art4.js";
|
|
2
3
|
import { Result } from "better-result";
|
|
3
4
|
/**
|
|
4
5
|
* Metadata attached to every response envelope.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hint types for agent-navigable responses.
|
|
3
|
+
*
|
|
4
|
+
* Hints are transport-local suggestions attached to command/tool responses.
|
|
5
|
+
* They guide agents (and humans) toward next actions without coupling
|
|
6
|
+
* handler logic to any specific transport.
|
|
7
|
+
*
|
|
8
|
+
* - {@link ActionHint} — Base hint with description and optional params
|
|
9
|
+
* - {@link CLIHint} — CLI-specific hint with a runnable command
|
|
10
|
+
* - {@link MCPHint} — MCP-specific hint with tool name and optional input
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Base hint type for action responses.
|
|
16
|
+
*
|
|
17
|
+
* Describes a suggested next action with optional structured parameters.
|
|
18
|
+
* Transport-specific hints ({@link CLIHint}, {@link MCPHint}) extend this
|
|
19
|
+
* with transport-appropriate fields.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const hint: ActionHint = {
|
|
24
|
+
* description: "Retry the operation with a longer timeout",
|
|
25
|
+
* params: { timeoutMs: 10_000 },
|
|
26
|
+
* };
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
interface ActionHint {
|
|
30
|
+
/** Human-readable description of the suggested action. */
|
|
31
|
+
readonly description: string;
|
|
32
|
+
/** Optional structured parameters for the suggested action. */
|
|
33
|
+
readonly params?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* CLI-specific hint with a runnable command string.
|
|
37
|
+
*
|
|
38
|
+
* Extends {@link ActionHint} with a `command` field that agents or users
|
|
39
|
+
* can execute directly in the terminal.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const hint: CLIHint = {
|
|
44
|
+
* description: "Fix lint issues automatically",
|
|
45
|
+
* command: "outfitter lint --fix",
|
|
46
|
+
* };
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
interface CLIHint extends ActionHint {
|
|
50
|
+
/** CLI command string that can be executed to perform the suggested action. */
|
|
51
|
+
readonly command: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* MCP-specific hint with a tool name and optional input.
|
|
55
|
+
*
|
|
56
|
+
* Extends {@link ActionHint} with a `tool` field identifying the MCP tool
|
|
57
|
+
* to invoke, and an optional `input` payload for that tool.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const hint: MCPHint = {
|
|
62
|
+
* description: "Search for related notes",
|
|
63
|
+
* tool: "search-notes",
|
|
64
|
+
* input: { query: "architecture patterns", limit: 5 },
|
|
65
|
+
* };
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
interface MCPHint extends ActionHint {
|
|
69
|
+
/** MCP tool name to invoke for the suggested action. */
|
|
70
|
+
readonly tool: string;
|
|
71
|
+
/** Optional input payload for the MCP tool. */
|
|
72
|
+
readonly input?: unknown;
|
|
73
|
+
}
|
|
74
|
+
export { ActionHint, CLIHint, MCPHint };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Handler, SyncHandler } from "./contracts-
|
|
2
|
-
import { OutfitterError } from "./contracts-
|
|
1
|
+
import { Handler, SyncHandler } from "./contracts-zma4mscd.js";
|
|
2
|
+
import { OutfitterError } from "./contracts-7a0xmwbg.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];
|
|
@@ -25,7 +25,13 @@ interface ActionCliSpec<TInput = unknown> {
|
|
|
25
25
|
interface ActionMcpSpec<TInput = unknown> {
|
|
26
26
|
readonly deferLoading?: boolean;
|
|
27
27
|
readonly description?: string;
|
|
28
|
+
/** When true, the action modifies or deletes data */
|
|
29
|
+
readonly destructive?: boolean;
|
|
30
|
+
/** When true, calling the action multiple times with the same input has the same effect */
|
|
31
|
+
readonly idempotent?: boolean;
|
|
28
32
|
readonly mapInput?: (input: unknown) => TInput;
|
|
33
|
+
/** When true, the action does not modify any state */
|
|
34
|
+
readonly readOnly?: boolean;
|
|
29
35
|
readonly tool?: string;
|
|
30
36
|
}
|
|
31
37
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ERROR_CODES, errorCategoryMeta, exitCodeMap, getExitCode, getStatusCode, jsonRpcCodeMap, retryableMap, statusCodeMap } from "../../internal/error-taxonomy.js";
|
|
2
|
+
export { AlreadyExistsError, AmbiguousError, AssertionError, ConflictError, NotFoundError, ValidationError } from "../../internal/error-validation.js";
|
|
3
|
+
export { AuthError, CancelledError, InternalError, NetworkError, PermissionError, RateLimitError, TimeoutError } from "../../internal/error-operational.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema type definitions and Zod introspection helpers.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* JSON Schema representation.
|
|
8
|
+
*/
|
|
9
|
+
interface JsonSchema {
|
|
10
|
+
$defs?: Record<string, JsonSchema>;
|
|
11
|
+
$ref?: string;
|
|
12
|
+
$schema?: string;
|
|
13
|
+
additionalProperties?: boolean | JsonSchema;
|
|
14
|
+
allOf?: JsonSchema[];
|
|
15
|
+
anyOf?: JsonSchema[];
|
|
16
|
+
const?: unknown;
|
|
17
|
+
default?: unknown;
|
|
18
|
+
definitions?: Record<string, JsonSchema>;
|
|
19
|
+
description?: string;
|
|
20
|
+
enum?: unknown[];
|
|
21
|
+
exclusiveMaximum?: number;
|
|
22
|
+
exclusiveMinimum?: number;
|
|
23
|
+
format?: string;
|
|
24
|
+
items?: JsonSchema | JsonSchema[];
|
|
25
|
+
maximum?: number;
|
|
26
|
+
maxLength?: number;
|
|
27
|
+
minimum?: number;
|
|
28
|
+
minLength?: number;
|
|
29
|
+
not?: JsonSchema | Record<string, never>;
|
|
30
|
+
oneOf?: JsonSchema[];
|
|
31
|
+
pattern?: string;
|
|
32
|
+
properties?: Record<string, JsonSchema>;
|
|
33
|
+
required?: string[];
|
|
34
|
+
type?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extract the internal _def object from a Zod schema or def.
|
|
38
|
+
*/
|
|
39
|
+
declare function getDef(schemaOrDef: any): any;
|
|
40
|
+
/**
|
|
41
|
+
* Extract description from a Zod schema or its def.
|
|
42
|
+
*/
|
|
43
|
+
declare function getDescription(schema: any, def: any): string | undefined;
|
|
44
|
+
export { JsonSchema, getDef, getDescription };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ValidationError } from "./contracts-mehpmvwp.js";
|
|
2
|
+
import { Result } from "better-result";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* Format Zod issues into a human-readable error message.
|
|
6
|
+
*
|
|
7
|
+
* @param issues - Array of Zod validation issues
|
|
8
|
+
* @returns Formatted error message string
|
|
9
|
+
*/
|
|
10
|
+
declare function formatZodIssues(issues: z.ZodIssue[]): string;
|
|
11
|
+
/**
|
|
12
|
+
* Create a validator function from a Zod schema.
|
|
13
|
+
*
|
|
14
|
+
* @typeParam T - The validated output type
|
|
15
|
+
* @param schema - Zod schema to validate against
|
|
16
|
+
* @returns A function that validates input and returns Result
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const NoteSchema = z.object({
|
|
21
|
+
* id: z.string().uuid(),
|
|
22
|
+
* title: z.string().min(1),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const validateNote = createValidator(NoteSchema);
|
|
26
|
+
* const result = validateNote(input); // Result<Note, ValidationError>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare function createValidator<T>(schema: z.ZodType<T>): (input: unknown) => Result<T, ValidationError>;
|
|
30
|
+
/**
|
|
31
|
+
* Validate input against a Zod schema.
|
|
32
|
+
*
|
|
33
|
+
* Standardized wrapper for Zod schemas that returns Result instead of throwing.
|
|
34
|
+
*
|
|
35
|
+
* @typeParam T - The validated output type
|
|
36
|
+
* @param schema - Zod schema to validate against
|
|
37
|
+
* @param input - Unknown input to validate
|
|
38
|
+
* @returns Result with validated data or ValidationError
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const result = validateInput(NoteSchema, userInput);
|
|
43
|
+
* if (result.isErr()) {
|
|
44
|
+
* console.error(result.unwrapErr().message);
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function validateInput<T>(schema: z.ZodType<T>, input: unknown): Result<T, ValidationError>;
|
|
49
|
+
/**
|
|
50
|
+
* Parse and validate data against a Zod schema, returning a Result.
|
|
51
|
+
*
|
|
52
|
+
* Wraps Zod's `safeParse` into `Result<T, ValidationError>` where `T` is
|
|
53
|
+
* automatically inferred from the schema — no manual type argument needed.
|
|
54
|
+
*
|
|
55
|
+
* @typeParam TSchema - The Zod schema type (inferred from `schema` argument)
|
|
56
|
+
* @param schema - Zod schema to parse/validate against
|
|
57
|
+
* @param data - Unknown data to parse
|
|
58
|
+
* @returns `Ok<z.infer<TSchema>>` for valid data, `Err<ValidationError>` for invalid data
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const UserSchema = z.object({
|
|
63
|
+
* name: z.string().min(1),
|
|
64
|
+
* email: z.string().email(),
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* const result = parseInput(UserSchema, input);
|
|
68
|
+
* // Result<{ name: string; email: string }, ValidationError>
|
|
69
|
+
*
|
|
70
|
+
* if (result.isOk()) {
|
|
71
|
+
* result.value.name; // string — fully typed, no manual annotation
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare function parseInput<TSchema extends z.ZodType>(schema: TSchema, data: unknown): Result<z.infer<TSchema>, ValidationError>;
|
|
76
|
+
export { formatZodIssues, createValidator, validateInput, parseInput };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProgressCallback } from "./contracts-msxdg52h.js";
|
|
2
|
+
import { OutfitterError } from "./contracts-7a0xmwbg.js";
|
|
2
3
|
import { Logger } from "./contracts-rwzqy9rn.js";
|
|
3
4
|
import { Result } from "better-result";
|
|
4
5
|
/**
|
|
@@ -29,6 +30,20 @@ interface HandlerContext {
|
|
|
29
30
|
env: Record<string, string | undefined>;
|
|
30
31
|
/** Structured logger with automatic redaction */
|
|
31
32
|
logger: Logger;
|
|
33
|
+
/**
|
|
34
|
+
* Optional streaming progress callback.
|
|
35
|
+
*
|
|
36
|
+
* When provided by a transport adapter, the handler can emit progress
|
|
37
|
+
* events without knowing which transport consumes them. When `undefined`,
|
|
38
|
+
* the handler does not stream — it simply returns its final result.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* ctx.progress?.({ type: "start", command: "check", ts: new Date().toISOString() });
|
|
43
|
+
* ctx.progress?.({ type: "progress", current: 5, total: 10 });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
progress?: ProgressCallback;
|
|
32
47
|
/** Unique request identifier for tracing (UUIDv7) */
|
|
33
48
|
requestId: string;
|
|
34
49
|
/** Abort signal for cancellation propagation */
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { OutfitterError } from "./contracts-7a0xmwbg.js";
|
|
2
|
+
/**
|
|
3
|
+
* An error mapper converts an unknown error into a typed OutfitterError.
|
|
4
|
+
*
|
|
5
|
+
* Return `undefined` if the mapper does not handle this error (pass to next mapper or default).
|
|
6
|
+
*/
|
|
7
|
+
type ErrorMapper = (error: unknown) => OutfitterError | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Type guard: checks whether `value` is a typed Outfitter error (has a `category` field
|
|
10
|
+
* matching a known {@link ErrorCategory}).
|
|
11
|
+
*/
|
|
12
|
+
declare function isOutfitterError(value: unknown): value is OutfitterError;
|
|
13
|
+
/**
|
|
14
|
+
* Extract a human-readable message from an unknown error value.
|
|
15
|
+
*
|
|
16
|
+
* Handles Error instances, plain strings, objects with a `message` property,
|
|
17
|
+
* and falls back to `"Unknown error"` for everything else.
|
|
18
|
+
*/
|
|
19
|
+
declare function extractMessage(error: unknown): string;
|
|
20
|
+
/**
|
|
21
|
+
* Normalize an unknown error into a typed OutfitterError.
|
|
22
|
+
*
|
|
23
|
+
* - Typed Outfitter errors pass through unchanged (same reference, mapper NOT called).
|
|
24
|
+
* - Untyped errors go through optional mapper.
|
|
25
|
+
* - Without mapper or when mapper returns `undefined`, wraps as {@link InternalError}.
|
|
26
|
+
* - Plain strings are wrapped as InternalError with the string as message.
|
|
27
|
+
*
|
|
28
|
+
* @param error - The unknown error to normalize
|
|
29
|
+
* @param mapper - Optional mapper to convert untyped errors into typed OutfitterErrors
|
|
30
|
+
* @returns A typed OutfitterError
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // Typed errors pass through
|
|
35
|
+
* const typed = new ValidationError({ message: "bad input" });
|
|
36
|
+
* wrapError(typed) === typed; // true — same reference
|
|
37
|
+
*
|
|
38
|
+
* // Untyped errors go through mapper
|
|
39
|
+
* const mapper: ErrorMapper = (err) => {
|
|
40
|
+
* if (err instanceof Error && err.message.includes("ECONNREFUSED")) {
|
|
41
|
+
* return new NetworkError({ message: err.message });
|
|
42
|
+
* }
|
|
43
|
+
* return undefined;
|
|
44
|
+
* };
|
|
45
|
+
* wrapError(new Error("ECONNREFUSED"), mapper); // NetworkError
|
|
46
|
+
*
|
|
47
|
+
* // Unmatched errors become InternalError
|
|
48
|
+
* wrapError(new Error("unknown")); // InternalError
|
|
49
|
+
*
|
|
50
|
+
* // Strings become InternalError with message
|
|
51
|
+
* wrapError("something failed"); // InternalError { message: "something failed" }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function wrapError(error: unknown, mapper?: ErrorMapper): OutfitterError;
|
|
55
|
+
/**
|
|
56
|
+
* Compose multiple error mappers into a single mapper.
|
|
57
|
+
*
|
|
58
|
+
* Mappers run in declared order and short-circuit on the first match
|
|
59
|
+
* (first mapper to return a non-`undefined` value wins).
|
|
60
|
+
*
|
|
61
|
+
* @param mappers - Error mappers to compose
|
|
62
|
+
* @returns A single composed error mapper
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const networkMapper: ErrorMapper = (err) => {
|
|
67
|
+
* if (err instanceof Error && err.message.includes("ECONNREFUSED")) {
|
|
68
|
+
* return new NetworkError({ message: err.message });
|
|
69
|
+
* }
|
|
70
|
+
* return undefined;
|
|
71
|
+
* };
|
|
72
|
+
* const timeoutMapper: ErrorMapper = (err) => {
|
|
73
|
+
* if (err instanceof Error && err.message.includes("ETIMEDOUT")) {
|
|
74
|
+
* return TimeoutError.create("request", 5000);
|
|
75
|
+
* }
|
|
76
|
+
* return undefined;
|
|
77
|
+
* };
|
|
78
|
+
*
|
|
79
|
+
* const composed = composeMappers(networkMapper, timeoutMapper);
|
|
80
|
+
* wrapError(new Error("ECONNREFUSED"), composed); // NetworkError
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function composeMappers(...mappers: ErrorMapper[]): ErrorMapper;
|
|
84
|
+
export { ErrorMapper, isOutfitterError, extractMessage, wrapError, composeMappers };
|
package/dist/stream.d.ts
ADDED
package/dist/stream.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// @bun
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import { createValidator, validateInput } from "./shared/@outfitter/contracts-
|
|
2
|
-
import "./shared/@outfitter/contracts-
|
|
3
|
-
|
|
1
|
+
import { createValidator, formatZodIssues, parseInput, validateInput } from "./shared/@outfitter/contracts-x0ppyt7e.js";
|
|
2
|
+
import "./shared/@outfitter/contracts-7a0xmwbg.js";
|
|
3
|
+
import "./shared/@outfitter/contracts-735ecmbq.js";
|
|
4
|
+
import "./shared/@outfitter/contracts-mehpmvwp.js";
|
|
5
|
+
import "./shared/@outfitter/contracts-qpbv29bg.js";
|
|
6
|
+
import "./shared/@outfitter/contracts-njb2art4.js";
|
|
7
|
+
export { validateInput, parseInput, formatZodIssues, createValidator };
|
package/dist/validation.js
CHANGED
|
@@ -1,42 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return issues.map((issue) => {
|
|
10
|
-
const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
11
|
-
return `${path}: ${issue.message}`;
|
|
12
|
-
}).join("; ");
|
|
13
|
-
}
|
|
14
|
-
function extractField(issues) {
|
|
15
|
-
const firstIssue = issues[0];
|
|
16
|
-
if (firstIssue && firstIssue.path.length > 0) {
|
|
17
|
-
return firstIssue.path.join(".");
|
|
18
|
-
}
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
function createValidator(schema) {
|
|
22
|
-
return (input) => {
|
|
23
|
-
return validateInput(schema, input);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
function validateInput(schema, input) {
|
|
27
|
-
const parseResult = schema.safeParse(input);
|
|
28
|
-
if (parseResult.success) {
|
|
29
|
-
return Result.ok(parseResult.data);
|
|
30
|
-
}
|
|
31
|
-
const message = formatZodIssues(parseResult.error.issues);
|
|
32
|
-
const field = extractField(parseResult.error.issues);
|
|
33
|
-
const errorProps = { message };
|
|
34
|
-
if (field !== undefined) {
|
|
35
|
-
errorProps.field = field;
|
|
36
|
-
}
|
|
37
|
-
return Result.err(new ValidationError(errorProps));
|
|
38
|
-
}
|
|
3
|
+
createValidator,
|
|
4
|
+
formatZodIssues,
|
|
5
|
+
parseInput,
|
|
6
|
+
validateInput
|
|
7
|
+
} from "./shared/@outfitter/contracts-hgh47193.js";
|
|
8
|
+
import"./shared/@outfitter/contracts-vhr2ep6b.js";
|
|
39
9
|
export {
|
|
40
10
|
validateInput,
|
|
11
|
+
parseInput,
|
|
12
|
+
formatZodIssues,
|
|
41
13
|
createValidator
|
|
42
14
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ErrorMapper, composeMappers, extractMessage, isOutfitterError, wrapError } from "./shared/@outfitter/contracts-zsgxsa91.js";
|
|
2
|
+
import "./shared/@outfitter/contracts-7a0xmwbg.js";
|
|
3
|
+
import "./shared/@outfitter/contracts-735ecmbq.js";
|
|
4
|
+
import "./shared/@outfitter/contracts-mehpmvwp.js";
|
|
5
|
+
import "./shared/@outfitter/contracts-qpbv29bg.js";
|
|
6
|
+
import "./shared/@outfitter/contracts-njb2art4.js";
|
|
7
|
+
export { wrapError, isOutfitterError, extractMessage, composeMappers, ErrorMapper };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
InternalError
|
|
4
|
+
} from "./shared/@outfitter/contracts-vhr2ep6b.js";
|
|
5
|
+
|
|
6
|
+
// packages/contracts/src/wrap-error.ts
|
|
7
|
+
function isOutfitterError(value) {
|
|
8
|
+
if (!(value instanceof Error)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const candidate = value;
|
|
12
|
+
return typeof candidate["category"] === "string" && typeof candidate["message"] === "string" && typeof candidate["_tag"] === "string" && isErrorCategory(candidate["category"]);
|
|
13
|
+
}
|
|
14
|
+
var ERROR_CATEGORIES = new Set([
|
|
15
|
+
"validation",
|
|
16
|
+
"not_found",
|
|
17
|
+
"conflict",
|
|
18
|
+
"permission",
|
|
19
|
+
"timeout",
|
|
20
|
+
"rate_limit",
|
|
21
|
+
"network",
|
|
22
|
+
"internal",
|
|
23
|
+
"auth",
|
|
24
|
+
"cancelled"
|
|
25
|
+
]);
|
|
26
|
+
function isErrorCategory(value) {
|
|
27
|
+
return ERROR_CATEGORIES.has(value);
|
|
28
|
+
}
|
|
29
|
+
function extractMessage(error) {
|
|
30
|
+
if (typeof error === "string") {
|
|
31
|
+
return error || "Unknown error";
|
|
32
|
+
}
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
return error.message || "Unknown error";
|
|
35
|
+
}
|
|
36
|
+
if (error != null && typeof error === "object" && "message" in error) {
|
|
37
|
+
const msg = error["message"];
|
|
38
|
+
return typeof msg === "string" && msg ? msg : "Unknown error";
|
|
39
|
+
}
|
|
40
|
+
return "Unknown error";
|
|
41
|
+
}
|
|
42
|
+
function wrapError(error, mapper) {
|
|
43
|
+
if (isOutfitterError(error)) {
|
|
44
|
+
return error;
|
|
45
|
+
}
|
|
46
|
+
if (mapper != null) {
|
|
47
|
+
const mapped = mapper(error);
|
|
48
|
+
if (mapped != null) {
|
|
49
|
+
return mapped;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const message = extractMessage(error);
|
|
53
|
+
return new InternalError({ message });
|
|
54
|
+
}
|
|
55
|
+
function composeMappers(...mappers) {
|
|
56
|
+
return (error) => {
|
|
57
|
+
for (const mapper of mappers) {
|
|
58
|
+
const result = mapper(error);
|
|
59
|
+
if (result != null) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
wrapError,
|
|
68
|
+
isOutfitterError,
|
|
69
|
+
extractMessage,
|
|
70
|
+
composeMappers
|
|
71
|
+
};
|