@lifi/composer-sdk 0.10.0 → 0.11.3

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 (58) hide show
  1. package/README.md +36 -2
  2. package/dist/authoring/raw.cjs +12 -7
  3. package/dist/authoring/raw.cjs.map +1 -1
  4. package/dist/authoring/raw.d.cts +12 -7
  5. package/dist/authoring/raw.d.ts +12 -7
  6. package/dist/authoring/raw.js +12 -7
  7. package/dist/authoring/raw.js.map +1 -1
  8. package/dist/client.cjs +11 -1
  9. package/dist/client.cjs.map +1 -1
  10. package/dist/client.js +11 -1
  11. package/dist/client.js.map +1 -1
  12. package/dist/errors.cjs +35 -13
  13. package/dist/errors.cjs.map +1 -1
  14. package/dist/errors.d.cts +19 -1
  15. package/dist/errors.d.ts +19 -1
  16. package/dist/errors.js +35 -14
  17. package/dist/errors.js.map +1 -1
  18. package/dist/generated/config.generated.d.cts +96 -1
  19. package/dist/generated/config.generated.d.ts +96 -1
  20. package/dist/generated/operations.generated.cjs +10 -0
  21. package/dist/generated/operations.generated.cjs.map +1 -1
  22. package/dist/generated/operations.generated.d.cts +56 -1
  23. package/dist/generated/operations.generated.d.ts +56 -1
  24. package/dist/generated/operations.generated.js +10 -0
  25. package/dist/generated/operations.generated.js.map +1 -1
  26. package/dist/index.cjs +1 -0
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +4 -4
  29. package/dist/index.d.ts +4 -4
  30. package/dist/index.js +2 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/outputs.cjs +3 -2
  33. package/dist/outputs.cjs.map +1 -1
  34. package/dist/outputs.d.cts +3 -2
  35. package/dist/outputs.d.ts +3 -2
  36. package/dist/outputs.js +3 -2
  37. package/dist/outputs.js.map +1 -1
  38. package/dist/responseSchemas.cjs.map +1 -1
  39. package/dist/responseSchemas.d.cts +2 -2
  40. package/dist/responseSchemas.d.ts +2 -2
  41. package/dist/responseSchemas.js.map +1 -1
  42. package/dist/run/inputs.cjs.map +1 -1
  43. package/dist/run/inputs.d.cts +3 -3
  44. package/dist/run/inputs.d.ts +3 -3
  45. package/dist/run/inputs.js.map +1 -1
  46. package/package.json +2 -2
  47. package/src/authoring/raw.ts +12 -7
  48. package/src/client.ts +24 -1
  49. package/src/errors.ts +48 -17
  50. package/src/examples/continuationBridgeSettle.ts +100 -0
  51. package/src/examples/continuationSettle.ts +113 -0
  52. package/src/examples/run.ts +8 -0
  53. package/src/generated/config.generated.ts +109 -1
  54. package/src/generated/operations.generated.ts +98 -0
  55. package/src/index.ts +5 -1
  56. package/src/outputs.ts +3 -2
  57. package/src/responseSchemas.ts +9 -5
  58. package/src/run/inputs.ts +3 -3
