@capxul/sdk 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{InMemoryAuthCacheAdapter-uOcqpqu8.mjs → InMemoryAuthCacheAdapter-VZBv1fOH.mjs} +158 -6
- package/dist/{create-capxul-client-CpBVKg10.mjs → create-capxul-client-BuEjwJS6.mjs} +4589 -4470
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +1 -1
- package/dist/{observation-E28xIx4S.d.mts → observation-Desw1A8U.d.mts} +96 -61
- package/dist/{signer-DIZRkFHh.d.mts → signer-tokSaxrJ.d.mts} +45 -20
- package/dist/testing/index.d.mts +1 -1
- package/dist/testing/index.mjs +2 -2
- package/package.json +5 -5
package/dist/{InMemoryAuthCacheAdapter-uOcqpqu8.mjs → InMemoryAuthCacheAdapter-VZBv1fOH.mjs}
RENAMED
|
@@ -1,4 +1,135 @@
|
|
|
1
1
|
import { Context, Data, Effect, Layer } from "effect";
|
|
2
|
+
//#region ../errors/src/chain-cause.ts
|
|
3
|
+
/**
|
|
4
|
+
* Why an operation failed — the one flat vocabulary. The first four are the
|
|
5
|
+
* auth/provider diagnoses that predate this file. The rest name the chain
|
|
6
|
+
* path. `FailureMode` is derived from this list so a runtime membership check
|
|
7
|
+
* (the SDK's `$exception` projection, the observability schema) and the type
|
|
8
|
+
* can never drift apart.
|
|
9
|
+
*/
|
|
10
|
+
const FAILURE_MODES = [
|
|
11
|
+
"auth-origin-mismatch",
|
|
12
|
+
"stale-openfort-cache",
|
|
13
|
+
"app-env-allowlist",
|
|
14
|
+
"no-secure-context",
|
|
15
|
+
"rate-limited",
|
|
16
|
+
"timeout",
|
|
17
|
+
"upstream-down",
|
|
18
|
+
"revert",
|
|
19
|
+
"insufficient-balance",
|
|
20
|
+
"insufficient-allowance",
|
|
21
|
+
"rejected",
|
|
22
|
+
"unauthorized",
|
|
23
|
+
"unknown"
|
|
24
|
+
];
|
|
25
|
+
function isFailureMode(value) {
|
|
26
|
+
return typeof value === "string" && FAILURE_MODES.includes(value);
|
|
27
|
+
}
|
|
28
|
+
/** Who answered. `alto` is the bundler; `gateway` is the AA gateway's own logic. */
|
|
29
|
+
const CHAIN_UPSTREAMS = [
|
|
30
|
+
"alchemy",
|
|
31
|
+
"infura",
|
|
32
|
+
"public",
|
|
33
|
+
"alto",
|
|
34
|
+
"gateway"
|
|
35
|
+
];
|
|
36
|
+
function isChainUpstream(value) {
|
|
37
|
+
return typeof value === "string" && CHAIN_UPSTREAMS.includes(value);
|
|
38
|
+
}
|
|
39
|
+
const PROVIDER_MESSAGE_MAX = 300;
|
|
40
|
+
const METHOD_MAX = 64;
|
|
41
|
+
const REVERT_NAME_MAX = 64;
|
|
42
|
+
const REVERT_ARG_KEY_MAX = 32;
|
|
43
|
+
const REVERT_ARG_VALUE_MAX = 128;
|
|
44
|
+
const REVERT_ARGS_MAX = 8;
|
|
45
|
+
const SELECTOR_RE = /^0x(?:[0-9a-fA-F]{8})?$/u;
|
|
46
|
+
const MASKS = [
|
|
47
|
+
[/\bBearer\s+[^\s,;]+/giu, "Bearer [REDACTED]"],
|
|
48
|
+
[/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[REDACTED]"],
|
|
49
|
+
[/\b0x[a-fA-F0-9]{40,}\b/gu, "[REDACTED]"],
|
|
50
|
+
[/(^|[^a-fA-F0-9])[a-fA-F0-9]{64}(?=$|[^a-fA-F0-9])/gu, "$1[REDACTED]"],
|
|
51
|
+
[/(?:(?:sk|pk|rk)_(?:live|test)|(?:phc|phx|ghp|gho|ghu|ghs|ghr|whsec)_|github_pat_|xox[baprs]-|AKIA[0-9A-Z]{16}|AIza)[A-Za-z0-9_-]*/giu, "[REDACTED]"],
|
|
52
|
+
[/(https?:\/\/[^\s"']+?\/v[0-9]\/)[A-Za-z0-9_-]{16,}/giu, "$1[REDACTED]"],
|
|
53
|
+
[/\b(api[ _-]?key|access[ _-]?token|token|secret|password|passphrase|private[ _-]?key|authorization|cookie|signature|credential|otp)\b\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;&]+)/giu, "$1=[REDACTED]"]
|
|
54
|
+
];
|
|
55
|
+
/** Mask credential-shaped content, then cap the length. Total on any string. */
|
|
56
|
+
function boundedEvidence(value, max) {
|
|
57
|
+
let text = value;
|
|
58
|
+
for (const [pattern, replacement] of MASKS) text = text.replace(pattern, replacement);
|
|
59
|
+
return text.length <= max ? text : text.slice(0, max);
|
|
60
|
+
}
|
|
61
|
+
function isRecord(value) {
|
|
62
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
63
|
+
}
|
|
64
|
+
function decodeRevert(value) {
|
|
65
|
+
if (!isRecord(value)) return null;
|
|
66
|
+
if (value.name !== null && typeof value.name !== "string") return null;
|
|
67
|
+
if (typeof value.selector !== "string" || !SELECTOR_RE.test(value.selector)) return null;
|
|
68
|
+
if (!isRecord(value.args)) return null;
|
|
69
|
+
const args = {};
|
|
70
|
+
for (const [key, arg] of Object.entries(value.args).slice(0, REVERT_ARGS_MAX)) {
|
|
71
|
+
if (typeof arg !== "string") return null;
|
|
72
|
+
args[boundedEvidence(key, REVERT_ARG_KEY_MAX)] = boundedEvidence(arg, REVERT_ARG_VALUE_MAX);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
name: value.name === null ? null : boundedEvidence(value.name, REVERT_NAME_MAX),
|
|
76
|
+
selector: value.selector,
|
|
77
|
+
args
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Decode a `ChainCause` from untrusted wire data (gateway JSON-RPC `error.data`,
|
|
82
|
+
* a Convex error payload). Every string is masked and bounded; an unrecognized
|
|
83
|
+
* shape yields null, because a consumer must never invent a cause.
|
|
84
|
+
*/
|
|
85
|
+
function decodeChainCause(value) {
|
|
86
|
+
if (!isRecord(value)) return null;
|
|
87
|
+
if (!isFailureMode(value.mode) || !isChainUpstream(value.upstream)) return null;
|
|
88
|
+
if (typeof value.method !== "string" || typeof value.retryable !== "boolean") return null;
|
|
89
|
+
const cause = {
|
|
90
|
+
mode: value.mode,
|
|
91
|
+
upstream: value.upstream,
|
|
92
|
+
method: boundedEvidence(value.method, METHOD_MAX),
|
|
93
|
+
retryable: value.retryable
|
|
94
|
+
};
|
|
95
|
+
if (typeof value.httpStatus === "number" && Number.isInteger(value.httpStatus)) cause.httpStatus = value.httpStatus;
|
|
96
|
+
if (typeof value.rpcCode === "number" && Number.isInteger(value.rpcCode)) cause.rpcCode = value.rpcCode;
|
|
97
|
+
const revert = decodeRevert(value.revert);
|
|
98
|
+
if (revert !== null) cause.revert = revert;
|
|
99
|
+
if (typeof value.providerMessage === "string") cause.providerMessage = boundedEvidence(value.providerMessage, PROVIDER_MESSAGE_MAX);
|
|
100
|
+
return cause;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The cause as flat PostHog properties. Same keys from every producer, so one
|
|
104
|
+
* filter (`failure_mode = 'rate-limited'`) finds the gateway's, the backend's,
|
|
105
|
+
* and the SDK's rows alike.
|
|
106
|
+
*/
|
|
107
|
+
function chainCauseProperties(chain) {
|
|
108
|
+
return {
|
|
109
|
+
failure_mode: chain.mode,
|
|
110
|
+
chain_upstream: chain.upstream,
|
|
111
|
+
chain_method: chain.method,
|
|
112
|
+
chain_retryable: chain.retryable,
|
|
113
|
+
...chain.httpStatus === void 0 ? {} : { chain_http_status: chain.httpStatus },
|
|
114
|
+
...chain.rpcCode === void 0 ? {} : { chain_rpc_code: chain.rpcCode },
|
|
115
|
+
...chain.revert === void 0 ? {} : {
|
|
116
|
+
chain_revert_name: chain.revert.name ?? "unknown",
|
|
117
|
+
chain_revert_selector: chain.revert.selector,
|
|
118
|
+
chain_revert_args: chain.revert.args
|
|
119
|
+
},
|
|
120
|
+
...chain.providerMessage === void 0 ? {} : { chain_provider_message: chain.providerMessage }
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The error-tracking fingerprint for a failure: the code, the one-word cause,
|
|
125
|
+
* and the operation. PostHog groups `$exception` rows by this value, so one
|
|
126
|
+
* issue is one cause at one operation instead of every provider failure in
|
|
127
|
+
* one bucket (money-path audit 2026-09-02, row P1).
|
|
128
|
+
*/
|
|
129
|
+
function failureFingerprint(code, mode, operation) {
|
|
130
|
+
return `${code}:${mode ?? "none"}:${operation}`;
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
2
133
|
//#region ../errors/src/errors.ts
|
|
3
134
|
const CAPXUL_ERROR_CODES = [
|
|
4
135
|
"NOT_AUTHENTICATED",
|
|
@@ -60,6 +191,10 @@ var CapxulError = class extends Error {
|
|
|
60
191
|
details;
|
|
61
192
|
correlationId;
|
|
62
193
|
layer;
|
|
194
|
+
/** The one-word cause (`FailureMode`). `chain.mode` when a chain cause is set. */
|
|
195
|
+
mode;
|
|
196
|
+
/** The structured chain-path cause. Never rewritten by a later layer. */
|
|
197
|
+
chain;
|
|
63
198
|
constructor(code, message, options = {}) {
|
|
64
199
|
super(message, "cause" in options ? { cause: options.cause } : void 0);
|
|
65
200
|
this.name = "CapxulError";
|
|
@@ -67,6 +202,10 @@ var CapxulError = class extends Error {
|
|
|
67
202
|
if (options.details !== void 0) this.details = options.details;
|
|
68
203
|
if (options.correlationId !== void 0) this.correlationId = options.correlationId;
|
|
69
204
|
if (options.layer !== void 0) this.layer = options.layer;
|
|
205
|
+
const legacy = options.details?.failure_mode;
|
|
206
|
+
const mode = options.chain?.mode ?? (isFailureMode(options.mode) ? options.mode : void 0) ?? (isFailureMode(legacy) ? legacy : void 0);
|
|
207
|
+
if (mode !== void 0) this.mode = mode;
|
|
208
|
+
if (options.chain !== void 0) this.chain = options.chain;
|
|
70
209
|
}
|
|
71
210
|
};
|
|
72
211
|
function isCapxulError(value) {
|
|
@@ -76,7 +215,9 @@ function deserializeCapxulError(serialized) {
|
|
|
76
215
|
return new CapxulError(serialized.code, serialized.message, compactErrorOptions({
|
|
77
216
|
details: serialized.details,
|
|
78
217
|
correlationId: serialized.correlationId,
|
|
79
|
-
layer: serialized.layer
|
|
218
|
+
layer: serialized.layer,
|
|
219
|
+
mode: serialized.mode,
|
|
220
|
+
chain: serialized.chain === void 0 ? void 0 : decodeChainCause(serialized.chain) ?? void 0
|
|
80
221
|
}));
|
|
81
222
|
}
|
|
82
223
|
function compactErrorOptions(options) {
|
|
@@ -85,6 +226,8 @@ function compactErrorOptions(options) {
|
|
|
85
226
|
if (options.details !== void 0) result.details = options.details;
|
|
86
227
|
if (options.correlationId !== void 0) result.correlationId = options.correlationId;
|
|
87
228
|
if (options.layer !== void 0) result.layer = options.layer;
|
|
229
|
+
if (options.mode !== void 0) result.mode = options.mode;
|
|
230
|
+
if (options.chain !== void 0) result.chain = options.chain;
|
|
88
231
|
return result;
|
|
89
232
|
}
|
|
90
233
|
const Errors = {
|
|
@@ -100,11 +243,14 @@ const Errors = {
|
|
|
100
243
|
provider,
|
|
101
244
|
operation
|
|
102
245
|
};
|
|
103
|
-
|
|
246
|
+
const mode = opts?.chain?.mode ?? opts?.failure_mode;
|
|
247
|
+
if (mode !== void 0) details.failure_mode = mode;
|
|
104
248
|
if (opts?.httpStatus !== void 0) details.httpStatus = opts.httpStatus;
|
|
105
249
|
return new CapxulError("PROVIDER_ERROR", `Provider error: ${provider} ${operation}`, {
|
|
106
250
|
cause,
|
|
107
|
-
details
|
|
251
|
+
details,
|
|
252
|
+
...mode === void 0 ? {} : { mode },
|
|
253
|
+
...opts?.chain === void 0 ? {} : { chain: opts.chain }
|
|
108
254
|
});
|
|
109
255
|
},
|
|
110
256
|
capabilityUnavailable: (provider, operation) => new CapxulError("CAPABILITY_UNAVAILABLE", "Provider capability is unavailable", { details: {
|
|
@@ -209,12 +355,18 @@ function isCapxulCode(value) {
|
|
|
209
355
|
}
|
|
210
356
|
function reconstruct(serialized) {
|
|
211
357
|
if (!isCapxulCode(serialized.code)) return null;
|
|
212
|
-
|
|
358
|
+
const payload = {
|
|
213
359
|
code: serialized.code,
|
|
214
360
|
message: typeof serialized.message === "string" ? serialized.message : String(serialized.code),
|
|
215
361
|
...typeof serialized.details === "object" && serialized.details !== null && !Array.isArray(serialized.details) ? { details: serialized.details } : {},
|
|
216
362
|
...typeof serialized.correlationId === "string" ? { correlationId: serialized.correlationId } : {},
|
|
217
|
-
...typeof serialized.layer === "string" ? { layer: serialized.layer } : {}
|
|
363
|
+
...typeof serialized.layer === "string" ? { layer: serialized.layer } : {},
|
|
364
|
+
...isFailureMode(serialized.mode) ? { mode: serialized.mode } : {}
|
|
365
|
+
};
|
|
366
|
+
const chain = decodeChainCause(serialized.chain);
|
|
367
|
+
return deserializeCapxulError(chain === null ? payload : {
|
|
368
|
+
...payload,
|
|
369
|
+
chain
|
|
218
370
|
});
|
|
219
371
|
}
|
|
220
372
|
function decodeConvexError(err) {
|
|
@@ -496,4 +648,4 @@ Layer.effect(AuthCachePortTag, Effect.sync(() => new InMemoryAuthCacheAdapter())
|
|
|
496
648
|
cause
|
|
497
649
|
}))));
|
|
498
650
|
//#endregion
|
|
499
|
-
export { toPartyId as A, Errors as B, toDurationMs as C, toJwtToken as D, toEpochSeconds as E, toSessionToken as F, decodeConvexError as I, CAPXUL_ERROR_CODES as L, toPayrollRunId as M, toPublishableKey as N, toKycTier as O, toRoleKey as P, CapxulError as R, toCurrencyCode as S, toEpochMs as T, isCapxulError as V, toAppId as _, AuthCacheError as a, toChainId as b, BYTES32_RE as c, WEI_RE as d, ZERO_BYTES32 as f, toAllowedOrigin as g, toAddress as h, parseCachedJwt as i, toPayrollGroupId as j, toOrgId as k, EVM_ADDRESS_RE as l, toAccountId as m, BrowserAuthCacheAdapter as n, AuthCachePortTag as o, currencySymbolFor as p, parseAuthSession as r, APP_ID_RE as s, InMemoryAuthCacheAdapter as t, SUPPORTED_CURRENCY_CODES as u, toAuthUserId as v, toEmail as w, toCountryCode as x, toBudgetId as y, EXPECTED_OPERATION_OUTCOMES as z };
|
|
651
|
+
export { toPartyId as A, Errors as B, toDurationMs as C, toJwtToken as D, toEpochSeconds as E, toSessionToken as F, failureFingerprint as G, CHAIN_UPSTREAMS as H, decodeConvexError as I, isFailureMode as K, CAPXUL_ERROR_CODES as L, toPayrollRunId as M, toPublishableKey as N, toKycTier as O, toRoleKey as P, CapxulError as R, toCurrencyCode as S, toEpochMs as T, FAILURE_MODES as U, isCapxulError as V, chainCauseProperties as W, toAppId as _, AuthCacheError as a, toChainId as b, BYTES32_RE as c, WEI_RE as d, ZERO_BYTES32 as f, toAllowedOrigin as g, toAddress as h, parseCachedJwt as i, toPayrollGroupId as j, toOrgId as k, EVM_ADDRESS_RE as l, toAccountId as m, BrowserAuthCacheAdapter as n, AuthCachePortTag as o, currencySymbolFor as p, parseAuthSession as r, APP_ID_RE as s, InMemoryAuthCacheAdapter as t, SUPPORTED_CURRENCY_CODES as u, toAuthUserId as v, toEmail as w, toCountryCode as x, toBudgetId as y, EXPECTED_OPERATION_OUTCOMES as z };
|