@settlemint/dalp-sdk 3.1.15 → 3.1.16-main.33748846737
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/README.md +154 -169
- package/dist/auth/client.d.ts +113 -0
- package/dist/auth/live.d.ts +4366 -0
- package/dist/{auth-permissions.d.ts → auth/permissions.d.ts} +1 -2
- package/dist/{auth-wallet-plugins.d.ts → auth/wallet-plugins.d.ts} +69 -5
- package/dist/auth.d.ts +22 -115
- package/dist/auth.js +329 -0
- package/dist/bundler.d.ts +14 -207
- package/dist/bundler.js +99 -0
- package/dist/chunk-0m709wz4.js +4 -0
- package/dist/chunk-4wb2zpjw.js +260 -0
- package/dist/chunk-def7rqy6.js +946 -0
- package/dist/chunk-f4t1bm86.js +67 -0
- package/dist/chunk-fjnq61hj.js +11 -0
- package/dist/chunk-h12fatty.js +63 -0
- package/dist/chunk-n0b075da.js +33 -0
- package/dist/chunk-r0vsftj4.js +102 -0
- package/dist/chunk-y0d2c7kp.js +54 -0
- package/dist/client/conditional-request.d.ts +30 -0
- package/dist/client/factory.d.ts +14 -0
- package/dist/client/query-serializer.d.ts +2 -0
- package/dist/client/request-compression.d.ts +47 -0
- package/dist/client/ssr-fetch.d.ts +12 -0
- package/dist/effect.d.ts +69 -0
- package/dist/effect.js +82 -0
- package/dist/errors/api-error.d.ts +29 -0
- package/dist/errors/find-current-error.d.ts +8 -0
- package/dist/errors/sdk-error.d.ts +52 -0
- package/dist/errors/sdk-error.js +8 -0
- package/dist/generated/api-types.d.ts +41238 -0
- package/dist/generated/response-scalars.d.ts +9 -0
- package/dist/generated/routes.d.ts +12 -0
- package/dist/index.d.ts +28 -40
- package/dist/index.js +131 -96108
- package/dist/proxy/builder.d.ts +47 -0
- package/dist/proxy/client.d.ts +32 -0
- package/dist/proxy/fetch-executor.d.ts +28 -0
- package/dist/proxy/flat-args.d.ts +51 -0
- package/dist/proxy/settlement.d.ts +67 -0
- package/dist/proxy/sse.d.ts +54 -0
- package/dist/proxy/tanstack.d.ts +27 -0
- package/dist/proxy/transport.d.ts +73 -0
- package/dist/react-query.d.ts +16 -0
- package/dist/react-query.js +13 -0
- package/dist/readonly-deep.d.ts +12 -0
- package/dist/reads-as-funding-paused.d.ts +20 -0
- package/dist/routes/index.d.ts +20 -0
- package/dist/routes/index.js +10 -0
- package/dist/routes/types.d.ts +51 -0
- package/dist/runtime-exports.d.ts +20 -0
- package/dist/runtime-exports.js +16 -0
- package/dist/scalars/big-decimal.d.ts +16 -0
- package/dist/scalars/ethereum-address.d.ts +20 -0
- package/dist/scalars/exchange-rates.d.ts +27 -0
- package/dist/scalars/index.d.ts +18 -0
- package/dist/scalars/index.js +86 -0
- package/dist/scalars/organization-id.d.ts +20 -0
- package/dist/secret.d.ts +14 -0
- package/dist/sign-webhook-receipt.d.ts +76 -0
- package/dist/sign-webhook-receipt.js +26 -0
- package/dist/transport/cookie-store.d.ts +9 -0
- package/dist/transport/sse-lifecycle.d.ts +44 -0
- package/dist/types.d.ts +65 -102
- package/dist/url.d.ts +0 -1
- package/dist/verify-webhook.d.ts +17 -28
- package/dist/verify-webhook.js +8 -0
- package/dist/version.d.ts +0 -1
- package/dist/wait-for-transaction.d.ts +54 -81
- package/dist/wait-for-transaction.js +120 -0
- package/dist/webhook-events.d.ts +44 -27
- package/package.json +103 -30
- package/dist/auth-permissions.d.ts.map +0 -1
- package/dist/auth-wallet-plugins.d.ts.map +0 -1
- package/dist/auth.d.ts.map +0 -1
- package/dist/bundler.d.ts.map +0 -1
- package/dist/chunk-xm8h1dzh.js +0 -33
- package/dist/client.d.ts +0 -19
- package/dist/client.d.ts.map +0 -1
- package/dist/contract-errors.d.ts +0 -4156
- package/dist/contract-errors.d.ts.map +0 -1
- package/dist/contract.d.ts +0 -17
- package/dist/contract.d.ts.map +0 -1
- package/dist/cookie-store.d.ts +0 -10
- package/dist/cookie-store.d.ts.map +0 -1
- package/dist/dapi-errors.d.ts +0 -650
- package/dist/dapi-errors.d.ts.map +0 -1
- package/dist/errors.d.ts +0 -633
- package/dist/errors.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/platform.d.ts +0 -41
- package/dist/platform.d.ts.map +0 -1
- package/dist/plugins/index.d.ts +0 -13
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -10
- package/dist/sdk-error.d.ts +0 -74
- package/dist/sdk-error.d.ts.map +0 -1
- package/dist/serializers.d.ts +0 -41
- package/dist/serializers.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/url.d.ts.map +0 -1
- package/dist/verify-webhook.d.ts.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/wait-for-transaction.d.ts.map +0 -1
- package/dist/webhook-events.d.ts.map +0 -1
|
@@ -0,0 +1,946 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PAUSED_POLL_INTERVAL_MAX_MS,
|
|
3
|
+
readsAsFundingPaused
|
|
4
|
+
} from "./chunk-fjnq61hj.js";
|
|
5
|
+
import {
|
|
6
|
+
Secret,
|
|
7
|
+
normalizeDalpBaseUrl,
|
|
8
|
+
secret,
|
|
9
|
+
unwrapSecret
|
|
10
|
+
} from "./chunk-h12fatty.js";
|
|
11
|
+
import {
|
|
12
|
+
DalpSdkError,
|
|
13
|
+
createDalpSdkConfigurationError
|
|
14
|
+
} from "./chunk-y0d2c7kp.js";
|
|
15
|
+
|
|
16
|
+
// src/errors/find-current-error.ts
|
|
17
|
+
var readProperty = (target, key) => Reflect.get(target, key);
|
|
18
|
+
var findCurrentError = (error, maxNodes = 20) => {
|
|
19
|
+
const queue = [error];
|
|
20
|
+
const seen = new Set;
|
|
21
|
+
let visited = 0;
|
|
22
|
+
while (queue.length > 0 && visited < maxNodes) {
|
|
23
|
+
const current = queue.shift();
|
|
24
|
+
if (current === null || current === undefined || seen.has(current)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
seen.add(current);
|
|
28
|
+
visited += 1;
|
|
29
|
+
if (current instanceof DalpSdkError) {
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
if (typeof current !== "object") {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
queue.push(readProperty(current, "cause"));
|
|
36
|
+
const reasons = readProperty(current, "reasons");
|
|
37
|
+
if (Array.isArray(reasons)) {
|
|
38
|
+
for (const reason of reasons) {
|
|
39
|
+
if (typeof reason === "object" && reason !== null) {
|
|
40
|
+
queue.push(readProperty(reason, "error"), readProperty(reason, "defect"));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/errors/api-error.ts
|
|
49
|
+
class DalpApiError extends Error {
|
|
50
|
+
id;
|
|
51
|
+
code;
|
|
52
|
+
category;
|
|
53
|
+
status;
|
|
54
|
+
retryable;
|
|
55
|
+
why;
|
|
56
|
+
fix;
|
|
57
|
+
retryAfterSeconds;
|
|
58
|
+
constructor(options) {
|
|
59
|
+
super(options.message, { cause: options.cause });
|
|
60
|
+
this.name = "DalpApiError";
|
|
61
|
+
this.id = options.id;
|
|
62
|
+
this.code = options.code;
|
|
63
|
+
this.category = options.category;
|
|
64
|
+
this.status = options.status;
|
|
65
|
+
this.retryable = options.retryable;
|
|
66
|
+
this.why = options.why;
|
|
67
|
+
this.fix = options.fix;
|
|
68
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
69
|
+
}
|
|
70
|
+
static make(options) {
|
|
71
|
+
return new DalpApiError(options);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
var isDalpApiError = (error) => error instanceof DalpApiError;
|
|
75
|
+
var findDalpSdkError = findCurrentError;
|
|
76
|
+
var API_ERROR_CATEGORIES = new Set([
|
|
77
|
+
"client",
|
|
78
|
+
"auth",
|
|
79
|
+
"permission",
|
|
80
|
+
"domain",
|
|
81
|
+
"contract",
|
|
82
|
+
"dependency",
|
|
83
|
+
"operational",
|
|
84
|
+
"config",
|
|
85
|
+
"unknown"
|
|
86
|
+
]);
|
|
87
|
+
var mapSdkErrorCategory = (category) => {
|
|
88
|
+
if (category === "sdk.configuration") {
|
|
89
|
+
return "config";
|
|
90
|
+
}
|
|
91
|
+
if (API_ERROR_CATEGORIES.has(category)) {
|
|
92
|
+
return category;
|
|
93
|
+
}
|
|
94
|
+
return "operational";
|
|
95
|
+
};
|
|
96
|
+
var makeDalpApiError = (error) => {
|
|
97
|
+
const sdkError = findDalpSdkError(error);
|
|
98
|
+
if (sdkError === undefined) {
|
|
99
|
+
return new DalpApiError({
|
|
100
|
+
message: "DALP API request failed",
|
|
101
|
+
cause: error,
|
|
102
|
+
code: "sdk.transport.REQUEST_FAILED",
|
|
103
|
+
category: "dependency",
|
|
104
|
+
retryable: true,
|
|
105
|
+
why: "The DALP API request failed before the server returned a structured response.",
|
|
106
|
+
fix: "Check network connectivity and retry the request."
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return new DalpApiError({
|
|
110
|
+
message: sdkError.message,
|
|
111
|
+
cause: sdkError,
|
|
112
|
+
code: sdkError.code,
|
|
113
|
+
category: mapSdkErrorCategory(sdkError.category),
|
|
114
|
+
retryable: sdkError.retryable,
|
|
115
|
+
why: sdkError.why,
|
|
116
|
+
fix: sdkError.fix,
|
|
117
|
+
status: sdkError.status,
|
|
118
|
+
retryAfterSeconds: sdkError.retryAfterSeconds
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// src/client/query-serializer.ts
|
|
123
|
+
function appendQueryValue(search, path, value) {
|
|
124
|
+
if (value === undefined || value === null) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (value instanceof Date) {
|
|
128
|
+
search.append(path, value.toISOString());
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(value)) {
|
|
132
|
+
for (const [index, item] of value.entries()) {
|
|
133
|
+
const itemPath = typeof item === "object" && item !== null ? `${path}[${String(index)}]` : path;
|
|
134
|
+
appendQueryValue(search, itemPath, item);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (typeof value === "object") {
|
|
139
|
+
for (const [key, item] of Object.entries(value)) {
|
|
140
|
+
appendQueryValue(search, `${path}[${key}]`, item);
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
search.append(path, String(value));
|
|
145
|
+
}
|
|
146
|
+
function serializeDalpQuery(query) {
|
|
147
|
+
const search = new URLSearchParams;
|
|
148
|
+
if (typeof query === "object" && query !== null) {
|
|
149
|
+
for (const [key, value] of Object.entries(query)) {
|
|
150
|
+
appendQueryValue(search, key, value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return search.toString();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/client/request-compression.ts
|
|
157
|
+
var DALP_SDK_REQUEST_COMPRESSION_MIN_BODY_BYTES = 1024;
|
|
158
|
+
var DALP_SDK_REQUEST_COMPRESSION_MAX_BODY_BYTES = 16777216;
|
|
159
|
+
var NO_BODY_METHODS = new Set(["GET", "HEAD"]);
|
|
160
|
+
function bufferedBodySize(body) {
|
|
161
|
+
if (typeof body === "string") {
|
|
162
|
+
return Buffer.byteLength(body);
|
|
163
|
+
}
|
|
164
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
|
|
165
|
+
return body.byteLength;
|
|
166
|
+
}
|
|
167
|
+
if (body instanceof Blob) {
|
|
168
|
+
return body.size;
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
function isCompressibleMediaType(contentType) {
|
|
173
|
+
const mediaType = contentType?.split(";")[0]?.trim().toLowerCase();
|
|
174
|
+
if (mediaType === undefined || mediaType === "") {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
return mediaType === "application/json" || mediaType.endsWith("+json") || mediaType.startsWith("text/");
|
|
178
|
+
}
|
|
179
|
+
async function cancelReaderBestEffort(reader) {
|
|
180
|
+
try {
|
|
181
|
+
await reader.cancel();
|
|
182
|
+
} catch {}
|
|
183
|
+
}
|
|
184
|
+
async function readRequestBodyWithinCap(request, maxBodyBytes) {
|
|
185
|
+
let body;
|
|
186
|
+
try {
|
|
187
|
+
const { body: clonedBody } = request.clone();
|
|
188
|
+
body = clonedBody;
|
|
189
|
+
} catch {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (body === null) {
|
|
193
|
+
return Buffer.alloc(0);
|
|
194
|
+
}
|
|
195
|
+
const reader = body.getReader();
|
|
196
|
+
const chunks = [];
|
|
197
|
+
let totalBytes = 0;
|
|
198
|
+
try {
|
|
199
|
+
while (true) {
|
|
200
|
+
const next = await reader.read();
|
|
201
|
+
if (next.done) {
|
|
202
|
+
return Buffer.concat(chunks, totalBytes);
|
|
203
|
+
}
|
|
204
|
+
totalBytes += next.value.byteLength;
|
|
205
|
+
if (totalBytes > maxBodyBytes) {
|
|
206
|
+
cancelReaderBestEffort(reader);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
chunks.push(next.value);
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
return;
|
|
213
|
+
} finally {
|
|
214
|
+
reader.releaseLock();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function withRequestBodyCompression(fetchImpl, options) {
|
|
218
|
+
const minBodyBytes = options?.minBodyBytes ?? DALP_SDK_REQUEST_COMPRESSION_MIN_BODY_BYTES;
|
|
219
|
+
const maxBodyBytes = options?.maxBodyBytes ?? DALP_SDK_REQUEST_COMPRESSION_MAX_BODY_BYTES;
|
|
220
|
+
const requestCompressionFetch = async (input, init) => {
|
|
221
|
+
if (init?.compress !== undefined) {
|
|
222
|
+
return fetchImpl(input, init);
|
|
223
|
+
}
|
|
224
|
+
let request;
|
|
225
|
+
if (input instanceof Request) {
|
|
226
|
+
request = init === undefined ? input : new Request(input, init);
|
|
227
|
+
}
|
|
228
|
+
const method = (request?.method ?? init?.method ?? "GET").toUpperCase();
|
|
229
|
+
if (NO_BODY_METHODS.has(method)) {
|
|
230
|
+
return fetchImpl(input, init);
|
|
231
|
+
}
|
|
232
|
+
const headers = new Headers(request?.headers ?? init?.headers);
|
|
233
|
+
if (headers.get("content-encoding") !== null) {
|
|
234
|
+
return fetchImpl(input, init);
|
|
235
|
+
}
|
|
236
|
+
let compress;
|
|
237
|
+
let bufferedRequestBody;
|
|
238
|
+
if (request !== undefined && request.body !== null && isCompressibleMediaType(headers.get("content-type"))) {
|
|
239
|
+
bufferedRequestBody = await readRequestBodyWithinCap(request, maxBodyBytes);
|
|
240
|
+
if (bufferedRequestBody !== undefined && bufferedRequestBody.byteLength >= minBodyBytes) {
|
|
241
|
+
compress = "gzip";
|
|
242
|
+
}
|
|
243
|
+
} else if (init?.body !== null && init?.body !== undefined) {
|
|
244
|
+
const size = bufferedBodySize(init.body);
|
|
245
|
+
if (size !== undefined && size >= minBodyBytes && size <= maxBodyBytes) {
|
|
246
|
+
compress = "gzip";
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (compress === undefined) {
|
|
250
|
+
return fetchImpl(input, init);
|
|
251
|
+
}
|
|
252
|
+
if (request !== undefined && bufferedRequestBody !== undefined) {
|
|
253
|
+
return fetchImpl(request.url, {
|
|
254
|
+
...init,
|
|
255
|
+
body: bufferedRequestBody,
|
|
256
|
+
cache: init?.cache ?? request.cache,
|
|
257
|
+
compress,
|
|
258
|
+
credentials: init?.credentials ?? request.credentials,
|
|
259
|
+
headers: request.headers,
|
|
260
|
+
integrity: init?.integrity ?? request.integrity,
|
|
261
|
+
keepalive: init?.keepalive ?? request.keepalive,
|
|
262
|
+
method: request.method,
|
|
263
|
+
mode: init?.mode ?? request.mode,
|
|
264
|
+
redirect: init?.redirect ?? request.redirect,
|
|
265
|
+
referrer: init?.referrer ?? request.referrer,
|
|
266
|
+
referrerPolicy: init?.referrerPolicy ?? request.referrerPolicy,
|
|
267
|
+
signal: init?.signal ?? request.signal
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return fetchImpl(input, { ...init, compress });
|
|
271
|
+
};
|
|
272
|
+
return Object.assign(requestCompressionFetch, {
|
|
273
|
+
preconnect: fetchImpl.preconnect
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/client/ssr-fetch.ts
|
|
278
|
+
class DalpSsrSecurityError extends Error {
|
|
279
|
+
name = "DalpSsrSecurityError";
|
|
280
|
+
}
|
|
281
|
+
var originOf = (value) => {
|
|
282
|
+
const url = new URL(value);
|
|
283
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
284
|
+
throw new DalpSsrSecurityError(`DALP SDK: ${url.protocol} is not an approved SSR protocol.`);
|
|
285
|
+
}
|
|
286
|
+
return url.origin;
|
|
287
|
+
};
|
|
288
|
+
var REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
289
|
+
var SENSITIVE_HEADERS = [
|
|
290
|
+
"authorization",
|
|
291
|
+
"baggage",
|
|
292
|
+
"cookie",
|
|
293
|
+
"idempotency-key",
|
|
294
|
+
"origin",
|
|
295
|
+
"referer",
|
|
296
|
+
"traceparent",
|
|
297
|
+
"tracestate",
|
|
298
|
+
"x-api-key",
|
|
299
|
+
"x-chain-id",
|
|
300
|
+
"x-executor",
|
|
301
|
+
"x-organization-id",
|
|
302
|
+
"x-participant",
|
|
303
|
+
"x-selected-signers"
|
|
304
|
+
];
|
|
305
|
+
var withoutSensitiveHeaders = (source) => {
|
|
306
|
+
const headers = new Headers(source);
|
|
307
|
+
for (const name of SENSITIVE_HEADERS) {
|
|
308
|
+
headers.delete(name);
|
|
309
|
+
}
|
|
310
|
+
return headers;
|
|
311
|
+
};
|
|
312
|
+
function createSsrFetch(options) {
|
|
313
|
+
const incoming = new Headers(options.requestHeaders);
|
|
314
|
+
const approvedOrigins = new Set([originOf(options.baseUrl), ...(options.allowedOrigins ?? []).map(originOf)]);
|
|
315
|
+
const ssrFetch = async (input, init) => {
|
|
316
|
+
const request = input instanceof Request && init === undefined ? input : new Request(input, init);
|
|
317
|
+
if (!approvedOrigins.has(new URL(request.url).origin)) {
|
|
318
|
+
throw new DalpSsrSecurityError(`DALP SDK: ${request.url} is not an approved SSR destination.`);
|
|
319
|
+
}
|
|
320
|
+
const cookie = incoming.get("cookie");
|
|
321
|
+
if (cookie !== null && !["GET", "HEAD", "OPTIONS"].includes(request.method)) {
|
|
322
|
+
const incomingOrigin = incoming.get("origin");
|
|
323
|
+
let trustedOrigin = false;
|
|
324
|
+
try {
|
|
325
|
+
trustedOrigin = incomingOrigin !== null && approvedOrigins.has(originOf(incomingOrigin));
|
|
326
|
+
} catch {
|
|
327
|
+
trustedOrigin = false;
|
|
328
|
+
}
|
|
329
|
+
if (!trustedOrigin || incoming.get("sec-fetch-site") === "cross-site") {
|
|
330
|
+
throw new DalpSsrSecurityError("DALP SDK: a cookie-authenticated SSR mutation requires a trusted Origin.");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const headers = new Headers(request.headers);
|
|
334
|
+
if (cookie === null) {
|
|
335
|
+
headers.delete("cookie");
|
|
336
|
+
} else {
|
|
337
|
+
headers.set("cookie", cookie);
|
|
338
|
+
}
|
|
339
|
+
for (const name of ["origin", "traceparent", "tracestate", "baggage"]) {
|
|
340
|
+
const value = incoming.get(name);
|
|
341
|
+
if (value !== null && !headers.has(name)) {
|
|
342
|
+
headers.set(name, value);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
let current = new Request(request, { headers, redirect: "manual" });
|
|
346
|
+
let sensitiveAllowed = true;
|
|
347
|
+
for (let redirectCount = 0;redirectCount <= 5; redirectCount += 1) {
|
|
348
|
+
const replay = current.clone();
|
|
349
|
+
const response = await options.fetch(current, { credentials: "omit", redirect: "manual" });
|
|
350
|
+
const location = response.headers.get("location");
|
|
351
|
+
if (!REDIRECT_STATUSES.has(response.status) || location === null) {
|
|
352
|
+
return response;
|
|
353
|
+
}
|
|
354
|
+
if (redirectCount === 5) {
|
|
355
|
+
throw new DalpSsrSecurityError("DALP SDK: SSR fetch exceeded the redirect limit.");
|
|
356
|
+
}
|
|
357
|
+
const nextUrl = new URL(location, current.url);
|
|
358
|
+
sensitiveAllowed = sensitiveAllowed && approvedOrigins.has(nextUrl.origin);
|
|
359
|
+
const redirectToGet = response.status === 303 || (response.status === 301 || response.status === 302) && replay.method === "POST";
|
|
360
|
+
const method = redirectToGet ? "GET" : replay.method;
|
|
361
|
+
if (!sensitiveAllowed && method !== "GET" && method !== "HEAD") {
|
|
362
|
+
throw new DalpSsrSecurityError("DALP SDK: refused to forward an SSR request body outside the trust boundary.");
|
|
363
|
+
}
|
|
364
|
+
const nextHeaders = sensitiveAllowed ? new Headers(replay.headers) : withoutSensitiveHeaders(replay.headers);
|
|
365
|
+
if (redirectToGet) {
|
|
366
|
+
nextHeaders.delete("content-length");
|
|
367
|
+
nextHeaders.delete("content-type");
|
|
368
|
+
}
|
|
369
|
+
current = new Request(nextUrl, {
|
|
370
|
+
body: method === "GET" || method === "HEAD" ? undefined : await replay.arrayBuffer(),
|
|
371
|
+
credentials: sensitiveAllowed ? replay.credentials : "omit",
|
|
372
|
+
headers: nextHeaders,
|
|
373
|
+
method,
|
|
374
|
+
redirect: "manual",
|
|
375
|
+
signal: replay.signal
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
throw new DalpSsrSecurityError("DALP SDK: unreachable redirect state.");
|
|
379
|
+
};
|
|
380
|
+
return Object.assign(ssrFetch, {
|
|
381
|
+
preconnect: options.fetch.preconnect ?? (() => {})
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// src/client/conditional-request.ts
|
|
386
|
+
var IF_NONE_MATCH = "If-None-Match";
|
|
387
|
+
var CONDITIONAL_RESPONSE_STORE_CAPACITY = 64;
|
|
388
|
+
var CONDITIONAL_RESPONSE_MAX_BODY_BYTES = 1048576;
|
|
389
|
+
var IDENTITY_RESET_PATH_SUFFIXES = [
|
|
390
|
+
"/api/auth/sign-out",
|
|
391
|
+
"/api/auth/revoke-session",
|
|
392
|
+
"/api/auth/revoke-sessions",
|
|
393
|
+
"/api/auth/revoke-other-sessions",
|
|
394
|
+
"/api/auth/organization/set-active"
|
|
395
|
+
];
|
|
396
|
+
var headerOrDefault = (headers, name) => headers.get(name)?.trim() || "default";
|
|
397
|
+
var tenantOf = (headers) => `${headerOrDefault(headers, "X-Organization-Id")}\x00${headerOrDefault(headers, "X-Participant")}`;
|
|
398
|
+
var resourceKey = (request) => {
|
|
399
|
+
const url = new URL(request.url);
|
|
400
|
+
return `${url.origin}${url.pathname}${url.search}\x00${tenantOf(request.headers)}`;
|
|
401
|
+
};
|
|
402
|
+
var isIdentityResetPath = (url) => {
|
|
403
|
+
const path = new URL(url).pathname;
|
|
404
|
+
return IDENTITY_RESET_PATH_SUFFIXES.some((suffix) => path === suffix || path.endsWith(suffix));
|
|
405
|
+
};
|
|
406
|
+
var isEventStream = (response) => (response.headers.get("content-type") ?? "").includes("text/event-stream");
|
|
407
|
+
var remember = (store, key, entry) => {
|
|
408
|
+
store.delete(key);
|
|
409
|
+
store.set(key, entry);
|
|
410
|
+
if (store.size > CONDITIONAL_RESPONSE_STORE_CAPACITY) {
|
|
411
|
+
const oldest = store.keys().next().value;
|
|
412
|
+
if (oldest !== undefined) {
|
|
413
|
+
store.delete(oldest);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
var touch = (store, key) => {
|
|
418
|
+
const entry = store.get(key);
|
|
419
|
+
if (entry === undefined) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
store.delete(key);
|
|
423
|
+
store.set(key, entry);
|
|
424
|
+
return entry;
|
|
425
|
+
};
|
|
426
|
+
var requestWithoutIfNoneMatch = (request) => {
|
|
427
|
+
const headers = new Headers;
|
|
428
|
+
for (const [name, value] of request.headers.entries()) {
|
|
429
|
+
if (name.toLowerCase() !== IF_NONE_MATCH.toLowerCase()) {
|
|
430
|
+
headers.append(name, value);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return new Request(request.url, {
|
|
434
|
+
method: request.method,
|
|
435
|
+
headers,
|
|
436
|
+
signal: request.signal,
|
|
437
|
+
credentials: request.credentials,
|
|
438
|
+
redirect: request.redirect
|
|
439
|
+
});
|
|
440
|
+
};
|
|
441
|
+
async function captureSuccessfulGet(store, key, response) {
|
|
442
|
+
if (!response.ok || isEventStream(response)) {
|
|
443
|
+
return response;
|
|
444
|
+
}
|
|
445
|
+
const etag = response.headers.get("etag")?.trim();
|
|
446
|
+
if (etag === undefined || etag.length === 0) {
|
|
447
|
+
store.delete(key);
|
|
448
|
+
return response;
|
|
449
|
+
}
|
|
450
|
+
const body = new Uint8Array(await response.arrayBuffer());
|
|
451
|
+
const headers = new Headers(response.headers);
|
|
452
|
+
headers.set("etag", etag);
|
|
453
|
+
if (body.byteLength <= CONDITIONAL_RESPONSE_MAX_BODY_BYTES) {
|
|
454
|
+
remember(store, key, { body, etag, headers });
|
|
455
|
+
}
|
|
456
|
+
return new Response(body, {
|
|
457
|
+
headers,
|
|
458
|
+
status: response.status,
|
|
459
|
+
statusText: response.statusText
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
function withConditionalRequests(base) {
|
|
463
|
+
const state = { store: new Map, lastIdentity: undefined };
|
|
464
|
+
const syncIdentity = (headers) => {
|
|
465
|
+
const identity = tenantOf(headers);
|
|
466
|
+
if (state.lastIdentity !== undefined && identity !== state.lastIdentity) {
|
|
467
|
+
state.store.clear();
|
|
468
|
+
}
|
|
469
|
+
state.lastIdentity = identity;
|
|
470
|
+
};
|
|
471
|
+
const decorated = async (input, init) => {
|
|
472
|
+
const request = new Request(input, init);
|
|
473
|
+
syncIdentity(request.headers);
|
|
474
|
+
if (request.method !== "GET") {
|
|
475
|
+
const response2 = await base(request);
|
|
476
|
+
if (isIdentityResetPath(request.url) && response2.ok) {
|
|
477
|
+
state.store.clear();
|
|
478
|
+
state.lastIdentity = undefined;
|
|
479
|
+
}
|
|
480
|
+
return response2;
|
|
481
|
+
}
|
|
482
|
+
const key = resourceKey(request);
|
|
483
|
+
let sent = request;
|
|
484
|
+
if (!request.headers.has(IF_NONE_MATCH)) {
|
|
485
|
+
const entry2 = touch(state.store, key);
|
|
486
|
+
if (entry2 !== undefined) {
|
|
487
|
+
const headers = new Headers(request.headers);
|
|
488
|
+
headers.set(IF_NONE_MATCH, entry2.etag);
|
|
489
|
+
sent = new Request(request, { headers });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
const response = await base(sent);
|
|
493
|
+
if (response.status !== 304) {
|
|
494
|
+
return captureSuccessfulGet(state.store, key, response);
|
|
495
|
+
}
|
|
496
|
+
const entry = touch(state.store, key);
|
|
497
|
+
if (entry === undefined) {
|
|
498
|
+
const retried = await base(requestWithoutIfNoneMatch(sent));
|
|
499
|
+
return retried.status === 304 ? retried : captureSuccessfulGet(state.store, key, retried);
|
|
500
|
+
}
|
|
501
|
+
return new Response(new Uint8Array(entry.body), { status: 200, statusText: "OK", headers: entry.headers });
|
|
502
|
+
};
|
|
503
|
+
return {
|
|
504
|
+
fetch: decorated,
|
|
505
|
+
store: {
|
|
506
|
+
clear: () => {
|
|
507
|
+
state.store.clear();
|
|
508
|
+
state.lastIdentity = undefined;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/proxy/flat-args.ts
|
|
515
|
+
function splitFlatArgs(route, input) {
|
|
516
|
+
const source = input === null || input === undefined || typeof input !== "object" ? {} : input;
|
|
517
|
+
const path = {};
|
|
518
|
+
const rest = {};
|
|
519
|
+
const pathParams = new Set(route.params);
|
|
520
|
+
for (const [key, value] of Object.entries(source)) {
|
|
521
|
+
if (pathParams.has(key)) {
|
|
522
|
+
path[key] = value;
|
|
523
|
+
} else {
|
|
524
|
+
rest[key] = value;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const missing = route.params.filter((name) => path[name] === undefined);
|
|
528
|
+
if (missing.length > 0) {
|
|
529
|
+
throw new TypeError(`Missing path parameter${missing.length === 1 ? "" : "s"} ${missing.map((name) => `\`${name}\``).join(", ")} for ${route.method} ${route.path}`);
|
|
530
|
+
}
|
|
531
|
+
if (!route.hasPayload) {
|
|
532
|
+
return { path, query: rest, body: undefined };
|
|
533
|
+
}
|
|
534
|
+
if (input === null || input === undefined) {
|
|
535
|
+
return { path, query: {}, body: undefined };
|
|
536
|
+
}
|
|
537
|
+
for (const name of route.bodyParams) {
|
|
538
|
+
const value = path[name];
|
|
539
|
+
if (value !== undefined) {
|
|
540
|
+
rest[name] = value;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return { path, query: {}, body: rest };
|
|
544
|
+
}
|
|
545
|
+
function buildPath(route, path) {
|
|
546
|
+
return route.path.replaceAll(/:([A-Za-z0-9_]+)/gu, (_match, name) => {
|
|
547
|
+
const value = path[name];
|
|
548
|
+
return encodeURIComponent(typeof value === "string" ? value : String(value));
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/proxy/transport.ts
|
|
553
|
+
var CONTEXT_HEADERS = {
|
|
554
|
+
organizationId: "X-Organization-Id",
|
|
555
|
+
participant: "X-Participant",
|
|
556
|
+
executor: "X-Executor",
|
|
557
|
+
chainId: "X-Chain-Id",
|
|
558
|
+
selectedSigners: "X-Selected-Signers",
|
|
559
|
+
idempotencyKey: "Idempotency-Key"
|
|
560
|
+
};
|
|
561
|
+
function setNonEmptyHeader(headers, name, value) {
|
|
562
|
+
if (value !== undefined && String(value).trim().length > 0) {
|
|
563
|
+
headers.set(name, String(value));
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function createDalpContextHeaders(context) {
|
|
567
|
+
const headers = new Headers;
|
|
568
|
+
setNonEmptyHeader(headers, CONTEXT_HEADERS.organizationId, context.organizationId);
|
|
569
|
+
setNonEmptyHeader(headers, CONTEXT_HEADERS.participant, context.participant);
|
|
570
|
+
setNonEmptyHeader(headers, CONTEXT_HEADERS.executor, context.executor);
|
|
571
|
+
setNonEmptyHeader(headers, CONTEXT_HEADERS.chainId, context.chainId);
|
|
572
|
+
setNonEmptyHeader(headers, CONTEXT_HEADERS.idempotencyKey, context.idempotencyKey);
|
|
573
|
+
if (context.selectedSigners !== undefined && context.selectedSigners.length > 0) {
|
|
574
|
+
headers.set(CONTEXT_HEADERS.selectedSigners, JSON.stringify(context.selectedSigners));
|
|
575
|
+
}
|
|
576
|
+
return headers;
|
|
577
|
+
}
|
|
578
|
+
var DEFAULT_PREFER_WAIT_SECONDS = 15;
|
|
579
|
+
function createTransport(options) {
|
|
580
|
+
const baseUrl = normalizeDalpBaseUrl(String(options.baseUrl));
|
|
581
|
+
const runtime = options.runtime ?? (globalThis.window === undefined ? "server" : "browser");
|
|
582
|
+
const baseFetch = options.fetch ?? globalThis.fetch;
|
|
583
|
+
const transportFetch = runtime === "browser" ? baseFetch : withRequestBodyCompression(baseFetch);
|
|
584
|
+
const { apiKey: apiKeyOption } = options;
|
|
585
|
+
let apiKey;
|
|
586
|
+
if (apiKeyOption === undefined) {
|
|
587
|
+
apiKey = undefined;
|
|
588
|
+
} else if (apiKeyOption instanceof Secret) {
|
|
589
|
+
apiKey = apiKeyOption;
|
|
590
|
+
} else {
|
|
591
|
+
apiKey = secret(apiKeyOption.trim());
|
|
592
|
+
}
|
|
593
|
+
if (runtime === "browser" && apiKey !== undefined) {
|
|
594
|
+
throw createDalpSdkConfigurationError({
|
|
595
|
+
message: "DALP SDK: API keys are server/CLI-only credentials and cannot configure a browser client.",
|
|
596
|
+
why: "An API key placed in a browser client ships the credential to every visitor's bundle.",
|
|
597
|
+
fix: "Keep the API key on the server or CLI process; browser clients authenticate with the session cookie."
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
const sessionFetch = options.ssr === undefined ? transportFetch : createSsrFetch({
|
|
601
|
+
allowedOrigins: options.ssr.allowedOrigins,
|
|
602
|
+
baseUrl,
|
|
603
|
+
fetch: transportFetch,
|
|
604
|
+
requestHeaders: options.ssr.requestHeaders
|
|
605
|
+
});
|
|
606
|
+
const conditional = withConditionalRequests(sessionFetch);
|
|
607
|
+
return {
|
|
608
|
+
baseUrl,
|
|
609
|
+
fetch: conditional.fetch,
|
|
610
|
+
conditionalRequests: conditional.store,
|
|
611
|
+
credentials: runtime === "browser" ? "include" : "omit",
|
|
612
|
+
apiKey,
|
|
613
|
+
contextHeaders: createDalpContextHeaders(options.context ?? {}),
|
|
614
|
+
settlementTimeoutMs: options.settlementTimeoutMs
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function callHeaders(transport, options) {
|
|
618
|
+
const headers = new Headers({ Accept: "application/json" });
|
|
619
|
+
if (transport.apiKey !== undefined) {
|
|
620
|
+
headers.set("X-Api-Key", unwrapSecret(transport.apiKey));
|
|
621
|
+
}
|
|
622
|
+
for (const [name, value] of transport.contextHeaders) {
|
|
623
|
+
if (!headers.has(name)) {
|
|
624
|
+
headers.set(name, value);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
const extra = typeof options?.headers === "function" ? options.headers() : options?.headers ?? {};
|
|
628
|
+
for (const [name, value] of Object.entries(extra)) {
|
|
629
|
+
headers.set(name, value);
|
|
630
|
+
}
|
|
631
|
+
return headers;
|
|
632
|
+
}
|
|
633
|
+
function prepareRequest(transport, route, input, options) {
|
|
634
|
+
const split = splitFlatArgs(route, input);
|
|
635
|
+
const query = serializeDalpQuery(split.query);
|
|
636
|
+
const url = `${transport.baseUrl}/api/v2${buildPath(route, split.path)}${query === "" ? "" : `?${query}`}`;
|
|
637
|
+
const headers = callHeaders(transport, options);
|
|
638
|
+
if (split.body !== undefined) {
|
|
639
|
+
headers.set("Content-Type", "application/json");
|
|
640
|
+
}
|
|
641
|
+
if (route.queueBacked) {
|
|
642
|
+
headers.set("Prefer", `wait=${String(DEFAULT_PREFER_WAIT_SECONDS)}`);
|
|
643
|
+
}
|
|
644
|
+
return {
|
|
645
|
+
url,
|
|
646
|
+
method: route.method,
|
|
647
|
+
headers,
|
|
648
|
+
body: split.body === undefined ? undefined : JSON.stringify(split.body, wireValue)
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
function wireValue(_key, value) {
|
|
652
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
653
|
+
}
|
|
654
|
+
function readString(source, key) {
|
|
655
|
+
if (source === null || typeof source !== "object") {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const value = Reflect.get(source, key);
|
|
659
|
+
return typeof value === "string" ? value : undefined;
|
|
660
|
+
}
|
|
661
|
+
function sdkErrorFromEnvelope(payload, response) {
|
|
662
|
+
const envelope = payload !== null && typeof payload === "object" ? payload : {};
|
|
663
|
+
const rawData = Reflect.get(envelope, "data");
|
|
664
|
+
const data = rawData !== null && typeof rawData === "object" ? rawData : {};
|
|
665
|
+
const retryable = Reflect.get(data, "retryable");
|
|
666
|
+
return new DalpSdkError({
|
|
667
|
+
code: readString(envelope, "code") ?? `sdk.transport.HTTP_${String(response.status)}`,
|
|
668
|
+
category: "dependency",
|
|
669
|
+
status: response.status,
|
|
670
|
+
retryable: typeof retryable === "boolean" ? retryable : response.status >= 500,
|
|
671
|
+
message: readString(envelope, "message") ?? `DALP API responded ${String(response.status)}`,
|
|
672
|
+
why: readString(data, "why") ?? `The platform answered ${String(response.status)}.`,
|
|
673
|
+
fix: readString(data, "fix") ?? "Inspect the response body and the request id before retrying.",
|
|
674
|
+
...readString(data, "id") === undefined ? {} : { details: { id: readString(data, "id") } }
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
async function readResponse(response) {
|
|
678
|
+
const text = await response.text();
|
|
679
|
+
let payload;
|
|
680
|
+
try {
|
|
681
|
+
payload = text === "" ? undefined : JSON.parse(text);
|
|
682
|
+
} catch {
|
|
683
|
+
payload = text;
|
|
684
|
+
}
|
|
685
|
+
if (!response.ok) {
|
|
686
|
+
throw makeDalpApiError(sdkErrorFromEnvelope(payload, response));
|
|
687
|
+
}
|
|
688
|
+
return payload;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/proxy/settlement.ts
|
|
692
|
+
var SUCCESS_STATE = "COMPLETED";
|
|
693
|
+
var FAILURE_STATES = new Set(["FAILED", "DEAD_LETTER", "CANCELLED"]);
|
|
694
|
+
var DEFAULT_SETTLEMENT_TIMEOUT_MS = 120000;
|
|
695
|
+
var POLL_INTERVAL_MS = 1000;
|
|
696
|
+
|
|
697
|
+
class SettlementTimeoutError extends DalpSdkError {
|
|
698
|
+
transactionId;
|
|
699
|
+
statusUrl;
|
|
700
|
+
constructor(transactionId, statusUrl, timeoutMs) {
|
|
701
|
+
super({
|
|
702
|
+
code: "sdk.settlement.TIMEOUT",
|
|
703
|
+
category: "dependency",
|
|
704
|
+
retryable: true,
|
|
705
|
+
message: `The mutation did not settle within ${String(Math.round(timeoutMs / 1000))}s and is still queued.`,
|
|
706
|
+
why: "The platform accepted the write and is still working on it. The wait ended before the work did.",
|
|
707
|
+
fix: `Follow ${statusUrl} or pass the transaction id to waitForTransaction. Do not resubmit the mutation.`,
|
|
708
|
+
details: { transactionId, statusUrl }
|
|
709
|
+
});
|
|
710
|
+
this.name = "SettlementTimeoutError";
|
|
711
|
+
this.transactionId = transactionId;
|
|
712
|
+
this.statusUrl = statusUrl;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
class SettlementFailedError extends DalpSdkError {
|
|
717
|
+
transactionId;
|
|
718
|
+
constructor(transactionId, state, reason) {
|
|
719
|
+
super({
|
|
720
|
+
code: "sdk.settlement.FAILED",
|
|
721
|
+
category: "dependency",
|
|
722
|
+
retryable: false,
|
|
723
|
+
message: reason ?? `The mutation reached terminal state ${state}.`,
|
|
724
|
+
why: `The platform reported ${state} for transaction ${transactionId}.`,
|
|
725
|
+
fix: "Inspect the transaction request before submitting the mutation again.",
|
|
726
|
+
details: { transactionId, state }
|
|
727
|
+
});
|
|
728
|
+
this.name = "SettlementFailedError";
|
|
729
|
+
this.transactionId = transactionId;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function readString2(source, key) {
|
|
733
|
+
if (source === null || typeof source !== "object") {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const value = Reflect.get(source, key);
|
|
737
|
+
return typeof value === "string" ? value : undefined;
|
|
738
|
+
}
|
|
739
|
+
function readHandle(payload) {
|
|
740
|
+
const body = payload !== null && typeof payload === "object" ? Reflect.get(payload, "data") ?? payload : payload;
|
|
741
|
+
const transactionId = readString2(body, "transactionId");
|
|
742
|
+
const statusUrl = readString2(body, "statusUrl");
|
|
743
|
+
if (transactionId === undefined || statusUrl === undefined) {
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
return { transactionId, status: readString2(body, "status") ?? "QUEUED", statusUrl };
|
|
747
|
+
}
|
|
748
|
+
async function resolveSettlement(transport, payload, options, now = Date.now, sleep = (ms) => new Promise((resolve) => {
|
|
749
|
+
setTimeout(resolve, ms);
|
|
750
|
+
})) {
|
|
751
|
+
const handle = readHandle(payload);
|
|
752
|
+
if (handle === undefined) {
|
|
753
|
+
return payload;
|
|
754
|
+
}
|
|
755
|
+
const timeoutMs = options?.settlementTimeoutMs ?? transport.settlementTimeoutMs ?? DEFAULT_SETTLEMENT_TIMEOUT_MS;
|
|
756
|
+
let deadline = now() + timeoutMs;
|
|
757
|
+
let pollIntervalMs = POLL_INTERVAL_MS;
|
|
758
|
+
const statusUrl = handle.statusUrl.startsWith("http") ? handle.statusUrl : `${transport.baseUrl}${handle.statusUrl}`;
|
|
759
|
+
for (;; ) {
|
|
760
|
+
if (now() >= deadline) {
|
|
761
|
+
throw new SettlementTimeoutError(handle.transactionId, handle.statusUrl, timeoutMs);
|
|
762
|
+
}
|
|
763
|
+
await sleep(pollIntervalMs);
|
|
764
|
+
const response = await transport.fetch(statusUrl, {
|
|
765
|
+
method: "GET",
|
|
766
|
+
headers: callHeaders(transport, options),
|
|
767
|
+
credentials: transport.credentials,
|
|
768
|
+
...options?.signal === undefined ? {} : { signal: options.signal }
|
|
769
|
+
});
|
|
770
|
+
const status = await readResponse(response);
|
|
771
|
+
const body = status !== null && typeof status === "object" ? Reflect.get(status, "data") ?? status : status;
|
|
772
|
+
const state = readString2(body, "status");
|
|
773
|
+
if (state === SUCCESS_STATE) {
|
|
774
|
+
return status;
|
|
775
|
+
}
|
|
776
|
+
if (state !== undefined && FAILURE_STATES.has(state)) {
|
|
777
|
+
throw new SettlementFailedError(handle.transactionId, state, readString2(body, "errorMessage"));
|
|
778
|
+
}
|
|
779
|
+
if (readsAsFundingPaused(body)) {
|
|
780
|
+
deadline = now() + timeoutMs;
|
|
781
|
+
pollIntervalMs = Math.min(pollIntervalMs * 2, PAUSED_POLL_INTERVAL_MAX_MS);
|
|
782
|
+
} else {
|
|
783
|
+
pollIntervalMs = POLL_INTERVAL_MS;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// src/proxy/sse.ts
|
|
789
|
+
var RESERVED_STREAM_FAILURE_EVENT = "effect/httpapi/stream/failure";
|
|
790
|
+
var STREAM_FAILED_ERROR_CODE = "sdk.stream.FAILED";
|
|
791
|
+
function parseFrame(raw) {
|
|
792
|
+
try {
|
|
793
|
+
return JSON.parse(raw.data);
|
|
794
|
+
} catch {
|
|
795
|
+
return raw.data;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function dispatchFrame(raw) {
|
|
799
|
+
if (raw.event === RESERVED_STREAM_FAILURE_EVENT) {
|
|
800
|
+
throw makeDalpApiError(new DalpSdkError({
|
|
801
|
+
code: STREAM_FAILED_ERROR_CODE,
|
|
802
|
+
category: "dependency",
|
|
803
|
+
retryable: true,
|
|
804
|
+
message: "The DALP API stream failed before it completed.",
|
|
805
|
+
why: "The route ended the stream with its reserved failure event, so the remaining frames were never sent.",
|
|
806
|
+
fix: "Retry the stream. If it fails again, read the route's logs for the failure the server recorded.",
|
|
807
|
+
details: { cause: raw.data }
|
|
808
|
+
}));
|
|
809
|
+
}
|
|
810
|
+
return parseFrame(raw);
|
|
811
|
+
}
|
|
812
|
+
function readBlock(block) {
|
|
813
|
+
let event = "message";
|
|
814
|
+
const data = [];
|
|
815
|
+
for (const line of block.split(`
|
|
816
|
+
`)) {
|
|
817
|
+
if (line === "" || line.startsWith(":")) {
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
const separator = line.indexOf(":");
|
|
821
|
+
const field = separator === -1 ? line : line.slice(0, separator);
|
|
822
|
+
const rest = separator === -1 ? "" : line.slice(separator + 1).replace(/^ /u, "");
|
|
823
|
+
if (field === "event") {
|
|
824
|
+
event = rest;
|
|
825
|
+
} else if (field === "data") {
|
|
826
|
+
data.push(rest);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return data.length === 0 ? undefined : { event, data: data.join(`
|
|
830
|
+
`) };
|
|
831
|
+
}
|
|
832
|
+
async function* decodeEventStream(body) {
|
|
833
|
+
const reader = body.getReader();
|
|
834
|
+
const decoder = new TextDecoder;
|
|
835
|
+
let buffer = "";
|
|
836
|
+
try {
|
|
837
|
+
for (;; ) {
|
|
838
|
+
const chunk = await reader.read();
|
|
839
|
+
if (chunk.done) {
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
843
|
+
buffer = buffer.replaceAll(`\r
|
|
844
|
+
`, `
|
|
845
|
+
`);
|
|
846
|
+
let boundary = buffer.indexOf(`
|
|
847
|
+
|
|
848
|
+
`);
|
|
849
|
+
while (boundary !== -1) {
|
|
850
|
+
const raw = readBlock(buffer.slice(0, boundary));
|
|
851
|
+
buffer = buffer.slice(boundary + 2);
|
|
852
|
+
if (raw !== undefined) {
|
|
853
|
+
yield dispatchFrame(raw);
|
|
854
|
+
}
|
|
855
|
+
boundary = buffer.indexOf(`
|
|
856
|
+
|
|
857
|
+
`);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
const trailing = readBlock(buffer);
|
|
861
|
+
if (trailing !== undefined) {
|
|
862
|
+
yield dispatchFrame(trailing);
|
|
863
|
+
}
|
|
864
|
+
} finally {
|
|
865
|
+
await reader.cancel().catch(() => {});
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
async function* streamRequest(transport, route, input, options) {
|
|
869
|
+
const prepared = prepareRequest(transport, route, input, options);
|
|
870
|
+
prepared.headers.set("Accept", "text/event-stream");
|
|
871
|
+
const response = await transport.fetch(prepared.url, {
|
|
872
|
+
method: prepared.method,
|
|
873
|
+
headers: prepared.headers,
|
|
874
|
+
credentials: transport.credentials,
|
|
875
|
+
...prepared.body === undefined ? {} : { body: prepared.body },
|
|
876
|
+
...options?.signal === undefined ? {} : { signal: options.signal }
|
|
877
|
+
});
|
|
878
|
+
if (!response.ok) {
|
|
879
|
+
await readResponse(response);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (response.body === null) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
yield* decodeEventStream(response.body);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// src/proxy/fetch-executor.ts
|
|
889
|
+
async function sendRequest(transport, route, input, options) {
|
|
890
|
+
const prepared = prepareRequest(transport, route, input, options);
|
|
891
|
+
const response = await transport.fetch(prepared.url, {
|
|
892
|
+
method: prepared.method,
|
|
893
|
+
headers: prepared.headers,
|
|
894
|
+
credentials: transport.credentials,
|
|
895
|
+
...prepared.body === undefined ? {} : { body: prepared.body },
|
|
896
|
+
...options?.signal === undefined ? {} : { signal: options.signal }
|
|
897
|
+
});
|
|
898
|
+
const payload = await readResponse(response);
|
|
899
|
+
if (!route.queueBacked || response.status !== 202) {
|
|
900
|
+
return payload;
|
|
901
|
+
}
|
|
902
|
+
return resolveSettlement(transport, payload, options);
|
|
903
|
+
}
|
|
904
|
+
function createFetchExecutor(transport) {
|
|
905
|
+
return (route, _id, input, options) => route.serializer === "sse" ? streamRequest(transport, route, input, options) : sendRequest(transport, route, input, options);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// src/proxy/tanstack.ts
|
|
909
|
+
function canonicalize(value) {
|
|
910
|
+
if (Array.isArray(value)) {
|
|
911
|
+
return value.map(canonicalize);
|
|
912
|
+
}
|
|
913
|
+
if (value === null || typeof value !== "object") {
|
|
914
|
+
return value;
|
|
915
|
+
}
|
|
916
|
+
const entries = [];
|
|
917
|
+
for (const key of Object.keys(value).sort((left, right) => left.localeCompare(right))) {
|
|
918
|
+
const entry = Reflect.get(value, key);
|
|
919
|
+
if (entry !== undefined) {
|
|
920
|
+
entries.push([key, canonicalize(entry)]);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
return Object.fromEntries(entries);
|
|
924
|
+
}
|
|
925
|
+
function queryKeyFor(id, input) {
|
|
926
|
+
const canonical = canonicalize(input);
|
|
927
|
+
return canonical === undefined ? ["dalp", id] : ["dalp", id, canonical];
|
|
928
|
+
}
|
|
929
|
+
var UI_SETTLEMENT_TIMEOUT_MS = 30000;
|
|
930
|
+
function createTanstackFactories(transport) {
|
|
931
|
+
return {
|
|
932
|
+
queryOptions: (route, id, input, options) => ({
|
|
933
|
+
queryKey: queryKeyFor(id, input),
|
|
934
|
+
queryFn: (context) => sendRequest(transport, route, input, {
|
|
935
|
+
...options,
|
|
936
|
+
...context.signal === undefined ? {} : { signal: context.signal }
|
|
937
|
+
})
|
|
938
|
+
}),
|
|
939
|
+
mutationOptions: (route, id, options) => ({
|
|
940
|
+
mutationKey: ["dalp", id],
|
|
941
|
+
mutationFn: (input) => sendRequest(transport, route, input, { settlementTimeoutMs: UI_SETTLEMENT_TIMEOUT_MS, ...options })
|
|
942
|
+
})
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
export { DalpApiError, isDalpApiError, findDalpSdkError, makeDalpApiError, createDalpContextHeaders, createTransport, DEFAULT_SETTLEMENT_TIMEOUT_MS, SettlementTimeoutError, SettlementFailedError, RESERVED_STREAM_FAILURE_EVENT, STREAM_FAILED_ERROR_CODE, decodeEventStream, streamRequest, sendRequest, createFetchExecutor, canonicalize, queryKeyFor, UI_SETTLEMENT_TIMEOUT_MS, createTanstackFactories };
|