@ontrails/core 0.2.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/CHANGELOG.md +849 -0
- package/README.md +190 -0
- package/package.json +36 -0
- package/src/activation-provenance.ts +116 -0
- package/src/activation-source-compatibility.ts +430 -0
- package/src/activation-source-derivation.ts +227 -0
- package/src/activation-source.ts +93 -0
- package/src/blob-ref.ts +90 -0
- package/src/branded.ts +135 -0
- package/src/collections.ts +99 -0
- package/src/compose-batch.ts +69 -0
- package/src/compose-schema.ts +36 -0
- package/src/context.ts +66 -0
- package/src/derive.ts +485 -0
- 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-rendering.ts +87 -0
- package/src/errors.ts +483 -0
- package/src/execute.ts +1577 -0
- package/src/fetch.ts +138 -0
- package/src/fire.ts +1172 -0
- package/src/glob.ts +81 -0
- package/src/guards.ts +37 -0
- package/src/index.ts +704 -0
- package/src/internal/fork-ctx.ts +69 -0
- package/src/layer-field-rendering.ts +193 -0
- package/src/layer.ts +81 -0
- package/src/observe.ts +361 -0
- package/src/path-scope.ts +66 -0
- package/src/path-security.ts +98 -0
- package/src/patterns/bulk.ts +16 -0
- package/src/patterns/change.ts +12 -0
- package/src/patterns/date-range.ts +12 -0
- package/src/patterns/index.ts +8 -0
- package/src/patterns/pagination.ts +22 -0
- package/src/patterns/progress.ts +13 -0
- package/src/patterns/sorting.ts +14 -0
- package/src/patterns/status.ts +11 -0
- package/src/patterns/timestamps.ts +12 -0
- package/src/permits.ts +12 -0
- package/src/queue.ts +163 -0
- package/src/redaction/index.ts +3 -0
- package/src/redaction/patterns.ts +50 -0
- package/src/redaction/redactor.ts +178 -0
- package/src/resilience.ts +234 -0
- package/src/resource-config.ts +804 -0
- package/src/resource.ts +194 -0
- package/src/result.ts +212 -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 +265 -0
- 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 +835 -0
- package/src/tracing.ts +346 -0
- package/src/trail-id-glob.ts +15 -0
- package/src/trail.ts +1351 -0
- 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 +163 -0
- package/src/type-utils.ts +87 -0
- package/src/types.ts +300 -0
- package/src/validate-established-topo.ts +73 -0
- package/src/validate-topo.ts +725 -0
- package/src/validation.ts +330 -0
- 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 +244 -0
- package/src/zod-wrappers.ts +72 -0
package/src/fetch.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch utilities for @ontrails/core
|
|
3
|
+
*
|
|
4
|
+
* Wraps the standard fetch API, mapping errors and HTTP status codes
|
|
5
|
+
* to the TrailsError taxonomy.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
AuthError,
|
|
10
|
+
CancelledError,
|
|
11
|
+
ConflictError,
|
|
12
|
+
InternalError,
|
|
13
|
+
NetworkError,
|
|
14
|
+
NotFoundError,
|
|
15
|
+
PermissionError,
|
|
16
|
+
RateLimitError,
|
|
17
|
+
TimeoutError,
|
|
18
|
+
ValidationError,
|
|
19
|
+
} from './errors.js';
|
|
20
|
+
import { Result } from './result.js';
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Internal helpers (defined before usage)
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
const toError = (err: unknown): Error =>
|
|
27
|
+
err instanceof Error ? err : new Error(String(err));
|
|
28
|
+
|
|
29
|
+
const parseRetryAfter = (header: string | null): number | undefined => {
|
|
30
|
+
if (!header) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const seconds = Number(header);
|
|
34
|
+
if (Number.isFinite(seconds) && seconds > 0) {
|
|
35
|
+
return seconds;
|
|
36
|
+
}
|
|
37
|
+
// Try parsing as HTTP-date
|
|
38
|
+
const date = Date.parse(header);
|
|
39
|
+
if (!Number.isNaN(date)) {
|
|
40
|
+
const delta = Math.ceil((date - Date.now()) / 1000);
|
|
41
|
+
return delta > 0 ? delta : undefined;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const mapFetchError = (err: unknown): Error => {
|
|
47
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
48
|
+
return new CancelledError('Request was aborted', { cause: toError(err) });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// TypeError is thrown for network failures in the fetch spec
|
|
52
|
+
if (err instanceof TypeError) {
|
|
53
|
+
return new NetworkError('Network request failed', { cause: err });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return new NetworkError('Network request failed', {
|
|
57
|
+
cause: toError(err),
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type StatusMapper = (
|
|
62
|
+
context: Record<string, unknown>,
|
|
63
|
+
response: Response
|
|
64
|
+
) => Error;
|
|
65
|
+
|
|
66
|
+
const statusMappers: Record<number, StatusMapper> = {
|
|
67
|
+
401: (ctx) => new AuthError('Unauthorized', { context: ctx }),
|
|
68
|
+
403: (ctx) => new PermissionError('Forbidden', { context: ctx }),
|
|
69
|
+
404: (ctx) => new NotFoundError('Not found', { context: ctx }),
|
|
70
|
+
429: (ctx, response) => {
|
|
71
|
+
const retryAfter = parseRetryAfter(response.headers.get('retry-after'));
|
|
72
|
+
const opts: { context: Record<string, unknown>; retryAfter?: number } = {
|
|
73
|
+
context: ctx,
|
|
74
|
+
};
|
|
75
|
+
if (retryAfter !== undefined) {
|
|
76
|
+
opts.retryAfter = retryAfter;
|
|
77
|
+
}
|
|
78
|
+
return new RateLimitError('Rate limited', opts);
|
|
79
|
+
},
|
|
80
|
+
500: (ctx) => new InternalError('Internal server error', { context: ctx }),
|
|
81
|
+
502: (ctx) => new NetworkError('Bad gateway', { context: ctx }),
|
|
82
|
+
504: (ctx) => new TimeoutError('Gateway timeout', { context: ctx }),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Map 4xx status codes not in the explicit mapper to appropriate error types. */
|
|
86
|
+
const mapClientError = (
|
|
87
|
+
status: number,
|
|
88
|
+
context: Record<string, unknown>
|
|
89
|
+
): Error => {
|
|
90
|
+
if (status === 400 || status === 422) {
|
|
91
|
+
return new ValidationError(`Validation error (${status})`, { context });
|
|
92
|
+
}
|
|
93
|
+
if (status === 409) {
|
|
94
|
+
return new ConflictError(`Conflict (${status})`, { context });
|
|
95
|
+
}
|
|
96
|
+
return new InternalError(`HTTP error (${status})`, { context });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const mapStatusCode = (response: Response): Error => {
|
|
100
|
+
const context = { status: response.status, url: response.url };
|
|
101
|
+
const mapper = statusMappers[response.status];
|
|
102
|
+
if (mapper) {
|
|
103
|
+
return mapper(context, response);
|
|
104
|
+
}
|
|
105
|
+
if (response.status >= 500) {
|
|
106
|
+
return new InternalError(`Server error (${response.status})`, { context });
|
|
107
|
+
}
|
|
108
|
+
return mapClientError(response.status, context);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// fromFetch
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Wrap a fetch call in a Result, mapping failures to TrailsError subclasses.
|
|
117
|
+
*
|
|
118
|
+
* Network errors become NetworkError. Abort signals become CancelledError.
|
|
119
|
+
* HTTP error status codes map to the appropriate error category.
|
|
120
|
+
*/
|
|
121
|
+
export const fromFetch = async (
|
|
122
|
+
input: string | URL | Request,
|
|
123
|
+
init?: RequestInit
|
|
124
|
+
): Promise<Result<Response, Error>> => {
|
|
125
|
+
let response: Response;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
response = await fetch(input, init);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
return Result.err(mapFetchError(error));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (response.ok) {
|
|
134
|
+
return Result.ok(response);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return Result.err(mapStatusCode(response));
|
|
138
|
+
};
|