@elysra/tungsten-runtime 0.0.0-bootstrap.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/LICENSE +55 -0
- package/dist/auth.d.ts +50 -0
- package/dist/auth.js +264 -0
- package/dist/classify.d.ts +64 -0
- package/dist/classify.js +301 -0
- package/dist/client.d.ts +49 -0
- package/dist/client.js +2309 -0
- package/dist/confirm.d.ts +7 -0
- package/dist/confirm.js +32 -0
- package/dist/define.d.ts +13 -0
- package/dist/define.js +12 -0
- package/dist/envelope.d.ts +24 -0
- package/dist/envelope.js +152 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.js +75 -0
- package/dist/expr.d.ts +24 -0
- package/dist/expr.js +198 -0
- package/dist/idempotency.d.ts +27 -0
- package/dist/idempotency.js +56 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +19 -0
- package/dist/node.d.ts +17 -0
- package/dist/node.js +98 -0
- package/dist/oauth.d.ts +124 -0
- package/dist/oauth.js +367 -0
- package/dist/serialize.d.ts +55 -0
- package/dist/serialize.js +323 -0
- package/dist/sse.d.ts +42 -0
- package/dist/sse.js +166 -0
- package/dist/streams.d.ts +65 -0
- package/dist/streams.js +96 -0
- package/dist/transport.d.ts +88 -0
- package/dist/transport.js +245 -0
- package/dist/types.d.ts +667 -0
- package/dist/types.js +1 -0
- package/dist/util.d.ts +73 -0
- package/dist/util.js +317 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +4 -0
- package/package.json +55 -0
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small pure helpers shared by the runtime modules: value inspection,
|
|
3
|
+
* field paths, canonical JSON, hashing, encodings and redaction. Only
|
|
4
|
+
* platform APIs available in every supported runtime are used (Web Crypto,
|
|
5
|
+
* TextEncoder, btoa).
|
|
6
|
+
*/
|
|
7
|
+
/** Placeholder written wherever a secret or sensitive value would appear. */
|
|
8
|
+
export declare const REDACTED = "<redacted>";
|
|
9
|
+
/** Longest string kept in `Diagnostic.received_value`. */
|
|
10
|
+
export declare const MAX_RECEIVED_CHARS = 200;
|
|
11
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
12
|
+
export declare function isBlob(value: unknown): value is Blob;
|
|
13
|
+
export declare function isBinary(value: unknown): value is Uint8Array | ArrayBuffer | Blob;
|
|
14
|
+
/** Binary data with the file name and media type of its multipart part. A
|
|
15
|
+
* `File` carries its own name and type; use this for bytes or a plain
|
|
16
|
+
* `Blob`. Without a file name a part is named after its field. */
|
|
17
|
+
export interface NamedBinary {
|
|
18
|
+
data: Uint8Array | ArrayBuffer | Blob;
|
|
19
|
+
filename?: string;
|
|
20
|
+
contentType?: string;
|
|
21
|
+
}
|
|
22
|
+
/** What a binary request field takes: bytes, a `Blob` or `File`, or
|
|
23
|
+
* {@link NamedBinary}. */
|
|
24
|
+
export type BinaryInput = Uint8Array | ArrayBuffer | Blob | NamedBinary;
|
|
25
|
+
export declare function isNamedBinary(value: unknown): value is NamedBinary;
|
|
26
|
+
/** Whether `value` is a `BinaryInput`: bytes, a Blob or File, or `{ data, filename?, contentType? }`. */
|
|
27
|
+
export declare function isBinaryInput(value: unknown): value is BinaryInput;
|
|
28
|
+
export declare function binarySize(value: Uint8Array | ArrayBuffer | Blob): number;
|
|
29
|
+
export declare function hasOwn(value: object, key: string): boolean;
|
|
30
|
+
/** Split a field path (`a.b`, `items[0].id`, `items.0.id`) into segments. */
|
|
31
|
+
export declare function splitPath(path: string): string[];
|
|
32
|
+
/** Read a field path from a JSON-like value; `undefined` when absent. */
|
|
33
|
+
export declare function getPath(value: unknown, path: string | string[]): unknown;
|
|
34
|
+
/** Structural equality over JSON-like values. */
|
|
35
|
+
export declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
36
|
+
/** Every field of `pattern` appears in `value` with an equal (recursively
|
|
37
|
+
* contained) value. Arrays in `pattern` match when each element is
|
|
38
|
+
* contained by some element of the corresponding array. */
|
|
39
|
+
export declare function containsSubset(value: unknown, pattern: unknown): boolean;
|
|
40
|
+
export declare function bytesToBase64(bytes: Uint8Array): string;
|
|
41
|
+
export declare function base64url(bytes: Uint8Array): string;
|
|
42
|
+
export declare function utf8(text: string): Uint8Array;
|
|
43
|
+
/** Lowercase hex SHA-256 of UTF-8 text or bytes. */
|
|
44
|
+
export declare function sha256Hex(data: string | Uint8Array): Promise<string>;
|
|
45
|
+
/** HMAC-SHA-256 of `message` under `key`. */
|
|
46
|
+
export declare function hmacSha256(key: Uint8Array, message: string): Promise<Uint8Array>;
|
|
47
|
+
/** Constant-time comparison of two strings of known public length. */
|
|
48
|
+
export declare function timingSafeEqual(a: string, b: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Canonical JSON: object keys sorted by UTF-16 code units, `undefined` and
|
|
51
|
+
* functions dropped from objects (`null` in arrays), non-finite numbers as
|
|
52
|
+
* `null`, dates as ISO strings, bytes as `{"$bytes": base64}`, blobs as
|
|
53
|
+
* `{"$blob": {size, type}}`. Throws `TypeError` on cycles.
|
|
54
|
+
*/
|
|
55
|
+
export declare function canonicalJson(value: unknown): string;
|
|
56
|
+
/** Names that very likely hold a secret, redacted even without metadata. */
|
|
57
|
+
export declare function looksSensitive(name: string): boolean;
|
|
58
|
+
/** Deep copy of a JSON-like value with sensitive-looking keys redacted. */
|
|
59
|
+
export declare function redactSensitiveKeys(value: unknown, depth?: number): unknown;
|
|
60
|
+
/** Deep copy with every listed field path redacted; arrays on the way fan
|
|
61
|
+
* out, so `items.secret` redacts the field in each item. */
|
|
62
|
+
export declare function redactPaths(value: unknown, paths: readonly string[]): unknown;
|
|
63
|
+
/** A value made safe for `Diagnostic.received_value`: redacted when
|
|
64
|
+
* sensitive, binary summarised, strings and large values cut to 200
|
|
65
|
+
* characters, sensitive-looking nested keys redacted. */
|
|
66
|
+
export declare function envelopeValue(value: unknown, sensitive: boolean): unknown;
|
|
67
|
+
/** Sleep for `ms`, resolving early (to `false`) when `signal` aborts. */
|
|
68
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<boolean>;
|
|
69
|
+
/** A short, secret-free description of an unknown thrown value. */
|
|
70
|
+
export declare function describeError(error: unknown): string;
|
|
71
|
+
/** The `Accept` value of a stream call: the caller's media ranges in order
|
|
72
|
+
* without repeats, `text/event-stream` first when they do not name it. */
|
|
73
|
+
export declare function mergeAccept(value: string): string;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Small pure helpers shared by the runtime modules: value inspection,
|
|
4
|
+
* field paths, canonical JSON, hashing, encodings and redaction. Only
|
|
5
|
+
* platform APIs available in every supported runtime are used (Web Crypto,
|
|
6
|
+
* TextEncoder, btoa).
|
|
7
|
+
*/
|
|
8
|
+
/** Placeholder written wherever a secret or sensitive value would appear. */
|
|
9
|
+
export const REDACTED = "<redacted>";
|
|
10
|
+
/** Longest string kept in `Diagnostic.received_value`. */
|
|
11
|
+
export const MAX_RECEIVED_CHARS = 200;
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
export function isRecord(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
export function isBlob(value) {
|
|
17
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
18
|
+
}
|
|
19
|
+
export function isBinary(value) {
|
|
20
|
+
return value instanceof Uint8Array || value instanceof ArrayBuffer || isBlob(value);
|
|
21
|
+
}
|
|
22
|
+
export function isNamedBinary(value) {
|
|
23
|
+
if (!isRecord(value) || isBinary(value) || value instanceof Date)
|
|
24
|
+
return false;
|
|
25
|
+
const keys = Object.keys(value);
|
|
26
|
+
return (keys.includes("data") &&
|
|
27
|
+
keys.every((k) => k === "data" || k === "filename" || k === "contentType") &&
|
|
28
|
+
isBinary(value.data) &&
|
|
29
|
+
(value.filename === undefined || typeof value.filename === "string") &&
|
|
30
|
+
(value.contentType === undefined || typeof value.contentType === "string"));
|
|
31
|
+
}
|
|
32
|
+
/** Whether `value` is a `BinaryInput`: bytes, a Blob or File, or `{ data, filename?, contentType? }`. */
|
|
33
|
+
export function isBinaryInput(value) {
|
|
34
|
+
return isBinary(value) || isNamedBinary(value);
|
|
35
|
+
}
|
|
36
|
+
export function binarySize(value) {
|
|
37
|
+
return isBlob(value) ? value.size : value.byteLength;
|
|
38
|
+
}
|
|
39
|
+
export function hasOwn(value, key) {
|
|
40
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
41
|
+
}
|
|
42
|
+
/** Split a field path (`a.b`, `items[0].id`, `items.0.id`) into segments. */
|
|
43
|
+
export function splitPath(path) {
|
|
44
|
+
if (path === "" || path === ".")
|
|
45
|
+
return [];
|
|
46
|
+
return path
|
|
47
|
+
.replace(/\[(\d+)\]/g, ".$1")
|
|
48
|
+
.split(".")
|
|
49
|
+
.filter((s) => s !== "");
|
|
50
|
+
}
|
|
51
|
+
/** Read a field path from a JSON-like value; `undefined` when absent. */
|
|
52
|
+
export function getPath(value, path) {
|
|
53
|
+
const segments = typeof path === "string" ? splitPath(path) : path;
|
|
54
|
+
let current = value;
|
|
55
|
+
for (const segment of segments) {
|
|
56
|
+
if (Array.isArray(current)) {
|
|
57
|
+
if (!/^\d+$/.test(segment))
|
|
58
|
+
return undefined;
|
|
59
|
+
current = current[Number(segment)];
|
|
60
|
+
}
|
|
61
|
+
else if (isRecord(current)) {
|
|
62
|
+
if (!hasOwn(current, segment))
|
|
63
|
+
return undefined;
|
|
64
|
+
current = current[segment];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return current;
|
|
71
|
+
}
|
|
72
|
+
/** Structural equality over JSON-like values. */
|
|
73
|
+
export function deepEqual(a, b) {
|
|
74
|
+
if (Object.is(a, b))
|
|
75
|
+
return true;
|
|
76
|
+
if (typeof a === "number" && typeof b === "number")
|
|
77
|
+
return a === b;
|
|
78
|
+
if (Array.isArray(a)) {
|
|
79
|
+
return Array.isArray(b) && a.length === b.length && a.every((x, i) => deepEqual(x, b[i]));
|
|
80
|
+
}
|
|
81
|
+
if (isRecord(a) && isRecord(b) && !Array.isArray(b)) {
|
|
82
|
+
const ka = Object.keys(a).filter((k) => a[k] !== undefined);
|
|
83
|
+
const kb = Object.keys(b).filter((k) => b[k] !== undefined);
|
|
84
|
+
return ka.length === kb.length && ka.every((k) => hasOwn(b, k) && deepEqual(a[k], b[k]));
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
/** Every field of `pattern` appears in `value` with an equal (recursively
|
|
89
|
+
* contained) value. Arrays in `pattern` match when each element is
|
|
90
|
+
* contained by some element of the corresponding array. */
|
|
91
|
+
export function containsSubset(value, pattern) {
|
|
92
|
+
if (isRecord(pattern)) {
|
|
93
|
+
if (!isRecord(value))
|
|
94
|
+
return false;
|
|
95
|
+
return Object.keys(pattern).every((k) => hasOwn(value, k) && containsSubset(value[k], pattern[k]));
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(pattern)) {
|
|
98
|
+
if (!Array.isArray(value))
|
|
99
|
+
return false;
|
|
100
|
+
return pattern.every((p) => value.some((v) => containsSubset(v, p)));
|
|
101
|
+
}
|
|
102
|
+
return deepEqual(value, pattern);
|
|
103
|
+
}
|
|
104
|
+
export function bytesToBase64(bytes) {
|
|
105
|
+
let binary = "";
|
|
106
|
+
const chunk = 0x8000;
|
|
107
|
+
for (let i = 0; i < bytes.length; i += chunk) {
|
|
108
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
109
|
+
}
|
|
110
|
+
return btoa(binary);
|
|
111
|
+
}
|
|
112
|
+
export function base64url(bytes) {
|
|
113
|
+
return bytesToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
114
|
+
}
|
|
115
|
+
export function utf8(text) {
|
|
116
|
+
return encoder.encode(text);
|
|
117
|
+
}
|
|
118
|
+
function toHex(buffer) {
|
|
119
|
+
return Array.from(new Uint8Array(buffer), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
120
|
+
}
|
|
121
|
+
function bufferSource(data) {
|
|
122
|
+
const bytes = typeof data === "string" ? utf8(data) : data;
|
|
123
|
+
const copy = new Uint8Array(new ArrayBuffer(bytes.byteLength));
|
|
124
|
+
copy.set(bytes);
|
|
125
|
+
return copy;
|
|
126
|
+
}
|
|
127
|
+
/** Lowercase hex SHA-256 of UTF-8 text or bytes. */
|
|
128
|
+
export async function sha256Hex(data) {
|
|
129
|
+
return toHex(await crypto.subtle.digest("SHA-256", bufferSource(data)));
|
|
130
|
+
}
|
|
131
|
+
/** HMAC-SHA-256 of `message` under `key`. */
|
|
132
|
+
export async function hmacSha256(key, message) {
|
|
133
|
+
const cryptoKey = await crypto.subtle.importKey("raw", bufferSource(key), { name: "HMAC", hash: "SHA-256" }, false, [
|
|
134
|
+
"sign",
|
|
135
|
+
]);
|
|
136
|
+
return new Uint8Array(await crypto.subtle.sign("HMAC", cryptoKey, bufferSource(message)));
|
|
137
|
+
}
|
|
138
|
+
/** Constant-time comparison of two strings of known public length. */
|
|
139
|
+
export function timingSafeEqual(a, b) {
|
|
140
|
+
if (a.length !== b.length)
|
|
141
|
+
return false;
|
|
142
|
+
let diff = 0;
|
|
143
|
+
for (let i = 0; i < a.length; i++)
|
|
144
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
145
|
+
return diff === 0;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Canonical JSON: object keys sorted by UTF-16 code units, `undefined` and
|
|
149
|
+
* functions dropped from objects (`null` in arrays), non-finite numbers as
|
|
150
|
+
* `null`, dates as ISO strings, bytes as `{"$bytes": base64}`, blobs as
|
|
151
|
+
* `{"$blob": {size, type}}`. Throws `TypeError` on cycles.
|
|
152
|
+
*/
|
|
153
|
+
export function canonicalJson(value) {
|
|
154
|
+
const stack = new Set();
|
|
155
|
+
const encode = (v) => {
|
|
156
|
+
switch (typeof v) {
|
|
157
|
+
case "undefined":
|
|
158
|
+
case "function":
|
|
159
|
+
case "symbol":
|
|
160
|
+
return undefined;
|
|
161
|
+
case "string":
|
|
162
|
+
return JSON.stringify(v);
|
|
163
|
+
case "number":
|
|
164
|
+
return Number.isFinite(v) ? JSON.stringify(v) : "null";
|
|
165
|
+
case "boolean":
|
|
166
|
+
return v ? "true" : "false";
|
|
167
|
+
case "bigint":
|
|
168
|
+
return JSON.stringify(v.toString());
|
|
169
|
+
}
|
|
170
|
+
if (v === null)
|
|
171
|
+
return "null";
|
|
172
|
+
if (v instanceof Date)
|
|
173
|
+
return Number.isNaN(v.getTime()) ? "null" : JSON.stringify(v.toISOString());
|
|
174
|
+
if (v instanceof Uint8Array)
|
|
175
|
+
return `{"$bytes":${JSON.stringify(bytesToBase64(v))}}`;
|
|
176
|
+
if (v instanceof ArrayBuffer)
|
|
177
|
+
return `{"$bytes":${JSON.stringify(bytesToBase64(new Uint8Array(v)))}}`;
|
|
178
|
+
if (isBlob(v))
|
|
179
|
+
return `{"$blob":{"size":${v.size},"type":${JSON.stringify(v.type)}}}`;
|
|
180
|
+
const obj = v;
|
|
181
|
+
if (stack.has(obj))
|
|
182
|
+
throw new TypeError("the value contains a cycle");
|
|
183
|
+
stack.add(obj);
|
|
184
|
+
let out;
|
|
185
|
+
if (Array.isArray(obj)) {
|
|
186
|
+
out = `[${obj.map((item) => encode(item) ?? "null").join(",")}]`;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const record = obj;
|
|
190
|
+
const parts = [];
|
|
191
|
+
for (const key of Object.keys(record).sort()) {
|
|
192
|
+
const encoded = encode(record[key]);
|
|
193
|
+
if (encoded !== undefined)
|
|
194
|
+
parts.push(`${JSON.stringify(key)}:${encoded}`);
|
|
195
|
+
}
|
|
196
|
+
out = `{${parts.join(",")}}`;
|
|
197
|
+
}
|
|
198
|
+
stack.delete(obj);
|
|
199
|
+
return out;
|
|
200
|
+
};
|
|
201
|
+
return encode(value) ?? "null";
|
|
202
|
+
}
|
|
203
|
+
const SENSITIVE_NAME = /(secret|password|passwd|passphrase|token|api[-_]?key|private[-_]?key|credential|authorization|cookie|session)/i;
|
|
204
|
+
/** Names that very likely hold a secret, redacted even without metadata. */
|
|
205
|
+
export function looksSensitive(name) {
|
|
206
|
+
return SENSITIVE_NAME.test(name);
|
|
207
|
+
}
|
|
208
|
+
/** Deep copy of a JSON-like value with sensitive-looking keys redacted. */
|
|
209
|
+
export function redactSensitiveKeys(value, depth = 0) {
|
|
210
|
+
if (depth > 32)
|
|
211
|
+
return null;
|
|
212
|
+
if (Array.isArray(value))
|
|
213
|
+
return value.map((v) => redactSensitiveKeys(v, depth + 1));
|
|
214
|
+
if (isRecord(value) && !isBinary(value) && !(value instanceof Date)) {
|
|
215
|
+
const out = {};
|
|
216
|
+
for (const key of Object.keys(value)) {
|
|
217
|
+
out[key] = looksSensitive(key) ? REDACTED : redactSensitiveKeys(value[key], depth + 1);
|
|
218
|
+
}
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
/** Deep copy with every listed field path redacted; arrays on the way fan
|
|
224
|
+
* out, so `items.secret` redacts the field in each item. */
|
|
225
|
+
export function redactPaths(value, paths) {
|
|
226
|
+
if (paths.length === 0)
|
|
227
|
+
return value;
|
|
228
|
+
const apply = (v, segments) => {
|
|
229
|
+
if (segments.length === 0)
|
|
230
|
+
return REDACTED;
|
|
231
|
+
if (Array.isArray(v))
|
|
232
|
+
return v.map((item) => apply(item, segments));
|
|
233
|
+
if (!isRecord(v))
|
|
234
|
+
return v;
|
|
235
|
+
const [head, ...rest] = segments;
|
|
236
|
+
if (!hasOwn(v, head))
|
|
237
|
+
return v;
|
|
238
|
+
return { ...v, [head]: apply(v[head], rest) };
|
|
239
|
+
};
|
|
240
|
+
let out = value;
|
|
241
|
+
for (const path of paths) {
|
|
242
|
+
const segments = splitPath(path);
|
|
243
|
+
if (segments.length > 0)
|
|
244
|
+
out = apply(out, segments);
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
function cut(text) {
|
|
249
|
+
return text.length > MAX_RECEIVED_CHARS ? `${text.slice(0, MAX_RECEIVED_CHARS - 1)}…` : text;
|
|
250
|
+
}
|
|
251
|
+
/** A value made safe for `Diagnostic.received_value`: redacted when
|
|
252
|
+
* sensitive, binary summarised, strings and large values cut to 200
|
|
253
|
+
* characters, sensitive-looking nested keys redacted. */
|
|
254
|
+
export function envelopeValue(value, sensitive) {
|
|
255
|
+
if (sensitive)
|
|
256
|
+
return REDACTED;
|
|
257
|
+
if (value === undefined)
|
|
258
|
+
return null;
|
|
259
|
+
if (typeof value === "string")
|
|
260
|
+
return cut(value);
|
|
261
|
+
if (typeof value === "number")
|
|
262
|
+
return Number.isFinite(value) ? value : String(value);
|
|
263
|
+
if (typeof value === "boolean" || value === null)
|
|
264
|
+
return value;
|
|
265
|
+
if (typeof value === "bigint")
|
|
266
|
+
return value.toString();
|
|
267
|
+
if (isBinary(value))
|
|
268
|
+
return `<${binarySize(value)} bytes>`;
|
|
269
|
+
if (typeof value !== "object")
|
|
270
|
+
return `<${typeof value}>`;
|
|
271
|
+
let json;
|
|
272
|
+
try {
|
|
273
|
+
json = JSON.stringify(redactSensitiveKeys(value)) ?? "null";
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return "<unserializable value>";
|
|
277
|
+
}
|
|
278
|
+
return json.length > MAX_RECEIVED_CHARS ? cut(json) : JSON.parse(json);
|
|
279
|
+
}
|
|
280
|
+
/** Sleep for `ms`, resolving early (to `false`) when `signal` aborts. */
|
|
281
|
+
export function sleep(ms, signal) {
|
|
282
|
+
return new Promise((resolve) => {
|
|
283
|
+
if (signal?.aborted) {
|
|
284
|
+
resolve(false);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const onAbort = () => {
|
|
288
|
+
clearTimeout(timer);
|
|
289
|
+
resolve(false);
|
|
290
|
+
};
|
|
291
|
+
const timer = setTimeout(() => {
|
|
292
|
+
signal?.removeEventListener("abort", onAbort);
|
|
293
|
+
resolve(true);
|
|
294
|
+
}, Math.max(0, ms));
|
|
295
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/** A short, secret-free description of an unknown thrown value. */
|
|
299
|
+
export function describeError(error) {
|
|
300
|
+
if (error instanceof Error) {
|
|
301
|
+
const name = error.name && error.name !== "Error" ? `${error.name}: ` : "";
|
|
302
|
+
return cut(`${name}${error.message}`);
|
|
303
|
+
}
|
|
304
|
+
return cut(typeof error === "string" ? error : "unknown error");
|
|
305
|
+
}
|
|
306
|
+
/** The `Accept` value of a stream call: the caller's media ranges in order
|
|
307
|
+
* without repeats, `text/event-stream` first when they do not name it. */
|
|
308
|
+
export function mergeAccept(value) {
|
|
309
|
+
const ranges = [];
|
|
310
|
+
for (const part of value.split(",")) {
|
|
311
|
+
const range = part.trim();
|
|
312
|
+
if (range !== "" && !ranges.includes(range))
|
|
313
|
+
ranges.push(range);
|
|
314
|
+
}
|
|
315
|
+
const names = ranges.some((range) => (range.split(";")[0] ?? "").trim().toLowerCase() === "text/event-stream");
|
|
316
|
+
return (names ? ranges : ["text/event-stream", ...ranges]).join(", ");
|
|
317
|
+
}
|
package/dist/version.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elysra/tungsten-runtime",
|
|
3
|
+
"version": "0.0.0-bootstrap.0",
|
|
4
|
+
"description": "Runtime for SDKs generated by tungsten: transport, retries, idempotency, diagnostic error envelopes, previews and pagination.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openapi",
|
|
7
|
+
"sdk",
|
|
8
|
+
"tungsten",
|
|
9
|
+
"agents",
|
|
10
|
+
"runtime",
|
|
11
|
+
"typescript"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/pboachie/tungsten",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/pboachie/tungsten.git",
|
|
17
|
+
"directory": "runtimes/ts"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/pboachie/tungsten/issues"
|
|
21
|
+
},
|
|
22
|
+
"author": "Prince Boachie",
|
|
23
|
+
"license": "Apache-2.0",
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"import": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./node": {
|
|
37
|
+
"types": "./dist/node.d.ts",
|
|
38
|
+
"import": "./dist/node.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.json"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "26.6.4",
|
|
53
|
+
"typescript": "7.0.2"
|
|
54
|
+
}
|
|
55
|
+
}
|