@intentproof/sdk 0.1.4 → 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/LICENSE +0 -25
- package/NOTICE +16 -0
- package/README.md +40 -408
- package/dist/canon.d.ts +11 -0
- package/dist/canon.js +17 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +114 -0
- package/dist/exporter.d.ts +12 -0
- package/dist/exporter.js +68 -0
- package/dist/index.d.ts +3 -524
- package/dist/index.js +22 -1119
- package/dist/instrumentation.d.ts +6 -0
- package/dist/instrumentation.js +129 -0
- package/dist/outbox.d.ts +11 -0
- package/dist/outbox.js +53 -0
- package/dist/signing.d.ts +6 -0
- package/dist/signing.js +55 -0
- package/package.json +40 -71
- package/dist/index.cjs +0 -1172
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -524
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,1119 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return this.events;
|
|
24
|
-
}
|
|
25
|
-
clear() {
|
|
26
|
-
this.events.length = 0;
|
|
27
|
-
}
|
|
28
|
-
flush() {
|
|
29
|
-
return Promise.resolve();
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// src/runtime.ts
|
|
34
|
-
function describeValueType(value) {
|
|
35
|
-
if (value === null) return "null";
|
|
36
|
-
if (Array.isArray(value)) return "array";
|
|
37
|
-
return typeof value;
|
|
38
|
-
}
|
|
39
|
-
function isPromiseLike(x) {
|
|
40
|
-
return x !== null && typeof x === "object" && typeof x.then === "function";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// src/snapshot.ts
|
|
44
|
-
var DEFAULT_MAX_DEPTH = 6;
|
|
45
|
-
var DEFAULT_MAX_KEYS = 50;
|
|
46
|
-
function snapshotLimit(n, fallback) {
|
|
47
|
-
if (n === void 0) return fallback;
|
|
48
|
-
if (!Number.isFinite(n)) return fallback;
|
|
49
|
-
const i = Math.trunc(n);
|
|
50
|
-
return i < 0 ? fallback : i;
|
|
51
|
-
}
|
|
52
|
-
function snapshotStringLimit(n) {
|
|
53
|
-
if (n === void 0) return void 0;
|
|
54
|
-
if (!Number.isFinite(n)) return void 0;
|
|
55
|
-
const i = Math.trunc(n);
|
|
56
|
-
return i < 0 ? void 0 : i;
|
|
57
|
-
}
|
|
58
|
-
function normalizeRedactSet(redactKeys) {
|
|
59
|
-
if (!redactKeys?.length) return void 0;
|
|
60
|
-
const set = new Set(
|
|
61
|
-
redactKeys.filter((k) => typeof k === "string" && k.length > 0).map((k) => k.toLowerCase())
|
|
62
|
-
);
|
|
63
|
-
return set.size > 0 ? set : void 0;
|
|
64
|
-
}
|
|
65
|
-
function shouldRedactKey(key, redact) {
|
|
66
|
-
if (!redact) return false;
|
|
67
|
-
return redact.has(key.toLowerCase());
|
|
68
|
-
}
|
|
69
|
-
function truncateString(s, maxLen) {
|
|
70
|
-
if (maxLen === void 0 || s.length <= maxLen) return s;
|
|
71
|
-
return `${s.slice(0, maxLen)}\u2026[truncated ${s.length - maxLen} chars]`;
|
|
72
|
-
}
|
|
73
|
-
function snapshot(value, options = {}) {
|
|
74
|
-
const maxDepth = snapshotLimit(options.maxDepth, DEFAULT_MAX_DEPTH);
|
|
75
|
-
const maxKeys = snapshotLimit(options.maxKeys, DEFAULT_MAX_KEYS);
|
|
76
|
-
const maxStringLength = snapshotStringLimit(options.maxStringLength);
|
|
77
|
-
const redact = normalizeRedactSet(options.redactKeys);
|
|
78
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
79
|
-
function walk(v, depth) {
|
|
80
|
-
if (v === null || v === void 0) return v;
|
|
81
|
-
const t = typeof v;
|
|
82
|
-
if (t === "string" || t === "number" || t === "boolean") {
|
|
83
|
-
if (t === "string") return truncateString(v, maxStringLength);
|
|
84
|
-
return v;
|
|
85
|
-
}
|
|
86
|
-
if (t === "bigint") return v.toString();
|
|
87
|
-
if (t === "symbol") return v.toString();
|
|
88
|
-
if (t === "function") {
|
|
89
|
-
const fn = v;
|
|
90
|
-
return `[Function ${fn.name || "anonymous"}]`;
|
|
91
|
-
}
|
|
92
|
-
if (v instanceof Date) return v.toISOString();
|
|
93
|
-
if (Array.isArray(v)) {
|
|
94
|
-
if (depth >= maxDepth) return "[Array]";
|
|
95
|
-
return v.slice(0, maxKeys).map((item) => walk(item, depth + 1));
|
|
96
|
-
}
|
|
97
|
-
const o = v;
|
|
98
|
-
if (seen.has(o)) return "[Circular]";
|
|
99
|
-
seen.add(o);
|
|
100
|
-
if (depth >= maxDepth) return "[Object]";
|
|
101
|
-
const out = {};
|
|
102
|
-
const keys = Object.keys(o);
|
|
103
|
-
let n = 0;
|
|
104
|
-
for (const k of keys) {
|
|
105
|
-
if (n >= maxKeys) {
|
|
106
|
-
out["\u2026"] = `${keys.length - maxKeys} more keys`;
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
if (shouldRedactKey(k, redact)) {
|
|
111
|
-
out[k] = "[REDACTED]";
|
|
112
|
-
} else {
|
|
113
|
-
out[k] = walk(o[k], depth + 1);
|
|
114
|
-
}
|
|
115
|
-
} catch {
|
|
116
|
-
out[k] = "[Unserializable]";
|
|
117
|
-
}
|
|
118
|
-
n += 1;
|
|
119
|
-
}
|
|
120
|
-
return out;
|
|
121
|
-
}
|
|
122
|
-
try {
|
|
123
|
-
return walk(value, 0);
|
|
124
|
-
} catch {
|
|
125
|
-
return "[SnapshotError]";
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// src/validators.ts
|
|
130
|
-
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
131
|
-
import * as AjvFormats from "ajv-formats";
|
|
132
|
-
|
|
133
|
-
// src/generated/embed/execution-event.v1.ts
|
|
134
|
-
var execution_event_v1_default = {
|
|
135
|
-
$comment: "Normative IntentProof source tree: https://github.com/IntentProof/intentproof-spec/tree/main/schema \u2014 $id is a logical URI; see README.",
|
|
136
|
-
$defs: {
|
|
137
|
-
ExecutionError: {
|
|
138
|
-
additionalProperties: false,
|
|
139
|
-
properties: {
|
|
140
|
-
cause: {
|
|
141
|
-
$ref: "#/$defs/ExecutionError",
|
|
142
|
-
description: "Optional chained cause; MUST conform to ExecutionError when present."
|
|
143
|
-
},
|
|
144
|
-
code: { description: "Optional stable machine-readable code.", type: "string" },
|
|
145
|
-
message: {
|
|
146
|
-
description: "Human-readable error message (may be empty string if the runtime provides none).",
|
|
147
|
-
type: "string"
|
|
148
|
-
},
|
|
149
|
-
name: {
|
|
150
|
-
description: "Exception or error type name (e.g. Error, TypeError).",
|
|
151
|
-
minLength: 1,
|
|
152
|
-
type: "string"
|
|
153
|
-
},
|
|
154
|
-
stack: {
|
|
155
|
-
description: "Optional stringified stack trace; null when stacks are suppressed.",
|
|
156
|
-
type: ["string", "null"]
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
required: ["name", "message"],
|
|
160
|
-
type: "object"
|
|
161
|
-
},
|
|
162
|
-
JsonValue: {
|
|
163
|
-
anyOf: [
|
|
164
|
-
{ type: "null" },
|
|
165
|
-
{ type: "boolean" },
|
|
166
|
-
{ type: "number" },
|
|
167
|
-
{ type: "string" },
|
|
168
|
-
{ items: { $ref: "#/$defs/JsonValue" }, type: "array" },
|
|
169
|
-
{ additionalProperties: { $ref: "#/$defs/JsonValue" }, type: "object" }
|
|
170
|
-
],
|
|
171
|
-
description: "Any JSON-serializable value per semantics/serialization_rules.md."
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
$id: "https://intentproof.dev/schema/execution_event.v1.schema.json",
|
|
175
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
176
|
-
additionalProperties: false,
|
|
177
|
-
allOf: [
|
|
178
|
-
{
|
|
179
|
-
if: { properties: { status: { const: "ok" } }, required: ["status"] },
|
|
180
|
-
then: { not: { required: ["error"] }, required: ["output"] }
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
if: { properties: { status: { const: "error" } }, required: ["status"] },
|
|
184
|
-
then: { required: ["error"] }
|
|
185
|
-
}
|
|
186
|
-
],
|
|
187
|
-
properties: {
|
|
188
|
-
action: {
|
|
189
|
-
description: "Stable identifier for the concrete operation. Many systems use hierarchical dotted names (e.g. vendor.resource.operation); REST paths, RPC names, or other conventions are allowed. The schema does not constrain the format.",
|
|
190
|
-
minLength: 1,
|
|
191
|
-
type: "string"
|
|
192
|
-
},
|
|
193
|
-
attributes: {
|
|
194
|
-
additionalProperties: { type: ["string", "number", "boolean", "null"] },
|
|
195
|
-
description: "Flat primitive key/value metadata attached to the event.",
|
|
196
|
-
propertyNames: { pattern: "^[A-Za-z0-9_.:-]{1,256}$" },
|
|
197
|
-
type: "object"
|
|
198
|
-
},
|
|
199
|
-
completedAt: {
|
|
200
|
-
description: "RFC 3339 / ISO 8601 instant when execution completed.",
|
|
201
|
-
format: "date-time",
|
|
202
|
-
type: "string"
|
|
203
|
-
},
|
|
204
|
-
correlationId: {
|
|
205
|
-
description: "Optional cross-cutting identifier for distributed tracing. MUST be trimmed and non-empty when present.",
|
|
206
|
-
minLength: 1,
|
|
207
|
-
type: "string"
|
|
208
|
-
},
|
|
209
|
-
durationMs: {
|
|
210
|
-
description: "Wall-clock duration in milliseconds between startedAt and completedAt.",
|
|
211
|
-
minimum: 0,
|
|
212
|
-
type: "number"
|
|
213
|
-
},
|
|
214
|
-
error: {
|
|
215
|
-
$ref: "#/$defs/ExecutionError",
|
|
216
|
-
description: "Structured error when status is error."
|
|
217
|
-
},
|
|
218
|
-
id: {
|
|
219
|
-
description: "Stable unique identifier for this execution record.",
|
|
220
|
-
minLength: 1,
|
|
221
|
-
type: "string"
|
|
222
|
-
},
|
|
223
|
-
inputs: {
|
|
224
|
-
additionalProperties: true,
|
|
225
|
-
description: "Captured call inputs. Values MUST be JSON-serializable (see semantics/serialization_rules.md).",
|
|
226
|
-
type: "object"
|
|
227
|
-
},
|
|
228
|
-
intent: {
|
|
229
|
-
description: "Natural-language description of what the user or caller was trying to achieve (often a full sentence or question). No fixed grammar; SHOULD stay human-readable in logs and UIs.",
|
|
230
|
-
minLength: 1,
|
|
231
|
-
type: "string"
|
|
232
|
-
},
|
|
233
|
-
output: {
|
|
234
|
-
$ref: "#/$defs/JsonValue",
|
|
235
|
-
description: "Captured return value when status is ok, or optional captured value when captureError allows output on failure."
|
|
236
|
-
},
|
|
237
|
-
startedAt: {
|
|
238
|
-
description: "RFC 3339 / ISO 8601 instant when execution started.",
|
|
239
|
-
format: "date-time",
|
|
240
|
-
type: "string"
|
|
241
|
-
},
|
|
242
|
-
status: {
|
|
243
|
-
description: "Terminal execution status.",
|
|
244
|
-
enum: ["ok", "error"],
|
|
245
|
-
type: "string"
|
|
246
|
-
}
|
|
247
|
-
},
|
|
248
|
-
required: [
|
|
249
|
-
"id",
|
|
250
|
-
"intent",
|
|
251
|
-
"action",
|
|
252
|
-
"status",
|
|
253
|
-
"inputs",
|
|
254
|
-
"startedAt",
|
|
255
|
-
"completedAt",
|
|
256
|
-
"durationMs"
|
|
257
|
-
],
|
|
258
|
-
title: "IntentProof ExecutionEvent v1",
|
|
259
|
-
type: "object"
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// src/generated/embed/intentproof-config.v1.ts
|
|
263
|
-
var intentproof_config_v1_default = {
|
|
264
|
-
$comment: "Normative IntentProof source tree: https://github.com/IntentProof/intentproof-spec/tree/main/schema \u2014 $id is a logical URI; see README.",
|
|
265
|
-
$defs: {
|
|
266
|
-
WrapOptionsV1: {
|
|
267
|
-
$comment: "Normative IntentProof source tree: https://github.com/IntentProof/intentproof-spec/tree/main/schema \u2014 $id is a logical URI; see README.",
|
|
268
|
-
$id: "https://intentproof.dev/schema/wrap_options.v1.schema.json",
|
|
269
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
270
|
-
additionalProperties: false,
|
|
271
|
-
properties: {
|
|
272
|
-
action: {
|
|
273
|
-
description: "Default operation identifier (often dotted like vendor.service.method); SDKs MAY derive from the callable when omitted.",
|
|
274
|
-
minLength: 1,
|
|
275
|
-
type: "string"
|
|
276
|
-
},
|
|
277
|
-
attributes: {
|
|
278
|
-
additionalProperties: { type: ["string", "number", "boolean", "null"] },
|
|
279
|
-
description: "Static attributes merged into each emitted ExecutionEvent.attributes.",
|
|
280
|
-
type: "object"
|
|
281
|
-
},
|
|
282
|
-
captureError: {
|
|
283
|
-
default: true,
|
|
284
|
-
description: "When true, failures MUST populate error; when false with captureOutput semantics, see semantics/wrap_behavior.md.",
|
|
285
|
-
type: "boolean"
|
|
286
|
-
},
|
|
287
|
-
captureInputs: {
|
|
288
|
-
default: true,
|
|
289
|
-
description: "When false, inputs MUST be serialized as an empty object {}.",
|
|
290
|
-
type: "boolean"
|
|
291
|
-
},
|
|
292
|
-
captureOutput: {
|
|
293
|
-
default: true,
|
|
294
|
-
description: "When false and status is ok, output MUST be null.",
|
|
295
|
-
type: "boolean"
|
|
296
|
-
},
|
|
297
|
-
captureStack: {
|
|
298
|
-
default: true,
|
|
299
|
-
description: "When false, error.stack MUST be null on emitted events.",
|
|
300
|
-
type: "boolean"
|
|
301
|
-
},
|
|
302
|
-
exporterTimeoutMs: {
|
|
303
|
-
description: "Maximum time an exporter hook may block the wrap boundary; 0 means SDK default.",
|
|
304
|
-
minimum: 0,
|
|
305
|
-
type: "number"
|
|
306
|
-
},
|
|
307
|
-
intent: {
|
|
308
|
-
description: "Default natural-language intent for wrapped executions when the call site does not override it.",
|
|
309
|
-
minLength: 1,
|
|
310
|
-
type: "string"
|
|
311
|
-
},
|
|
312
|
-
propagateCorrelation: {
|
|
313
|
-
default: true,
|
|
314
|
-
description: "When true, nested wraps inherit the active correlationId.",
|
|
315
|
-
type: "boolean"
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
title: "IntentProof WrapOptions v1",
|
|
319
|
-
type: "object"
|
|
320
|
-
}
|
|
321
|
-
},
|
|
322
|
-
$id: "https://intentproof.dev/schema/intentproof_config.v1.schema.json",
|
|
323
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
324
|
-
additionalProperties: false,
|
|
325
|
-
properties: {
|
|
326
|
-
correlation: {
|
|
327
|
-
additionalProperties: false,
|
|
328
|
-
properties: {
|
|
329
|
-
generateOnMissing: {
|
|
330
|
-
default: true,
|
|
331
|
-
description: "When true, SDK generates a UUID when no correlation is active.",
|
|
332
|
-
type: "boolean"
|
|
333
|
-
},
|
|
334
|
-
headerName: {
|
|
335
|
-
default: "x-intentproof-correlation-id",
|
|
336
|
-
description: "HTTP header used for inbound correlation extraction when applicable.",
|
|
337
|
-
type: "string"
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
type: "object"
|
|
341
|
-
},
|
|
342
|
-
defaultWrapOptions: { $ref: "#/$defs/WrapOptionsV1" },
|
|
343
|
-
exporters: {
|
|
344
|
-
description: "Ordered list of exporter identifiers or inline hooks (SDK-defined encoding).",
|
|
345
|
-
items: {
|
|
346
|
-
additionalProperties: true,
|
|
347
|
-
properties: {
|
|
348
|
-
endpoint: {
|
|
349
|
-
description: "Required for http exporters when used.",
|
|
350
|
-
format: "uri",
|
|
351
|
-
type: "string"
|
|
352
|
-
},
|
|
353
|
-
failOpen: {
|
|
354
|
-
default: true,
|
|
355
|
-
description: "When true, exporter failures MUST NOT change user-visible outcomes.",
|
|
356
|
-
type: "boolean"
|
|
357
|
-
},
|
|
358
|
-
headers: {
|
|
359
|
-
additionalProperties: { type: "string" },
|
|
360
|
-
description: "Optional HTTP headers for http exporters.",
|
|
361
|
-
type: "object"
|
|
362
|
-
},
|
|
363
|
-
type: {
|
|
364
|
-
description: "Exporter kind; custom MUST include implementation-specific fields.",
|
|
365
|
-
enum: ["console", "http", "otel", "custom"],
|
|
366
|
-
type: "string"
|
|
367
|
-
}
|
|
368
|
-
},
|
|
369
|
-
required: ["type"],
|
|
370
|
-
type: "object"
|
|
371
|
-
},
|
|
372
|
-
type: "array"
|
|
373
|
-
},
|
|
374
|
-
serialization: {
|
|
375
|
-
additionalProperties: false,
|
|
376
|
-
properties: {
|
|
377
|
-
maxDepth: {
|
|
378
|
-
default: 32,
|
|
379
|
-
description: "Maximum object graph depth for input/output capture.",
|
|
380
|
-
minimum: 1,
|
|
381
|
-
type: "integer"
|
|
382
|
-
},
|
|
383
|
-
maxStringLength: {
|
|
384
|
-
default: 65536,
|
|
385
|
-
description: "Maximum serialized string length for any single field.",
|
|
386
|
-
minimum: 1,
|
|
387
|
-
type: "integer"
|
|
388
|
-
},
|
|
389
|
-
redactKeys: {
|
|
390
|
-
description: "Case-insensitive key names to replace with [REDACTED] in captured objects.",
|
|
391
|
-
items: { type: "string" },
|
|
392
|
-
type: "array"
|
|
393
|
-
}
|
|
394
|
-
},
|
|
395
|
-
type: "object"
|
|
396
|
-
},
|
|
397
|
-
version: {
|
|
398
|
-
const: 1,
|
|
399
|
-
description: "Config document version; MUST be 1 for this schema.",
|
|
400
|
-
type: "integer"
|
|
401
|
-
}
|
|
402
|
-
},
|
|
403
|
-
title: "IntentProof Runtime Config v1",
|
|
404
|
-
type: "object"
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
// src/generated/embed/wrap-options.v1.ts
|
|
408
|
-
var wrap_options_v1_default = {
|
|
409
|
-
$comment: "Normative IntentProof source tree: https://github.com/IntentProof/intentproof-spec/tree/main/schema \u2014 $id is a logical URI; see README.",
|
|
410
|
-
$id: "https://intentproof.dev/schema/wrap_options.v1.schema.json",
|
|
411
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
412
|
-
additionalProperties: false,
|
|
413
|
-
properties: {
|
|
414
|
-
action: {
|
|
415
|
-
description: "Default operation identifier (often dotted like vendor.service.method); SDKs MAY derive from the callable when omitted.",
|
|
416
|
-
minLength: 1,
|
|
417
|
-
type: "string"
|
|
418
|
-
},
|
|
419
|
-
attributes: {
|
|
420
|
-
additionalProperties: { type: ["string", "number", "boolean", "null"] },
|
|
421
|
-
description: "Static attributes merged into each emitted ExecutionEvent.attributes.",
|
|
422
|
-
type: "object"
|
|
423
|
-
},
|
|
424
|
-
captureError: {
|
|
425
|
-
default: true,
|
|
426
|
-
description: "When true, failures MUST populate error; when false with captureOutput semantics, see semantics/wrap_behavior.md.",
|
|
427
|
-
type: "boolean"
|
|
428
|
-
},
|
|
429
|
-
captureInputs: {
|
|
430
|
-
default: true,
|
|
431
|
-
description: "When false, inputs MUST be serialized as an empty object {}.",
|
|
432
|
-
type: "boolean"
|
|
433
|
-
},
|
|
434
|
-
captureOutput: {
|
|
435
|
-
default: true,
|
|
436
|
-
description: "When false and status is ok, output MUST be null.",
|
|
437
|
-
type: "boolean"
|
|
438
|
-
},
|
|
439
|
-
captureStack: {
|
|
440
|
-
default: true,
|
|
441
|
-
description: "When false, error.stack MUST be null on emitted events.",
|
|
442
|
-
type: "boolean"
|
|
443
|
-
},
|
|
444
|
-
exporterTimeoutMs: {
|
|
445
|
-
description: "Maximum time an exporter hook may block the wrap boundary; 0 means SDK default.",
|
|
446
|
-
minimum: 0,
|
|
447
|
-
type: "number"
|
|
448
|
-
},
|
|
449
|
-
intent: {
|
|
450
|
-
description: "Default natural-language intent for wrapped executions when the call site does not override it.",
|
|
451
|
-
minLength: 1,
|
|
452
|
-
type: "string"
|
|
453
|
-
},
|
|
454
|
-
propagateCorrelation: {
|
|
455
|
-
default: true,
|
|
456
|
-
description: "When true, nested wraps inherit the active correlationId.",
|
|
457
|
-
type: "boolean"
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
title: "IntentProof WrapOptions v1",
|
|
461
|
-
type: "object"
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
// src/validators.ts
|
|
465
|
-
var ajv = new Ajv2020({
|
|
466
|
-
allErrors: true,
|
|
467
|
-
strict: false
|
|
468
|
-
});
|
|
469
|
-
var addFormats = AjvFormats.default;
|
|
470
|
-
addFormats(ajv);
|
|
471
|
-
var validateExecutionEvent = ajv.compile(
|
|
472
|
-
execution_event_v1_default
|
|
473
|
-
);
|
|
474
|
-
var validateWrapOptions = ajv.compile(
|
|
475
|
-
wrap_options_v1_default
|
|
476
|
-
);
|
|
477
|
-
var validateIntentProofConfig = ajv.compile(
|
|
478
|
-
intentproof_config_v1_default
|
|
479
|
-
);
|
|
480
|
-
function errorsText(v) {
|
|
481
|
-
return ajv.errorsText(v.errors, { separator: "; " });
|
|
482
|
-
}
|
|
483
|
-
function assertValidExecutionEventWire(data) {
|
|
484
|
-
if (!validateExecutionEvent(data)) {
|
|
485
|
-
throw new TypeError(
|
|
486
|
-
`ExecutionEvent wire JSON failed schema validation: ${errorsText(validateExecutionEvent)}`
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// src/client.ts
|
|
492
|
-
var correlationStore = new AsyncLocalStorage();
|
|
493
|
-
function normalizeInputsForExecutionEvent(inputs) {
|
|
494
|
-
if (inputs !== null && typeof inputs === "object" && !Array.isArray(inputs)) {
|
|
495
|
-
return inputs;
|
|
496
|
-
}
|
|
497
|
-
return { args: inputs };
|
|
498
|
-
}
|
|
499
|
-
function assertCorrelationId(id) {
|
|
500
|
-
if (typeof id !== "string") {
|
|
501
|
-
throw new TypeError(
|
|
502
|
-
`IntentProofClient: "correlationId" must be a string, got ${describeValueType(id)}`
|
|
503
|
-
);
|
|
504
|
-
}
|
|
505
|
-
if (id.trim().length === 0) {
|
|
506
|
-
throw new TypeError(
|
|
507
|
-
`IntentProofClient: "correlationId" must be a non-empty string (trimmed length is 0)`
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
function getCorrelationId() {
|
|
512
|
-
return correlationStore.getStore();
|
|
513
|
-
}
|
|
514
|
-
function runWithCorrelationId(correlationId, fn) {
|
|
515
|
-
if (typeof fn !== "function") {
|
|
516
|
-
throw new TypeError(
|
|
517
|
-
"IntentProofClient: expected runWithCorrelationId(correlationId, fn)"
|
|
518
|
-
);
|
|
519
|
-
}
|
|
520
|
-
assertCorrelationId(correlationId);
|
|
521
|
-
return correlationStore.run(correlationId, fn);
|
|
522
|
-
}
|
|
523
|
-
function defaultOnExporterError(error, _event) {
|
|
524
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
525
|
-
console.error("[intentproof] exporter error", message);
|
|
526
|
-
}
|
|
527
|
-
function toErrorSnapshot(e, includeStack) {
|
|
528
|
-
if (e instanceof Error) {
|
|
529
|
-
return includeStack ? { name: e.name, message: e.message, stack: e.stack } : { name: e.name, message: e.message };
|
|
530
|
-
}
|
|
531
|
-
return { name: "Error", message: String(e) };
|
|
532
|
-
}
|
|
533
|
-
function assertExporterAtIndex(ex, index) {
|
|
534
|
-
if (ex == null || typeof ex !== "object" || typeof ex.export !== "function") {
|
|
535
|
-
throw new TypeError(
|
|
536
|
-
`IntentProofClient: exporters[${index}] must be an object with an export() method`
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
function assertAttributesRecord(label, value) {
|
|
541
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
542
|
-
throw new TypeError(
|
|
543
|
-
`IntentProofClient: ${label} must be a plain object, got ${describeValueType(value)}`
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
const o = value;
|
|
547
|
-
for (const key of Object.keys(o)) {
|
|
548
|
-
const v = o[key];
|
|
549
|
-
const t = typeof v;
|
|
550
|
-
if (t !== "string" && t !== "number" && t !== "boolean") {
|
|
551
|
-
throw new TypeError(
|
|
552
|
-
`IntentProofClient: ${label}[${JSON.stringify(key)}] must be a string, number, or boolean, got ${describeValueType(v)}`
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
function assertWrapOptionsShape(options) {
|
|
558
|
-
if (typeof options.intent !== "string") {
|
|
559
|
-
throw new TypeError(
|
|
560
|
-
`IntentProofClient: "intent" must be a string, got ${describeValueType(options.intent)}`
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
if (options.intent.trim().length === 0) {
|
|
564
|
-
throw new TypeError(
|
|
565
|
-
`IntentProofClient: "intent" must be a non-empty string (trimmed length is 0)`
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
if (typeof options.action !== "string") {
|
|
569
|
-
throw new TypeError(
|
|
570
|
-
`IntentProofClient: "action" must be a string, got ${describeValueType(options.action)}`
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
if (options.action.trim().length === 0) {
|
|
574
|
-
throw new TypeError(
|
|
575
|
-
`IntentProofClient: "action" must be a non-empty string (trimmed length is 0)`
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
if (options.correlationId !== void 0 && typeof options.correlationId !== "string") {
|
|
579
|
-
throw new TypeError(
|
|
580
|
-
`IntentProofClient: "correlationId" must be a string when provided, got ${describeValueType(options.correlationId)}`
|
|
581
|
-
);
|
|
582
|
-
}
|
|
583
|
-
if (options.correlationId !== void 0 && options.correlationId.trim().length === 0) {
|
|
584
|
-
throw new TypeError(
|
|
585
|
-
`IntentProofClient: "correlationId" must be a non-empty string when provided (trimmed length is 0)`
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
if (options.attributes !== void 0) {
|
|
589
|
-
assertAttributesRecord("WrapOptions.attributes", options.attributes);
|
|
590
|
-
}
|
|
591
|
-
if (options.includeErrorStack !== void 0) {
|
|
592
|
-
if (typeof options.includeErrorStack !== "boolean") {
|
|
593
|
-
throw new TypeError(
|
|
594
|
-
`IntentProofClient: "includeErrorStack" must be a boolean when provided, got ${describeValueType(options.includeErrorStack)}`
|
|
595
|
-
);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
var IntentProofClient = class {
|
|
600
|
-
exporters = [new MemoryExporter()];
|
|
601
|
-
onExporterError = defaultOnExporterError;
|
|
602
|
-
defaultAttributes = {};
|
|
603
|
-
includeErrorStack = true;
|
|
604
|
-
constructor(config = {}) {
|
|
605
|
-
this.configure(config);
|
|
606
|
-
}
|
|
607
|
-
configure(config) {
|
|
608
|
-
if (config.exporters !== void 0) {
|
|
609
|
-
for (let i = 0; i < config.exporters.length; i++) {
|
|
610
|
-
assertExporterAtIndex(config.exporters[i], i);
|
|
611
|
-
}
|
|
612
|
-
this.exporters = [...config.exporters];
|
|
613
|
-
}
|
|
614
|
-
if (config.onExporterError !== void 0) {
|
|
615
|
-
if (typeof config.onExporterError !== "function") {
|
|
616
|
-
throw new TypeError(
|
|
617
|
-
`IntentProofClient: onExporterError must be a function, got ${describeValueType(config.onExporterError)}`
|
|
618
|
-
);
|
|
619
|
-
}
|
|
620
|
-
this.onExporterError = config.onExporterError;
|
|
621
|
-
}
|
|
622
|
-
if (config.defaultAttributes !== void 0) {
|
|
623
|
-
assertAttributesRecord("defaultAttributes", config.defaultAttributes);
|
|
624
|
-
this.defaultAttributes = config.defaultAttributes;
|
|
625
|
-
}
|
|
626
|
-
if (config.includeErrorStack !== void 0) {
|
|
627
|
-
if (typeof config.includeErrorStack !== "boolean") {
|
|
628
|
-
throw new TypeError(
|
|
629
|
-
`IntentProofClient: includeErrorStack must be a boolean when provided, got ${describeValueType(config.includeErrorStack)}`
|
|
630
|
-
);
|
|
631
|
-
}
|
|
632
|
-
this.includeErrorStack = config.includeErrorStack;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Await optional {@link Exporter.flush} on each exporter (parallel).
|
|
637
|
-
* Used for graceful shutdown or tests.
|
|
638
|
-
*/
|
|
639
|
-
flush() {
|
|
640
|
-
return Promise.all(
|
|
641
|
-
this.exporters.map(
|
|
642
|
-
(ex) => typeof ex.flush === "function" ? Promise.resolve(ex.flush()) : Promise.resolve()
|
|
643
|
-
)
|
|
644
|
-
).then(() => {
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* {@link Exporter.shutdown} when present, otherwise {@link Exporter.flush}.
|
|
649
|
-
*/
|
|
650
|
-
shutdown() {
|
|
651
|
-
return Promise.all(
|
|
652
|
-
this.exporters.map((ex) => {
|
|
653
|
-
if (typeof ex.shutdown === "function") {
|
|
654
|
-
return Promise.resolve(ex.shutdown());
|
|
655
|
-
}
|
|
656
|
-
if (typeof ex.flush === "function") {
|
|
657
|
-
return Promise.resolve(ex.flush());
|
|
658
|
-
}
|
|
659
|
-
return Promise.resolve();
|
|
660
|
-
})
|
|
661
|
-
).then(() => {
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
/** Read active correlation id (AsyncLocalStorage). */
|
|
665
|
-
getCorrelationId() {
|
|
666
|
-
return getCorrelationId();
|
|
667
|
-
}
|
|
668
|
-
withCorrelation(correlationIdOrFn, maybeFn) {
|
|
669
|
-
if (typeof correlationIdOrFn === "function") {
|
|
670
|
-
return runWithCorrelationId(randomUUID(), correlationIdOrFn);
|
|
671
|
-
}
|
|
672
|
-
if (typeof correlationIdOrFn !== "string") {
|
|
673
|
-
throw new TypeError(
|
|
674
|
-
"IntentProofClient: withCorrelation: correlation id must be a string"
|
|
675
|
-
);
|
|
676
|
-
}
|
|
677
|
-
if (typeof maybeFn !== "function") {
|
|
678
|
-
throw new TypeError(
|
|
679
|
-
"IntentProofClient: expected withCorrelation(fn) or withCorrelation(correlationId, fn)"
|
|
680
|
-
);
|
|
681
|
-
}
|
|
682
|
-
const fn = maybeFn;
|
|
683
|
-
const id = correlationIdOrFn;
|
|
684
|
-
if (id.trim().length === 0) {
|
|
685
|
-
return runWithCorrelationId(randomUUID(), fn);
|
|
686
|
-
}
|
|
687
|
-
return runWithCorrelationId(id, fn);
|
|
688
|
-
}
|
|
689
|
-
/**
|
|
690
|
-
* Wrap a function to emit one `ExecutionEvent` per invocation (sync or async).
|
|
691
|
-
*/
|
|
692
|
-
wrap(options, fn) {
|
|
693
|
-
assertWrapOptionsShape(options);
|
|
694
|
-
if (typeof fn !== "function") {
|
|
695
|
-
throw new TypeError(
|
|
696
|
-
`IntentProofClient: wrap() second argument must be a function, got ${describeValueType(fn)}`
|
|
697
|
-
);
|
|
698
|
-
}
|
|
699
|
-
const self = this;
|
|
700
|
-
const wrapped = function(...args) {
|
|
701
|
-
const correlationId = options.correlationId ?? getCorrelationId() ?? void 0;
|
|
702
|
-
const startedAt = /* @__PURE__ */ new Date();
|
|
703
|
-
const serOpts = {
|
|
704
|
-
maxDepth: options.maxDepth,
|
|
705
|
-
maxKeys: options.maxKeys,
|
|
706
|
-
redactKeys: options.redactKeys,
|
|
707
|
-
maxStringLength: options.maxStringLength
|
|
708
|
-
};
|
|
709
|
-
let inputs;
|
|
710
|
-
if (options.captureInput) {
|
|
711
|
-
try {
|
|
712
|
-
inputs = options.captureInput(args);
|
|
713
|
-
} catch {
|
|
714
|
-
inputs = snapshot(args, serOpts);
|
|
715
|
-
}
|
|
716
|
-
} else {
|
|
717
|
-
inputs = snapshot(args, serOpts);
|
|
718
|
-
}
|
|
719
|
-
const base = {
|
|
720
|
-
id: randomUUID(),
|
|
721
|
-
correlationId,
|
|
722
|
-
intent: options.intent,
|
|
723
|
-
action: options.action,
|
|
724
|
-
inputs: normalizeInputsForExecutionEvent(inputs),
|
|
725
|
-
startedAt: startedAt.toISOString(),
|
|
726
|
-
attributes: mergeAttrs(
|
|
727
|
-
self.defaultAttributes,
|
|
728
|
-
options.attributes
|
|
729
|
-
)
|
|
730
|
-
};
|
|
731
|
-
try {
|
|
732
|
-
const out = fn.apply(this, args);
|
|
733
|
-
if (isPromiseLike(out)) {
|
|
734
|
-
return self.handleAsync(out, base, options, serOpts, startedAt);
|
|
735
|
-
}
|
|
736
|
-
self.emitComplete(
|
|
737
|
-
base,
|
|
738
|
-
"ok",
|
|
739
|
-
out,
|
|
740
|
-
void 0,
|
|
741
|
-
options,
|
|
742
|
-
serOpts,
|
|
743
|
-
startedAt,
|
|
744
|
-
self.includeErrorStack
|
|
745
|
-
);
|
|
746
|
-
return out;
|
|
747
|
-
} catch (e) {
|
|
748
|
-
self.emitComplete(
|
|
749
|
-
base,
|
|
750
|
-
"error",
|
|
751
|
-
void 0,
|
|
752
|
-
e,
|
|
753
|
-
options,
|
|
754
|
-
serOpts,
|
|
755
|
-
startedAt,
|
|
756
|
-
self.includeErrorStack
|
|
757
|
-
);
|
|
758
|
-
throw e;
|
|
759
|
-
}
|
|
760
|
-
};
|
|
761
|
-
Object.defineProperty(wrapped, "name", {
|
|
762
|
-
value: `intentproof(${fn.name || "anonymous"})`,
|
|
763
|
-
configurable: true
|
|
764
|
-
});
|
|
765
|
-
return wrapped;
|
|
766
|
-
}
|
|
767
|
-
handleAsync(p, base, options, serOpts, startedAt) {
|
|
768
|
-
const includeStack = this.includeErrorStack;
|
|
769
|
-
return Promise.resolve(p).then(
|
|
770
|
-
(value) => {
|
|
771
|
-
this.emitComplete(
|
|
772
|
-
base,
|
|
773
|
-
"ok",
|
|
774
|
-
value,
|
|
775
|
-
void 0,
|
|
776
|
-
options,
|
|
777
|
-
serOpts,
|
|
778
|
-
startedAt,
|
|
779
|
-
includeStack
|
|
780
|
-
);
|
|
781
|
-
return value;
|
|
782
|
-
},
|
|
783
|
-
(err) => {
|
|
784
|
-
this.emitComplete(
|
|
785
|
-
base,
|
|
786
|
-
"error",
|
|
787
|
-
void 0,
|
|
788
|
-
err,
|
|
789
|
-
options,
|
|
790
|
-
serOpts,
|
|
791
|
-
startedAt,
|
|
792
|
-
includeStack
|
|
793
|
-
);
|
|
794
|
-
throw err;
|
|
795
|
-
}
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
emitComplete(base, status, result, error, options, serOpts, startedAt, defaultIncludeErrorStack) {
|
|
799
|
-
const completedAt = /* @__PURE__ */ new Date();
|
|
800
|
-
const durationMs = completedAt.getTime() - startedAt.getTime();
|
|
801
|
-
let output;
|
|
802
|
-
let errSnap;
|
|
803
|
-
const includeStack = options.includeErrorStack ?? defaultIncludeErrorStack;
|
|
804
|
-
if (status === "ok") {
|
|
805
|
-
try {
|
|
806
|
-
output = options.captureOutput ? options.captureOutput(result) : snapshot(result, serOpts);
|
|
807
|
-
} catch {
|
|
808
|
-
output = snapshot(result, serOpts);
|
|
809
|
-
}
|
|
810
|
-
} else {
|
|
811
|
-
errSnap = toErrorSnapshot(error, includeStack);
|
|
812
|
-
if (options.captureError) {
|
|
813
|
-
try {
|
|
814
|
-
output = options.captureError(error);
|
|
815
|
-
} catch {
|
|
816
|
-
output = void 0;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
const event = status === "ok" ? {
|
|
821
|
-
...base,
|
|
822
|
-
status,
|
|
823
|
-
completedAt: completedAt.toISOString(),
|
|
824
|
-
durationMs,
|
|
825
|
-
output
|
|
826
|
-
} : {
|
|
827
|
-
...base,
|
|
828
|
-
status,
|
|
829
|
-
completedAt: completedAt.toISOString(),
|
|
830
|
-
durationMs,
|
|
831
|
-
error: errSnap,
|
|
832
|
-
...output !== void 0 ? { output } : {}
|
|
833
|
-
};
|
|
834
|
-
this.dispatch(event);
|
|
835
|
-
}
|
|
836
|
-
dispatch(event) {
|
|
837
|
-
assertValidExecutionEventWire(JSON.parse(JSON.stringify(event)));
|
|
838
|
-
for (const ex of this.exporters) {
|
|
839
|
-
try {
|
|
840
|
-
const r = ex.export(event);
|
|
841
|
-
if (isPromiseLike(r)) {
|
|
842
|
-
void r.catch((e) => this.onExporterError(e, event));
|
|
843
|
-
}
|
|
844
|
-
} catch (e) {
|
|
845
|
-
this.onExporterError(e, event);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
function mergeAttrs(a, b) {
|
|
851
|
-
if (!b || Object.keys(b).length === 0) {
|
|
852
|
-
return Object.keys(a).length ? { ...a } : void 0;
|
|
853
|
-
}
|
|
854
|
-
return { ...a, ...b };
|
|
855
|
-
}
|
|
856
|
-
var defaultClient = null;
|
|
857
|
-
function getIntentProofClient() {
|
|
858
|
-
if (!defaultClient) defaultClient = new IntentProofClient();
|
|
859
|
-
return defaultClient;
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
// src/exporters/http.ts
|
|
863
|
-
var HTTP_EXPORTER_FALLBACK_BODY = '{"intentproof":"1","eventSerializeFailed":true}';
|
|
864
|
-
function safeJsonEnvelope(event) {
|
|
865
|
-
try {
|
|
866
|
-
return JSON.stringify({ intentproof: "1", event });
|
|
867
|
-
} catch {
|
|
868
|
-
try {
|
|
869
|
-
return JSON.stringify({
|
|
870
|
-
intentproof: "1",
|
|
871
|
-
eventPartial: {
|
|
872
|
-
id: event.id,
|
|
873
|
-
action: event.action,
|
|
874
|
-
intent: event.intent,
|
|
875
|
-
status: event.status,
|
|
876
|
-
correlationId: event.correlationId,
|
|
877
|
-
startedAt: event.startedAt,
|
|
878
|
-
completedAt: event.completedAt,
|
|
879
|
-
durationMs: event.durationMs
|
|
880
|
-
},
|
|
881
|
-
note: "full event not JSON-serializable"
|
|
882
|
-
});
|
|
883
|
-
} catch {
|
|
884
|
-
return HTTP_EXPORTER_FALLBACK_BODY;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
var HttpExporter = class {
|
|
889
|
-
url;
|
|
890
|
-
method;
|
|
891
|
-
headers;
|
|
892
|
-
body;
|
|
893
|
-
awaitEach;
|
|
894
|
-
timeoutMs;
|
|
895
|
-
onError;
|
|
896
|
-
inFlight = /* @__PURE__ */ new Set();
|
|
897
|
-
closed = false;
|
|
898
|
-
constructor(options) {
|
|
899
|
-
if (typeof options.url !== "string") {
|
|
900
|
-
throw new TypeError(
|
|
901
|
-
`HttpExporter: "url" must be a non-empty string, got ${describeValueType(options.url)}`
|
|
902
|
-
);
|
|
903
|
-
}
|
|
904
|
-
if (options.url.trim().length === 0) {
|
|
905
|
-
throw new TypeError(
|
|
906
|
-
'HttpExporter: "url" must be a non-empty string (trimmed length is 0)'
|
|
907
|
-
);
|
|
908
|
-
}
|
|
909
|
-
this.url = options.url;
|
|
910
|
-
this.method = (options.method ?? "POST").trim() || "POST";
|
|
911
|
-
const rawHeaders = options.headers;
|
|
912
|
-
const extraHeaders = rawHeaders !== void 0 && rawHeaders !== null && typeof rawHeaders === "object" && !Array.isArray(rawHeaders) ? rawHeaders : {};
|
|
913
|
-
this.headers = {
|
|
914
|
-
"content-type": "application/json",
|
|
915
|
-
...extraHeaders
|
|
916
|
-
};
|
|
917
|
-
this.body = options.body ?? ((event) => safeJsonEnvelope(event));
|
|
918
|
-
this.awaitEach = options.awaitEach ?? false;
|
|
919
|
-
if (options.timeoutMs !== void 0) {
|
|
920
|
-
const t = options.timeoutMs;
|
|
921
|
-
if (!Number.isFinite(t) || t <= 0) {
|
|
922
|
-
throw new TypeError(
|
|
923
|
-
'HttpExporter: "timeoutMs" must be a finite number > 0 when set'
|
|
924
|
-
);
|
|
925
|
-
}
|
|
926
|
-
this.timeoutMs = Math.trunc(t);
|
|
927
|
-
} else {
|
|
928
|
-
this.timeoutMs = void 0;
|
|
929
|
-
}
|
|
930
|
-
this.onError = options.onError;
|
|
931
|
-
}
|
|
932
|
-
track(p) {
|
|
933
|
-
this.inFlight.add(p);
|
|
934
|
-
void p.finally(() => this.inFlight.delete(p));
|
|
935
|
-
}
|
|
936
|
-
export(event) {
|
|
937
|
-
if (this.closed) {
|
|
938
|
-
this.onError?.(new Error("HttpExporter has been shut down"), event);
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
let payload;
|
|
942
|
-
try {
|
|
943
|
-
payload = this.body(event);
|
|
944
|
-
} catch (e) {
|
|
945
|
-
this.onError?.(e, event);
|
|
946
|
-
payload = safeJsonEnvelope(event);
|
|
947
|
-
}
|
|
948
|
-
const run = async () => {
|
|
949
|
-
try {
|
|
950
|
-
const res = await fetch(this.url, {
|
|
951
|
-
method: this.method,
|
|
952
|
-
headers: this.headers,
|
|
953
|
-
body: payload,
|
|
954
|
-
credentials: "omit",
|
|
955
|
-
signal: this.timeoutMs !== void 0 ? AbortSignal.timeout(this.timeoutMs) : void 0
|
|
956
|
-
});
|
|
957
|
-
if (!res.ok) {
|
|
958
|
-
const err = new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
959
|
-
this.onError?.(err, event);
|
|
960
|
-
}
|
|
961
|
-
} catch (e) {
|
|
962
|
-
this.onError?.(e, event);
|
|
963
|
-
}
|
|
964
|
-
};
|
|
965
|
-
const p = run();
|
|
966
|
-
this.track(p);
|
|
967
|
-
if (this.awaitEach) return p;
|
|
968
|
-
void p;
|
|
969
|
-
}
|
|
970
|
-
/** Waits until every started request has settled (success or failure). */
|
|
971
|
-
flush() {
|
|
972
|
-
if (this.inFlight.size === 0) return Promise.resolve();
|
|
973
|
-
return Promise.all([...this.inFlight]).then(() => {
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
/** Stops accepting new events and waits for in-flight requests to finish. */
|
|
977
|
-
async shutdown() {
|
|
978
|
-
this.closed = true;
|
|
979
|
-
await this.flush();
|
|
980
|
-
}
|
|
981
|
-
};
|
|
982
|
-
|
|
983
|
-
// src/exporters/queue.ts
|
|
984
|
-
var BoundedQueueExporter = class {
|
|
985
|
-
inner;
|
|
986
|
-
maxConcurrent;
|
|
987
|
-
maxQueue;
|
|
988
|
-
strategy;
|
|
989
|
-
onDrop;
|
|
990
|
-
onInnerError;
|
|
991
|
-
queue = [];
|
|
992
|
-
active = 0;
|
|
993
|
-
/** When false, {@link export} drops events with reason `shutdown`; queued work still drains. */
|
|
994
|
-
accepting = true;
|
|
995
|
-
idleResolvers = [];
|
|
996
|
-
constructor(options) {
|
|
997
|
-
const inner = options.exporter;
|
|
998
|
-
if (inner == null || typeof inner !== "object" || typeof inner.export !== "function") {
|
|
999
|
-
throw new TypeError(
|
|
1000
|
-
'BoundedQueueExporter: "exporter" must be an object with an export() method'
|
|
1001
|
-
);
|
|
1002
|
-
}
|
|
1003
|
-
this.inner = inner;
|
|
1004
|
-
const rawMc = options.maxConcurrent ?? 4;
|
|
1005
|
-
this.maxConcurrent = !Number.isFinite(rawMc) ? 4 : Math.max(1, Math.trunc(rawMc));
|
|
1006
|
-
const rawQ = options.maxQueue ?? 1e3;
|
|
1007
|
-
if (!Number.isFinite(rawQ)) {
|
|
1008
|
-
this.maxQueue = 1e3;
|
|
1009
|
-
} else {
|
|
1010
|
-
const q = Math.trunc(rawQ);
|
|
1011
|
-
if (q === 0) {
|
|
1012
|
-
this.maxQueue = 0;
|
|
1013
|
-
} else if (q < 0) {
|
|
1014
|
-
this.maxQueue = 1e3;
|
|
1015
|
-
} else {
|
|
1016
|
-
this.maxQueue = q;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
const strategy = options.strategy ?? "drop-newest";
|
|
1020
|
-
if (strategy !== "drop-newest" && strategy !== "drop-oldest") {
|
|
1021
|
-
throw new TypeError(
|
|
1022
|
-
'BoundedQueueExporter: "strategy" must be "drop-newest" or "drop-oldest"'
|
|
1023
|
-
);
|
|
1024
|
-
}
|
|
1025
|
-
this.strategy = strategy;
|
|
1026
|
-
this.onDrop = options.onDrop;
|
|
1027
|
-
this.onInnerError = options.onInnerError;
|
|
1028
|
-
}
|
|
1029
|
-
export(event) {
|
|
1030
|
-
if (!this.accepting) {
|
|
1031
|
-
this.onDrop?.(event, "shutdown");
|
|
1032
|
-
return;
|
|
1033
|
-
}
|
|
1034
|
-
const cap = this.maxQueue <= 0 ? Number.POSITIVE_INFINITY : this.maxQueue;
|
|
1035
|
-
if (this.queue.length >= cap) {
|
|
1036
|
-
if (this.strategy === "drop-oldest") {
|
|
1037
|
-
const dropped = this.queue.shift();
|
|
1038
|
-
this.onDrop?.(dropped, "queue-overflow-drop-oldest");
|
|
1039
|
-
this.queue.push(event);
|
|
1040
|
-
} else {
|
|
1041
|
-
this.onDrop?.(event, "queue-overflow-drop-newest");
|
|
1042
|
-
}
|
|
1043
|
-
this.pump();
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
this.queue.push(event);
|
|
1047
|
-
this.pump();
|
|
1048
|
-
}
|
|
1049
|
-
pump() {
|
|
1050
|
-
while (this.active < this.maxConcurrent && this.queue.length > 0) {
|
|
1051
|
-
const next = this.queue.shift();
|
|
1052
|
-
this.active++;
|
|
1053
|
-
void this.runInner(next).finally(() => {
|
|
1054
|
-
this.active--;
|
|
1055
|
-
this.pump();
|
|
1056
|
-
this.resolveIdleWaitersIfNeeded();
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
async runInner(event) {
|
|
1061
|
-
try {
|
|
1062
|
-
const r = this.inner.export(event);
|
|
1063
|
-
if (isPromiseLike(r)) await r;
|
|
1064
|
-
} catch (e) {
|
|
1065
|
-
this.onInnerError?.(e, event);
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
resolveIdleWaitersIfNeeded() {
|
|
1069
|
-
if (this.queue.length === 0 && this.active === 0) {
|
|
1070
|
-
const waiters = this.idleResolvers;
|
|
1071
|
-
this.idleResolvers = [];
|
|
1072
|
-
for (const r of waiters) r();
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
/** Resolves when the queue is empty and no inner export is in flight. */
|
|
1076
|
-
flush() {
|
|
1077
|
-
if (this.queue.length === 0 && this.active === 0) {
|
|
1078
|
-
return Promise.resolve();
|
|
1079
|
-
}
|
|
1080
|
-
return new Promise((resolve) => {
|
|
1081
|
-
this.idleResolvers.push(resolve);
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Stops accepting new events; does **not** drop items already in the queue—
|
|
1086
|
-
* {@link flush} waits until queued and in-flight work finishes.
|
|
1087
|
-
*/
|
|
1088
|
-
async shutdown() {
|
|
1089
|
-
this.accepting = false;
|
|
1090
|
-
await this.flush();
|
|
1091
|
-
}
|
|
1092
|
-
};
|
|
1093
|
-
|
|
1094
|
-
// src/index.ts
|
|
1095
|
-
var VERSION = "0.1.4";
|
|
1096
|
-
var client = getIntentProofClient();
|
|
1097
|
-
function createIntentProofClient(config) {
|
|
1098
|
-
return new IntentProofClient(config);
|
|
1099
|
-
}
|
|
1100
|
-
export {
|
|
1101
|
-
BoundedQueueExporter,
|
|
1102
|
-
HttpExporter,
|
|
1103
|
-
IntentProofClient,
|
|
1104
|
-
MemoryExporter,
|
|
1105
|
-
VERSION,
|
|
1106
|
-
assertCorrelationId,
|
|
1107
|
-
assertValidExecutionEventWire,
|
|
1108
|
-
assertWrapOptionsShape,
|
|
1109
|
-
client,
|
|
1110
|
-
createIntentProofClient,
|
|
1111
|
-
getCorrelationId,
|
|
1112
|
-
getIntentProofClient,
|
|
1113
|
-
runWithCorrelationId,
|
|
1114
|
-
snapshot,
|
|
1115
|
-
validateExecutionEvent,
|
|
1116
|
-
validateIntentProofConfig,
|
|
1117
|
-
validateWrapOptions
|
|
1118
|
-
};
|
|
1119
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SENTINEL_PREV_HASH = exports.verifyEventSignature = exports.signEvent = exports.loadPrivateKey = exports.eventContentHash = exports.canonicalizeEvent = exports.wrap = exports.runWithCorrelationId = exports.pushSubjectMapping = exports.SDK_VERSION = exports.getTenantId = exports.getPublicKey = exports.getOutbox = exports.getInstanceId = exports.flush = exports.configure = void 0;
|
|
4
|
+
var client_1 = require("./client");
|
|
5
|
+
Object.defineProperty(exports, "configure", { enumerable: true, get: function () { return client_1.configure; } });
|
|
6
|
+
Object.defineProperty(exports, "flush", { enumerable: true, get: function () { return client_1.flush; } });
|
|
7
|
+
Object.defineProperty(exports, "getInstanceId", { enumerable: true, get: function () { return client_1.getInstanceId; } });
|
|
8
|
+
Object.defineProperty(exports, "getOutbox", { enumerable: true, get: function () { return client_1.getOutbox; } });
|
|
9
|
+
Object.defineProperty(exports, "getPublicKey", { enumerable: true, get: function () { return client_1.getPublicKey; } });
|
|
10
|
+
Object.defineProperty(exports, "getTenantId", { enumerable: true, get: function () { return client_1.getTenantId; } });
|
|
11
|
+
Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return client_1.SDK_VERSION; } });
|
|
12
|
+
var instrumentation_1 = require("./instrumentation");
|
|
13
|
+
Object.defineProperty(exports, "pushSubjectMapping", { enumerable: true, get: function () { return instrumentation_1.pushSubjectMapping; } });
|
|
14
|
+
Object.defineProperty(exports, "runWithCorrelationId", { enumerable: true, get: function () { return instrumentation_1.runWithCorrelationId; } });
|
|
15
|
+
Object.defineProperty(exports, "wrap", { enumerable: true, get: function () { return instrumentation_1.wrap; } });
|
|
16
|
+
var signing_1 = require("./signing");
|
|
17
|
+
Object.defineProperty(exports, "canonicalizeEvent", { enumerable: true, get: function () { return signing_1.canonicalizeEvent; } });
|
|
18
|
+
Object.defineProperty(exports, "eventContentHash", { enumerable: true, get: function () { return signing_1.eventContentHash; } });
|
|
19
|
+
Object.defineProperty(exports, "loadPrivateKey", { enumerable: true, get: function () { return signing_1.loadPrivateKey; } });
|
|
20
|
+
Object.defineProperty(exports, "signEvent", { enumerable: true, get: function () { return signing_1.signEvent; } });
|
|
21
|
+
Object.defineProperty(exports, "verifyEventSignature", { enumerable: true, get: function () { return signing_1.verifyEventSignature; } });
|
|
22
|
+
Object.defineProperty(exports, "SENTINEL_PREV_HASH", { enumerable: true, get: function () { return signing_1.SENTINEL_PREV_HASH; } });
|