@ontrails/core 1.0.0-beta.4 → 1.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +412 -12
- package/README.md +112 -28
- package/package.json +11 -1
- package/src/activation-provenance.ts +116 -0
- package/src/activation-source-compatibility.ts +430 -0
- package/src/activation-source-projection.ts +227 -0
- package/src/activation-source.ts +93 -0
- package/src/blob-ref.ts +51 -0
- package/src/branded.ts +1 -1
- package/src/compose-batch.ts +69 -0
- package/src/compose-schema.ts +36 -0
- package/src/context.ts +59 -11
- package/src/derive.ts +271 -19
- package/src/detours.ts +8 -0
- package/src/diagnostics.ts +21 -0
- package/src/draft.ts +350 -0
- package/src/entity.ts +346 -0
- package/src/error-projection.ts +51 -0
- package/src/errors.ts +335 -48
- package/src/execute.ts +1577 -0
- package/src/fire.ts +1172 -0
- package/src/glob.ts +81 -0
- package/src/index.ts +568 -32
- package/src/internal/fork-ctx.ts +69 -0
- package/src/layer-projection.ts +193 -0
- package/src/layer.ts +43 -6
- package/src/observe.ts +361 -0
- package/src/path-scope.ts +66 -0
- package/src/path-security.ts +11 -3
- package/src/permits.ts +12 -0
- package/src/queue.ts +163 -0
- package/src/redaction/patterns.ts +6 -3
- package/src/resilience.ts +11 -11
- package/src/resource-config.ts +804 -0
- package/src/resource.ts +194 -0
- package/src/result.ts +18 -0
- package/src/run.ts +76 -0
- package/src/runtime-builtins.ts +69 -0
- package/src/schedule-runtime.ts +689 -0
- package/src/schedule.ts +326 -0
- package/src/serialization.ts +92 -55
- package/src/sha256.ts +136 -0
- package/src/signal-diagnostics.ts +633 -0
- package/src/signal-ref.ts +111 -0
- package/src/signal.ts +104 -0
- package/src/store/accessor-protocol.ts +56 -0
- package/src/store/index.ts +4 -0
- package/src/structured-examples.ts +248 -0
- package/src/surface-derivation.ts +91 -0
- package/src/surface-filter.ts +101 -0
- package/src/surface-overlay.ts +694 -0
- package/src/surface-versioning.ts +42 -0
- package/src/topo.ts +762 -38
- package/src/tracing.ts +346 -0
- package/src/trail-id-glob.ts +15 -0
- package/src/trail.ts +1244 -34
- package/src/trails/derive-trail.ts +835 -0
- package/src/trails/index.ts +9 -0
- package/src/trails/ingest.ts +152 -0
- package/src/trails-db.ts +212 -0
- package/src/transport-error-map.ts +174 -0
- package/src/type-utils.ts +87 -0
- package/src/types.ts +254 -12
- package/src/validate-established-topo.ts +73 -0
- package/src/validate-topo.ts +569 -55
- package/src/validation.ts +152 -4
- package/src/version-marker.ts +716 -0
- package/src/version-resolution.ts +308 -0
- package/src/version-runtime.ts +120 -0
- package/src/webhook.ts +461 -0
- package/src/workspace.ts +183 -16
- package/src/zod-wrappers.ts +72 -0
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/dist/adapters.d.ts +0 -39
- package/dist/adapters.d.ts.map +0 -1
- package/dist/adapters.js +0 -2
- package/dist/adapters.js.map +0 -1
- package/dist/blob-ref.d.ts +0 -20
- package/dist/blob-ref.d.ts.map +0 -1
- package/dist/blob-ref.js +0 -22
- package/dist/blob-ref.js.map +0 -1
- package/dist/branded.d.ts +0 -36
- package/dist/branded.d.ts.map +0 -1
- package/dist/branded.js +0 -89
- package/dist/branded.js.map +0 -1
- package/dist/collections.d.ts +0 -31
- package/dist/collections.d.ts.map +0 -1
- package/dist/collections.js +0 -60
- package/dist/collections.js.map +0 -1
- package/dist/context.d.ts +0 -10
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -15
- package/dist/context.js.map +0 -1
- package/dist/derive.d.ts +0 -33
- package/dist/derive.d.ts.map +0 -1
- package/dist/derive.js +0 -125
- package/dist/derive.js.map +0 -1
- package/dist/errors.d.ts +0 -83
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -142
- package/dist/errors.js.map +0 -1
- package/dist/event.d.ts +0 -45
- package/dist/event.d.ts.map +0 -1
- package/dist/event.js +0 -17
- package/dist/event.js.map +0 -1
- package/dist/fetch.d.ts +0 -15
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js +0 -102
- package/dist/fetch.js.map +0 -1
- package/dist/guards.d.ts +0 -17
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js +0 -25
- package/dist/guards.js.map +0 -1
- package/dist/health.d.ts +0 -18
- package/dist/health.d.ts.map +0 -1
- package/dist/health.js +0 -5
- package/dist/health.js.map +0 -1
- package/dist/index.d.ts +0 -34
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -38
- package/dist/index.js.map +0 -1
- package/dist/job.d.ts +0 -24
- package/dist/job.d.ts.map +0 -1
- package/dist/job.js +0 -17
- package/dist/job.js.map +0 -1
- package/dist/layer.d.ts +0 -17
- package/dist/layer.d.ts.map +0 -1
- package/dist/layer.js +0 -21
- package/dist/layer.js.map +0 -1
- package/dist/path-security.d.ts +0 -28
- package/dist/path-security.d.ts.map +0 -1
- package/dist/path-security.js +0 -63
- package/dist/path-security.js.map +0 -1
- package/dist/patterns/bulk.d.ts +0 -15
- package/dist/patterns/bulk.d.ts.map +0 -1
- package/dist/patterns/bulk.js +0 -14
- package/dist/patterns/bulk.js.map +0 -1
- package/dist/patterns/change.d.ts +0 -10
- package/dist/patterns/change.d.ts.map +0 -1
- package/dist/patterns/change.js +0 -10
- package/dist/patterns/change.js.map +0 -1
- package/dist/patterns/date-range.d.ts +0 -10
- package/dist/patterns/date-range.d.ts.map +0 -1
- package/dist/patterns/date-range.js +0 -10
- package/dist/patterns/date-range.js.map +0 -1
- package/dist/patterns/index.d.ts +0 -9
- package/dist/patterns/index.d.ts.map +0 -1
- package/dist/patterns/index.js +0 -9
- package/dist/patterns/index.js.map +0 -1
- package/dist/patterns/pagination.d.ts +0 -18
- package/dist/patterns/pagination.d.ts.map +0 -1
- package/dist/patterns/pagination.js +0 -18
- package/dist/patterns/pagination.js.map +0 -1
- package/dist/patterns/progress.d.ts +0 -11
- package/dist/patterns/progress.d.ts.map +0 -1
- package/dist/patterns/progress.js +0 -11
- package/dist/patterns/progress.js.map +0 -1
- package/dist/patterns/sorting.d.ts +0 -13
- package/dist/patterns/sorting.d.ts.map +0 -1
- package/dist/patterns/sorting.js +0 -10
- package/dist/patterns/sorting.js.map +0 -1
- package/dist/patterns/status.d.ts +0 -15
- package/dist/patterns/status.d.ts.map +0 -1
- package/dist/patterns/status.js +0 -9
- package/dist/patterns/status.js.map +0 -1
- package/dist/patterns/timestamps.d.ts +0 -10
- package/dist/patterns/timestamps.d.ts.map +0 -1
- package/dist/patterns/timestamps.js +0 -10
- package/dist/patterns/timestamps.js.map +0 -1
- package/dist/redaction/index.d.ts +0 -4
- package/dist/redaction/index.d.ts.map +0 -1
- package/dist/redaction/index.js +0 -3
- package/dist/redaction/index.js.map +0 -1
- package/dist/redaction/patterns.d.ts +0 -9
- package/dist/redaction/patterns.d.ts.map +0 -1
- package/dist/redaction/patterns.js +0 -39
- package/dist/redaction/patterns.js.map +0 -1
- package/dist/redaction/redactor.d.ts +0 -27
- package/dist/redaction/redactor.d.ts.map +0 -1
- package/dist/redaction/redactor.js +0 -89
- package/dist/redaction/redactor.js.map +0 -1
- package/dist/resilience.d.ts +0 -34
- package/dist/resilience.d.ts.map +0 -1
- package/dist/resilience.js +0 -164
- package/dist/resilience.js.map +0 -1
- package/dist/result.d.ts +0 -57
- package/dist/result.d.ts.map +0 -1
- package/dist/result.js +0 -156
- package/dist/result.js.map +0 -1
- package/dist/serialization.d.ts +0 -27
- package/dist/serialization.d.ts.map +0 -1
- package/dist/serialization.js +0 -153
- package/dist/serialization.js.map +0 -1
- package/dist/topo.d.ts +0 -16
- package/dist/topo.d.ts.map +0 -1
- package/dist/topo.js +0 -66
- package/dist/topo.js.map +0 -1
- package/dist/trail.d.ts +0 -89
- package/dist/trail.d.ts.map +0 -1
- package/dist/trail.js +0 -18
- package/dist/trail.js.map +0 -1
- package/dist/types.d.ts +0 -46
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/validate-topo.d.ts +0 -24
- package/dist/validate-topo.d.ts.map +0 -1
- package/dist/validate-topo.js +0 -158
- package/dist/validate-topo.js.map +0 -1
- package/dist/validation.d.ts +0 -27
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -134
- package/dist/validation.js.map +0 -1
- package/dist/workspace.d.ts +0 -25
- package/dist/workspace.d.ts.map +0 -1
- package/dist/workspace.js +0 -57
- package/dist/workspace.js.map +0 -1
- package/src/__tests__/blob-ref.test.ts +0 -103
- package/src/__tests__/branded.test.ts +0 -148
- package/src/__tests__/collections.test.ts +0 -126
- package/src/__tests__/context.test.ts +0 -66
- package/src/__tests__/derive.test.ts +0 -203
- package/src/__tests__/errors.test.ts +0 -309
- package/src/__tests__/event.test.ts +0 -82
- package/src/__tests__/fetch.test.ts +0 -217
- package/src/__tests__/guards.test.ts +0 -102
- package/src/__tests__/job.test.ts +0 -98
- package/src/__tests__/layer.test.ts +0 -212
- package/src/__tests__/path-security.test.ts +0 -114
- package/src/__tests__/patterns.test.ts +0 -273
- package/src/__tests__/redaction.test.ts +0 -244
- package/src/__tests__/resilience.test.ts +0 -246
- package/src/__tests__/result.test.ts +0 -155
- package/src/__tests__/serialization.test.ts +0 -401
- package/src/__tests__/topo.test.ts +0 -181
- package/src/__tests__/trail.test.ts +0 -217
- package/src/__tests__/validate-topo.test.ts +0 -278
- package/src/__tests__/validation.test.ts +0 -283
- package/src/__tests__/workspace.test.ts +0 -183
- package/src/adapters.ts +0 -68
- package/src/event.ts +0 -77
- package/src/health.ts +0 -23
- package/src/job.ts +0 -20
- package/tsconfig.json +0 -9
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ErrorCategory } from './errors.js';
|
|
2
|
+
import { isTrailsError } from './errors.js';
|
|
3
|
+
import { createRedactor } from './redaction/index.js';
|
|
4
|
+
|
|
5
|
+
const errorRedactor = createRedactor();
|
|
6
|
+
|
|
7
|
+
export const INTERNAL_ERROR_PUBLIC_MESSAGE = 'Internal server error';
|
|
8
|
+
|
|
9
|
+
export interface ErrorDiagnosticsProjection {
|
|
10
|
+
readonly category?: ErrorCategory | undefined;
|
|
11
|
+
readonly context?: Record<string, unknown> | undefined;
|
|
12
|
+
readonly message: string;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly retryable?: boolean | undefined;
|
|
15
|
+
readonly stack?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const redactErrorString = (value: string): string =>
|
|
19
|
+
errorRedactor.redact(value);
|
|
20
|
+
|
|
21
|
+
export const redactErrorContext = (
|
|
22
|
+
context: Record<string, unknown> | undefined
|
|
23
|
+
): Record<string, unknown> | undefined =>
|
|
24
|
+
context === undefined ? undefined : errorRedactor.redactObject(context);
|
|
25
|
+
|
|
26
|
+
export const redactErrorStack = (
|
|
27
|
+
stack: string | undefined
|
|
28
|
+
): string | undefined =>
|
|
29
|
+
stack === undefined ? undefined : redactErrorString(stack);
|
|
30
|
+
|
|
31
|
+
export const projectErrorDiagnostics = (
|
|
32
|
+
error: Error
|
|
33
|
+
): ErrorDiagnosticsProjection => {
|
|
34
|
+
const context = isTrailsError(error)
|
|
35
|
+
? redactErrorContext(error.context)
|
|
36
|
+
: undefined;
|
|
37
|
+
const stack = redactErrorStack(error.stack);
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
...(isTrailsError(error)
|
|
41
|
+
? {
|
|
42
|
+
category: error.category,
|
|
43
|
+
retryable: error.retryable,
|
|
44
|
+
}
|
|
45
|
+
: {}),
|
|
46
|
+
...(context === undefined ? {} : { context }),
|
|
47
|
+
message: redactErrorString(error.message),
|
|
48
|
+
name: error.name || error.constructor.name || 'Error',
|
|
49
|
+
...(stack === undefined ? {} : { stack }),
|
|
50
|
+
};
|
|
51
|
+
};
|
package/src/errors.ts
CHANGED
|
@@ -10,17 +10,21 @@
|
|
|
10
10
|
// Category
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
export const errorCategories = [
|
|
14
|
+
'validation',
|
|
15
|
+
'not_found',
|
|
16
|
+
'conflict',
|
|
17
|
+
'permission',
|
|
18
|
+
'timeout',
|
|
19
|
+
'rate_limit',
|
|
20
|
+
'network',
|
|
21
|
+
'shift',
|
|
22
|
+
'internal',
|
|
23
|
+
'auth',
|
|
24
|
+
'cancelled',
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
export type ErrorCategory = (typeof errorCategories)[number];
|
|
24
28
|
|
|
25
29
|
// ---------------------------------------------------------------------------
|
|
26
30
|
// Base class
|
|
@@ -65,6 +69,64 @@ export class NotFoundError extends TrailsError {
|
|
|
65
69
|
readonly retryable = false as const;
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
export class VersionNotSupportedError extends NotFoundError {
|
|
73
|
+
readonly reason?: string | undefined;
|
|
74
|
+
readonly requested?: number | string | undefined;
|
|
75
|
+
readonly supported?: readonly number[] | undefined;
|
|
76
|
+
readonly trailId?: string | undefined;
|
|
77
|
+
|
|
78
|
+
constructor(
|
|
79
|
+
message: string,
|
|
80
|
+
options?: { cause?: Error; context?: Record<string, unknown> }
|
|
81
|
+
);
|
|
82
|
+
constructor(
|
|
83
|
+
trailId: string,
|
|
84
|
+
requested: number | string,
|
|
85
|
+
supported: readonly number[],
|
|
86
|
+
reason?: string | undefined
|
|
87
|
+
);
|
|
88
|
+
constructor(
|
|
89
|
+
messageOrTrailId: string,
|
|
90
|
+
optionsOrRequested?:
|
|
91
|
+
| { cause?: Error; context?: Record<string, unknown> }
|
|
92
|
+
| number
|
|
93
|
+
| string,
|
|
94
|
+
supported?: readonly number[],
|
|
95
|
+
reason?: string | undefined
|
|
96
|
+
) {
|
|
97
|
+
if (supported === undefined) {
|
|
98
|
+
super(
|
|
99
|
+
messageOrTrailId,
|
|
100
|
+
optionsOrRequested as
|
|
101
|
+
| { cause?: Error; context?: Record<string, unknown> }
|
|
102
|
+
| undefined
|
|
103
|
+
);
|
|
104
|
+
this.name = 'VersionNotSupportedError';
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const requested = optionsOrRequested as number | string;
|
|
109
|
+
const supportedLabel =
|
|
110
|
+
supported.length === 0 ? 'none' : supported.join(', ');
|
|
111
|
+
super(
|
|
112
|
+
`Trail "${messageOrTrailId}" version ${String(requested)} is not supported (supported: ${supportedLabel})`,
|
|
113
|
+
{
|
|
114
|
+
context: {
|
|
115
|
+
...(reason === undefined ? {} : { reason }),
|
|
116
|
+
requested,
|
|
117
|
+
supported,
|
|
118
|
+
trailId: messageOrTrailId,
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
this.name = 'VersionNotSupportedError';
|
|
123
|
+
this.reason = reason;
|
|
124
|
+
this.requested = requested;
|
|
125
|
+
this.supported = supported;
|
|
126
|
+
this.trailId = messageOrTrailId;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
68
130
|
export class AlreadyExistsError extends TrailsError {
|
|
69
131
|
readonly category = 'conflict' as const;
|
|
70
132
|
readonly retryable = false as const;
|
|
@@ -80,6 +142,16 @@ export class PermissionError extends TrailsError {
|
|
|
80
142
|
readonly retryable = false as const;
|
|
81
143
|
}
|
|
82
144
|
|
|
145
|
+
export class PermitError extends PermissionError {
|
|
146
|
+
constructor(
|
|
147
|
+
message: string,
|
|
148
|
+
options?: { cause?: Error; context?: Record<string, unknown> }
|
|
149
|
+
) {
|
|
150
|
+
super(message, options);
|
|
151
|
+
this.name = 'PermitError';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
83
155
|
export class TimeoutError extends TrailsError {
|
|
84
156
|
readonly category = 'timeout' as const;
|
|
85
157
|
readonly retryable = true as const;
|
|
@@ -108,11 +180,34 @@ export class NetworkError extends TrailsError {
|
|
|
108
180
|
readonly retryable = true as const;
|
|
109
181
|
}
|
|
110
182
|
|
|
183
|
+
/**
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* return Result.err(new WorkspaceShiftError('workspace changed during check'));
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* Raised when the observed workspace substrate moves during one run.
|
|
190
|
+
*
|
|
191
|
+
* A shift voids the run's verdict, including passes. Callers can retry on
|
|
192
|
+
* stable ground without changing their request.
|
|
193
|
+
*/
|
|
194
|
+
export class WorkspaceShiftError extends TrailsError {
|
|
195
|
+
readonly category = 'shift' as const;
|
|
196
|
+
readonly retryable = true as const;
|
|
197
|
+
}
|
|
198
|
+
|
|
111
199
|
export class InternalError extends TrailsError {
|
|
200
|
+
readonly category: ErrorCategory = 'internal';
|
|
201
|
+
readonly retryable = false as const;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export class DerivationError extends TrailsError {
|
|
112
205
|
readonly category = 'internal' as const;
|
|
113
206
|
readonly retryable = false as const;
|
|
114
207
|
}
|
|
115
208
|
|
|
209
|
+
export class RecoverableCompletionError extends InternalError {}
|
|
210
|
+
|
|
116
211
|
export class AuthError extends TrailsError {
|
|
117
212
|
readonly category = 'auth' as const;
|
|
118
213
|
readonly retryable = false as const;
|
|
@@ -123,48 +218,239 @@ export class CancelledError extends TrailsError {
|
|
|
123
218
|
readonly retryable = false as const;
|
|
124
219
|
}
|
|
125
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Returned when a detour exhausts all recovery attempts.
|
|
223
|
+
*
|
|
224
|
+
* Inherits the wrapped error's category for surface mapping (e.g. a
|
|
225
|
+
* `RetryExhaustedError<ConflictError>` maps to HTTP 409), but always
|
|
226
|
+
* sets `retryable = false` to prevent amplification across `ctx.compose()`
|
|
227
|
+
* boundaries or stacked layers.
|
|
228
|
+
*/
|
|
229
|
+
export class RetryExhaustedError<
|
|
230
|
+
TErr extends TrailsError = TrailsError,
|
|
231
|
+
> extends InternalError {
|
|
232
|
+
readonly category: ErrorCategory;
|
|
233
|
+
readonly cause: TErr;
|
|
234
|
+
|
|
235
|
+
/** Number of recovery attempts made before exhaustion. */
|
|
236
|
+
readonly attempts: number;
|
|
237
|
+
|
|
238
|
+
/** Name of the detour whose recovery was exhausted. */
|
|
239
|
+
readonly detour: string;
|
|
240
|
+
|
|
241
|
+
constructor(
|
|
242
|
+
wrapped: TErr,
|
|
243
|
+
metadata: { readonly attempts: number; readonly detour: string }
|
|
244
|
+
) {
|
|
245
|
+
super(
|
|
246
|
+
`Recovery exhausted after ${metadata.attempts} attempts: ${wrapped.message}`,
|
|
247
|
+
{ cause: wrapped }
|
|
248
|
+
);
|
|
249
|
+
this.cause = wrapped;
|
|
250
|
+
this.attempts = metadata.attempts;
|
|
251
|
+
this.detour = metadata.detour;
|
|
252
|
+
// Dynamic — inherited from wrapped error at construction time.
|
|
253
|
+
this.category = wrapped.category;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// Class registry
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
|
|
261
|
+
export type ErrorClassConstructor = new (...args: never[]) => TrailsError;
|
|
262
|
+
|
|
263
|
+
export interface FixedErrorClassRegistryEntry {
|
|
264
|
+
readonly category: ErrorCategory;
|
|
265
|
+
readonly ctor: ErrorClassConstructor;
|
|
266
|
+
readonly name: string;
|
|
267
|
+
readonly retryable: boolean;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface DynamicErrorClassRegistryEntry {
|
|
271
|
+
readonly category: 'dynamic';
|
|
272
|
+
readonly ctor: ErrorClassConstructor;
|
|
273
|
+
readonly inheritsCategoryFrom: 'wrapped-error';
|
|
274
|
+
readonly name: string;
|
|
275
|
+
readonly retryable: false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type ErrorClassRegistryEntry =
|
|
279
|
+
| DynamicErrorClassRegistryEntry
|
|
280
|
+
| FixedErrorClassRegistryEntry;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Authored registry of concrete TrailsError classes.
|
|
284
|
+
*
|
|
285
|
+
* JavaScript cannot enumerate subclasses at runtime, so rule and projection
|
|
286
|
+
* tooling should walk this owner-held list instead of hardcoding parallel
|
|
287
|
+
* class-name tables. `RetryExhaustedError` is marked dynamic because it
|
|
288
|
+
* inherits its runtime category from the wrapped error rather than always
|
|
289
|
+
* mapping as `internal`.
|
|
290
|
+
*/
|
|
291
|
+
export const errorClasses = [
|
|
292
|
+
{
|
|
293
|
+
category: 'validation',
|
|
294
|
+
ctor: ValidationError,
|
|
295
|
+
name: 'ValidationError',
|
|
296
|
+
retryable: false,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
category: 'validation',
|
|
300
|
+
ctor: AmbiguousError,
|
|
301
|
+
name: 'AmbiguousError',
|
|
302
|
+
retryable: false,
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
category: 'internal',
|
|
306
|
+
ctor: AssertionError,
|
|
307
|
+
name: 'AssertionError',
|
|
308
|
+
retryable: false,
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
category: 'not_found',
|
|
312
|
+
ctor: NotFoundError,
|
|
313
|
+
name: 'NotFoundError',
|
|
314
|
+
retryable: false,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
category: 'not_found',
|
|
318
|
+
ctor: VersionNotSupportedError,
|
|
319
|
+
name: 'VersionNotSupportedError',
|
|
320
|
+
retryable: false,
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
category: 'conflict',
|
|
324
|
+
ctor: AlreadyExistsError,
|
|
325
|
+
name: 'AlreadyExistsError',
|
|
326
|
+
retryable: false,
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
category: 'conflict',
|
|
330
|
+
ctor: ConflictError,
|
|
331
|
+
name: 'ConflictError',
|
|
332
|
+
retryable: false,
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
category: 'permission',
|
|
336
|
+
ctor: PermissionError,
|
|
337
|
+
name: 'PermissionError',
|
|
338
|
+
retryable: false,
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
category: 'permission',
|
|
342
|
+
ctor: PermitError,
|
|
343
|
+
name: 'PermitError',
|
|
344
|
+
retryable: false,
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
category: 'timeout',
|
|
348
|
+
ctor: TimeoutError,
|
|
349
|
+
name: 'TimeoutError',
|
|
350
|
+
retryable: true,
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
category: 'rate_limit',
|
|
354
|
+
ctor: RateLimitError,
|
|
355
|
+
name: 'RateLimitError',
|
|
356
|
+
retryable: true,
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
category: 'network',
|
|
360
|
+
ctor: NetworkError,
|
|
361
|
+
name: 'NetworkError',
|
|
362
|
+
retryable: true,
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
category: 'shift',
|
|
366
|
+
ctor: WorkspaceShiftError,
|
|
367
|
+
name: 'WorkspaceShiftError',
|
|
368
|
+
retryable: true,
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
category: 'internal',
|
|
372
|
+
ctor: InternalError,
|
|
373
|
+
name: 'InternalError',
|
|
374
|
+
retryable: false,
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
category: 'internal',
|
|
378
|
+
ctor: DerivationError,
|
|
379
|
+
name: 'DerivationError',
|
|
380
|
+
retryable: false,
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
category: 'internal',
|
|
384
|
+
ctor: RecoverableCompletionError,
|
|
385
|
+
name: 'RecoverableCompletionError',
|
|
386
|
+
retryable: false,
|
|
387
|
+
},
|
|
388
|
+
{ category: 'auth', ctor: AuthError, name: 'AuthError', retryable: false },
|
|
389
|
+
{
|
|
390
|
+
category: 'cancelled',
|
|
391
|
+
ctor: CancelledError,
|
|
392
|
+
name: 'CancelledError',
|
|
393
|
+
retryable: false,
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
category: 'dynamic',
|
|
397
|
+
ctor: RetryExhaustedError,
|
|
398
|
+
inheritsCategoryFrom: 'wrapped-error',
|
|
399
|
+
name: 'RetryExhaustedError',
|
|
400
|
+
retryable: false,
|
|
401
|
+
},
|
|
402
|
+
] as const satisfies readonly ErrorClassRegistryEntry[];
|
|
403
|
+
|
|
126
404
|
// ---------------------------------------------------------------------------
|
|
127
405
|
// Taxonomy maps
|
|
128
406
|
// ---------------------------------------------------------------------------
|
|
129
407
|
|
|
130
|
-
export
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
network: 7,
|
|
136
|
-
not_found: 2,
|
|
137
|
-
permission: 4,
|
|
138
|
-
rate_limit: 6,
|
|
139
|
-
timeout: 5,
|
|
140
|
-
validation: 1,
|
|
141
|
-
} as const;
|
|
408
|
+
export interface ErrorCategoryCodes {
|
|
409
|
+
readonly exit: number;
|
|
410
|
+
readonly http: number;
|
|
411
|
+
readonly jsonRpc: number;
|
|
412
|
+
}
|
|
142
413
|
|
|
143
|
-
export const
|
|
144
|
-
auth: 401,
|
|
145
|
-
cancelled: 499,
|
|
146
|
-
conflict: 409,
|
|
147
|
-
internal: 500,
|
|
148
|
-
network: 502,
|
|
149
|
-
not_found: 404,
|
|
150
|
-
permission: 403,
|
|
151
|
-
rate_limit: 429,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
414
|
+
export const codesByCategory = {
|
|
415
|
+
auth: { exit: 9, http: 401, jsonRpc: -32_600 },
|
|
416
|
+
cancelled: { exit: 130, http: 499, jsonRpc: -32_603 },
|
|
417
|
+
conflict: { exit: 3, http: 409, jsonRpc: -32_603 },
|
|
418
|
+
internal: { exit: 8, http: 500, jsonRpc: -32_603 },
|
|
419
|
+
network: { exit: 7, http: 502, jsonRpc: -32_603 },
|
|
420
|
+
not_found: { exit: 2, http: 404, jsonRpc: -32_601 },
|
|
421
|
+
permission: { exit: 4, http: 403, jsonRpc: -32_600 },
|
|
422
|
+
rate_limit: { exit: 6, http: 429, jsonRpc: -32_603 },
|
|
423
|
+
shift: { exit: 10, http: 503, jsonRpc: -32_603 },
|
|
424
|
+
timeout: { exit: 5, http: 504, jsonRpc: -32_603 },
|
|
425
|
+
validation: { exit: 1, http: 400, jsonRpc: -32_602 },
|
|
426
|
+
} as const satisfies Record<ErrorCategory, ErrorCategoryCodes>;
|
|
155
427
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
428
|
+
const deriveCodeMap = <TCode extends keyof ErrorCategoryCodes>(
|
|
429
|
+
code: TCode
|
|
430
|
+
): {
|
|
431
|
+
readonly [TCategory in ErrorCategory]: (typeof codesByCategory)[TCategory][TCode];
|
|
432
|
+
} => ({
|
|
433
|
+
auth: codesByCategory.auth[code],
|
|
434
|
+
cancelled: codesByCategory.cancelled[code],
|
|
435
|
+
conflict: codesByCategory.conflict[code],
|
|
436
|
+
internal: codesByCategory.internal[code],
|
|
437
|
+
network: codesByCategory.network[code],
|
|
438
|
+
not_found: codesByCategory.not_found[code],
|
|
439
|
+
permission: codesByCategory.permission[code],
|
|
440
|
+
rate_limit: codesByCategory.rate_limit[code],
|
|
441
|
+
shift: codesByCategory.shift[code],
|
|
442
|
+
timeout: codesByCategory.timeout[code],
|
|
443
|
+
validation: codesByCategory.validation[code],
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
/** @deprecated Prefer `codesByCategory[category].exit`. */
|
|
447
|
+
export const exitCodeMap = deriveCodeMap('exit');
|
|
448
|
+
|
|
449
|
+
/** @deprecated Prefer `codesByCategory[category].http`. */
|
|
450
|
+
export const statusCodeMap = deriveCodeMap('http');
|
|
451
|
+
|
|
452
|
+
/** @deprecated Prefer `codesByCategory[category].jsonRpc`. */
|
|
453
|
+
export const jsonRpcCodeMap = deriveCodeMap('jsonRpc');
|
|
168
454
|
|
|
169
455
|
export const retryableMap: Record<ErrorCategory, boolean> = {
|
|
170
456
|
auth: false,
|
|
@@ -175,6 +461,7 @@ export const retryableMap: Record<ErrorCategory, boolean> = {
|
|
|
175
461
|
not_found: false,
|
|
176
462
|
permission: false,
|
|
177
463
|
rate_limit: true,
|
|
464
|
+
shift: true,
|
|
178
465
|
timeout: true,
|
|
179
466
|
validation: false,
|
|
180
467
|
} as const;
|
|
@@ -190,7 +477,7 @@ export const isTrailsError = (error?: unknown): error is TrailsError =>
|
|
|
190
477
|
/** Returns true if the error is retryable (TrailsError with retryable category). */
|
|
191
478
|
export const isRetryable = (error: Error): boolean => {
|
|
192
479
|
if (isTrailsError(error)) {
|
|
193
|
-
return
|
|
480
|
+
return error.retryable;
|
|
194
481
|
}
|
|
195
482
|
return false;
|
|
196
483
|
};
|