@settlemint/dalp-sdk 3.1.17 → 3.1.18-main.33796706856

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.
Files changed (104) hide show
  1. package/README.md +154 -169
  2. package/dist/auth/client.d.ts +113 -0
  3. package/dist/auth/live.d.ts +4366 -0
  4. package/dist/{auth-permissions.d.ts → auth/permissions.d.ts} +1 -2
  5. package/dist/{auth-wallet-plugins.d.ts → auth/wallet-plugins.d.ts} +69 -5
  6. package/dist/auth.d.ts +22 -115
  7. package/dist/auth.js +329 -0
  8. package/dist/bundler.d.ts +14 -207
  9. package/dist/bundler.js +99 -0
  10. package/dist/chunk-18qmk0m7.js +4 -0
  11. package/dist/chunk-1c6n8fap.js +260 -0
  12. package/dist/chunk-def7rqy6.js +946 -0
  13. package/dist/chunk-f4t1bm86.js +67 -0
  14. package/dist/chunk-fjnq61hj.js +11 -0
  15. package/dist/chunk-h12fatty.js +63 -0
  16. package/dist/chunk-r0vsftj4.js +102 -0
  17. package/dist/chunk-x0z79vz6.js +33 -0
  18. package/dist/chunk-y0d2c7kp.js +54 -0
  19. package/dist/client/conditional-request.d.ts +30 -0
  20. package/dist/client/factory.d.ts +14 -0
  21. package/dist/client/query-serializer.d.ts +2 -0
  22. package/dist/client/request-compression.d.ts +47 -0
  23. package/dist/client/ssr-fetch.d.ts +12 -0
  24. package/dist/effect.d.ts +69 -0
  25. package/dist/effect.js +82 -0
  26. package/dist/errors/api-error.d.ts +29 -0
  27. package/dist/errors/find-current-error.d.ts +8 -0
  28. package/dist/errors/sdk-error.d.ts +52 -0
  29. package/dist/errors/sdk-error.js +8 -0
  30. package/dist/generated/api-types.d.ts +41271 -0
  31. package/dist/generated/response-scalars.d.ts +9 -0
  32. package/dist/generated/routes.d.ts +12 -0
  33. package/dist/index.d.ts +28 -40
  34. package/dist/index.js +131 -96109
  35. package/dist/proxy/builder.d.ts +47 -0
  36. package/dist/proxy/client.d.ts +32 -0
  37. package/dist/proxy/fetch-executor.d.ts +28 -0
  38. package/dist/proxy/flat-args.d.ts +51 -0
  39. package/dist/proxy/settlement.d.ts +67 -0
  40. package/dist/proxy/sse.d.ts +54 -0
  41. package/dist/proxy/tanstack.d.ts +27 -0
  42. package/dist/proxy/transport.d.ts +73 -0
  43. package/dist/react-query.d.ts +16 -0
  44. package/dist/react-query.js +13 -0
  45. package/dist/readonly-deep.d.ts +12 -0
  46. package/dist/reads-as-funding-paused.d.ts +20 -0
  47. package/dist/routes/index.d.ts +20 -0
  48. package/dist/routes/index.js +10 -0
  49. package/dist/routes/types.d.ts +51 -0
  50. package/dist/runtime-exports.d.ts +20 -0
  51. package/dist/runtime-exports.js +16 -0
  52. package/dist/scalars/big-decimal.d.ts +16 -0
  53. package/dist/scalars/ethereum-address.d.ts +20 -0
  54. package/dist/scalars/exchange-rates.d.ts +27 -0
  55. package/dist/scalars/index.d.ts +18 -0
  56. package/dist/scalars/index.js +86 -0
  57. package/dist/scalars/organization-id.d.ts +20 -0
  58. package/dist/secret.d.ts +14 -0
  59. package/dist/sign-webhook-receipt.d.ts +76 -0
  60. package/dist/sign-webhook-receipt.js +26 -0
  61. package/dist/transport/cookie-store.d.ts +9 -0
  62. package/dist/transport/sse-lifecycle.d.ts +44 -0
  63. package/dist/types.d.ts +65 -102
  64. package/dist/url.d.ts +0 -1
  65. package/dist/verify-webhook.d.ts +17 -28
  66. package/dist/verify-webhook.js +8 -0
  67. package/dist/version.d.ts +0 -1
  68. package/dist/wait-for-transaction.d.ts +54 -81
  69. package/dist/wait-for-transaction.js +120 -0
  70. package/dist/webhook-events.d.ts +44 -27
  71. package/package.json +103 -30
  72. package/dist/auth-permissions.d.ts.map +0 -1
  73. package/dist/auth-wallet-plugins.d.ts.map +0 -1
  74. package/dist/auth.d.ts.map +0 -1
  75. package/dist/bundler.d.ts.map +0 -1
  76. package/dist/chunk-xm8h1dzh.js +0 -33
  77. package/dist/client.d.ts +0 -19
  78. package/dist/client.d.ts.map +0 -1
  79. package/dist/contract-errors.d.ts +0 -4156
  80. package/dist/contract-errors.d.ts.map +0 -1
  81. package/dist/contract.d.ts +0 -17
  82. package/dist/contract.d.ts.map +0 -1
  83. package/dist/cookie-store.d.ts +0 -10
  84. package/dist/cookie-store.d.ts.map +0 -1
  85. package/dist/dapi-errors.d.ts +0 -650
  86. package/dist/dapi-errors.d.ts.map +0 -1
  87. package/dist/errors.d.ts +0 -633
  88. package/dist/errors.d.ts.map +0 -1
  89. package/dist/index.d.ts.map +0 -1
  90. package/dist/platform.d.ts +0 -41
  91. package/dist/platform.d.ts.map +0 -1
  92. package/dist/plugins/index.d.ts +0 -13
  93. package/dist/plugins/index.d.ts.map +0 -1
  94. package/dist/plugins/index.js +0 -10
  95. package/dist/sdk-error.d.ts +0 -74
  96. package/dist/sdk-error.d.ts.map +0 -1
  97. package/dist/serializers.d.ts +0 -41
  98. package/dist/serializers.d.ts.map +0 -1
  99. package/dist/types.d.ts.map +0 -1
  100. package/dist/url.d.ts.map +0 -1
  101. package/dist/verify-webhook.d.ts.map +0 -1
  102. package/dist/version.d.ts.map +0 -1
  103. package/dist/wait-for-transaction.d.ts.map +0 -1
  104. package/dist/webhook-events.d.ts.map +0 -1