package/dist/errors.cjs CHANGED
@@ -55,6 +55,12 @@ var ComposeError = class extends Error {
55
55
  */
56
56
  details;
57
57
  /**
58
+ * The delivery tranche's reason, first quote, and abandoned escrow,
59
+ * attached to `delivery_error` errors. Narrow with
60
+ * {@link isComposeDeliveryError}.
61
+ */
62
+ delivery;
63
+ /**
58
64
  * The prepared ops that failed, attached to `preparation_error` errors.
59
65
  * Each entry carries the `callId` of the failing node so callers can drop
60
66
  * the unroutable legs and resubmit a smaller flow.
@@ -79,6 +85,7 @@ var ComposeError = class extends Error {
79
85
  this.port = options?.port;
80
86
  this.fix = options?.fix;
81
87
  this.details = options?.details;
88
+ this.delivery = options?.delivery;
82
89
  this.failedOps = options?.failedOps;
83
90
  this.succeededOps = options?.succeededOps;
84
91
  this.sdkOutdated = options?.sdkOutdated;
@@ -113,6 +120,15 @@ const isComposeError = (e) => e instanceof ComposeError || e instanceof Error &&
113
120
  * ```
114
121
  */
115
122
  const isComposePreparationError = (e) => isComposeError(e) && e.kind === "preparation_error" && Array.isArray(e.failedOps) && Array.isArray(e.succeededOps);
123
+ /**
124
+ * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into
125
+ * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to
126
+ * present. Recompile: each compile quotes and registers afresh.
127
+ *
128
+ * @param e - The value to check.
129
+ * @returns `true` if `e` is a `ComposeError` carrying delivery details.
130
+ */
131
+ const isComposeDeliveryError = (e) => isComposeError(e) && e.kind === "delivery_error" && e.delivery !== void 0;
116
132
  const sdkOutdatedSchema = zod.default.object({
117
133
  sdkVersion: zod.default.string(),
118
134
  serverVersion: zod.default.string(),
@@ -178,15 +194,22 @@ const tryParseErrorBody = (body) => {
178
194
  };
179
195
  /**
180
196
  * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope
181
- * carries. The slots reuse the same schemas the type guards narrow with. Zod
182
- * strips keys the schema does not declare, so the parsed value is exactly the
183
- * triple; a partial payload fails the parse and yields `undefined` rather than
184
- * a half-populated object.
197
+ * carries, and routes the wire `details` by kind. The version slots reuse the
198
+ * same schemas the type guards narrow with. Zod strips keys the schema does
199
+ * not declare, so the parsed value is exactly the triple; a partial payload
200
+ * fails the parse and yields `undefined` rather than a half-populated object.
201
+ * A `delivery_error`'s `details` land in `delivery`; every other kind's are
202
+ * forwarded verbatim as `details`.
185
203
  */
186
- const readVersionSlots = (serverError) => ({
187
- sdkOutdated: serverError?.kind === "sdk_outdated" ? sdkOutdatedSchema.safeParse(serverError).data : void 0,
188
- serverOutdated: serverError?.kind === "server_outdated" ? serverOutdatedSchema.safeParse(serverError).data : void 0
189
- });
204
+ const readKindSlots = (serverError) => {
205
+ const delivery = serverError?.kind === "delivery_error";
206
+ return {
207
+ sdkOutdated: serverError?.kind === "sdk_outdated" ? sdkOutdatedSchema.safeParse(serverError).data : void 0,
208
+ serverOutdated: serverError?.kind === "server_outdated" ? serverOutdatedSchema.safeParse(serverError).data : void 0,
209
+ details: delivery ? void 0 : serverError?.details,
210
+ delivery: delivery ? serverError.details : void 0
211
+ };
212
+ };
190
213
  /**
191
214
  * Constructs a {@link ComposeError} from an HTTP error response, extracting
192
215
  * structured error details from the response body when available.
@@ -198,7 +221,7 @@ const readVersionSlots = (serverError) => ({
198
221
  */
199
222
  const errorFromHttpResponse = (status, body, url) => {
200
223
  const serverError = tryParseErrorBody(body)?.error;
201
- const { sdkOutdated, serverOutdated } = readVersionSlots(serverError);
224
+ const slots = readKindSlots(serverError);
202
225
  return new ComposeError(STATUS_TO_CODE.get(status) ?? (status >= 500 ? "SERVER_ERROR" : "UNKNOWN_ERROR"), (serverError?.message ?? body) || `HTTP ${status}`, {
203
226
  status,
204
227
  url,
@@ -206,19 +229,18 @@ const errorFromHttpResponse = (status, body, url) => {
206
229
  path: serverError?.path,
207
230
  port: serverError?.port,
208
231
  fix: serverError?.fix,
209
- details: serverError?.details,
232
+ ...slots,
210
233
  failedOps: serverError?.failedOps?.map((op) => ({
211
234
  ...op,
212
235
  kind: op.kind
213
236
  })),
214
- succeededOps: serverError?.succeededOps,
215
- sdkOutdated,
216
- serverOutdated
237
+ succeededOps: serverError?.succeededOps
217
238
  });
218
239
  };
219
240
  //#endregion
220
241
  exports.ComposeError = ComposeError;
221
242
  exports.errorFromHttpResponse = errorFromHttpResponse;
243
+ exports.isComposeDeliveryError = isComposeDeliveryError;
222
244
  exports.isComposeError = isComposeError;
223
245
  exports.isComposePreparationError = isComposePreparationError;
224
246
  exports.isComposeSdkOutdatedError = isComposeSdkOutdatedError;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":["z","parseServerErrorBody"],"sources":["../src/errors.ts"],"sourcesContent":["import type {\n ComposeErrorKind,\n ComposeRouteErrorKind,\n FailedPreparedOp,\n GenericComposeErrorKind,\n SimulationRevert,\n} from '@lifi/compose-spec';\nimport z from 'zod';\n\nimport {\n parseServerErrorBody,\n type ServerErrorBody,\n} from './responseSchemas.js';\n\n/**\n * Machine-readable error codes returned by the SDK.\n *\n * - `NETWORK_ERROR` — The HTTP request failed (DNS, timeout, connection refused).\n * - `VALIDATION_ERROR` — The server rejected the request (HTTP 400/422).\n * - `UNAUTHENTICATED` — The request lacks valid authentication credentials (HTTP 401).\n * - `FORBIDDEN` — The server understood the request but refuses to authorise it (HTTP 403).\n * - `SERVER_ERROR` — The server returned a 5xx status.\n * - `RATE_LIMITED` — The server returned HTTP 429.\n * - `NOT_FOUND` — The requested resource does not exist (HTTP 404).\n * - `UNKNOWN_ERROR` — An unexpected error that doesn't fit other categories.\n */\nexport type ComposeErrorCode =\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN'\n | 'SERVER_ERROR'\n | 'RATE_LIMITED'\n | 'NOT_FOUND'\n | 'UNKNOWN_ERROR';\n\n/** Version details returned when the backend rejects an outdated SDK. */\nexport interface ComposeSdkOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n readonly minimumSdkVersion: string;\n}\n\n/**\n * Version details attached when the SDK is ahead of the backend it reached.\n * Raised by the backend's version gate, or by the SDK itself when the\n * `x-lifi-composer-version` response header names an older contract than the\n * one this SDK was built against.\n */\nexport interface ComposeServerOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n}\n\n/**\n * Error class for all failures originating from the Compose SDK or API.\n *\n * Includes structured metadata beyond the error message to support\n * programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeError(e) && e.code === 'VALIDATION_ERROR') {\n * console.error('Invalid request:', e.message, e.path);\n * }\n * }\n * ```\n */\nexport class ComposeError extends Error {\n override readonly name = 'ComposeError';\n /** Machine-readable error category. */\n readonly code: ComposeErrorCode;\n /** HTTP status code, when the error originated from an HTTP response. */\n readonly status?: number;\n /** The request URL that produced the error. */\n readonly url?: string;\n /** Server-provided error kind for finer-grained classification. */\n readonly kind?: ComposeErrorKind | ComposeRouteErrorKind;\n /**\n * Where a validation error points: the node id for a rejection of an\n * authored node, or a JSON-pointer path for a rejection of the request shape.\n */\n readonly path?: string;\n /**\n * The input port of {@link ComposeError.path}'s node whose binding caused the\n * error. Set when the rejection is about what a port binds rather than about\n * the node's config.\n */\n readonly port?: string;\n /**\n * The one edit that clears the error, written for whoever authored the flow.\n * Set on `continuation.settle` authoring rejections; may be absent on other\n * `validation_error`s.\n */\n readonly fix?: string;\n /**\n * Simulation revert diagnostics attached to `simulation_revert` errors.\n * Contains the raw error bytes and decoded error candidates when the\n * backend can parse the revert reason.\n */\n readonly details?: SimulationRevert;\n /**\n * The prepared ops that failed, attached to `preparation_error` errors.\n * Each entry carries the `callId` of the failing node so callers can drop\n * the unroutable legs and resubmit a smaller flow.\n */\n readonly failedOps?: readonly FailedPreparedOp[];\n /**\n * The `callId`s of the prepared ops that succeeded, attached to\n * `preparation_error` errors alongside {@link ComposeError.failedOps}.\n */\n readonly succeededOps?: readonly string[];\n /** Version details attached only to `sdk_outdated` errors. */\n readonly sdkOutdated?: ComposeSdkOutdated;\n /** Version details attached only to `server_outdated` errors. */\n readonly serverOutdated?: ComposeServerOutdated;\n\n constructor(\n code: ComposeErrorCode,\n message: string,\n options?: {\n status?: number;\n url?: string;\n cause?: unknown;\n kind?: ComposeErrorKind | ComposeRouteErrorKind;\n path?: string;\n port?: string;\n fix?: string;\n details?: SimulationRevert;\n failedOps?: readonly FailedPreparedOp[];\n succeededOps?: readonly string[];\n sdkOutdated?: ComposeSdkOutdated;\n serverOutdated?: ComposeServerOutdated;\n },\n ) {\n super(message, { cause: options?.cause });\n this.code = code;\n this.status = options?.status;\n this.url = options?.url;\n this.kind = options?.kind;\n this.path = options?.path;\n this.port = options?.port;\n this.fix = options?.fix;\n this.details = options?.details;\n this.failedOps = options?.failedOps;\n this.succeededOps = options?.succeededOps;\n this.sdkOutdated = options?.sdkOutdated;\n this.serverOutdated = options?.serverOutdated;\n }\n}\n\n/**\n * The per-op preparation diagnostics carried by `preparation_error` responses,\n * with both arrays known to be present. Produced by narrowing with\n * {@link isComposePreparationError}.\n */\nexport interface ComposePreparationOps {\n readonly failedOps: readonly FailedPreparedOp[];\n readonly succeededOps: readonly string[];\n}\n\n/**\n * Type guard that narrows an unknown error to {@link ComposeError}.\n * @param e - The value to check.\n * @returns `true` if `e` is an instance of `ComposeError`.\n */\nexport const isComposeError = (e: unknown): e is ComposeError =>\n e instanceof ComposeError ||\n (e instanceof Error && e.name === 'ComposeError' && 'code' in e);\n\n/**\n * Type guard for `preparation_error` failures (HTTP 422): a mixed basket where\n * some prepared ops failed and others succeeded. Narrows both\n * {@link ComposeError.failedOps} and {@link ComposeError.succeededOps} to\n * present, so callers can read them without a cast or a truthiness check.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying per-op preparation diagnostics.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposePreparationError(e)) {\n * console.error('Failed ops:', e.failedOps);\n * console.error('Succeeded ops:', e.succeededOps);\n * }\n * }\n * ```\n */\nexport const isComposePreparationError = (\n e: unknown,\n): e is ComposeError & ComposePreparationOps =>\n isComposeError(e) &&\n e.kind === 'preparation_error' &&\n Array.isArray(e.failedOps) &&\n Array.isArray(e.succeededOps);\n\n// `isComposeError` accepts a structurally-similar error by name, so an error\n// raised by a *second* copy of this package in the dependency tree reaches the\n// guard below without its `sdkOutdated` field being type-guaranteed. Parse it.\nconst sdkOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n minimumSdkVersion: z.string(),\n});\n\n/**\n * Narrows an outdated-SDK rejection to its required version details.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeSdkOutdatedError(e)) {\n * console.error(`Upgrade to at least ${e.sdkOutdated.minimumSdkVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeSdkOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly sdkOutdated: ComposeSdkOutdated } =>\n isComposeError(e) &&\n e.kind === 'sdk_outdated' &&\n sdkOutdatedSchema.safeParse(e.sdkOutdated).success;\n\nconst serverOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n});\n\n/**\n * Narrows a server-behind-SDK rejection to its required version details.\n *\n * This is the deploy-window error: the SDK on npm is ahead of the backend that\n * answered. Pin the SDK to the server's `major.minor`, or wait for the rollout.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeServerOutdatedError(e)) {\n * console.error(`Server serves ${e.serverOutdated.serverVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeServerOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly serverOutdated: ComposeServerOutdated } =>\n isComposeError(e) &&\n e.kind === 'server_outdated' &&\n serverOutdatedSchema.safeParse(e.serverOutdated).success;\n\nconst STATUS_TO_CODE: ReadonlyMap<number, ComposeErrorCode> = new Map<\n number,\n ComposeErrorCode\n>([\n [400, 'VALIDATION_ERROR'],\n [401, 'UNAUTHENTICATED'],\n [403, 'FORBIDDEN'],\n [404, 'NOT_FOUND'],\n [422, 'VALIDATION_ERROR'],\n [429, 'RATE_LIMITED'],\n]);\n\nconst tryParseErrorBody = (body: string): ServerErrorBody | null => {\n let json: unknown;\n try {\n json = JSON.parse(body);\n } catch {\n return null;\n }\n return parseServerErrorBody(json);\n};\n\n/**\n * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope\n * carries. The slots reuse the same schemas the type guards narrow with. Zod\n * strips keys the schema does not declare, so the parsed value is exactly the\n * triple; a partial payload fails the parse and yields `undefined` rather than\n * a half-populated object.\n */\nconst readVersionSlots = (serverError: ServerErrorBody['error']) => ({\n sdkOutdated:\n serverError?.kind === 'sdk_outdated'\n ? sdkOutdatedSchema.safeParse(serverError).data\n : undefined,\n serverOutdated:\n serverError?.kind === 'server_outdated'\n ? serverOutdatedSchema.safeParse(serverError).data\n : undefined,\n});\n\n/**\n * Constructs a {@link ComposeError} from an HTTP error response, extracting\n * structured error details from the response body when available.\n *\n * @param status - The HTTP status code.\n * @param body - The raw response body text.\n * @param url - The request URL that produced the error.\n * @returns A `ComposeError` with the appropriate error code and metadata.\n */\nexport const errorFromHttpResponse = (\n status: number,\n body: string,\n url: string,\n): ComposeError => {\n const parsed = tryParseErrorBody(body);\n const serverError = parsed?.error;\n const { sdkOutdated, serverOutdated } = readVersionSlots(serverError);\n\n return new ComposeError(\n STATUS_TO_CODE.get(status) ??\n (status >= 500 ? 'SERVER_ERROR' : 'UNKNOWN_ERROR'),\n (serverError?.message ?? body) || `HTTP ${status}`,\n {\n status,\n url,\n kind: serverError?.kind as\n ComposeErrorKind | ComposeRouteErrorKind | undefined,\n path: serverError?.path,\n port: serverError?.port,\n fix: serverError?.fix,\n details: serverError?.details,\n // The wire schema types `kind` as a bare string; the server only ever\n // reports generic kinds for individual ops.\n failedOps: serverError?.failedOps?.map((op) => ({\n ...op,\n kind: op.kind as GenericComposeErrorKind,\n })),\n succeededOps: serverError?.succeededOps,\n sdkOutdated,\n serverOutdated,\n },\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuEA,IAAa,eAAb,cAAkC,MAAM;CACtC,OAAyB;;CAEzB;;CAEA;;CAEA;;CAEA;;;;;CAKA;;;;;;CAMA;;;;;;CAMA;;;;;;CAMA;;;;;;CAMA;;;;;CAKA;;CAEA;;CAEA;CAEA,YACE,MACA,SACA,SAcA;EACA,MAAM,SAAS,EAAE,OAAO,SAAS,MAAM,CAAC;EACxC,KAAK,OAAO;EACZ,KAAK,SAAS,SAAS;EACvB,KAAK,MAAM,SAAS;EACpB,KAAK,OAAO,SAAS;EACrB,KAAK,OAAO,SAAS;EACrB,KAAK,OAAO,SAAS;EACrB,KAAK,MAAM,SAAS;EACpB,KAAK,UAAU,SAAS;EACxB,KAAK,YAAY,SAAS;EAC1B,KAAK,eAAe,SAAS;EAC7B,KAAK,cAAc,SAAS;EAC5B,KAAK,iBAAiB,SAAS;CACjC;AACF;;;;;;AAiBA,MAAa,kBAAkB,MAC7B,aAAa,gBACZ,aAAa,SAAS,EAAE,SAAS,kBAAkB,UAAU;;;;;;;;;;;;;;;;;;;;;;AAuBhE,MAAa,6BACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,uBACX,MAAM,QAAQ,EAAE,SAAS,KACzB,MAAM,QAAQ,EAAE,YAAY;AAK9B,MAAM,oBAAoBA,IAAAA,QAAE,OAAO;CACjC,YAAYA,IAAAA,QAAE,OAAO;CACrB,eAAeA,IAAAA,QAAE,OAAO;CACxB,mBAAmBA,IAAAA,QAAE,OAAO;AAC9B,CAAC;;;;;;;;;;;;;;;;;AAkBD,MAAa,6BACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,kBACX,kBAAkB,UAAU,EAAE,WAAW,CAAC,CAAC;AAE7C,MAAM,uBAAuBA,IAAAA,QAAE,OAAO;CACpC,YAAYA,IAAAA,QAAE,OAAO;CACrB,eAAeA,IAAAA,QAAE,OAAO;AAC1B,CAAC;;;;;;;;;;;;;;;;;;;;AAqBD,MAAa,gCACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,qBACX,qBAAqB,UAAU,EAAE,cAAc,CAAC,CAAC;AAEnD,MAAM,iCAAwD,IAAI,IAGhE;CACA,CAAC,KAAK,kBAAkB;CACxB,CAAC,KAAK,iBAAiB;CACvB,CAAC,KAAK,WAAW;CACjB,CAAC,KAAK,WAAW;CACjB,CAAC,KAAK,kBAAkB;CACxB,CAAC,KAAK,cAAc;AACtB,CAAC;AAED,MAAM,qBAAqB,SAAyC;CAClE,IAAI;CACJ,IAAI;EACF,OAAO,KAAK,MAAM,IAAI;CACxB,QAAQ;EACN,OAAO;CACT;CACA,OAAOC,wBAAAA,qBAAqB,IAAI;AAClC;;;;;;;;AASA,MAAM,oBAAoB,iBAA2C;CACnE,aACE,aAAa,SAAS,iBAClB,kBAAkB,UAAU,WAAW,CAAC,CAAC,OACzC,KAAA;CACN,gBACE,aAAa,SAAS,oBAClB,qBAAqB,UAAU,WAAW,CAAC,CAAC,OAC5C,KAAA;AACR;;;;;;;;;;AAWA,MAAa,yBACX,QACA,MACA,QACiB;CAEjB,MAAM,cADS,kBAAkB,IACR,CAAC,EAAE;CAC5B,MAAM,EAAE,aAAa,mBAAmB,iBAAiB,WAAW;CAEpE,OAAO,IAAI,aACT,eAAe,IAAI,MAAM,MACtB,UAAU,MAAM,iBAAiB,mBACnC,aAAa,WAAW,SAAS,QAAQ,UAC1C;EACE;EACA;EACA,MAAM,aAAa;EAEnB,MAAM,aAAa;EACnB,MAAM,aAAa;EACnB,KAAK,aAAa;EAClB,SAAS,aAAa;EAGtB,WAAW,aAAa,WAAW,KAAK,QAAQ;GAC9C,GAAG;GACH,MAAM,GAAG;EACX,EAAE;EACF,cAAc,aAAa;EAC3B;EACA;CACF,CACF;AACF"}
1
+ {"version":3,"file":"errors.cjs","names":["z","parseServerErrorBody"],"sources":["../src/errors.ts"],"sourcesContent":["import type {\n ComposeErrorKind,\n ComposeRouteErrorKind,\n DeliveryErrorDetails,\n FailedPreparedOp,\n GenericComposeErrorKind,\n SimulationRevert,\n} from '@lifi/compose-spec';\nimport z from 'zod';\n\nimport {\n parseServerErrorBody,\n type ServerErrorBody,\n} from './responseSchemas.js';\n\n/**\n * Machine-readable error codes returned by the SDK.\n *\n * - `NETWORK_ERROR` — The HTTP request failed (DNS, timeout, connection refused).\n * - `VALIDATION_ERROR` — The server rejected the request (HTTP 400/422).\n * - `UNAUTHENTICATED` — The request lacks valid authentication credentials (HTTP 401).\n * - `FORBIDDEN` — The server understood the request but refuses to authorise it (HTTP 403).\n * - `SERVER_ERROR` — The server returned a 5xx status.\n * - `RATE_LIMITED` — The server returned HTTP 429.\n * - `NOT_FOUND` — The requested resource does not exist (HTTP 404).\n * - `UNKNOWN_ERROR` — An unexpected error that doesn't fit other categories.\n */\nexport type ComposeErrorCode =\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN'\n | 'SERVER_ERROR'\n | 'RATE_LIMITED'\n | 'NOT_FOUND'\n | 'UNKNOWN_ERROR';\n\n/** Version details returned when the backend rejects an outdated SDK. */\nexport interface ComposeSdkOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n readonly minimumSdkVersion: string;\n}\n\n/**\n * Version details attached when the SDK is ahead of the backend it reached.\n * Raised by the backend's version gate, or by the SDK itself when the\n * `x-lifi-composer-version` response header names an older contract than the\n * one this SDK was built against.\n */\nexport interface ComposeServerOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n}\n\n/**\n * Error class for all failures originating from the Compose SDK or API.\n *\n * Includes structured metadata beyond the error message to support\n * programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeError(e) && e.code === 'VALIDATION_ERROR') {\n * console.error('Invalid request:', e.message, e.path);\n * }\n * }\n * ```\n */\nexport class ComposeError extends Error {\n override readonly name = 'ComposeError';\n /** Machine-readable error category. */\n readonly code: ComposeErrorCode;\n /** HTTP status code, when the error originated from an HTTP response. */\n readonly status?: number;\n /** The request URL that produced the error. */\n readonly url?: string;\n /** Server-provided error kind for finer-grained classification. */\n readonly kind?: ComposeErrorKind | ComposeRouteErrorKind;\n /**\n * Where a validation error points: the node id for a rejection of an\n * authored node, or a JSON-pointer path for a rejection of the request shape.\n */\n readonly path?: string;\n /**\n * The input port of {@link ComposeError.path}'s node whose binding caused the\n * error. Set when the rejection is about what a port binds rather than about\n * the node's config.\n */\n readonly port?: string;\n /**\n * The one edit that clears the error, written for whoever authored the flow.\n * Set on `continuation.settle` authoring rejections; may be absent on other\n * `validation_error`s.\n */\n readonly fix?: string;\n /**\n * Simulation revert diagnostics attached to `simulation_revert` errors.\n * Contains the raw error bytes and decoded error candidates when the\n * backend can parse the revert reason.\n */\n readonly details?: SimulationRevert;\n /**\n * The delivery tranche's reason, first quote, and abandoned escrow,\n * attached to `delivery_error` errors. Narrow with\n * {@link isComposeDeliveryError}.\n */\n readonly delivery?: DeliveryErrorDetails;\n /**\n * The prepared ops that failed, attached to `preparation_error` errors.\n * Each entry carries the `callId` of the failing node so callers can drop\n * the unroutable legs and resubmit a smaller flow.\n */\n readonly failedOps?: readonly FailedPreparedOp[];\n /**\n * The `callId`s of the prepared ops that succeeded, attached to\n * `preparation_error` errors alongside {@link ComposeError.failedOps}.\n */\n readonly succeededOps?: readonly string[];\n /** Version details attached only to `sdk_outdated` errors. */\n readonly sdkOutdated?: ComposeSdkOutdated;\n /** Version details attached only to `server_outdated` errors. */\n readonly serverOutdated?: ComposeServerOutdated;\n\n constructor(\n code: ComposeErrorCode,\n message: string,\n options?: {\n status?: number;\n url?: string;\n cause?: unknown;\n kind?: ComposeErrorKind | ComposeRouteErrorKind;\n path?: string;\n port?: string;\n fix?: string;\n details?: SimulationRevert;\n delivery?: DeliveryErrorDetails;\n failedOps?: readonly FailedPreparedOp[];\n succeededOps?: readonly string[];\n sdkOutdated?: ComposeSdkOutdated;\n serverOutdated?: ComposeServerOutdated;\n },\n ) {\n super(message, { cause: options?.cause });\n this.code = code;\n this.status = options?.status;\n this.url = options?.url;\n this.kind = options?.kind;\n this.path = options?.path;\n this.port = options?.port;\n this.fix = options?.fix;\n this.details = options?.details;\n this.delivery = options?.delivery;\n this.failedOps = options?.failedOps;\n this.succeededOps = options?.succeededOps;\n this.sdkOutdated = options?.sdkOutdated;\n this.serverOutdated = options?.serverOutdated;\n }\n}\n\n/**\n * The per-op preparation diagnostics carried by `preparation_error` responses,\n * with both arrays known to be present. Produced by narrowing with\n * {@link isComposePreparationError}.\n */\nexport interface ComposePreparationOps {\n readonly failedOps: readonly FailedPreparedOp[];\n readonly succeededOps: readonly string[];\n}\n\n/**\n * Type guard that narrows an unknown error to {@link ComposeError}.\n * @param e - The value to check.\n * @returns `true` if `e` is an instance of `ComposeError`.\n */\nexport const isComposeError = (e: unknown): e is ComposeError =>\n e instanceof ComposeError ||\n (e instanceof Error && e.name === 'ComposeError' && 'code' in e);\n\n/**\n * Type guard for `preparation_error` failures (HTTP 422): a mixed basket where\n * some prepared ops failed and others succeeded. Narrows both\n * {@link ComposeError.failedOps} and {@link ComposeError.succeededOps} to\n * present, so callers can read them without a cast or a truthiness check.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying per-op preparation diagnostics.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposePreparationError(e)) {\n * console.error('Failed ops:', e.failedOps);\n * console.error('Succeeded ops:', e.succeededOps);\n * }\n * }\n * ```\n */\nexport const isComposePreparationError = (\n e: unknown,\n): e is ComposeError & ComposePreparationOps =>\n isComposeError(e) &&\n e.kind === 'preparation_error' &&\n Array.isArray(e.failedOps) &&\n Array.isArray(e.succeededOps);\n\n/**\n * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into\n * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to\n * present. Recompile: each compile quotes and registers afresh.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying delivery details.\n */\nexport const isComposeDeliveryError = (\n e: unknown,\n): e is ComposeError & { readonly delivery: DeliveryErrorDetails } =>\n isComposeError(e) && e.kind === 'delivery_error' && e.delivery !== undefined;\n\n// `isComposeError` accepts a structurally-similar error by name, so an error\n// raised by a *second* copy of this package in the dependency tree reaches the\n// guard below without its `sdkOutdated` field being type-guaranteed. Parse it.\nconst sdkOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n minimumSdkVersion: z.string(),\n});\n\n/**\n * Narrows an outdated-SDK rejection to its required version details.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeSdkOutdatedError(e)) {\n * console.error(`Upgrade to at least ${e.sdkOutdated.minimumSdkVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeSdkOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly sdkOutdated: ComposeSdkOutdated } =>\n isComposeError(e) &&\n e.kind === 'sdk_outdated' &&\n sdkOutdatedSchema.safeParse(e.sdkOutdated).success;\n\nconst serverOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n});\n\n/**\n * Narrows a server-behind-SDK rejection to its required version details.\n *\n * This is the deploy-window error: the SDK on npm is ahead of the backend that\n * answered. Pin the SDK to the server's `major.minor`, or wait for the rollout.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeServerOutdatedError(e)) {\n * console.error(`Server serves ${e.serverOutdated.serverVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeServerOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly serverOutdated: ComposeServerOutdated } =>\n isComposeError(e) &&\n e.kind === 'server_outdated' &&\n serverOutdatedSchema.safeParse(e.serverOutdated).success;\n\nconst STATUS_TO_CODE: ReadonlyMap<number, ComposeErrorCode> = new Map<\n number,\n ComposeErrorCode\n>([\n [400, 'VALIDATION_ERROR'],\n [401, 'UNAUTHENTICATED'],\n [403, 'FORBIDDEN'],\n [404, 'NOT_FOUND'],\n [422, 'VALIDATION_ERROR'],\n [429, 'RATE_LIMITED'],\n]);\n\nconst tryParseErrorBody = (body: string): ServerErrorBody | null => {\n let json: unknown;\n try {\n json = JSON.parse(body);\n } catch {\n return null;\n }\n return parseServerErrorBody(json);\n};\n\n/**\n * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope\n * carries, and routes the wire `details` by kind. The version slots reuse the\n * same schemas the type guards narrow with. Zod strips keys the schema does\n * not declare, so the parsed value is exactly the triple; a partial payload\n * fails the parse and yields `undefined` rather than a half-populated object.\n * A `delivery_error`'s `details` land in `delivery`; every other kind's are\n * forwarded verbatim as `details`.\n */\nconst readKindSlots = (serverError: ServerErrorBody['error']) => {\n const delivery = serverError?.kind === 'delivery_error';\n return {\n sdkOutdated:\n serverError?.kind === 'sdk_outdated'\n ? sdkOutdatedSchema.safeParse(serverError).data\n : undefined,\n serverOutdated:\n serverError?.kind === 'server_outdated'\n ? serverOutdatedSchema.safeParse(serverError).data\n : undefined,\n details: delivery\n ? undefined\n : (serverError?.details as SimulationRevert | undefined),\n delivery: delivery\n ? (serverError.details as DeliveryErrorDetails | undefined)\n : undefined,\n };\n};\n\n/**\n * Constructs a {@link ComposeError} from an HTTP error response, extracting\n * structured error details from the response body when available.\n *\n * @param status - The HTTP status code.\n * @param body - The raw response body text.\n * @param url - The request URL that produced the error.\n * @returns A `ComposeError` with the appropriate error code and metadata.\n */\nexport const errorFromHttpResponse = (\n status: number,\n body: string,\n url: string,\n): ComposeError => {\n const parsed = tryParseErrorBody(body);\n const serverError = parsed?.error;\n const slots = readKindSlots(serverError);\n\n return new ComposeError(\n STATUS_TO_CODE.get(status) ??\n (status >= 500 ? 'SERVER_ERROR' : 'UNKNOWN_ERROR'),\n (serverError?.message ?? body) || `HTTP ${status}`,\n {\n status,\n url,\n kind: serverError?.kind as\n ComposeErrorKind | ComposeRouteErrorKind | undefined,\n path: serverError?.path,\n port: serverError?.port,\n fix: serverError?.fix,\n ...slots,\n // The wire schema types `kind` as a bare string; the server only ever\n // reports generic kinds for individual ops.\n failedOps: serverError?.failedOps?.map((op) => ({\n ...op,\n kind: op.kind as GenericComposeErrorKind,\n })),\n succeededOps: serverError?.succeededOps,\n },\n );\n};\n"],"mappings":"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"}
package/dist/errors.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComposeErrorKind, ComposeRouteErrorKind, FailedPreparedOp, SimulationRevert } from "@lifi/compose-spec";
1
+ import { ComposeErrorKind, ComposeRouteErrorKind, DeliveryErrorDetails, FailedPreparedOp, SimulationRevert } from "@lifi/compose-spec";
2
2
  //#region src/errors.d.ts
3
3
  /**
4
4
  * Machine-readable error codes returned by the SDK.
@@ -79,6 +79,12 @@ export declare class ComposeError extends Error {
79
79
  * backend can parse the revert reason.
80
80
  */
81
81
  readonly details?: SimulationRevert;
82
+ /**
83
+ * The delivery tranche's reason, first quote, and abandoned escrow,
84
+ * attached to `delivery_error` errors. Narrow with
85
+ * {@link isComposeDeliveryError}.
86
+ */
87
+ readonly delivery?: DeliveryErrorDetails;
82
88
  /**
83
89
  * The prepared ops that failed, attached to `preparation_error` errors.
84
90
  * Each entry carries the `callId` of the failing node so callers can drop
@@ -103,6 +109,7 @@ export declare class ComposeError extends Error {
103
109
  port?: string;
104
110
  fix?: string;
105
111
  details?: SimulationRevert;
112
+ delivery?: DeliveryErrorDetails;
106
113
  failedOps?: readonly FailedPreparedOp[];
107
114
  succeededOps?: readonly string[];
108
115
  sdkOutdated?: ComposeSdkOutdated;
@@ -146,6 +153,17 @@ export declare const isComposeError: (e: unknown) => e is ComposeError;
146
153
  * ```
147
154
  */
148
155
  export declare const isComposePreparationError: (e: unknown) => e is ComposeError & ComposePreparationOps;
156
+ /**
157
+ * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into
158
+ * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to
159
+ * present. Recompile: each compile quotes and registers afresh.
160
+ *
161
+ * @param e - The value to check.
162
+ * @returns `true` if `e` is a `ComposeError` carrying delivery details.
163
+ */
164
+ export declare const isComposeDeliveryError: (e: unknown) => e is ComposeError & {
165
+ readonly delivery: DeliveryErrorDetails;
166
+ };
149
167
  /**
150
168
  * Narrows an outdated-SDK rejection to its required version details.
151
169
  *
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComposeErrorKind, ComposeRouteErrorKind, FailedPreparedOp, SimulationRevert } from "@lifi/compose-spec";
1
+ import { ComposeErrorKind, ComposeRouteErrorKind, DeliveryErrorDetails, FailedPreparedOp, SimulationRevert } from "@lifi/compose-spec";
2
2
  //#region src/errors.d.ts
3
3
  /**
4
4
  * Machine-readable error codes returned by the SDK.
@@ -79,6 +79,12 @@ export declare class ComposeError extends Error {
79
79
  * backend can parse the revert reason.
80
80
  */
81
81
  readonly details?: SimulationRevert;
82
+ /**
83
+ * The delivery tranche's reason, first quote, and abandoned escrow,
84
+ * attached to `delivery_error` errors. Narrow with
85
+ * {@link isComposeDeliveryError}.
86
+ */
87
+ readonly delivery?: DeliveryErrorDetails;
82
88
  /**
83
89
  * The prepared ops that failed, attached to `preparation_error` errors.
84
90
  * Each entry carries the `callId` of the failing node so callers can drop
@@ -103,6 +109,7 @@ export declare class ComposeError extends Error {
103
109
  port?: string;
104
110
  fix?: string;
105
111
  details?: SimulationRevert;
112
+ delivery?: DeliveryErrorDetails;
106
113
  failedOps?: readonly FailedPreparedOp[];
107
114
  succeededOps?: readonly string[];
108
115
  sdkOutdated?: ComposeSdkOutdated;
@@ -146,6 +153,17 @@ export declare const isComposeError: (e: unknown) => e is ComposeError;
146
153
  * ```
147
154
  */
148
155
  export declare const isComposePreparationError: (e: unknown) => e is ComposeError & ComposePreparationOps;
156
+ /**
157
+ * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into
158
+ * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to
159
+ * present. Recompile: each compile quotes and registers afresh.
160
+ *
161
+ * @param e - The value to check.
162
+ * @returns `true` if `e` is a `ComposeError` carrying delivery details.
163
+ */
164
+ export declare const isComposeDeliveryError: (e: unknown) => e is ComposeError & {
165
+ readonly delivery: DeliveryErrorDetails;
166
+ };
149
167
  /**
150
168
  * Narrows an outdated-SDK rejection to its required version details.
151
169
  *
package/dist/errors.js CHANGED
@@ -52,6 +52,12 @@ var ComposeError = class extends Error {
52
52
  */
53
53
  details;
54
54
  /**
55
+ * The delivery tranche's reason, first quote, and abandoned escrow,
56
+ * attached to `delivery_error` errors. Narrow with
57
+ * {@link isComposeDeliveryError}.
58
+ */
59
+ delivery;
60
+ /**
55
61
  * The prepared ops that failed, attached to `preparation_error` errors.
56
62
  * Each entry carries the `callId` of the failing node so callers can drop
57
63
  * the unroutable legs and resubmit a smaller flow.
@@ -76,6 +82,7 @@ var ComposeError = class extends Error {
76
82
  this.port = options?.port;
77
83
  this.fix = options?.fix;
78
84
  this.details = options?.details;
85
+ this.delivery = options?.delivery;
79
86
  this.failedOps = options?.failedOps;
80
87
  this.succeededOps = options?.succeededOps;
81
88
  this.sdkOutdated = options?.sdkOutdated;
@@ -110,6 +117,15 @@ const isComposeError = (e) => e instanceof ComposeError || e instanceof Error &&
110
117
  * ```
111
118
  */
112
119
  const isComposePreparationError = (e) => isComposeError(e) && e.kind === "preparation_error" && Array.isArray(e.failedOps) && Array.isArray(e.succeededOps);
120
+ /**
121
+ * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into
122
+ * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to
123
+ * present. Recompile: each compile quotes and registers afresh.
124
+ *
125
+ * @param e - The value to check.
126
+ * @returns `true` if `e` is a `ComposeError` carrying delivery details.
127
+ */
128
+ const isComposeDeliveryError = (e) => isComposeError(e) && e.kind === "delivery_error" && e.delivery !== void 0;
113
129
  const sdkOutdatedSchema = z.object({
114
130
  sdkVersion: z.string(),
115
131
  serverVersion: z.string(),
@@ -175,15 +191,22 @@ const tryParseErrorBody = (body) => {
175
191
  };
176
192
  /**
177
193
  * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope
178
- * carries. The slots reuse the same schemas the type guards narrow with. Zod
179
- * strips keys the schema does not declare, so the parsed value is exactly the
180
- * triple; a partial payload fails the parse and yields `undefined` rather than
181
- * a half-populated object.
194
+ * carries, and routes the wire `details` by kind. The version slots reuse the
195
+ * same schemas the type guards narrow with. Zod strips keys the schema does
196
+ * not declare, so the parsed value is exactly the triple; a partial payload
197
+ * fails the parse and yields `undefined` rather than a half-populated object.
198
+ * A `delivery_error`'s `details` land in `delivery`; every other kind's are
199
+ * forwarded verbatim as `details`.
182
200
  */
183
- const readVersionSlots = (serverError) => ({
184
- sdkOutdated: serverError?.kind === "sdk_outdated" ? sdkOutdatedSchema.safeParse(serverError).data : void 0,
185
- serverOutdated: serverError?.kind === "server_outdated" ? serverOutdatedSchema.safeParse(serverError).data : void 0
186
- });
201
+ const readKindSlots = (serverError) => {
202
+ const delivery = serverError?.kind === "delivery_error";
203
+ return {
204
+ sdkOutdated: serverError?.kind === "sdk_outdated" ? sdkOutdatedSchema.safeParse(serverError).data : void 0,
205
+ serverOutdated: serverError?.kind === "server_outdated" ? serverOutdatedSchema.safeParse(serverError).data : void 0,
206
+ details: delivery ? void 0 : serverError?.details,
207
+ delivery: delivery ? serverError.details : void 0
208
+ };
209
+ };
187
210
  /**
188
211
  * Constructs a {@link ComposeError} from an HTTP error response, extracting
189
212
  * structured error details from the response body when available.
@@ -195,7 +218,7 @@ const readVersionSlots = (serverError) => ({
195
218
  */
196
219
  const errorFromHttpResponse = (status, body, url) => {
197
220
  const serverError = tryParseErrorBody(body)?.error;
198
- const { sdkOutdated, serverOutdated } = readVersionSlots(serverError);
221
+ const slots = readKindSlots(serverError);
199
222
  return new ComposeError(STATUS_TO_CODE.get(status) ?? (status >= 500 ? "SERVER_ERROR" : "UNKNOWN_ERROR"), (serverError?.message ?? body) || `HTTP ${status}`, {
200
223
  status,
201
224
  url,
@@ -203,17 +226,15 @@ const errorFromHttpResponse = (status, body, url) => {
203
226
  path: serverError?.path,
204
227
  port: serverError?.port,
205
228
  fix: serverError?.fix,
206
- details: serverError?.details,
229
+ ...slots,
207
230
  failedOps: serverError?.failedOps?.map((op) => ({
208
231
  ...op,
209
232
  kind: op.kind
210
233
  })),
211
- succeededOps: serverError?.succeededOps,
212
- sdkOutdated,
213
- serverOutdated
234
+ succeededOps: serverError?.succeededOps
214
235
  });
215
236
  };
216
237
  //#endregion
217
- export { ComposeError, errorFromHttpResponse, isComposeError, isComposePreparationError, isComposeSdkOutdatedError, isComposeServerOutdatedError };
238
+ export { ComposeError, errorFromHttpResponse, isComposeDeliveryError, isComposeError, isComposePreparationError, isComposeSdkOutdatedError, isComposeServerOutdatedError };
218
239
 
219
240
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import type {\n ComposeErrorKind,\n ComposeRouteErrorKind,\n FailedPreparedOp,\n GenericComposeErrorKind,\n SimulationRevert,\n} from '@lifi/compose-spec';\nimport z from 'zod';\n\nimport {\n parseServerErrorBody,\n type ServerErrorBody,\n} from './responseSchemas.js';\n\n/**\n * Machine-readable error codes returned by the SDK.\n *\n * - `NETWORK_ERROR` — The HTTP request failed (DNS, timeout, connection refused).\n * - `VALIDATION_ERROR` — The server rejected the request (HTTP 400/422).\n * - `UNAUTHENTICATED` — The request lacks valid authentication credentials (HTTP 401).\n * - `FORBIDDEN` — The server understood the request but refuses to authorise it (HTTP 403).\n * - `SERVER_ERROR` — The server returned a 5xx status.\n * - `RATE_LIMITED` — The server returned HTTP 429.\n * - `NOT_FOUND` — The requested resource does not exist (HTTP 404).\n * - `UNKNOWN_ERROR` — An unexpected error that doesn't fit other categories.\n */\nexport type ComposeErrorCode =\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN'\n | 'SERVER_ERROR'\n | 'RATE_LIMITED'\n | 'NOT_FOUND'\n | 'UNKNOWN_ERROR';\n\n/** Version details returned when the backend rejects an outdated SDK. */\nexport interface ComposeSdkOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n readonly minimumSdkVersion: string;\n}\n\n/**\n * Version details attached when the SDK is ahead of the backend it reached.\n * Raised by the backend's version gate, or by the SDK itself when the\n * `x-lifi-composer-version` response header names an older contract than the\n * one this SDK was built against.\n */\nexport interface ComposeServerOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n}\n\n/**\n * Error class for all failures originating from the Compose SDK or API.\n *\n * Includes structured metadata beyond the error message to support\n * programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeError(e) && e.code === 'VALIDATION_ERROR') {\n * console.error('Invalid request:', e.message, e.path);\n * }\n * }\n * ```\n */\nexport class ComposeError extends Error {\n override readonly name = 'ComposeError';\n /** Machine-readable error category. */\n readonly code: ComposeErrorCode;\n /** HTTP status code, when the error originated from an HTTP response. */\n readonly status?: number;\n /** The request URL that produced the error. */\n readonly url?: string;\n /** Server-provided error kind for finer-grained classification. */\n readonly kind?: ComposeErrorKind | ComposeRouteErrorKind;\n /**\n * Where a validation error points: the node id for a rejection of an\n * authored node, or a JSON-pointer path for a rejection of the request shape.\n */\n readonly path?: string;\n /**\n * The input port of {@link ComposeError.path}'s node whose binding caused the\n * error. Set when the rejection is about what a port binds rather than about\n * the node's config.\n */\n readonly port?: string;\n /**\n * The one edit that clears the error, written for whoever authored the flow.\n * Set on `continuation.settle` authoring rejections; may be absent on other\n * `validation_error`s.\n */\n readonly fix?: string;\n /**\n * Simulation revert diagnostics attached to `simulation_revert` errors.\n * Contains the raw error bytes and decoded error candidates when the\n * backend can parse the revert reason.\n */\n readonly details?: SimulationRevert;\n /**\n * The prepared ops that failed, attached to `preparation_error` errors.\n * Each entry carries the `callId` of the failing node so callers can drop\n * the unroutable legs and resubmit a smaller flow.\n */\n readonly failedOps?: readonly FailedPreparedOp[];\n /**\n * The `callId`s of the prepared ops that succeeded, attached to\n * `preparation_error` errors alongside {@link ComposeError.failedOps}.\n */\n readonly succeededOps?: readonly string[];\n /** Version details attached only to `sdk_outdated` errors. */\n readonly sdkOutdated?: ComposeSdkOutdated;\n /** Version details attached only to `server_outdated` errors. */\n readonly serverOutdated?: ComposeServerOutdated;\n\n constructor(\n code: ComposeErrorCode,\n message: string,\n options?: {\n status?: number;\n url?: string;\n cause?: unknown;\n kind?: ComposeErrorKind | ComposeRouteErrorKind;\n path?: string;\n port?: string;\n fix?: string;\n details?: SimulationRevert;\n failedOps?: readonly FailedPreparedOp[];\n succeededOps?: readonly string[];\n sdkOutdated?: ComposeSdkOutdated;\n serverOutdated?: ComposeServerOutdated;\n },\n ) {\n super(message, { cause: options?.cause });\n this.code = code;\n this.status = options?.status;\n this.url = options?.url;\n this.kind = options?.kind;\n this.path = options?.path;\n this.port = options?.port;\n this.fix = options?.fix;\n this.details = options?.details;\n this.failedOps = options?.failedOps;\n this.succeededOps = options?.succeededOps;\n this.sdkOutdated = options?.sdkOutdated;\n this.serverOutdated = options?.serverOutdated;\n }\n}\n\n/**\n * The per-op preparation diagnostics carried by `preparation_error` responses,\n * with both arrays known to be present. Produced by narrowing with\n * {@link isComposePreparationError}.\n */\nexport interface ComposePreparationOps {\n readonly failedOps: readonly FailedPreparedOp[];\n readonly succeededOps: readonly string[];\n}\n\n/**\n * Type guard that narrows an unknown error to {@link ComposeError}.\n * @param e - The value to check.\n * @returns `true` if `e` is an instance of `ComposeError`.\n */\nexport const isComposeError = (e: unknown): e is ComposeError =>\n e instanceof ComposeError ||\n (e instanceof Error && e.name === 'ComposeError' && 'code' in e);\n\n/**\n * Type guard for `preparation_error` failures (HTTP 422): a mixed basket where\n * some prepared ops failed and others succeeded. Narrows both\n * {@link ComposeError.failedOps} and {@link ComposeError.succeededOps} to\n * present, so callers can read them without a cast or a truthiness check.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying per-op preparation diagnostics.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposePreparationError(e)) {\n * console.error('Failed ops:', e.failedOps);\n * console.error('Succeeded ops:', e.succeededOps);\n * }\n * }\n * ```\n */\nexport const isComposePreparationError = (\n e: unknown,\n): e is ComposeError & ComposePreparationOps =>\n isComposeError(e) &&\n e.kind === 'preparation_error' &&\n Array.isArray(e.failedOps) &&\n Array.isArray(e.succeededOps);\n\n// `isComposeError` accepts a structurally-similar error by name, so an error\n// raised by a *second* copy of this package in the dependency tree reaches the\n// guard below without its `sdkOutdated` field being type-guaranteed. Parse it.\nconst sdkOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n minimumSdkVersion: z.string(),\n});\n\n/**\n * Narrows an outdated-SDK rejection to its required version details.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeSdkOutdatedError(e)) {\n * console.error(`Upgrade to at least ${e.sdkOutdated.minimumSdkVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeSdkOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly sdkOutdated: ComposeSdkOutdated } =>\n isComposeError(e) &&\n e.kind === 'sdk_outdated' &&\n sdkOutdatedSchema.safeParse(e.sdkOutdated).success;\n\nconst serverOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n});\n\n/**\n * Narrows a server-behind-SDK rejection to its required version details.\n *\n * This is the deploy-window error: the SDK on npm is ahead of the backend that\n * answered. Pin the SDK to the server's `major.minor`, or wait for the rollout.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeServerOutdatedError(e)) {\n * console.error(`Server serves ${e.serverOutdated.serverVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeServerOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly serverOutdated: ComposeServerOutdated } =>\n isComposeError(e) &&\n e.kind === 'server_outdated' &&\n serverOutdatedSchema.safeParse(e.serverOutdated).success;\n\nconst STATUS_TO_CODE: ReadonlyMap<number, ComposeErrorCode> = new Map<\n number,\n ComposeErrorCode\n>([\n [400, 'VALIDATION_ERROR'],\n [401, 'UNAUTHENTICATED'],\n [403, 'FORBIDDEN'],\n [404, 'NOT_FOUND'],\n [422, 'VALIDATION_ERROR'],\n [429, 'RATE_LIMITED'],\n]);\n\nconst tryParseErrorBody = (body: string): ServerErrorBody | null => {\n let json: unknown;\n try {\n json = JSON.parse(body);\n } catch {\n return null;\n }\n return parseServerErrorBody(json);\n};\n\n/**\n * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope\n * carries. The slots reuse the same schemas the type guards narrow with. Zod\n * strips keys the schema does not declare, so the parsed value is exactly the\n * triple; a partial payload fails the parse and yields `undefined` rather than\n * a half-populated object.\n */\nconst readVersionSlots = (serverError: ServerErrorBody['error']) => ({\n sdkOutdated:\n serverError?.kind === 'sdk_outdated'\n ? sdkOutdatedSchema.safeParse(serverError).data\n : undefined,\n serverOutdated:\n serverError?.kind === 'server_outdated'\n ? serverOutdatedSchema.safeParse(serverError).data\n : undefined,\n});\n\n/**\n * Constructs a {@link ComposeError} from an HTTP error response, extracting\n * structured error details from the response body when available.\n *\n * @param status - The HTTP status code.\n * @param body - The raw response body text.\n * @param url - The request URL that produced the error.\n * @returns A `ComposeError` with the appropriate error code and metadata.\n */\nexport const errorFromHttpResponse = (\n status: number,\n body: string,\n url: string,\n): ComposeError => {\n const parsed = tryParseErrorBody(body);\n const serverError = parsed?.error;\n const { sdkOutdated, serverOutdated } = readVersionSlots(serverError);\n\n return new ComposeError(\n STATUS_TO_CODE.get(status) ??\n (status >= 500 ? 'SERVER_ERROR' : 'UNKNOWN_ERROR'),\n (serverError?.message ?? body) || `HTTP ${status}`,\n {\n status,\n url,\n kind: serverError?.kind as\n ComposeErrorKind | ComposeRouteErrorKind | undefined,\n path: serverError?.path,\n port: serverError?.port,\n fix: serverError?.fix,\n details: serverError?.details,\n // The wire schema types `kind` as a bare string; the server only ever\n // reports generic kinds for individual ops.\n failedOps: serverError?.failedOps?.map((op) => ({\n ...op,\n kind: op.kind as GenericComposeErrorKind,\n })),\n succeededOps: serverError?.succeededOps,\n sdkOutdated,\n serverOutdated,\n },\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuEA,IAAa,eAAb,cAAkC,MAAM;CACtC,OAAyB;;CAEzB;;CAEA;;CAEA;;CAEA;;;;;CAKA;;;;;;CAMA;;;;;;CAMA;;;;;;CAMA;;;;;;CAMA;;;;;CAKA;;CAEA;;CAEA;CAEA,YACE,MACA,SACA,SAcA;EACA,MAAM,SAAS,EAAE,OAAO,SAAS,MAAM,CAAC;EACxC,KAAK,OAAO;EACZ,KAAK,SAAS,SAAS;EACvB,KAAK,MAAM,SAAS;EACpB,KAAK,OAAO,SAAS;EACrB,KAAK,OAAO,SAAS;EACrB,KAAK,OAAO,SAAS;EACrB,KAAK,MAAM,SAAS;EACpB,KAAK,UAAU,SAAS;EACxB,KAAK,YAAY,SAAS;EAC1B,KAAK,eAAe,SAAS;EAC7B,KAAK,cAAc,SAAS;EAC5B,KAAK,iBAAiB,SAAS;CACjC;AACF;;;;;;AAiBA,MAAa,kBAAkB,MAC7B,aAAa,gBACZ,aAAa,SAAS,EAAE,SAAS,kBAAkB,UAAU;;;;;;;;;;;;;;;;;;;;;;AAuBhE,MAAa,6BACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,uBACX,MAAM,QAAQ,EAAE,SAAS,KACzB,MAAM,QAAQ,EAAE,YAAY;AAK9B,MAAM,oBAAoB,EAAE,OAAO;CACjC,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,mBAAmB,EAAE,OAAO;AAC9B,CAAC;;;;;;;;;;;;;;;;;AAkBD,MAAa,6BACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,kBACX,kBAAkB,UAAU,EAAE,WAAW,CAAC,CAAC;AAE7C,MAAM,uBAAuB,EAAE,OAAO;CACpC,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;AAC1B,CAAC;;;;;;;;;;;;;;;;;;;;AAqBD,MAAa,gCACX,MAEA,eAAe,CAAC,KAChB,EAAE,SAAS,qBACX,qBAAqB,UAAU,EAAE,cAAc,CAAC,CAAC;AAEnD,MAAM,iCAAwD,IAAI,IAGhE;CACA,CAAC,KAAK,kBAAkB;CACxB,CAAC,KAAK,iBAAiB;CACvB,CAAC,KAAK,WAAW;CACjB,CAAC,KAAK,WAAW;CACjB,CAAC,KAAK,kBAAkB;CACxB,CAAC,KAAK,cAAc;AACtB,CAAC;AAED,MAAM,qBAAqB,SAAyC;CAClE,IAAI;CACJ,IAAI;EACF,OAAO,KAAK,MAAM,IAAI;CACxB,QAAQ;EACN,OAAO;CACT;CACA,OAAO,qBAAqB,IAAI;AAClC;;;;;;;;AASA,MAAM,oBAAoB,iBAA2C;CACnE,aACE,aAAa,SAAS,iBAClB,kBAAkB,UAAU,WAAW,CAAC,CAAC,OACzC,KAAA;CACN,gBACE,aAAa,SAAS,oBAClB,qBAAqB,UAAU,WAAW,CAAC,CAAC,OAC5C,KAAA;AACR;;;;;;;;;;AAWA,MAAa,yBACX,QACA,MACA,QACiB;CAEjB,MAAM,cADS,kBAAkB,IACR,CAAC,EAAE;CAC5B,MAAM,EAAE,aAAa,mBAAmB,iBAAiB,WAAW;CAEpE,OAAO,IAAI,aACT,eAAe,IAAI,MAAM,MACtB,UAAU,MAAM,iBAAiB,mBACnC,aAAa,WAAW,SAAS,QAAQ,UAC1C;EACE;EACA;EACA,MAAM,aAAa;EAEnB,MAAM,aAAa;EACnB,MAAM,aAAa;EACnB,KAAK,aAAa;EAClB,SAAS,aAAa;EAGtB,WAAW,aAAa,WAAW,KAAK,QAAQ;GAC9C,GAAG;GACH,MAAM,GAAG;EACX,EAAE;EACF,cAAc,aAAa;EAC3B;EACA;CACF,CACF;AACF"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import type {\n ComposeErrorKind,\n ComposeRouteErrorKind,\n DeliveryErrorDetails,\n FailedPreparedOp,\n GenericComposeErrorKind,\n SimulationRevert,\n} from '@lifi/compose-spec';\nimport z from 'zod';\n\nimport {\n parseServerErrorBody,\n type ServerErrorBody,\n} from './responseSchemas.js';\n\n/**\n * Machine-readable error codes returned by the SDK.\n *\n * - `NETWORK_ERROR` — The HTTP request failed (DNS, timeout, connection refused).\n * - `VALIDATION_ERROR` — The server rejected the request (HTTP 400/422).\n * - `UNAUTHENTICATED` — The request lacks valid authentication credentials (HTTP 401).\n * - `FORBIDDEN` — The server understood the request but refuses to authorise it (HTTP 403).\n * - `SERVER_ERROR` — The server returned a 5xx status.\n * - `RATE_LIMITED` — The server returned HTTP 429.\n * - `NOT_FOUND` — The requested resource does not exist (HTTP 404).\n * - `UNKNOWN_ERROR` — An unexpected error that doesn't fit other categories.\n */\nexport type ComposeErrorCode =\n | 'NETWORK_ERROR'\n | 'VALIDATION_ERROR'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN'\n | 'SERVER_ERROR'\n | 'RATE_LIMITED'\n | 'NOT_FOUND'\n | 'UNKNOWN_ERROR';\n\n/** Version details returned when the backend rejects an outdated SDK. */\nexport interface ComposeSdkOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n readonly minimumSdkVersion: string;\n}\n\n/**\n * Version details attached when the SDK is ahead of the backend it reached.\n * Raised by the backend's version gate, or by the SDK itself when the\n * `x-lifi-composer-version` response header names an older contract than the\n * one this SDK was built against.\n */\nexport interface ComposeServerOutdated {\n readonly sdkVersion: string;\n readonly serverVersion: string;\n}\n\n/**\n * Error class for all failures originating from the Compose SDK or API.\n *\n * Includes structured metadata beyond the error message to support\n * programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeError(e) && e.code === 'VALIDATION_ERROR') {\n * console.error('Invalid request:', e.message, e.path);\n * }\n * }\n * ```\n */\nexport class ComposeError extends Error {\n override readonly name = 'ComposeError';\n /** Machine-readable error category. */\n readonly code: ComposeErrorCode;\n /** HTTP status code, when the error originated from an HTTP response. */\n readonly status?: number;\n /** The request URL that produced the error. */\n readonly url?: string;\n /** Server-provided error kind for finer-grained classification. */\n readonly kind?: ComposeErrorKind | ComposeRouteErrorKind;\n /**\n * Where a validation error points: the node id for a rejection of an\n * authored node, or a JSON-pointer path for a rejection of the request shape.\n */\n readonly path?: string;\n /**\n * The input port of {@link ComposeError.path}'s node whose binding caused the\n * error. Set when the rejection is about what a port binds rather than about\n * the node's config.\n */\n readonly port?: string;\n /**\n * The one edit that clears the error, written for whoever authored the flow.\n * Set on `continuation.settle` authoring rejections; may be absent on other\n * `validation_error`s.\n */\n readonly fix?: string;\n /**\n * Simulation revert diagnostics attached to `simulation_revert` errors.\n * Contains the raw error bytes and decoded error candidates when the\n * backend can parse the revert reason.\n */\n readonly details?: SimulationRevert;\n /**\n * The delivery tranche's reason, first quote, and abandoned escrow,\n * attached to `delivery_error` errors. Narrow with\n * {@link isComposeDeliveryError}.\n */\n readonly delivery?: DeliveryErrorDetails;\n /**\n * The prepared ops that failed, attached to `preparation_error` errors.\n * Each entry carries the `callId` of the failing node so callers can drop\n * the unroutable legs and resubmit a smaller flow.\n */\n readonly failedOps?: readonly FailedPreparedOp[];\n /**\n * The `callId`s of the prepared ops that succeeded, attached to\n * `preparation_error` errors alongside {@link ComposeError.failedOps}.\n */\n readonly succeededOps?: readonly string[];\n /** Version details attached only to `sdk_outdated` errors. */\n readonly sdkOutdated?: ComposeSdkOutdated;\n /** Version details attached only to `server_outdated` errors. */\n readonly serverOutdated?: ComposeServerOutdated;\n\n constructor(\n code: ComposeErrorCode,\n message: string,\n options?: {\n status?: number;\n url?: string;\n cause?: unknown;\n kind?: ComposeErrorKind | ComposeRouteErrorKind;\n path?: string;\n port?: string;\n fix?: string;\n details?: SimulationRevert;\n delivery?: DeliveryErrorDetails;\n failedOps?: readonly FailedPreparedOp[];\n succeededOps?: readonly string[];\n sdkOutdated?: ComposeSdkOutdated;\n serverOutdated?: ComposeServerOutdated;\n },\n ) {\n super(message, { cause: options?.cause });\n this.code = code;\n this.status = options?.status;\n this.url = options?.url;\n this.kind = options?.kind;\n this.path = options?.path;\n this.port = options?.port;\n this.fix = options?.fix;\n this.details = options?.details;\n this.delivery = options?.delivery;\n this.failedOps = options?.failedOps;\n this.succeededOps = options?.succeededOps;\n this.sdkOutdated = options?.sdkOutdated;\n this.serverOutdated = options?.serverOutdated;\n }\n}\n\n/**\n * The per-op preparation diagnostics carried by `preparation_error` responses,\n * with both arrays known to be present. Produced by narrowing with\n * {@link isComposePreparationError}.\n */\nexport interface ComposePreparationOps {\n readonly failedOps: readonly FailedPreparedOp[];\n readonly succeededOps: readonly string[];\n}\n\n/**\n * Type guard that narrows an unknown error to {@link ComposeError}.\n * @param e - The value to check.\n * @returns `true` if `e` is an instance of `ComposeError`.\n */\nexport const isComposeError = (e: unknown): e is ComposeError =>\n e instanceof ComposeError ||\n (e instanceof Error && e.name === 'ComposeError' && 'code' in e);\n\n/**\n * Type guard for `preparation_error` failures (HTTP 422): a mixed basket where\n * some prepared ops failed and others succeeded. Narrows both\n * {@link ComposeError.failedOps} and {@link ComposeError.succeededOps} to\n * present, so callers can read them without a cast or a truthiness check.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying per-op preparation diagnostics.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposePreparationError(e)) {\n * console.error('Failed ops:', e.failedOps);\n * console.error('Succeeded ops:', e.succeededOps);\n * }\n * }\n * ```\n */\nexport const isComposePreparationError = (\n e: unknown,\n): e is ComposeError & ComposePreparationOps =>\n isComposeError(e) &&\n e.kind === 'preparation_error' &&\n Array.isArray(e.failedOps) &&\n Array.isArray(e.succeededOps);\n\n/**\n * Type guard for `delivery_error` failures (HTTP 422): a bridge delivering into\n * a settle escrow no longer fits it. Narrows {@link ComposeError.delivery} to\n * present. Recompile: each compile quotes and registers afresh.\n *\n * @param e - The value to check.\n * @returns `true` if `e` is a `ComposeError` carrying delivery details.\n */\nexport const isComposeDeliveryError = (\n e: unknown,\n): e is ComposeError & { readonly delivery: DeliveryErrorDetails } =>\n isComposeError(e) && e.kind === 'delivery_error' && e.delivery !== undefined;\n\n// `isComposeError` accepts a structurally-similar error by name, so an error\n// raised by a *second* copy of this package in the dependency tree reaches the\n// guard below without its `sdkOutdated` field being type-guaranteed. Parse it.\nconst sdkOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n minimumSdkVersion: z.string(),\n});\n\n/**\n * Narrows an outdated-SDK rejection to its required version details.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeSdkOutdatedError(e)) {\n * console.error(`Upgrade to at least ${e.sdkOutdated.minimumSdkVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeSdkOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly sdkOutdated: ComposeSdkOutdated } =>\n isComposeError(e) &&\n e.kind === 'sdk_outdated' &&\n sdkOutdatedSchema.safeParse(e.sdkOutdated).success;\n\nconst serverOutdatedSchema = z.object({\n sdkVersion: z.string(),\n serverVersion: z.string(),\n});\n\n/**\n * Narrows a server-behind-SDK rejection to its required version details.\n *\n * This is the deploy-window error: the SDK on npm is ahead of the backend that\n * answered. Pin the SDK to the server's `major.minor`, or wait for the rollout.\n *\n * @example\n * ```ts\n * try {\n * await builder.compile(run);\n * } catch (e) {\n * if (isComposeServerOutdatedError(e)) {\n * console.error(`Server serves ${e.serverOutdated.serverVersion}`);\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport const isComposeServerOutdatedError = (\n e: unknown,\n): e is ComposeError & { readonly serverOutdated: ComposeServerOutdated } =>\n isComposeError(e) &&\n e.kind === 'server_outdated' &&\n serverOutdatedSchema.safeParse(e.serverOutdated).success;\n\nconst STATUS_TO_CODE: ReadonlyMap<number, ComposeErrorCode> = new Map<\n number,\n ComposeErrorCode\n>([\n [400, 'VALIDATION_ERROR'],\n [401, 'UNAUTHENTICATED'],\n [403, 'FORBIDDEN'],\n [404, 'NOT_FOUND'],\n [422, 'VALIDATION_ERROR'],\n [429, 'RATE_LIMITED'],\n]);\n\nconst tryParseErrorBody = (body: string): ServerErrorBody | null => {\n let json: unknown;\n try {\n json = JSON.parse(body);\n } catch {\n return null;\n }\n return parseServerErrorBody(json);\n};\n\n/**\n * Extracts the version triple an `sdk_outdated` or `server_outdated` envelope\n * carries, and routes the wire `details` by kind. The version slots reuse the\n * same schemas the type guards narrow with. Zod strips keys the schema does\n * not declare, so the parsed value is exactly the triple; a partial payload\n * fails the parse and yields `undefined` rather than a half-populated object.\n * A `delivery_error`'s `details` land in `delivery`; every other kind's are\n * forwarded verbatim as `details`.\n */\nconst readKindSlots = (serverError: ServerErrorBody['error']) => {\n const delivery = serverError?.kind === 'delivery_error';\n return {\n sdkOutdated:\n serverError?.kind === 'sdk_outdated'\n ? sdkOutdatedSchema.safeParse(serverError).data\n : undefined,\n serverOutdated:\n serverError?.kind === 'server_outdated'\n ? serverOutdatedSchema.safeParse(serverError).data\n : undefined,\n details: delivery\n ? undefined\n : (serverError?.details as SimulationRevert | undefined),\n delivery: delivery\n ? (serverError.details as DeliveryErrorDetails | undefined)\n : undefined,\n };\n};\n\n/**\n * Constructs a {@link ComposeError} from an HTTP error response, extracting\n * structured error details from the response body when available.\n *\n * @param status - The HTTP status code.\n * @param body - The raw response body text.\n * @param url - The request URL that produced the error.\n * @returns A `ComposeError` with the appropriate error code and metadata.\n */\nexport const errorFromHttpResponse = (\n status: number,\n body: string,\n url: string,\n): ComposeError => {\n const parsed = tryParseErrorBody(body);\n const serverError = parsed?.error;\n const slots = readKindSlots(serverError);\n\n return new ComposeError(\n STATUS_TO_CODE.get(status) ??\n (status >= 500 ? 'SERVER_ERROR' : 'UNKNOWN_ERROR'),\n (serverError?.message ?? body) || `HTTP ${status}`,\n {\n status,\n url,\n kind: serverError?.kind as\n ComposeErrorKind | ComposeRouteErrorKind | undefined,\n path: serverError?.path,\n port: serverError?.port,\n fix: serverError?.fix,\n ...slots,\n // The wire schema types `kind` as a bare string; the server only ever\n // reports generic kinds for individual ops.\n failedOps: serverError?.failedOps?.map((op) => ({\n ...op,\n kind: op.kind as GenericComposeErrorKind,\n })),\n succeededOps: serverError?.succeededOps,\n },\n );\n};\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { Address, IntegerStringInput } from "../types.cjs";
2
+ import { Flow } from "@lifi/compose-spec";
2
3
  //#region src/generated/config.generated.d.ts
3
4
  /**
4
5
  * a number between 0 and 10000
@@ -91,7 +92,7 @@ export interface LifiBridgeConfig {
91
92
  token: Address;
92
93
  chainId: Positive;
93
94
  };
94
- destination: StartsWith0X;
95
+ destination?: StartsWith0X;
95
96
  slippage?: Between01;
96
97
  timing?: {
97
98
  swapStepTimingStrategies?: {
@@ -879,6 +880,49 @@ export interface FlySwapConfig {
879
880
  inputVarianceBps?: Between03318;
880
881
  maxSlippageBps?: Between05000;
881
882
  }
883
+ /**
884
+ * a number between -8640000000000000 and 8640000000000000
885
+ */
886
+ export type Between86400000000000008640000000000000 = number;
887
+ export interface ContinuationSettleConfig {
888
+ /**
889
+ * @minItems 1
890
+ */
891
+ outcomes: [{
892
+ /**
893
+ * EVM address: 0x followed by 40 hex characters
894
+ */
895
+ token: Address;
896
+ minAmount?: IntegerStringInput;
897
+ /**
898
+ * EVM address: 0x followed by 40 hex characters
899
+ */
900
+ destination: Address;
901
+ chainId: Positive;
902
+ }, ...{
903
+ /**
904
+ * EVM address: 0x followed by 40 hex characters
905
+ */
906
+ token: Address;
907
+ minAmount?: IntegerStringInput;
908
+ /**
909
+ * EVM address: 0x followed by 40 hex characters
910
+ */
911
+ destination: Address;
912
+ chainId: Positive;
913
+ }[]];
914
+ continuationFlow?: Flow;
915
+ validity: {
916
+ expiresAtMs: Between86400000000000008640000000000000;
917
+ };
918
+ perpetual?: boolean;
919
+ provider?: string;
920
+ funding?: "inline" | "external";
921
+ /**
922
+ * EVM address: 0x followed by 40 hex characters
923
+ */
924
+ refund?: Address;
925
+ }
882
926
  export interface UniswapV2AddLiquidityConfig {
883
927
  /**
884
928
  * EVM address: 0x followed by 40 hex characters
@@ -951,6 +995,57 @@ export interface UniswapV3IncreaseLiquidityConfig {
951
995
  pool: string;
952
996
  tokenId: string;
953
997
  }
998
+ /**
999
+ * a number less than 1
1000
+ */
1001
+ export type LessThan1 = number;
1002
+ /**
1003
+ * a number between 1 and 300
1004
+ */
1005
+ export type Between1300 = number;
1006
+ /**
1007
+ * a number between 0 and 120
1008
+ */
1009
+ export type Between0120 = number;
1010
+ export interface LifiIntentsOrderConfig {
1011
+ resourceOut: {
1012
+ kind: "native";
1013
+ chainId: Positive;
1014
+ } | {
1015
+ kind: "erc20";
1016
+ /**
1017
+ * EVM address: 0x followed by 40 hex characters
1018
+ */
1019
+ token: Address;
1020
+ chainId: Positive;
1021
+ };
1022
+ destination?: StartsWith0X;
1023
+ slippage?: LessThan1;
1024
+ validitySeconds?: Between1300;
1025
+ exclusiveSeconds?: Between0120;
1026
+ }
1027
+ export interface LifiIntentsRefundConfig {
1028
+ /**
1029
+ * The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
1030
+ */
1031
+ orderId: string;
1032
+ }
1033
+ export interface LifiIntentsAttestNonFillConfig {
1034
+ /**
1035
+ * The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
1036
+ */
1037
+ orderId: string;
1038
+ }
1039
+ export interface LifiIntentsRefundOnNonFillConfig {
1040
+ /**
1041
+ * The order id: lifiIntents.order's delivery.trackingId, or topic1 of the escrow's Open log
1042
+ */
1043
+ orderId: string;
1044
+ /**
1045
+ * The output-chain transaction of lifiIntents.attestNonFill
1046
+ */
1047
+ attestationTxHash: string;
1048
+ }
954
1049
  export interface SlippageGuardConfig {
955
1050
  port: string;
956
1051
  bps: Between010000;