@@ -0,0 +1,67 @@
1
+ // src/proxy/builder.ts
2
+ function buildIndex(table) {
3
+ const root = { children: new Map };
4
+ for (const id of Object.keys(table.routes)) {
5
+ let cursor = root;
6
+ for (const segment of id.split("/")) {
7
+ let next = cursor.children.get(segment);
8
+ if (next === undefined) {
9
+ next = { children: new Map };
10
+ cursor.children.set(segment, next);
11
+ }
12
+ cursor = next;
13
+ }
14
+ cursor.routeId = id;
15
+ }
16
+ return root;
17
+ }
18
+ function makeNode(node, table, executor, factories, cache) {
19
+ const cached = cache.get(node);
20
+ if (cached !== undefined) {
21
+ return cached;
22
+ }
23
+ const route = node.routeId === undefined ? undefined : table.routes[node.routeId];
24
+ const id = node.routeId;
25
+ const target = route === undefined || id === undefined ? {} : Object.assign((input, options) => executor(route, id, input, options), {
26
+ queryOptions: (input, options) => factories.queryOptions(route, id, input, options),
27
+ mutationOptions: (options) => factories.mutationOptions(route, id, options)
28
+ });
29
+ const proxy = new Proxy(target, {
30
+ get(base, property, receiver) {
31
+ if (typeof property !== "string") {
32
+ return Reflect.get(base, property, receiver);
33
+ }
34
+ if (Object.hasOwn(base, property) || property in Function.prototype) {
35
+ return Reflect.get(base, property, receiver);
36
+ }
37
+ const child = node.children.get(property);
38
+ return child === undefined ? undefined : makeNode(child, table, executor, factories, cache);
39
+ },
40
+ has(base, property) {
41
+ return typeof property === "string" && node.children.has(property) || Reflect.has(base, property);
42
+ },
43
+ ownKeys(base) {
44
+ return [...new Set([...Reflect.ownKeys(base), ...node.children.keys()])];
45
+ },
46
+ getOwnPropertyDescriptor(base, property) {
47
+ if (typeof property === "string" && node.children.has(property)) {
48
+ return {
49
+ configurable: true,
50
+ enumerable: true,
51
+ value: makeNode(node.children.get(property), table, executor, factories, cache)
52
+ };
53
+ }
54
+ return Reflect.getOwnPropertyDescriptor(base, property);
55
+ }
56
+ });
57
+ cache.set(node, proxy);
58
+ return proxy;
59
+ }
60
+ function buildProxy(table, executor, factories) {
61
+ return makeNode(buildIndex(table), table, executor, factories, new Map);
62
+ }
63
+ function findRoute(table, id) {
64
+ return table.routes[id];
65
+ }
66
+
67
+ export { buildProxy, findRoute };
@@ -0,0 +1,11 @@
1
+ // src/reads-as-funding-paused.ts
2
+ function readsAsFundingPaused(status) {
3
+ if (status === null || typeof status !== "object") {
4
+ return false;
5
+ }
6
+ const requirement = Reflect.get(status, "activeRequirement");
7
+ return requirement !== undefined && requirement !== null;
8
+ }
9
+ var PAUSED_POLL_INTERVAL_MAX_MS = 30000;
10
+
11
+ export { readsAsFundingPaused, PAUSED_POLL_INTERVAL_MAX_MS };
@@ -0,0 +1,63 @@
1
+ import {
2
+ createDalpSdkConfigurationError
3
+ } from "./chunk-y0d2c7kp.js";
4
+
5
+ // src/secret.ts
6
+ var SECRET_REDACTION_MARKER = "[REDACTED]";
7
+ var inspectSymbol = Symbol.for("nodejs.util.inspect.custom");
8
+ var secretValue = new WeakMap;
9
+
10
+ class Secret {
11
+ constructor(value) {
12
+ secretValue.set(this, value);
13
+ Object.freeze(this);
14
+ }
15
+ static from(value) {
16
+ if (value.trim().length === 0) {
17
+ throw new TypeError("DALP SDK: a secret value must not be empty.");
18
+ }
19
+ return new Secret(value);
20
+ }
21
+ toString() {
22
+ return SECRET_REDACTION_MARKER;
23
+ }
24
+ toJSON() {
25
+ return SECRET_REDACTION_MARKER;
26
+ }
27
+ [inspectSymbol]() {
28
+ return SECRET_REDACTION_MARKER;
29
+ }
30
+ }
31
+ var secret = (value) => Secret.from(value);
32
+ var unwrapSecret = (value) => {
33
+ const raw = secretValue.get(value);
34
+ if (raw === undefined) {
35
+ throw new TypeError("DALP SDK: cannot unwrap an invalid secret value.");
36
+ }
37
+ return raw;
38
+ };
39
+
40
+ // src/url.ts
41
+ function normalizeDalpBaseUrl(url) {
42
+ let parsed;
43
+ try {
44
+ parsed = new URL(url);
45
+ } catch (error) {
46
+ throw createDalpSdkConfigurationError({
47
+ message: `DALP SDK: invalid url "${url}". Provide a full URL including the protocol (e.g., "https://dalp.example.com").`,
48
+ why: "The SDK could not parse the configured DALP API URL.",
49
+ fix: 'Provide a full http:// or https:// URL, for example "https://dalp.example.com".',
50
+ cause: error
51
+ });
52
+ }
53
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
54
+ throw createDalpSdkConfigurationError({
55
+ message: `DALP SDK: url must use https:// or http:// protocol, got "${parsed.protocol}".`,
56
+ why: `The SDK received a URL with the unsupported "${parsed.protocol}" protocol.`,
57
+ fix: 'Use a DALP API base URL that starts with "https://" or "http://".'
58
+ });
59
+ }
60
+ return `${parsed.origin}${parsed.pathname.replace(/\/+$/, "")}`;
61
+ }
62
+
63
+ export { SECRET_REDACTION_MARKER, Secret, secret, unwrapSecret, normalizeDalpBaseUrl };
@@ -0,0 +1,102 @@
1
+ // src/verify-webhook.ts
2
+ import { Webhook as StandardWebhook } from "standardwebhooks";
3
+ var DEFAULT_TIMESTAMP_TOLERANCE_SECONDS = 5 * 60;
4
+ function toStandardWebhookSecret(secret) {
5
+ return secret.replace(/^dalp_whsk_/u, "");
6
+ }
7
+ async function verifyWebhook(input) {
8
+ const headers = normalizeHeaders(input.headers);
9
+ const nowMillis = input.now instanceof Date ? input.now.getTime() : input.now ?? Date.now();
10
+ const tolerance = input.timestampToleranceSeconds ?? DEFAULT_TIMESTAMP_TOLERANCE_SECONDS;
11
+ if (!hasFiniteTimestamp(headers) || isOutsideTimestampTolerance(headers, nowMillis, tolerance)) {
12
+ return { ok: false, code: "TIMESTAMP_SKEW" };
13
+ }
14
+ const rawText = typeof input.rawBody === "string" ? input.rawBody : new TextDecoder().decode(input.rawBody);
15
+ const eventId = headers["webhook-id"];
16
+ if (eventId !== undefined && await input.replayStore?.has(eventId) === true) {
17
+ return { ok: false, code: "REPLAYED_EVENT" };
18
+ }
19
+ let sawMalformedBody = false;
20
+ let sawReplayStoreFailure = false;
21
+ for (const candidate of Array.isArray(input.secret) ? input.secret : [input.secret]) {
22
+ if (!matchesSignature(candidate, rawText, headers)) {
23
+ continue;
24
+ }
25
+ let event;
26
+ try {
27
+ event = JSON.parse(rawText);
28
+ } catch {
29
+ sawMalformedBody = true;
30
+ continue;
31
+ }
32
+ if (eventId !== undefined && input.replayStore !== undefined) {
33
+ try {
34
+ await input.replayStore.add(eventId);
35
+ } catch {
36
+ sawReplayStoreFailure = true;
37
+ continue;
38
+ }
39
+ }
40
+ return { ok: true, event };
41
+ }
42
+ if (sawReplayStoreFailure) {
43
+ return { ok: false, code: "REPLAY_STORE_FAILURE" };
44
+ }
45
+ if (sawMalformedBody) {
46
+ return { ok: false, code: "MALFORMED_BODY" };
47
+ }
48
+ return { ok: false, code: classifySignatureFailure(rawText, headers) };
49
+ }
50
+ function matchesSignature(secret, rawBody, headers) {
51
+ const eventId = headers["webhook-id"];
52
+ const timestamp = Number(headers["webhook-timestamp"]);
53
+ const signatures = headers["webhook-signature"];
54
+ if (eventId === undefined || !Number.isFinite(timestamp) || signatures === undefined) {
55
+ return false;
56
+ }
57
+ const expected = new StandardWebhook(toStandardWebhookSecret(secret)).sign(eventId, new Date(timestamp * 1000), rawBody);
58
+ return signatures.split(" ").some((signature) => {
59
+ const left = new TextEncoder().encode(signature);
60
+ const right = new TextEncoder().encode(expected);
61
+ if (left.byteLength !== right.byteLength) {
62
+ return false;
63
+ }
64
+ let difference = 0;
65
+ for (let index = 0;index < left.byteLength; index += 1) {
66
+ difference |= (left[index] ?? 0) ^ (right[index] ?? 0);
67
+ }
68
+ return difference === 0;
69
+ });
70
+ }
71
+ function normalizeHeaders(input) {
72
+ if (input instanceof Headers) {
73
+ return Object.fromEntries(input.entries());
74
+ }
75
+ const headers = {};
76
+ for (const [key, value] of Object.entries(input)) {
77
+ if (value !== undefined) {
78
+ headers[key.toLowerCase()] = typeof value === "string" ? value : value.join(",");
79
+ }
80
+ }
81
+ return headers;
82
+ }
83
+ function hasFiniteTimestamp(headers) {
84
+ return Number.isFinite(Number(headers["webhook-timestamp"]));
85
+ }
86
+ function isOutsideTimestampTolerance(headers, nowMillis, toleranceSeconds) {
87
+ const timestamp = Number(headers["webhook-timestamp"]);
88
+ return Number.isFinite(timestamp) && Math.abs(nowMillis / 1000 - timestamp) > toleranceSeconds;
89
+ }
90
+ function classifySignatureFailure(rawBody, headers) {
91
+ try {
92
+ const parsed = JSON.parse(rawBody);
93
+ if (typeof parsed.evt_id !== "string" || parsed.evt_id !== headers["webhook-id"]) {
94
+ return "BODY_HASH_MISMATCH";
95
+ }
96
+ } catch {
97
+ return "BODY_HASH_MISMATCH";
98
+ }
99
+ return "SECRET_MISMATCH";
100
+ }
101
+
102
+ export { toStandardWebhookSecret, verifyWebhook };
@@ -0,0 +1,33 @@
1
+ import {
2
+ buildProxy,
3
+ findRoute
4
+ } from "./chunk-f4t1bm86.js";
5
+ import {
6
+ createFetchExecutor,
7
+ createTanstackFactories,
8
+ createTransport,
9
+ sendRequest,
10
+ streamRequest
11
+ } from "./chunk-def7rqy6.js";
12
+ import {
13
+ data
14
+ } from "./chunk-18qmk0m7.js";
15
+
16
+ // src/proxy/client.ts
17
+ function createDalpClient(options) {
18
+ const transport = createTransport(options);
19
+ const api = buildProxy(data, createFetchExecutor(transport), createTanstackFactories(transport));
20
+ return {
21
+ api,
22
+ conditionalRequests: transport.conditionalRequests,
23
+ execute: async (routeId, input, callOptions) => {
24
+ const route = findRoute(data, routeId);
25
+ if (route === undefined) {
26
+ throw new TypeError(`Unknown DALP route \`${routeId}\``);
27
+ }
28
+ const result = route.serializer === "sse" ? streamRequest(transport, route, input, callOptions) : await sendRequest(transport, route, input, callOptions);
29
+ return result;
30
+ }
31
+ };
32
+ }
33
+ export { createDalpClient };
@@ -0,0 +1,54 @@
1
+ // src/errors/sdk-error.ts
2
+ var DALP_SDK_ERROR_CODE = "DALP_SDK_ERROR";
3
+ var DALP_SDK_ERROR_CATEGORY = "sdk.configuration";
4
+
5
+ class DalpSdkError extends Error {
6
+ code;
7
+ category;
8
+ status;
9
+ retryable;
10
+ why;
11
+ fix;
12
+ details;
13
+ retryAfterSeconds;
14
+ constructor(options) {
15
+ super(options.message, { cause: options.cause });
16
+ this.name = "DalpSdkError";
17
+ this.code = options.code ?? DALP_SDK_ERROR_CODE;
18
+ this.category = options.category;
19
+ this.status = options.status;
20
+ this.retryable = options.retryable;
21
+ this.why = options.why;
22
+ this.fix = options.fix;
23
+ this.details = options.details;
24
+ this.retryAfterSeconds = options.retryAfterSeconds;
25
+ }
26
+ toJSON() {
27
+ return {
28
+ name: "DalpSdkError",
29
+ code: this.code,
30
+ category: this.category,
31
+ retryable: this.retryable,
32
+ message: this.message,
33
+ why: this.why,
34
+ fix: this.fix,
35
+ ...this.status === undefined ? {} : { status: this.status },
36
+ ...this.details === undefined ? {} : { details: this.details },
37
+ ...this.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: this.retryAfterSeconds }
38
+ };
39
+ }
40
+ }
41
+ function createDalpSdkConfigurationError(input) {
42
+ return new DalpSdkError({
43
+ code: DALP_SDK_ERROR_CODE,
44
+ category: DALP_SDK_ERROR_CATEGORY,
45
+ status: 400,
46
+ retryable: false,
47
+ message: input.message,
48
+ why: input.why,
49
+ fix: input.fix,
50
+ cause: input.cause
51
+ });
52
+ }
53
+
54
+ export { DalpSdkError, createDalpSdkConfigurationError };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Conditional GET, as a fetch decorator.
3
+ *
4
+ * The policy is unchanged from the interceptor pair this replaces: hold the
5
+ * ETag and body of a successful GET, send `If-None-Match` on the next one, and
6
+ * serve the held body on a 304. Only the attachment point moved, from a
7
+ * generated client's interceptor list to the fetch the transport already wraps
8
+ * for compression and SSR.
9
+ */
10
+ import type { DalpFetch } from "./ssr-fetch.ts";
11
+ /** Handle a caller holds so it can clear the store on sign-out or org switch. */
12
+ export interface ConditionalRequestStore {
13
+ readonly clear: () => void;
14
+ }
15
+ /**
16
+ * Wrap `fetch` with the If-None-Match / 304 rewrite pair for conditional GET.
17
+ *
18
+ * Server ETags must be strong content digests computed after authorization
19
+ * inside the requester's partition. The dapi response cache guarantees this:
20
+ * `encodeResponseCacheEntry` sets `etag` to the SHA-256 of the serialized
21
+ * body after the request-context middleware has authenticated the session.
22
+ * Version-stamp ETags (generation counters, watermarks, table versions) are
23
+ * forbidden for conditional-request adopters: a stamp can collide across
24
+ * tenants or lag a body change and would let this store serve another
25
+ * partition's bytes as a 200.
26
+ */
27
+ export declare function withConditionalRequests(base: DalpFetch): {
28
+ fetch: DalpFetch;
29
+ store: ConditionalRequestStore;
30
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The client factory.
3
+ *
4
+ * The transport policy this used to assemble around the generated client now
5
+ * lives in `../proxy/transport.ts`, which both interpreters share. This module
6
+ * stays as the published entry point's seam so a consumer's import path did not
7
+ * move with the internals.
8
+ *
9
+ * @module
10
+ */
11
+ export { createDalpClient, type DalpClient } from "../proxy/client.ts";
12
+ export { createDalpContextHeaders } from "../proxy/transport.ts";
13
+ export type { CreateDalpClientOptions, DalpClientContext, DalpSsrOptions, Transport } from "../proxy/transport.ts";
14
+ export type { DalpFetch } from "./ssr-fetch.ts";
@@ -0,0 +1,2 @@
1
+ /** Serialize generated SDK query objects with recursive OpenAPI deepObject keys. */
2
+ export declare function serializeDalpQuery(query: unknown): string;
@@ -0,0 +1,47 @@
1
+ import type { DalpFetch } from "./ssr-fetch.ts";
2
+ /**
3
+ * Request-body compression for DALP server/CLI clients.
4
+ *
5
+ * Bun 1.4 added a `compress` fetch option: it compresses a buffered body
6
+ * before sending and sets `Content-Encoding` on the wire. This wrapper opts
7
+ * eligible outgoing bodies into gzip so big JSON payloads shrink in transit;
8
+ * the receiving DAPI host decodes them at its boundary
9
+ * (`@dapi/server/request-body-decoding`), so callers need no per-route work.
10
+ *
11
+ * Eligibility mirrors what the transport can actually do:
12
+ *
13
+ * - Only body-bearing methods (`GET`/`HEAD` never).
14
+ * - Bodies already carrying `Content-Encoding`, or an explicit caller
15
+ * `compress`, pass through untouched.
16
+ * - With `(url, init)` the body must be one of Bun's buffered types
17
+ * (string, ArrayBuffer, TypedArray/DataView, Blob) and fall inside the
18
+ * size window — gzip framing dominates tiny payloads, and huge explicitly
19
+ * sized bodies stay uncompressed (the DAPI decode cap mirrors this bound).
20
+ * - Streams, `FormData`, and `URLSearchParams` pass through: the transport
21
+ * forwards streaming bodies unchanged.
22
+ * - A `Request` instance is measured through a bounded clone before compression.
23
+ */
24
+ /** Bodies smaller than this stay uncompressed; gzip framing dominates tiny JSON. */
25
+ export declare const DALP_SDK_REQUEST_COMPRESSION_MIN_BODY_BYTES = 1024;
26
+ /** Explicitly-sized bodies larger than this are sent uncompressed. */
27
+ export declare const DALP_SDK_REQUEST_COMPRESSION_MAX_BODY_BYTES = 16777216;
28
+ /**
29
+ * Bun's `compress` fetch option. bun-types 1.4.0 still types `RequestInit`
30
+ * from lib.dom without it, so the field is declared here and set through one
31
+ * narrow cast at the transport seam.
32
+ */
33
+ export type FetchRequestCompression = true | "gzip" | "deflate" | "br" | "zstd";
34
+ export interface CompressionRequestInit extends RequestInit {
35
+ readonly compress?: FetchRequestCompression;
36
+ }
37
+ export interface RequestBodyCompressionOptions {
38
+ /** Test seam overriding DALP_SDK_REQUEST_COMPRESSION_MIN_BODY_BYTES. */
39
+ readonly minBodyBytes?: number;
40
+ /** Test seam overriding DALP_SDK_REQUEST_COMPRESSION_MAX_BODY_BYTES. */
41
+ readonly maxBodyBytes?: number;
42
+ }
43
+ /**
44
+ * Wrap a fetch seam so eligible request bodies travel gzip-compressed.
45
+ * Ineligible calls forward the original arguments untouched.
46
+ */
47
+ export declare function withRequestBodyCompression(fetchImpl: DalpFetch, options?: RequestBodyCompressionOptions): DalpFetch;
@@ -0,0 +1,12 @@
1
+ /** Minimal fetch shape — Bun's `typeof fetch` also requires `preconnect`. */
2
+ export type DalpFetch = ((input: RequestInfo | URL, init?: RequestInit) => Promise<Response>) & {
3
+ readonly preconnect?: typeof fetch.preconnect;
4
+ };
5
+ export interface CreateSsrFetchOptions {
6
+ readonly allowedOrigins?: ReadonlyArray<string | URL>;
7
+ readonly baseUrl: string | URL;
8
+ readonly fetch: DalpFetch;
9
+ readonly requestHeaders: HeadersInit;
10
+ }
11
+ /** Direct destinations must be approved; unapproved redirects lose all caller credentials and context. */
12
+ export declare function createSsrFetch(options: CreateSsrFetchOptions): DalpFetch;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The Effect call surface.
3
+ *
4
+ * The same namespaced tree as the root entry, returning `Effect` values instead
5
+ * of promises. It exists because the CLI and other code under our control want
6
+ * Effect, and hiding it behind promises there would mean unwrapping and
7
+ * rewrapping at every boundary.
8
+ *
9
+ * This entry is deliberately absent from `PUBLISHED_ENTRIES` in
10
+ * `scripts/check-zero-effect.ts`. That gate walks the import graph from every
11
+ * listed entry and fails on any reachable `effect` module, and Bun's transpiler
12
+ * reports a type-only import exactly like a value one. Keeping this entry off
13
+ * the list is what lets the root stay provably Effect-free while this one uses
14
+ * Effect freely.
15
+ *
16
+ * Errors are tagged from the wire envelope rather than decoded from per-route
17
+ * schemas. The envelope is identical across every route (`code`, `status`,
18
+ * `message`, and a `data` carrying the stable DALP id), so one reader covers
19
+ * 759 routes, and no runtime schema ships.
20
+ *
21
+ * @module
22
+ */
23
+ import * as Effect from "effect/Effect";
24
+ import type { DalpApi, DalpRouteId, DalpRouteTypes } from "./generated/api-types.d.ts";
25
+ import { type CallOptions } from "./proxy/builder.ts";
26
+ import { type CreateDalpClientOptions } from "./proxy/transport.ts";
27
+ /** The failure channel every route call carries. */
28
+ export declare class DalpRequestError extends Error {
29
+ readonly _tag = "DalpRequestError";
30
+ /** Stable DALP error id when the platform supplied one, else the SDK code. */
31
+ readonly id: string;
32
+ readonly status: number | undefined;
33
+ readonly retryable: boolean;
34
+ readonly routeId: string;
35
+ constructor(routeId: string, cause: unknown);
36
+ }
37
+ /** The Effect-shaped mirror of `DalpApi`. */
38
+ export type DalpEffectApi = DalpEffectApiNode<DalpApi>;
39
+ /**
40
+ * A stream leaf answers with its frame sequence rather than one body, so it is
41
+ * matched before the promise leaf: its call signature returns an `AsyncIterable`
42
+ * and would otherwise fall through to the recursive branch, which maps a call
43
+ * signature to an object with no keys and leaves the route uncallable.
44
+ */
45
+ type DalpEffectApiNode<T> = {
46
+ readonly [K in keyof T]: T[K] extends (...args: infer Args) => AsyncIterable<infer Frame> ? (...args: Args) => Effect.Effect<AsyncIterable<Frame>, DalpRequestError> : T[K] extends (...args: infer Args) => Promise<infer A> ? (...args: Args) => Effect.Effect<A, DalpRequestError> : DalpEffectApiNode<T[K]>;
47
+ };
48
+ /** The routes that answer with `text/event-stream`, named by the route table. */
49
+ export type DalpStreamingRouteId = {
50
+ [Id in DalpRouteId]: DalpRouteTypes[Id]["streaming"] extends true ? Id : never;
51
+ }[DalpRouteId];
52
+ export interface DalpEffectClient {
53
+ readonly api: DalpEffectApi;
54
+ /**
55
+ * Two signatures rather than one conditional return type. A caller generic over
56
+ * the streaming routes has to resolve the frame sequence from its own
57
+ * constraint, and a conditional keyed on `Id` stays unresolved until `Id` is a
58
+ * single route, which is what pushed every such caller into an assertion.
59
+ */
60
+ readonly execute: {
61
+ <Id extends DalpStreamingRouteId>(routeId: Id, input?: DalpRouteTypes[Id]["request"], options?: CallOptions): Effect.Effect<AsyncIterable<DalpRouteTypes[Id]["response"]>, DalpRequestError>;
62
+ <Id extends DalpRouteId>(routeId: Id, input?: DalpRouteTypes[Id]["request"], options?: CallOptions): Effect.Effect<DalpRouteTypes[Id]["response"], DalpRequestError>;
63
+ };
64
+ }
65
+ /** Create the Effect client. Same routes, same transport, different channel. */
66
+ export declare function createDalpEffectClient(options: CreateDalpClientOptions): DalpEffectClient;
67
+ export type { CallOptions } from "./proxy/builder.ts";
68
+ export type { CreateDalpClientOptions } from "./proxy/transport.ts";
69
+ export type { DalpRouteId, DalpRouteTypes } from "./generated/api-types.d.ts";
package/dist/effect.js ADDED
@@ -0,0 +1,82 @@
1
+ import {
2
+ buildProxy,
3
+ findRoute
4
+ } from "./chunk-f4t1bm86.js";
5
+ import {
6
+ DalpApiError,
7
+ createTransport,
8
+ queryKeyFor,
9
+ sendRequest,
10
+ streamRequest
11
+ } from "./chunk-def7rqy6.js";
12
+ import"./chunk-fjnq61hj.js";
13
+ import {
14
+ data
15
+ } from "./chunk-18qmk0m7.js";
16
+ import"./chunk-h12fatty.js";
17
+ import"./chunk-y0d2c7kp.js";
18
+
19
+ // src/effect.ts
20
+ import * as Effect from "effect/Effect";
21
+ class DalpRequestError extends Error {
22
+ _tag = "DalpRequestError";
23
+ id;
24
+ status;
25
+ retryable;
26
+ routeId;
27
+ constructor(routeId, cause) {
28
+ const api = cause instanceof DalpApiError ? cause : undefined;
29
+ super(api?.message ?? `DALP request failed for ${routeId}`, { cause });
30
+ this.name = "DalpRequestError";
31
+ this._tag = "DalpRequestError";
32
+ this.routeId = routeId;
33
+ this.id = api?.code ?? "sdk.transport.REQUEST_FAILED";
34
+ this.status = api?.status;
35
+ this.retryable = api?.retryable ?? true;
36
+ }
37
+ }
38
+ function runRoute(transport, route, id, input, options) {
39
+ return Effect.callback((resume) => {
40
+ const controller = new AbortController;
41
+ const signal = options?.signal ?? controller.signal;
42
+ const run = async () => {
43
+ try {
44
+ resume(Effect.succeed(route.serializer === "sse" ? streamRequest(transport, route, input, { ...options, signal }) : await sendRequest(transport, route, input, { ...options, signal })));
45
+ } catch (error) {
46
+ resume(Effect.fail(new DalpRequestError(id, error)));
47
+ }
48
+ };
49
+ run();
50
+ return Effect.sync(() => {
51
+ controller.abort();
52
+ });
53
+ });
54
+ }
55
+ function createDalpEffectClient(options) {
56
+ const transport = createTransport(options);
57
+ const executor = (route, id, input, callOptions) => runRoute(transport, route, id, input, callOptions);
58
+ const factories = {
59
+ queryOptions: (route, id, input, callOptions) => ({
60
+ queryKey: queryKeyFor(id, input),
61
+ queryFn: () => runRoute(transport, route, id, input, callOptions)
62
+ }),
63
+ mutationOptions: (route, id, callOptions) => ({
64
+ mutationKey: ["dalp", id],
65
+ mutationFn: (input) => runRoute(transport, route, id, input, callOptions)
66
+ })
67
+ };
68
+ return {
69
+ api: buildProxy(data, executor, factories),
70
+ execute: (routeId, input, callOptions) => {
71
+ const route = findRoute(data, routeId);
72
+ if (route === undefined) {
73
+ return Effect.fail(new DalpRequestError(routeId, new TypeError(`Unknown DALP route \`${routeId}\``)));
74
+ }
75
+ return runRoute(transport, route, routeId, input, callOptions);
76
+ }
77
+ };
78
+ }
79
+ export {
80
+ DalpRequestError,
81
+ createDalpEffectClient
82
+ };
@@ -0,0 +1,29 @@
1
+ import { findCurrentError } from "./find-current-error.ts";
2
+ export type DalpApiErrorCategory = "client" | "auth" | "permission" | "domain" | "contract" | "dependency" | "operational" | "config" | "unknown";
3
+ export interface DalpApiErrorOptions {
4
+ readonly message: string;
5
+ readonly cause?: unknown;
6
+ readonly id?: string;
7
+ readonly code: string;
8
+ readonly category: DalpApiErrorCategory;
9
+ readonly status?: number;
10
+ readonly retryable: boolean;
11
+ readonly why: string;
12
+ readonly fix: string;
13
+ readonly retryAfterSeconds?: number;
14
+ }
15
+ export declare class DalpApiError extends Error {
16
+ readonly id?: string;
17
+ readonly code: string;
18
+ readonly category: DalpApiErrorCategory;
19
+ readonly status?: number;
20
+ readonly retryable: boolean;
21
+ readonly why: string;
22
+ readonly fix: string;
23
+ readonly retryAfterSeconds?: number;
24
+ constructor(options: DalpApiErrorOptions);
25
+ static make(options: DalpApiErrorOptions): DalpApiError;
26
+ }
27
+ export declare const isDalpApiError: (error: unknown) => error is DalpApiError;
28
+ export declare const findDalpSdkError: typeof findCurrentError;
29
+ export declare const makeDalpApiError: (error: unknown) => DalpApiError;
@@ -0,0 +1,8 @@
1
+ import { DalpSdkError } from "./sdk-error.ts";
2
+ /**
3
+ * Walk a nested SDK error graph and return the first DalpSdkError.
4
+ *
5
+ * Follows `cause` and `reasons[].error` / `reasons[].defect`. Stops after
6
+ * `maxNodes` so a cyclic wrapper cannot loop forever.
7
+ */
8
+ export declare const findCurrentError: (error: unknown, maxNodes?: number) => DalpSdkError | undefined;