@polyester/sdk 0.23.1 → 0.24.1

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 (64) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/account-signer/types.d.ts +1 -1
  3. package/dist/account-signer/types.js.map +1 -1
  4. package/dist/core-client.d.ts.map +1 -1
  5. package/dist/core-client.js +18 -45
  6. package/dist/core-client.js.map +1 -1
  7. package/dist/gen/orders/v1/orders_read_pb.d.ts +136 -13
  8. package/dist/gen/orders/v1/orders_read_pb.d.ts.map +1 -1
  9. package/dist/gen/orders/v1/orders_read_pb.js +22 -16
  10. package/dist/gen/orders/v1/orders_read_pb.js.map +1 -1
  11. package/dist/index.d.ts +4 -3
  12. package/dist/realtime/client.js +45 -26
  13. package/dist/realtime/client.js.map +1 -1
  14. package/dist/services/auth/account-signer-auth.js +1 -1
  15. package/dist/services/auth/account-signer-auth.js.map +1 -1
  16. package/dist/services/candles/candles.schemas.d.ts +10 -10
  17. package/dist/services/heatmap/heatmap.schemas.d.ts +13 -13
  18. package/dist/services/market-overview/market-overview.js +5 -4
  19. package/dist/services/market-overview/market-overview.js.map +1 -1
  20. package/dist/services/market-overview/market-overview.schemas.d.ts +3 -3
  21. package/dist/services/orderbook/orderbook.schemas.d.ts +1 -1
  22. package/dist/services/orders/index.d.ts +4 -3
  23. package/dist/services/orders/order-lineage.schemas.d.ts +11 -0
  24. package/dist/services/orders/order-lineage.schemas.d.ts.map +1 -0
  25. package/dist/services/orders/order-lineage.schemas.js +13 -0
  26. package/dist/services/orders/order-lineage.schemas.js.map +1 -0
  27. package/dist/services/orders/orders-batch.schemas.d.ts +14 -14
  28. package/dist/services/orders/orders-batch.schemas.js +1 -1
  29. package/dist/services/orders/orders-input.schemas.d.ts +24 -1
  30. package/dist/services/orders/orders-input.schemas.d.ts.map +1 -1
  31. package/dist/services/orders/orders-input.schemas.js +5 -2
  32. package/dist/services/orders/orders-input.schemas.js.map +1 -1
  33. package/dist/services/orders/orders-modify.schemas.js +1 -1
  34. package/dist/services/orders/orders-output.schemas.d.ts +63 -20
  35. package/dist/services/orders/orders-output.schemas.d.ts.map +1 -1
  36. package/dist/services/orders/orders-output.schemas.js +7 -1
  37. package/dist/services/orders/orders-output.schemas.js.map +1 -1
  38. package/dist/services/orders/orders.d.ts +6 -2
  39. package/dist/services/orders/orders.d.ts.map +1 -1
  40. package/dist/services/orders/orders.js +6 -2
  41. package/dist/services/orders/orders.js.map +1 -1
  42. package/dist/services/orders/orders.schemas.d.ts +4 -3
  43. package/dist/services/orders/orders.types.d.ts +4 -3
  44. package/dist/services/subaccounts/subaccounts.schemas.d.ts +5 -5
  45. package/dist/services/trades/trades.d.ts +4 -0
  46. package/dist/services/trades/trades.d.ts.map +1 -1
  47. package/dist/services/trades/trades.js +4 -0
  48. package/dist/services/trades/trades.js.map +1 -1
  49. package/dist/services/trades/trades.schemas.d.ts +248 -4
  50. package/dist/services/trades/trades.schemas.d.ts.map +1 -1
  51. package/dist/services/trades/trades.schemas.js +52 -12
  52. package/dist/services/trades/trades.schemas.js.map +1 -1
  53. package/dist/services/triggers/trigger-input.schemas.d.ts +3 -3
  54. package/dist/services/triggers/triggers-output.schemas.d.ts +23 -23
  55. package/dist/shared/connect-error-mapping.d.ts.map +1 -1
  56. package/dist/shared/connect-error-mapping.js +15 -5
  57. package/dist/shared/connect-error-mapping.js.map +1 -1
  58. package/dist/shared/transports.d.ts +5 -1
  59. package/dist/shared/transports.d.ts.map +1 -1
  60. package/dist/shared/transports.js.map +1 -1
  61. package/dist/utils/errors.d.ts.map +1 -1
  62. package/dist/utils/errors.js +1 -0
  63. package/dist/utils/errors.js.map +1 -1
  64. package/package.json +1 -1
@@ -31,62 +31,62 @@ declare const CreateTriggerResultSchema: v.SchemaWithPipe<readonly [v.ObjectSche
31
31
  type CreateTriggerResult = v.InferOutput<typeof CreateTriggerResultSchema>;
32
32
  declare const CancelTriggerResultSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
33
33
  readonly triggerId: v.SchemaWithPipe<readonly [v.BigintSchema<undefined>, v.TransformAction<bigint, string>]>;
34
- readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused">]>;
34
+ readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused">]>;
35
35
  readonly tsNs: v.BigintSchema<undefined>;
36
36
  }, undefined>, v.TransformAction<{
37
37
  triggerId: string;
38
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
38
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
39
39
  tsNs: bigint;
40
40
  }, {
41
41
  ts: number;
42
42
  tsNs: string;
43
43
  triggerId: string;
44
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
44
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
45
45
  }>]>;
46
46
  type CancelTriggerResult = v.InferOutput<typeof CancelTriggerResultSchema>;
47
47
  declare const ModifyTriggerResultSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
48
48
  readonly triggerId: v.SchemaWithPipe<readonly [v.BigintSchema<undefined>, v.TransformAction<bigint, string>]>;
49
- readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused">]>;
49
+ readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused">]>;
50
50
  readonly tsNs: v.BigintSchema<undefined>;
51
51
  }, undefined>, v.TransformAction<{
52
52
  triggerId: string;
53
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
53
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
54
54
  tsNs: bigint;
55
55
  }, {
56
56
  ts: number;
57
57
  tsNs: string;
58
58
  triggerId: string;
59
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
59
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
60
60
  }>]>;
61
61
  type ModifyTriggerResult = v.InferOutput<typeof ModifyTriggerResultSchema>;
62
62
  declare const PauseTriggerResultSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
63
63
  readonly triggerId: v.SchemaWithPipe<readonly [v.BigintSchema<undefined>, v.TransformAction<bigint, string>]>;
64
- readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused">]>;
64
+ readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused">]>;
65
65
  readonly tsNs: v.BigintSchema<undefined>;
66
66
  }, undefined>, v.TransformAction<{
67
67
  triggerId: string;
68
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
68
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
69
69
  tsNs: bigint;
70
70
  }, {
71
71
  ts: number;
72
72
  tsNs: string;
73
73
  triggerId: string;
74
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
74
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
75
75
  }>]>;
76
76
  type PauseTriggerResult = v.InferOutput<typeof PauseTriggerResultSchema>;
77
77
  declare const ResumeTriggerResultSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
78
78
  readonly triggerId: v.SchemaWithPipe<readonly [v.BigintSchema<undefined>, v.TransformAction<bigint, string>]>;
79
- readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused">]>;
79
+ readonly status: v.SchemaWithPipe<readonly [v.EnumSchema<typeof TriggerStatus, undefined>, v.TransformAction<TriggerStatus, "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused">]>;
80
80
  readonly tsNs: v.BigintSchema<undefined>;
81
81
  }, undefined>, v.TransformAction<{
82
82
  triggerId: string;
83
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
83
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
84
84
  tsNs: bigint;
85
85
  }, {
86
86
  ts: number;
87
87
  tsNs: string;
88
88
  triggerId: string;
89
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
89
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
90
90
  }>]>;
91
91
  type ResumeTriggerResult = v.InferOutput<typeof ResumeTriggerResultSchema>;
92
92
  type StopDetailsOutput = {
@@ -553,12 +553,12 @@ declare function createTriggerSchema(scales: SdkScales): v.SchemaWithPipe<readon
553
553
  };
554
554
  }, {
555
555
  runtimeDetails: TriggerDetailsOutput;
556
- cancelReason: "unspecified" | "user_request" | "oco" | "parent_canceled_no_fill" | "missing_reason_code" | "internal_error";
556
+ cancelReason: "unspecified" | "oco" | "user_request" | "parent_canceled_no_fill" | "missing_reason_code" | "internal_error";
557
557
  failureReason: undefined;
558
558
  triggerId: string;
559
559
  subaccountId: string;
560
560
  symbolId: number;
561
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
561
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
562
562
  parentOrderId: string | undefined;
563
563
  qty: string;
564
564
  feeAsset: "unspecified" | "quote" | "base";
@@ -714,7 +714,7 @@ declare function createTriggerSchema(scales: SdkScales): v.SchemaWithPipe<readon
714
714
  triggerId: string;
715
715
  subaccountId: string;
716
716
  symbolId: number;
717
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
717
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
718
718
  parentOrderId: string | undefined;
719
719
  qty: string;
720
720
  feeAsset: "unspecified" | "quote" | "base";
@@ -870,7 +870,7 @@ declare function createTriggerSchema(scales: SdkScales): v.SchemaWithPipe<readon
870
870
  triggerId: string;
871
871
  subaccountId: string;
872
872
  symbolId: number;
873
- status: "unspecified" | "cancelled" | "created" | "failed" | "completed" | "armed" | "running" | "paused";
873
+ status: "unspecified" | "failed" | "cancelled" | "completed" | "created" | "armed" | "running" | "paused";
874
874
  parentOrderId: string | undefined;
875
875
  qty: string;
876
876
  feeAsset: "unspecified" | "quote" | "base";
@@ -1063,13 +1063,13 @@ declare function createTriggerEventSchema(scales: SdkScales): v.SchemaWithPipe<r
1063
1063
  value?: undefined;
1064
1064
  };
1065
1065
  }, {
1066
- cancelReason: "unspecified" | "user_request" | "oco" | "parent_canceled_no_fill" | "missing_reason_code" | "internal_error";
1066
+ cancelReason: "unspecified" | "oco" | "user_request" | "parent_canceled_no_fill" | "missing_reason_code" | "internal_error";
1067
1067
  failureReason: undefined;
1068
1068
  triggerId: string;
1069
1069
  subaccountId: string;
1070
1070
  symbolId: number;
1071
- triggerType: "unspecified" | "twap" | "ladder" | "stop_loss" | "take_profit" | "trailing_stop";
1072
- eventType: "unspecified" | "updated" | "failed" | "fired" | "canceled";
1071
+ triggerType: "unspecified" | "stop_loss" | "take_profit" | "trailing_stop" | "twap" | "ladder";
1072
+ eventType: "unspecified" | "failed" | "updated" | "canceled" | "fired";
1073
1073
  ts: number;
1074
1074
  childSeq: number;
1075
1075
  childOrderId: string | undefined;
@@ -1080,8 +1080,8 @@ declare function createTriggerEventSchema(scales: SdkScales): v.SchemaWithPipe<r
1080
1080
  triggerId: string;
1081
1081
  subaccountId: string;
1082
1082
  symbolId: number;
1083
- triggerType: "unspecified" | "twap" | "ladder" | "stop_loss" | "take_profit" | "trailing_stop";
1084
- eventType: "unspecified" | "updated" | "failed" | "fired" | "canceled";
1083
+ triggerType: "unspecified" | "stop_loss" | "take_profit" | "trailing_stop" | "twap" | "ladder";
1084
+ eventType: "unspecified" | "failed" | "updated" | "canceled" | "fired";
1085
1085
  ts: number;
1086
1086
  childSeq: number;
1087
1087
  childOrderId: string | undefined;
@@ -1092,8 +1092,8 @@ declare function createTriggerEventSchema(scales: SdkScales): v.SchemaWithPipe<r
1092
1092
  triggerId: string;
1093
1093
  subaccountId: string;
1094
1094
  symbolId: number;
1095
- triggerType: "unspecified" | "twap" | "ladder" | "stop_loss" | "take_profit" | "trailing_stop";
1096
- eventType: "unspecified" | "updated" | "failed" | "fired" | "canceled";
1095
+ triggerType: "unspecified" | "stop_loss" | "take_profit" | "trailing_stop" | "twap" | "ladder";
1096
+ eventType: "unspecified" | "failed" | "updated" | "canceled" | "fired";
1097
1097
  ts: number;
1098
1098
  childSeq: number;
1099
1099
  childOrderId: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"connect-error-mapping.d.ts","names":[],"sources":["../../src/shared/connect-error-mapping.ts"],"mappings":";;;;;;;iBA+HgB,6BAA6B,IAAI,eAAe;;;;;;iBAsJhD,iBAAiB;;;;;;iBAyBjB,iCAAiC"}
1
+ {"version":3,"file":"connect-error-mapping.d.ts","names":[],"sources":["../../src/shared/connect-error-mapping.ts"],"mappings":";;;;;;;iBA+HgB,6BAA6B,IAAI,eAAe;;;;;;iBAsJhD,iBAAiB;;;;;;iBA0CjB,iCAAiC"}
@@ -146,11 +146,19 @@ function toPolyesterError(err) {
146
146
  }
147
147
  return err;
148
148
  }
149
- async function* mapStreamErrors(source) {
149
+ function callerAbortError(signal) {
150
+ const reason = signal.reason;
151
+ return reason instanceof DOMException && reason.name === "AbortError" ? reason : new DOMException("Request canceled.", "AbortError");
152
+ }
153
+ function toTransportError(err, signal) {
154
+ if (signal?.aborted && err instanceof ConnectError && err.code === Code.Canceled) return callerAbortError(signal);
155
+ return toPolyesterError(err);
156
+ }
157
+ async function* mapStreamErrors(source, signal) {
150
158
  try {
151
159
  yield* source;
152
160
  } catch (err) {
153
- throw toPolyesterError(err);
161
+ throw toTransportError(err, signal);
154
162
  }
155
163
  }
156
164
  /**
@@ -179,21 +187,23 @@ function createErrorMappingInterceptor() {
179
187
  function createErrorMappingTransport(transport) {
180
188
  return {
181
189
  async unary(method, signal, timeoutMs, header, input, contextValues) {
190
+ if (signal?.aborted) throw callerAbortError(signal);
182
191
  try {
183
192
  return await transport.unary(method, signal, timeoutMs, header, input, contextValues);
184
193
  } catch (error) {
185
- throw toPolyesterError(error);
194
+ throw toTransportError(error, signal);
186
195
  }
187
196
  },
188
197
  async stream(method, signal, timeoutMs, header, input, contextValues) {
198
+ if (signal?.aborted) throw callerAbortError(signal);
189
199
  try {
190
200
  const response = await transport.stream(method, signal, timeoutMs, header, input, contextValues);
191
201
  return {
192
202
  ...response,
193
- message: mapStreamErrors(response.message)
203
+ message: mapStreamErrors(response.message, signal)
194
204
  };
195
205
  } catch (error) {
196
- throw toPolyesterError(error);
206
+ throw toTransportError(error, signal);
197
207
  }
198
208
  }
199
209
  };
@@ -1 +1 @@
1
- {"version":3,"file":"connect-error-mapping.js","names":[],"sources":["../../src/shared/connect-error-mapping.ts"],"sourcesContent":["import { Code, ConnectError, type Interceptor, type Transport } from \"@connectrpc/connect\";\nimport { parseConnectErrorDetail, type PolyesterErrorDetail } from \"./error-detail.js\";\nimport {\n AlreadyExistsError,\n AuthenticationError,\n InternalServerError,\n isAbortError,\n MfaEnrollmentRequiredError,\n MfaLastFactorRequiredError,\n MfaVerificationError,\n type MfaVerificationFailureReason,\n normalizeErrorMessage,\n PermissionError,\n PolicyInUseError,\n PolicyLockedError,\n PolicyScopeMismatchError,\n PolyesterError,\n type PolyesterErrorOptions,\n PreconditionFailedError,\n RateLimitError,\n ResourceNotFoundError,\n RevisionConflictError,\n ServiceUnavailableError,\n SessionElevationRequiredError,\n StaleQuoteError,\n StepUpRequiredError,\n TimeoutError,\n TransientError,\n ValidationError,\n} from \"./errors.js\";\nimport type { RateLimitDetail } from \"./rate-limit.schemas.js\";\n\nfunction hasTransientTransferError(detail: PolyesterErrorDetail | undefined): boolean {\n if (detail?.service === \"withdraw\") {\n return [\n \"SERVICE_UNAVAILABLE\",\n \"SOURCE_SMART_ACCOUNT_UNAVAILABLE\",\n \"CAPITAL_VIEW_UNAVAILABLE\",\n \"CHAIN_METADATA_UNAVAILABLE\",\n \"FEE_UNAVAILABLE\",\n \"SUPPLY_UNAVAILABLE\",\n \"STEP_UP_UNAVAILABLE\",\n \"DESTINATION_VALIDATION_UNAVAILABLE\",\n \"ACCOUNT_SHARD_UNAVAILABLE\",\n ].includes(detail.code);\n }\n if (detail?.service === \"internal_transfer\") {\n return [\n \"SERVICE_UNAVAILABLE\",\n \"SMART_ACCOUNT_UNAVAILABLE\",\n \"STEP_UP_UNAVAILABLE\",\n \"CAPITAL_VIEW_UNAVAILABLE\",\n \"ACCOUNT_SHARD_UNAVAILABLE\",\n ].includes(detail.code);\n }\n return false;\n}\n\nfunction safeRetryAfterMs(rateLimit: RateLimitDetail | undefined): number | undefined {\n if (rateLimit?.retryAfterMs === undefined) return undefined;\n const value = BigInt(rateLimit.retryAfterMs);\n return value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : undefined;\n}\n\nconst HTTP_WEEKDAY = \"(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\";\nconst HTTP_WEEKDAY_LONG = \"(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)\";\nconst HTTP_MONTH = \"(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\";\nconst HTTP_DATE_RE = new RegExp(\n `^(?:${HTTP_WEEKDAY}, \\\\d{2} ${HTTP_MONTH} \\\\d{4} \\\\d{2}:\\\\d{2}:\\\\d{2} GMT|${HTTP_WEEKDAY_LONG}, \\\\d{2}-${HTTP_MONTH}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2} GMT|${HTTP_WEEKDAY} ${HTTP_MONTH} {1,2}\\\\d{1,2} \\\\d{2}:\\\\d{2}:\\\\d{2} \\\\d{4})$`,\n \"u\",\n);\n\n/**\n * Returns the error message without the leading \"[code] \" prefix that\n * `ConnectError` prepends, e.g. \"[invalid_argument] Insufficient funds.\"\n * becomes \"Insufficient funds.\".\n */\nexport function getNormalizedConnectMessage(err: unknown): string {\n const ce = ConnectError.from(err);\n const raw = ce.message ?? \"\";\n return normalizeErrorMessage(raw);\n}\n\nexport type MfaErrorKind = \"session-elevation\" | \"enrollment\" | \"step-up\";\n\n/**\n * Classifies an error as one of the MFA flows the backend can demand.\n * Classification is based only on stable structured auth error details.\n */\nexport function detectMfaErrorKind(err: unknown): MfaErrorKind | null {\n const mapped = toPolyesterError(err);\n return mfaErrorKind(mapped instanceof PolyesterError ? mapped.detail : undefined);\n}\n\nfunction mfaErrorKind(detail: PolyesterErrorDetail | undefined): MfaErrorKind | null {\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_ELEVATION_REQUIRED\") {\n return \"session-elevation\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_STEP_UP_REQUIRED\") return \"step-up\";\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_NOT_ENROLLED\") return \"enrollment\";\n return null;\n}\n\nfunction parseRetryAfterMs(ce: ConnectError): number | undefined {\n const value = ce.metadata.get(\"retry-after\");\n if (!value) return undefined;\n if (/^\\d+$/u.test(value)) {\n const seconds = BigInt(value);\n const maxSafeSeconds = BigInt(Math.floor(Number.MAX_SAFE_INTEGER / 1000));\n return seconds <= maxSafeSeconds ? Number(seconds) * 1000 : undefined;\n }\n if (!HTTP_DATE_RE.test(value)) return undefined;\n const date = Date.parse(value);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return undefined;\n}\n\nconst MFA_ERROR_CLASSES = {\n \"session-elevation\": SessionElevationRequiredError,\n enrollment: MfaEnrollmentRequiredError,\n \"step-up\": StepUpRequiredError,\n} as const;\n\n/**\n * Maps a `ConnectError` from the Polyester backend onto the typed\n * {@link PolyesterError} tree. The original error is preserved as `cause`.\n */\nexport function connectErrorToPolyesterError(ce: ConnectError): PolyesterError {\n const message = getNormalizedConnectMessage(ce);\n const detail = parseConnectErrorDetail(ce);\n const options: PolyesterErrorOptions = { cause: ce, detail };\n const withFallback = (fallback: string) => message || fallback;\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_RESOURCE_NOT_FOUND\") {\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n }\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_REVISION_CONFLICT\") {\n return new RevisionConflictError(\n withFallback(\"Resource changed since it was last read.\"),\n options,\n );\n }\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_IN_USE\") {\n return new PolicyInUseError(withFallback(\"Policy is still in use.\"), options);\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_LOCKED\") {\n return new PolicyLockedError(withFallback(\"Policy is locked.\"), options);\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_SCOPE_MISMATCH\") {\n return new PolicyScopeMismatchError(\n withFallback(\"Policy does not belong to the target account scope.\"),\n options,\n );\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_LAST_FACTOR_REQUIRED\") {\n return new MfaLastFactorRequiredError(\n withFallback(\"At least one active MFA factor must remain enrolled.\"),\n options,\n );\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_INTERNAL_ERROR\") {\n return new InternalServerError(withFallback(\"Internal server error.\"), options);\n }\n\n const mfaVerificationReason = getMfaVerificationFailureReason(detail);\n if (mfaVerificationReason) {\n return new MfaVerificationError(\n withFallback(\"MFA verification failed.\"),\n mfaVerificationReason,\n options,\n );\n }\n\n const mfaKind = mfaErrorKind(detail);\n if (mfaKind) {\n return new MFA_ERROR_CLASSES[mfaKind](\n withFallback(\"Multi-factor authentication required.\"),\n options,\n );\n }\n\n if (detail?.service === \"orders\" && detail.code === \"STALE_QUOTE\") {\n return new StaleQuoteError(withFallback(\"The submitted market quote is stale.\"), options);\n }\n\n const rateLimit = detail?.service === \"orders\" ? detail.rateLimit : undefined;\n if (\n rateLimit ||\n ((detail?.service === \"orders\" ||\n detail?.service === \"withdraw\" ||\n detail?.service === \"internal_transfer\") &&\n detail.code === \"RATE_LIMIT_EXCEEDED\")\n ) {\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n rateLimit,\n retryAfterMs: safeRetryAfterMs(rateLimit) ?? parseRetryAfterMs(ce),\n });\n }\n\n if (hasTransientTransferError(detail)) {\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n }\n\n switch (ce.code) {\n case Code.InvalidArgument:\n case Code.OutOfRange:\n return new ValidationError(withFallback(\"Invalid request.\"), options);\n case Code.NotFound:\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n case Code.AlreadyExists:\n return new AlreadyExistsError(withFallback(\"Resource already exists.\"), options);\n case Code.PermissionDenied:\n return new PermissionError(withFallback(\"Permission denied.\"), options);\n case Code.Unauthenticated:\n return new AuthenticationError(withFallback(\"Authentication required.\"), options);\n case Code.FailedPrecondition:\n return new PreconditionFailedError(withFallback(\"Precondition failed.\"), options);\n case Code.ResourceExhausted:\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n retryAfterMs: parseRetryAfterMs(ce),\n });\n case Code.DeadlineExceeded:\n return new TimeoutError(withFallback(\"Request timed out.\"), options);\n case Code.Unavailable:\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n case Code.Aborted:\n return new TransientError(withFallback(\"Operation aborted by the backend.\"), options);\n default:\n // Gateways sometimes surface outages as Unknown with this stock phrase.\n if (/service temporarily unavailable/i.test(message)) {\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n }\n return new InternalServerError(withFallback(\"Internal server error.\"), options);\n }\n}\n\nfunction getMfaVerificationFailureReason(\n detail: PolyesterErrorDetail | undefined,\n): MfaVerificationFailureReason | null {\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_CHALLENGE_INVALID\") {\n return \"challenge-invalid\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_CHALLENGE_LOCKED\") {\n return \"challenge-locked\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_OTP_INVALID\") return \"otp-invalid\";\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_RECOVERY_INVALID\") {\n return \"recovery-code-invalid\";\n }\n if (\n (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_PASSKEY_CREDENTIAL_INVALID\") ||\n (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_PASSKEY_VERIFY_FAILED\")\n ) {\n return \"passkey-invalid\";\n }\n\n return null;\n}\n\nfunction findPolyesterErrorInCauseChain(err: unknown): PolyesterError | null {\n let current: unknown = err;\n for (let depth = 0; depth < 5 && current instanceof Error; depth++) {\n current = current.cause;\n if (current instanceof PolyesterError) return current;\n }\n return null;\n}\n\n/**\n * Converts any RPC-layer failure into its typed SDK error. Abort errors and\n * caller-cancelled requests pass through unchanged, as do errors that are\n * already typed (e.g. a `NetworkError` from the SDK fetch wrapper).\n */\nexport function toPolyesterError(err: unknown): unknown {\n if (err instanceof PolyesterError) return err;\n if (isAbortError(err)) return err;\n if (err instanceof ConnectError) {\n if (err.code === Code.Canceled) return err;\n const wrapped = findPolyesterErrorInCauseChain(err);\n if (wrapped) return wrapped;\n return connectErrorToPolyesterError(err);\n }\n return err;\n}\n\nasync function* mapStreamErrors<T>(source: AsyncIterable<T>): AsyncIterable<T> {\n try {\n yield* source;\n } catch (err) {\n throw toPolyesterError(err);\n }\n}\n\n/**\n * Interceptor that converts every RPC failure (unary and streaming) into the\n * typed {@link PolyesterError} hierarchy. Installed outermost by\n * `createTransports`, so callers of SDK services always see typed errors.\n */\nexport function createErrorMappingInterceptor(): Interceptor {\n return (next) => async (req) => {\n try {\n const res = await next(req);\n if (res.stream) {\n return { ...res, message: mapStreamErrors(res.message) };\n }\n return res;\n } catch (err) {\n throw toPolyesterError(err);\n }\n };\n}\n\n/**\n * Wraps a Connect transport so errors are translated after Connect's call\n * runner has applied its own error normalization.\n */\nexport function createErrorMappingTransport(transport: Transport): Transport {\n return {\n async unary(method, signal, timeoutMs, header, input, contextValues) {\n try {\n return await transport.unary(\n method,\n signal,\n timeoutMs,\n header,\n input,\n contextValues,\n );\n } catch (error) {\n throw toPolyesterError(error);\n }\n },\n async stream(method, signal, timeoutMs, header, input, contextValues) {\n try {\n const response = await transport.stream(\n method,\n signal,\n timeoutMs,\n header,\n input,\n contextValues,\n );\n return { ...response, message: mapStreamErrors(response.message) };\n } catch (error) {\n throw toPolyesterError(error);\n }\n },\n };\n}\n"],"mappings":";;;;AAgCA,SAAS,0BAA0B,QAAmD;CAClF,IAAI,QAAQ,YAAY,YACpB,OAAO;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ,CAAC,CAAC,SAAS,OAAO,IAAI;CAE1B,IAAI,QAAQ,YAAY,qBACpB,OAAO;EACH;EACA;EACA;EACA;EACA;CACJ,CAAC,CAAC,SAAS,OAAO,IAAI;CAE1B,OAAO;AACX;AAEA,SAAS,iBAAiB,WAA4D;CAClF,IAAI,WAAW,iBAAiB,KAAA,GAAW,OAAO,KAAA;CAClD,MAAM,QAAQ,OAAO,UAAU,YAAY;CAC3C,OAAO,SAAS,OAAO,OAAO,gBAAgB,IAAI,OAAO,KAAK,IAAI,KAAA;AACtE;AAEA,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,aAAa;AACnB,MAAM,eAAe,IAAI,OACrB,OAAO,aAAa,WAAW,WAAW,mCAAmC,kBAAkB,WAAW,WAAW,mCAAmC,aAAa,GAAG,WAAW,+CACnL,GACJ;;;;;;AAOA,SAAgB,4BAA4B,KAAsB;CAE9D,MAAM,MADK,aAAa,KAAK,GAChB,CAAC,CAAC,WAAW;CAC1B,OAAO,sBAAsB,GAAG;AACpC;AAaA,SAAS,aAAa,QAA+D;CACjF,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,+BAC9C,OAAO;CAEX,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,yBAAyB,OAAO;CAClF,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,yBAAyB,OAAO;CAClF,OAAO;AACX;AAEA,SAAS,kBAAkB,IAAsC;CAC7D,MAAM,QAAQ,GAAG,SAAS,IAAI,aAAa;CAC3C,IAAI,CAAC,OAAO,OAAO,KAAA;CACnB,IAAI,SAAS,KAAK,KAAK,GAAG;EACtB,MAAM,UAAU,OAAO,KAAK;EAE5B,OAAO,WADgB,OAAO,KAAK,MAAM,OAAO,mBAAmB,GAAI,CACxC,IAAI,OAAO,OAAO,IAAI,MAAO,KAAA;CAChE;CACA,IAAI,CAAC,aAAa,KAAK,KAAK,GAAG,OAAO,KAAA;CACtC,MAAM,OAAO,KAAK,MAAM,KAAK;CAC7B,IAAI,CAAC,OAAO,MAAM,IAAI,GAAG,OAAO,KAAK,IAAI,GAAG,OAAO,KAAK,IAAI,CAAC;AAEjE;AAEA,MAAM,oBAAoB;CACtB,qBAAqB;CACrB,YAAY;CACZ,WAAW;AACf;;;;;AAMA,SAAgB,6BAA6B,IAAkC;CAC3E,MAAM,UAAU,4BAA4B,EAAE;CAC9C,MAAM,SAAS,wBAAwB,EAAE;CACzC,MAAM,UAAiC;EAAE,OAAO;EAAI;CAAO;CAC3D,MAAM,gBAAgB,aAAqB,WAAW;CAEtD,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,2BAC9C,OAAO,IAAI,sBAAsB,aAAa,qBAAqB,GAAG,OAAO;CAGjF,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,0BAC9C,OAAO,IAAI,sBACP,aAAa,0CAA0C,GACvD,OACJ;CAGJ,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,sBAC9C,OAAO,IAAI,iBAAiB,aAAa,yBAAyB,GAAG,OAAO;CAEhF,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,sBAC9C,OAAO,IAAI,kBAAkB,aAAa,mBAAmB,GAAG,OAAO;CAE3E,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,8BAC9C,OAAO,IAAI,yBACP,aAAa,qDAAqD,GAClE,OACJ;CAEJ,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,iCAC9C,OAAO,IAAI,2BACP,aAAa,sDAAsD,GACnE,OACJ;CAEJ,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,uBAC9C,OAAO,IAAI,oBAAoB,aAAa,wBAAwB,GAAG,OAAO;CAGlF,MAAM,wBAAwB,gCAAgC,MAAM;CACpE,IAAI,uBACA,OAAO,IAAI,qBACP,aAAa,0BAA0B,GACvC,uBACA,OACJ;CAGJ,MAAM,UAAU,aAAa,MAAM;CACnC,IAAI,SACA,OAAO,IAAI,kBAAkB,SACzB,aAAa,uCAAuC,GACpD,OACJ;CAGJ,IAAI,QAAQ,YAAY,YAAY,OAAO,SAAS,eAChD,OAAO,IAAI,gBAAgB,aAAa,sCAAsC,GAAG,OAAO;CAG5F,MAAM,YAAY,QAAQ,YAAY,WAAW,OAAO,YAAY,KAAA;CACpE,IACI,cACE,QAAQ,YAAY,YAClB,QAAQ,YAAY,cACpB,QAAQ,YAAY,wBACpB,OAAO,SAAS,uBAEpB,OAAO,IAAI,eAAe,aAAa,sBAAsB,GAAG;EAC5D,GAAG;EACH;EACA,cAAc,iBAAiB,SAAS,KAAK,kBAAkB,EAAE;CACrE,CAAC;CAGL,IAAI,0BAA0B,MAAM,GAChC,OAAO,IAAI,wBAAwB,aAAa,sBAAsB,GAAG,OAAO;CAGpF,QAAQ,GAAG,MAAX;EACI,KAAK,KAAK;EACV,KAAK,KAAK,YACN,OAAO,IAAI,gBAAgB,aAAa,kBAAkB,GAAG,OAAO;EACxE,KAAK,KAAK,UACN,OAAO,IAAI,sBAAsB,aAAa,qBAAqB,GAAG,OAAO;EACjF,KAAK,KAAK,eACN,OAAO,IAAI,mBAAmB,aAAa,0BAA0B,GAAG,OAAO;EACnF,KAAK,KAAK,kBACN,OAAO,IAAI,gBAAgB,aAAa,oBAAoB,GAAG,OAAO;EAC1E,KAAK,KAAK,iBACN,OAAO,IAAI,oBAAoB,aAAa,0BAA0B,GAAG,OAAO;EACpF,KAAK,KAAK,oBACN,OAAO,IAAI,wBAAwB,aAAa,sBAAsB,GAAG,OAAO;EACpF,KAAK,KAAK,mBACN,OAAO,IAAI,eAAe,aAAa,sBAAsB,GAAG;GAC5D,GAAG;GACH,cAAc,kBAAkB,EAAE;EACtC,CAAC;EACL,KAAK,KAAK,kBACN,OAAO,IAAI,aAAa,aAAa,oBAAoB,GAAG,OAAO;EACvE,KAAK,KAAK,aACN,OAAO,IAAI,wBAAwB,aAAa,sBAAsB,GAAG,OAAO;EACpF,KAAK,KAAK,SACN,OAAO,IAAI,eAAe,aAAa,mCAAmC,GAAG,OAAO;EACxF;GAEI,IAAI,mCAAmC,KAAK,OAAO,GAC/C,OAAO,IAAI,wBAAwB,aAAa,sBAAsB,GAAG,OAAO;GAEpF,OAAO,IAAI,oBAAoB,aAAa,wBAAwB,GAAG,OAAO;CACtF;AACJ;AAEA,SAAS,gCACL,QACmC;CACnC,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,8BAC9C,OAAO;CAEX,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,6BAC9C,OAAO;CAEX,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,wBAAwB,OAAO;CACjF,IAAI,QAAQ,YAAY,UAAU,OAAO,SAAS,6BAC9C,OAAO;CAEX,IACK,QAAQ,YAAY,UAAU,OAAO,SAAS,yCAC9C,QAAQ,YAAY,UAAU,OAAO,SAAS,kCAE/C,OAAO;CAGX,OAAO;AACX;AAEA,SAAS,+BAA+B,KAAqC;CACzE,IAAI,UAAmB;CACvB,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,mBAAmB,OAAO,SAAS;EAChE,UAAU,QAAQ;EAClB,IAAI,mBAAmB,gBAAgB,OAAO;CAClD;CACA,OAAO;AACX;;;;;;AAOA,SAAgB,iBAAiB,KAAuB;CACpD,IAAI,eAAe,gBAAgB,OAAO;CAC1C,IAAI,aAAa,GAAG,GAAG,OAAO;CAC9B,IAAI,eAAe,cAAc;EAC7B,IAAI,IAAI,SAAS,KAAK,UAAU,OAAO;EACvC,MAAM,UAAU,+BAA+B,GAAG;EAClD,IAAI,SAAS,OAAO;EACpB,OAAO,6BAA6B,GAAG;CAC3C;CACA,OAAO;AACX;AAEA,gBAAgB,gBAAmB,QAA4C;CAC3E,IAAI;EACA,OAAO;CACX,SAAS,KAAK;EACV,MAAM,iBAAiB,GAAG;CAC9B;AACJ;;;;;;AAOA,SAAgB,gCAA6C;CACzD,QAAQ,SAAS,OAAO,QAAQ;EAC5B,IAAI;GACA,MAAM,MAAM,MAAM,KAAK,GAAG;GAC1B,IAAI,IAAI,QACJ,OAAO;IAAE,GAAG;IAAK,SAAS,gBAAgB,IAAI,OAAO;GAAE;GAE3D,OAAO;EACX,SAAS,KAAK;GACV,MAAM,iBAAiB,GAAG;EAC9B;CACJ;AACJ;;;;;AAMA,SAAgB,4BAA4B,WAAiC;CACzE,OAAO;EACH,MAAM,MAAM,QAAQ,QAAQ,WAAW,QAAQ,OAAO,eAAe;GACjE,IAAI;IACA,OAAO,MAAM,UAAU,MACnB,QACA,QACA,WACA,QACA,OACA,aACJ;GACJ,SAAS,OAAO;IACZ,MAAM,iBAAiB,KAAK;GAChC;EACJ;EACA,MAAM,OAAO,QAAQ,QAAQ,WAAW,QAAQ,OAAO,eAAe;GAClE,IAAI;IACA,MAAM,WAAW,MAAM,UAAU,OAC7B,QACA,QACA,WACA,QACA,OACA,aACJ;IACA,OAAO;KAAE,GAAG;KAAU,SAAS,gBAAgB,SAAS,OAAO;IAAE;GACrE,SAAS,OAAO;IACZ,MAAM,iBAAiB,KAAK;GAChC;EACJ;CACJ;AACJ"}
1
+ {"version":3,"file":"connect-error-mapping.js","names":[],"sources":["../../src/shared/connect-error-mapping.ts"],"sourcesContent":["import { Code, ConnectError, type Interceptor, type Transport } from \"@connectrpc/connect\";\nimport { parseConnectErrorDetail, type PolyesterErrorDetail } from \"./error-detail.js\";\nimport {\n AlreadyExistsError,\n AuthenticationError,\n InternalServerError,\n isAbortError,\n MfaEnrollmentRequiredError,\n MfaLastFactorRequiredError,\n MfaVerificationError,\n type MfaVerificationFailureReason,\n normalizeErrorMessage,\n PermissionError,\n PolicyInUseError,\n PolicyLockedError,\n PolicyScopeMismatchError,\n PolyesterError,\n type PolyesterErrorOptions,\n PreconditionFailedError,\n RateLimitError,\n ResourceNotFoundError,\n RevisionConflictError,\n ServiceUnavailableError,\n SessionElevationRequiredError,\n StaleQuoteError,\n StepUpRequiredError,\n TimeoutError,\n TransientError,\n ValidationError,\n} from \"./errors.js\";\nimport type { RateLimitDetail } from \"./rate-limit.schemas.js\";\n\nfunction hasTransientTransferError(detail: PolyesterErrorDetail | undefined): boolean {\n if (detail?.service === \"withdraw\") {\n return [\n \"SERVICE_UNAVAILABLE\",\n \"SOURCE_SMART_ACCOUNT_UNAVAILABLE\",\n \"CAPITAL_VIEW_UNAVAILABLE\",\n \"CHAIN_METADATA_UNAVAILABLE\",\n \"FEE_UNAVAILABLE\",\n \"SUPPLY_UNAVAILABLE\",\n \"STEP_UP_UNAVAILABLE\",\n \"DESTINATION_VALIDATION_UNAVAILABLE\",\n \"ACCOUNT_SHARD_UNAVAILABLE\",\n ].includes(detail.code);\n }\n if (detail?.service === \"internal_transfer\") {\n return [\n \"SERVICE_UNAVAILABLE\",\n \"SMART_ACCOUNT_UNAVAILABLE\",\n \"STEP_UP_UNAVAILABLE\",\n \"CAPITAL_VIEW_UNAVAILABLE\",\n \"ACCOUNT_SHARD_UNAVAILABLE\",\n ].includes(detail.code);\n }\n return false;\n}\n\nfunction safeRetryAfterMs(rateLimit: RateLimitDetail | undefined): number | undefined {\n if (rateLimit?.retryAfterMs === undefined) return undefined;\n const value = BigInt(rateLimit.retryAfterMs);\n return value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : undefined;\n}\n\nconst HTTP_WEEKDAY = \"(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\";\nconst HTTP_WEEKDAY_LONG = \"(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)\";\nconst HTTP_MONTH = \"(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\";\nconst HTTP_DATE_RE = new RegExp(\n `^(?:${HTTP_WEEKDAY}, \\\\d{2} ${HTTP_MONTH} \\\\d{4} \\\\d{2}:\\\\d{2}:\\\\d{2} GMT|${HTTP_WEEKDAY_LONG}, \\\\d{2}-${HTTP_MONTH}-\\\\d{2} \\\\d{2}:\\\\d{2}:\\\\d{2} GMT|${HTTP_WEEKDAY} ${HTTP_MONTH} {1,2}\\\\d{1,2} \\\\d{2}:\\\\d{2}:\\\\d{2} \\\\d{4})$`,\n \"u\",\n);\n\n/**\n * Returns the error message without the leading \"[code] \" prefix that\n * `ConnectError` prepends, e.g. \"[invalid_argument] Insufficient funds.\"\n * becomes \"Insufficient funds.\".\n */\nexport function getNormalizedConnectMessage(err: unknown): string {\n const ce = ConnectError.from(err);\n const raw = ce.message ?? \"\";\n return normalizeErrorMessage(raw);\n}\n\nexport type MfaErrorKind = \"session-elevation\" | \"enrollment\" | \"step-up\";\n\n/**\n * Classifies an error as one of the MFA flows the backend can demand.\n * Classification is based only on stable structured auth error details.\n */\nexport function detectMfaErrorKind(err: unknown): MfaErrorKind | null {\n const mapped = toPolyesterError(err);\n return mfaErrorKind(mapped instanceof PolyesterError ? mapped.detail : undefined);\n}\n\nfunction mfaErrorKind(detail: PolyesterErrorDetail | undefined): MfaErrorKind | null {\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_ELEVATION_REQUIRED\") {\n return \"session-elevation\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_STEP_UP_REQUIRED\") return \"step-up\";\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_NOT_ENROLLED\") return \"enrollment\";\n return null;\n}\n\nfunction parseRetryAfterMs(ce: ConnectError): number | undefined {\n const value = ce.metadata.get(\"retry-after\");\n if (!value) return undefined;\n if (/^\\d+$/u.test(value)) {\n const seconds = BigInt(value);\n const maxSafeSeconds = BigInt(Math.floor(Number.MAX_SAFE_INTEGER / 1000));\n return seconds <= maxSafeSeconds ? Number(seconds) * 1000 : undefined;\n }\n if (!HTTP_DATE_RE.test(value)) return undefined;\n const date = Date.parse(value);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return undefined;\n}\n\nconst MFA_ERROR_CLASSES = {\n \"session-elevation\": SessionElevationRequiredError,\n enrollment: MfaEnrollmentRequiredError,\n \"step-up\": StepUpRequiredError,\n} as const;\n\n/**\n * Maps a `ConnectError` from the Polyester backend onto the typed\n * {@link PolyesterError} tree. The original error is preserved as `cause`.\n */\nexport function connectErrorToPolyesterError(ce: ConnectError): PolyesterError {\n const message = getNormalizedConnectMessage(ce);\n const detail = parseConnectErrorDetail(ce);\n const options: PolyesterErrorOptions = { cause: ce, detail };\n const withFallback = (fallback: string) => message || fallback;\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_RESOURCE_NOT_FOUND\") {\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n }\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_REVISION_CONFLICT\") {\n return new RevisionConflictError(\n withFallback(\"Resource changed since it was last read.\"),\n options,\n );\n }\n\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_IN_USE\") {\n return new PolicyInUseError(withFallback(\"Policy is still in use.\"), options);\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_LOCKED\") {\n return new PolicyLockedError(withFallback(\"Policy is locked.\"), options);\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_POLICY_SCOPE_MISMATCH\") {\n return new PolicyScopeMismatchError(\n withFallback(\"Policy does not belong to the target account scope.\"),\n options,\n );\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_LAST_FACTOR_REQUIRED\") {\n return new MfaLastFactorRequiredError(\n withFallback(\"At least one active MFA factor must remain enrolled.\"),\n options,\n );\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_INTERNAL_ERROR\") {\n return new InternalServerError(withFallback(\"Internal server error.\"), options);\n }\n\n const mfaVerificationReason = getMfaVerificationFailureReason(detail);\n if (mfaVerificationReason) {\n return new MfaVerificationError(\n withFallback(\"MFA verification failed.\"),\n mfaVerificationReason,\n options,\n );\n }\n\n const mfaKind = mfaErrorKind(detail);\n if (mfaKind) {\n return new MFA_ERROR_CLASSES[mfaKind](\n withFallback(\"Multi-factor authentication required.\"),\n options,\n );\n }\n\n if (detail?.service === \"orders\" && detail.code === \"STALE_QUOTE\") {\n return new StaleQuoteError(withFallback(\"The submitted market quote is stale.\"), options);\n }\n\n const rateLimit = detail?.service === \"orders\" ? detail.rateLimit : undefined;\n if (\n rateLimit ||\n ((detail?.service === \"orders\" ||\n detail?.service === \"withdraw\" ||\n detail?.service === \"internal_transfer\") &&\n detail.code === \"RATE_LIMIT_EXCEEDED\")\n ) {\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n rateLimit,\n retryAfterMs: safeRetryAfterMs(rateLimit) ?? parseRetryAfterMs(ce),\n });\n }\n\n if (hasTransientTransferError(detail)) {\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n }\n\n switch (ce.code) {\n case Code.InvalidArgument:\n case Code.OutOfRange:\n return new ValidationError(withFallback(\"Invalid request.\"), options);\n case Code.NotFound:\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n case Code.AlreadyExists:\n return new AlreadyExistsError(withFallback(\"Resource already exists.\"), options);\n case Code.PermissionDenied:\n return new PermissionError(withFallback(\"Permission denied.\"), options);\n case Code.Unauthenticated:\n return new AuthenticationError(withFallback(\"Authentication required.\"), options);\n case Code.FailedPrecondition:\n return new PreconditionFailedError(withFallback(\"Precondition failed.\"), options);\n case Code.ResourceExhausted:\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n retryAfterMs: parseRetryAfterMs(ce),\n });\n case Code.DeadlineExceeded:\n return new TimeoutError(withFallback(\"Request timed out.\"), options);\n case Code.Unavailable:\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n case Code.Aborted:\n return new TransientError(withFallback(\"Operation aborted by the backend.\"), options);\n default:\n // Gateways sometimes surface outages as Unknown with this stock phrase.\n if (/service temporarily unavailable/i.test(message)) {\n return new ServiceUnavailableError(withFallback(\"Service unavailable.\"), options);\n }\n return new InternalServerError(withFallback(\"Internal server error.\"), options);\n }\n}\n\nfunction getMfaVerificationFailureReason(\n detail: PolyesterErrorDetail | undefined,\n): MfaVerificationFailureReason | null {\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_CHALLENGE_INVALID\") {\n return \"challenge-invalid\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_CHALLENGE_LOCKED\") {\n return \"challenge-locked\";\n }\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_OTP_INVALID\") return \"otp-invalid\";\n if (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_RECOVERY_INVALID\") {\n return \"recovery-code-invalid\";\n }\n if (\n (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_PASSKEY_CREDENTIAL_INVALID\") ||\n (detail?.service === \"auth\" && detail.code === \"AUTH_MFA_PASSKEY_VERIFY_FAILED\")\n ) {\n return \"passkey-invalid\";\n }\n\n return null;\n}\n\nfunction findPolyesterErrorInCauseChain(err: unknown): PolyesterError | null {\n let current: unknown = err;\n for (let depth = 0; depth < 5 && current instanceof Error; depth++) {\n current = current.cause;\n if (current instanceof PolyesterError) return current;\n }\n return null;\n}\n\n/**\n * Converts any RPC-layer failure into its typed SDK error. Abort errors and\n * caller-cancelled requests pass through unchanged, as do errors that are\n * already typed (e.g. a `NetworkError` from the SDK fetch wrapper).\n */\nexport function toPolyesterError(err: unknown): unknown {\n if (err instanceof PolyesterError) return err;\n if (isAbortError(err)) return err;\n if (err instanceof ConnectError) {\n if (err.code === Code.Canceled) return err;\n const wrapped = findPolyesterErrorInCauseChain(err);\n if (wrapped) return wrapped;\n return connectErrorToPolyesterError(err);\n }\n return err;\n}\n\nfunction callerAbortError(signal: AbortSignal): DOMException {\n const reason: unknown = signal.reason;\n return reason instanceof DOMException && reason.name === \"AbortError\"\n ? reason\n : new DOMException(\"Request canceled.\", \"AbortError\");\n}\n\nfunction toTransportError(err: unknown, signal?: AbortSignal): unknown {\n if (signal?.aborted && err instanceof ConnectError && err.code === Code.Canceled) {\n return callerAbortError(signal);\n }\n return toPolyesterError(err);\n}\n\nasync function* mapStreamErrors<T>(\n source: AsyncIterable<T>,\n signal?: AbortSignal,\n): AsyncIterable<T> {\n try {\n yield* source;\n } catch (err) {\n throw toTransportError(err, signal);\n }\n}\n\n/**\n * Interceptor that converts every RPC failure (unary and streaming) into the\n * typed {@link PolyesterError} hierarchy. Installed outermost by\n * `createTransports`, so callers of SDK services always see typed errors.\n */\nexport function createErrorMappingInterceptor(): Interceptor {\n return (next) => async (req) => {\n try {\n const res = await next(req);\n if (res.stream) {\n return { ...res, message: mapStreamErrors(res.message) };\n }\n return res;\n } catch (err) {\n throw toPolyesterError(err);\n }\n };\n}\n\n/**\n * Wraps a Connect transport so errors are translated after Connect's call\n * runner has applied its own error normalization.\n */\nexport function createErrorMappingTransport(transport: Transport): Transport {\n return {\n async unary(method, signal, timeoutMs, header, input, contextValues) {\n if (signal?.aborted) throw callerAbortError(signal);\n try {\n return await transport.unary(\n method,\n signal,\n timeoutMs,\n header,\n input,\n contextValues,\n );\n } catch (error) {\n throw toTransportError(error, signal);\n }\n },\n async stream(method, signal, timeoutMs, header, input, contextValues) {\n if (signal?.aborted) throw callerAbortError(signal);\n try {\n const response = await transport.stream(\n method,\n signal,\n timeoutMs,\n header,\n input,\n contextValues,\n );\n return { ...response, message: mapStreamErrors(response.message, signal) };\n } catch (error) {\n throw toTransportError(error, signal);\n }\n },\n };\n}\n"],"mappings":"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"}
@@ -16,7 +16,11 @@ type AuthAndPublicApiTransports = Pick<Transports, "authApi" | "publicApi">;
16
16
  */
17
17
  interface JwtAuthProvider {
18
18
  kind: "jwt";
19
- /** Typically wraps the configured browser auth token storage. */
19
+ /**
20
+ * Typically wraps the configured browser auth token storage. The SDK reads
21
+ * the current value for every request and for every realtime auth check, so
22
+ * keep this cheap and return the freshest credential rather than caching.
23
+ */
20
24
  getToken: () => string | null | Promise<string | null>;
21
25
  }
22
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"transports.d.ts","names":[],"sources":["../../src/shared/transports.ts"],"mappings":";;;UA8BiB;EACb,SAAS;EACT,WAAW;;;KAIH,oBAAoB,KAAK;;KAGzB,sBAAsB,KAAK;;KAG3B,6BAA6B,KAAK;;;;UAK7B;EACb;;EAEA,gCAAgC;;;;;;UAOnB;EACb;EACA,gCAAgC;;EAEhC,oBAAoB,oBAAoB,QAAQ"}
1
+ {"version":3,"file":"transports.d.ts","names":[],"sources":["../../src/shared/transports.ts"],"mappings":";;;UA8BiB;EACb,SAAS;EACT,WAAW;;;KAIH,oBAAoB,KAAK;;KAGzB,sBAAsB,KAAK;;KAG3B,6BAA6B,KAAK;;;;UAK7B;EACb;;;;;;EAMA,gCAAgC;;;;;;UAOnB;EACb;EACA,gCAAgC;;EAEhC,oBAAoB,oBAAoB,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"transports.js","names":[],"sources":["../../src/shared/transports.ts"],"sourcesContent":["import { createConnectTransport } from \"@connectrpc/connect-web\";\nimport type { Transport, Interceptor } from \"@connectrpc/connect\";\nimport { toBinary, toJsonString } from \"@bufbuild/protobuf\";\nimport { signAsync } from \"@noble/ed25519\";\nimport { createErrorMappingTransport } from \"./connect-error-mapping.js\";\nimport {\n AuthenticationError,\n ConfigurationError,\n isAbortError,\n NetworkError,\n PolyesterError,\n} from \"./errors.js\";\n\nexport { isAbortError };\n\nexport type ConnectWireFormat = \"binary\" | \"json\";\n\nexport const POLYESTER_MOCK_HEADER = \"x-polyester-mock\";\n\nexport interface TransportConfig {\n apiUrl: string;\n interceptors?: Interceptor[];\n auth?: JwtAuthProvider | ApiKeyEd25519AuthProvider;\n /**\n * Connect wire format. Defaults to binary for production performance.\n * Use `json` for the API Playground visualization.\n */\n wireFormat?: ConnectWireFormat;\n}\n\nexport interface Transports {\n authApi: Transport;\n publicApi: Transport;\n}\n\n/** Connect transports available to services that call authenticated APIs. */\nexport type AuthApiTransports = Pick<Transports, \"authApi\">;\n\n/** Connect transports available to services that call public APIs. */\nexport type PublicApiTransports = Pick<Transports, \"publicApi\">;\n\n/** Connect transports available to services that call both public and authenticated APIs. */\nexport type AuthAndPublicApiTransports = Pick<Transports, \"authApi\" | \"publicApi\">;\n\n/**\n * Generic JWT auth for HTTP/Connect endpoints that follow the Bearer token contract.\n */\nexport interface JwtAuthProvider {\n kind: \"jwt\";\n /** Typically wraps the configured browser auth token storage. */\n getToken: () => string | null | Promise<string | null>;\n}\n\n/**\n * Generic Ed25519 API key auth for HTTP/Connect endpoints that follow the\n * X-API-KEY-ID / X-API-TIMESTAMP / X-API-SIGNATURE contract.\n */\nexport interface ApiKeyEd25519AuthProvider {\n kind: \"api-key-ed25519\";\n getKeyId: () => string | null | Promise<string | null>;\n /** Ed25519 secret key bytes (not hex) for signing. */\n getSecretKey: () => Uint8Array | null | Promise<Uint8Array | null>;\n}\n\nexport interface ApiKeyEd25519SigningRequest {\n url: string | URL;\n method: string;\n body?: Uint8Array;\n timestamp?: string;\n}\n\n/**\n * Returns the fetch implementation used by SDK transports.\n */\nexport function makeFetch(): typeof fetch {\n const wrappedFetch = Object.assign(\n async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n // Normalize headers into a mutable Headers object\n const headers = new Headers(init?.headers);\n\n try {\n const res = await fetch(input, {\n ...init,\n headers,\n redirect: \"manual\",\n });\n\n return res;\n } catch (err) {\n if (isAbortError(err)) throw err;\n throw new NetworkError(\"Transport request failed\", { cause: err });\n }\n },\n fetch,\n );\n\n return wrappedFetch;\n}\n\n/**\n * Creates Connect transports for SDK service clients.\n */\nexport function createTransports(config: TransportConfig): Transports {\n const { apiUrl, interceptors = [], auth, wireFormat = \"binary\" } = config;\n const useBinaryFormat = wireFormat === \"binary\";\n const publicApi = createErrorMappingTransport(\n createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors,\n fetch: makeFetch(),\n }),\n );\n\n const authInterceptors = auth\n ? auth.kind === \"jwt\"\n ? [createAuthInterceptor(auth, { wireFormat }), ...interceptors]\n : [...interceptors, createAuthInterceptor(auth, { wireFormat })]\n : interceptors;\n const authApi = createErrorMappingTransport(\n createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors: authInterceptors,\n fetch: makeFetch(),\n }),\n );\n\n return { authApi, publicApi };\n}\n\n/**\n * Creates an interceptor that enables mock transport behavior.\n */\nexport function createMockInterceptor(getEnabled: () => boolean): Interceptor {\n return (next) => async (req) => {\n if (getEnabled()) req.header.set(POLYESTER_MOCK_HEADER, \"true\");\n return next(req);\n };\n}\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n if (typeof crypto === \"undefined\" || !crypto.subtle) {\n throw new ConfigurationError(\"SHA-256 not available in this environment\");\n }\n const hash = await crypto.subtle.digest(\"SHA-256\", bytes.slice());\n return Array.from(new Uint8Array(hash), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nlet lastTimestamp = 0;\nfunction nextTimestamp(): string {\n lastTimestamp = Math.max(lastTimestamp + 1, Date.now());\n return String(lastTimestamp);\n}\n\nfunction canonicalQueryString(params: URLSearchParams): string {\n const pairs: string[] = [];\n for (const [k, v] of params.entries()) {\n pairs.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`);\n }\n pairs.sort();\n return pairs.join(\"&\");\n}\n\n/**\n * Creates API-key authentication headers for endpoints using the Polyester Ed25519 signing contract.\n */\nexport async function createApiKeyEd25519AuthHeaders(\n auth: ApiKeyEd25519AuthProvider,\n request: ApiKeyEd25519SigningRequest,\n): Promise<Record<string, string>> {\n let keyId: string | null;\n let secretKey: Uint8Array | null;\n try {\n [keyId, secretKey] = await Promise.all([auth.getKeyId(), auth.getSecretKey()]);\n } catch (cause) {\n if (cause instanceof PolyesterError) throw cause;\n throw new ConfigurationError(\"API key credential provider failed\", { cause });\n }\n if (!keyId || !secretKey) throw new ConfigurationError(\"Missing API key ID or secret key\");\n if (!(secretKey instanceof Uint8Array) || secretKey.byteLength !== 32) {\n throw new ConfigurationError(\"API key secret key must contain exactly 32 bytes\");\n }\n\n const urlObj = new URL(request.url);\n const timestamp = request.timestamp ?? nextTimestamp();\n const bodyHash = await sha256Hex(request.body ?? new Uint8Array(0));\n const canonicalQuery = canonicalQueryString(urlObj.searchParams);\n const canonical = `${timestamp}\\n${request.method}\\n${urlObj.pathname}\\n${canonicalQuery}\\n${bodyHash}`;\n const msgBytes = new TextEncoder().encode(canonical);\n const sig = await signAsync(msgBytes, secretKey);\n const signatureHex = Array.from(sig, (b: number) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\n return {\n \"X-API-KEY-ID\": keyId,\n \"X-API-TIMESTAMP\": timestamp,\n \"X-API-SIGNATURE\": signatureHex,\n };\n}\n\n/**\n * Resolves a JWT credential and translates provider failures or invalid values\n * into stable SDK errors.\n */\nexport async function resolveJwtToken(auth: JwtAuthProvider): Promise<string | null> {\n let token: string | null;\n try {\n token = await auth.getToken();\n } catch (cause) {\n if (cause instanceof PolyesterError) throw cause;\n throw new AuthenticationError(\"JWT token provider failed\", { cause });\n }\n if (token !== null && typeof token !== \"string\") {\n throw new ConfigurationError(\"JWT token provider must return a string or null\");\n }\n return token;\n}\n\n/**\n * Creates an interceptor that attaches SDK authentication headers.\n */\nexport function createAuthInterceptor(\n auth: JwtAuthProvider | ApiKeyEd25519AuthProvider,\n options?: { wireFormat?: ConnectWireFormat },\n): Interceptor {\n return (next) => async (req) => {\n const wireFormat = options?.wireFormat ?? \"binary\";\n if (auth.kind === \"jwt\") {\n const token = await resolveJwtToken(auth);\n if (token) {\n req.header.set(\"Authorization\", `Bearer ${token}`);\n }\n } else if (auth.kind === \"api-key-ed25519\") {\n if (req.stream) {\n throw new ConfigurationError(\n \"API key authentication does not support streaming Connect RPCs\",\n );\n }\n // Unary request: serialize the message using the method's input schema.\n const inputSchema = req.method.input;\n const bodyBytes =\n wireFormat === \"json\"\n ? new TextEncoder().encode(toJsonString(inputSchema, req.message))\n : toBinary(inputSchema, req.message);\n\n const headers = await createApiKeyEd25519AuthHeaders(auth, {\n url: req.url,\n method: req.requestMethod,\n body: bodyBytes,\n });\n for (const [key, value] of Object.entries(headers)) {\n req.header.set(key, value);\n }\n }\n return next(req);\n };\n}\n"],"mappings":";;;;;;;;;AA0EA,SAAgB,YAA0B;CAsBtC,OArBqB,OAAO,OACxB,OAAO,OAAoC,SAAuC;EAE9E,MAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;EAEzC,IAAI;GAOA,OAAO,MANW,MAAM,OAAO;IAC3B,GAAG;IACH;IACA,UAAU;GACd,CAAC;EAGL,SAAS,KAAK;GACV,IAAI,aAAa,GAAG,GAAG,MAAM;GAC7B,MAAM,IAAI,aAAa,4BAA4B,EAAE,OAAO,IAAI,CAAC;EACrE;CACJ,GACA,KAGc;AACtB;;;;AAKA,SAAgB,iBAAiB,QAAqC;CAClE,MAAM,EAAE,QAAQ,eAAe,CAAC,GAAG,MAAM,aAAa,aAAa;CACnE,MAAM,kBAAkB,eAAe;CACvC,MAAM,YAAY,4BACd,uBAAuB;EACnB,SAAS;EACT;EACA;EACA,OAAO,UAAU;CACrB,CAAC,CACL;CAEA,MAAM,mBAAmB,OACnB,KAAK,SAAS,QACV,CAAC,sBAAsB,MAAM,EAAE,WAAW,CAAC,GAAG,GAAG,YAAY,IAC7D,CAAC,GAAG,cAAc,sBAAsB,MAAM,EAAE,WAAW,CAAC,CAAC,IACjE;CAUN,OAAO;EAAE,SATO,4BACZ,uBAAuB;GACnB,SAAS;GACT;GACA,cAAc;GACd,OAAO,UAAU;EACrB,CAAC,CAGU;EAAG;CAAU;AAChC;AAYA,eAAe,UAAU,OAAoC;CACzD,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,QACzC,MAAM,IAAI,mBAAmB,2CAA2C;CAE5E,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,MAAM,MAAM,CAAC;CAChE,OAAO,MAAM,KAAK,IAAI,WAAW,IAAI,IAAI,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AAC3F;AAEA,IAAI,gBAAgB;AACpB,SAAS,gBAAwB;CAC7B,gBAAgB,KAAK,IAAI,gBAAgB,GAAG,KAAK,IAAI,CAAC;CACtD,OAAO,OAAO,aAAa;AAC/B;AAEA,SAAS,qBAAqB,QAAiC;CAC3D,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,GAChC,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,GAAG,mBAAmB,CAAC,GAAG;CAElE,MAAM,KAAK;CACX,OAAO,MAAM,KAAK,GAAG;AACzB;;;;AAKA,eAAsB,+BAClB,MACA,SAC+B;CAC/B,IAAI;CACJ,IAAI;CACJ,IAAI;EACA,CAAC,OAAO,aAAa,MAAM,QAAQ,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,aAAa,CAAC,CAAC;CACjF,SAAS,OAAO;EACZ,IAAI,iBAAiB,gBAAgB,MAAM;EAC3C,MAAM,IAAI,mBAAmB,sCAAsC,EAAE,MAAM,CAAC;CAChF;CACA,IAAI,CAAC,SAAS,CAAC,WAAW,MAAM,IAAI,mBAAmB,kCAAkC;CACzF,IAAI,EAAE,qBAAqB,eAAe,UAAU,eAAe,IAC/D,MAAM,IAAI,mBAAmB,kDAAkD;CAGnF,MAAM,SAAS,IAAI,IAAI,QAAQ,GAAG;CAClC,MAAM,YAAY,QAAQ,aAAa,cAAc;CACrD,MAAM,WAAW,MAAM,UAAU,QAAQ,wBAAQ,IAAI,WAAW,CAAC,CAAC;CAClE,MAAM,iBAAiB,qBAAqB,OAAO,YAAY;CAC/D,MAAM,YAAY,GAAG,UAAU,IAAI,QAAQ,OAAO,IAAI,OAAO,SAAS,IAAI,eAAe,IAAI;CAC7F,MAAM,WAAW,IAAI,YAAY,CAAC,CAAC,OAAO,SAAS;CACnD,MAAM,MAAM,MAAM,UAAU,UAAU,SAAS;CAC/C,MAAM,eAAe,MAAM,KAAK,MAAM,MAAc,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;CAE5F,OAAO;EACH,gBAAgB;EAChB,mBAAmB;EACnB,mBAAmB;CACvB;AACJ;;;;;AAMA,eAAsB,gBAAgB,MAA+C;CACjF,IAAI;CACJ,IAAI;EACA,QAAQ,MAAM,KAAK,SAAS;CAChC,SAAS,OAAO;EACZ,IAAI,iBAAiB,gBAAgB,MAAM;EAC3C,MAAM,IAAI,oBAAoB,6BAA6B,EAAE,MAAM,CAAC;CACxE;CACA,IAAI,UAAU,QAAQ,OAAO,UAAU,UACnC,MAAM,IAAI,mBAAmB,iDAAiD;CAElF,OAAO;AACX;;;;AAKA,SAAgB,sBACZ,MACA,SACW;CACX,QAAQ,SAAS,OAAO,QAAQ;EAC5B,MAAM,aAAa,SAAS,cAAc;EAC1C,IAAI,KAAK,SAAS,OAAO;GACrB,MAAM,QAAQ,MAAM,gBAAgB,IAAI;GACxC,IAAI,OACA,IAAI,OAAO,IAAI,iBAAiB,UAAU,OAAO;EAEzD,OAAO,IAAI,KAAK,SAAS,mBAAmB;GACxC,IAAI,IAAI,QACJ,MAAM,IAAI,mBACN,gEACJ;GAGJ,MAAM,cAAc,IAAI,OAAO;GAC/B,MAAM,YACF,eAAe,SACT,IAAI,YAAY,CAAC,CAAC,OAAO,aAAa,aAAa,IAAI,OAAO,CAAC,IAC/D,SAAS,aAAa,IAAI,OAAO;GAE3C,MAAM,UAAU,MAAM,+BAA+B,MAAM;IACvD,KAAK,IAAI;IACT,QAAQ,IAAI;IACZ,MAAM;GACV,CAAC;GACD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC7C,IAAI,OAAO,IAAI,KAAK,KAAK;EAEjC;EACA,OAAO,KAAK,GAAG;CACnB;AACJ"}
1
+ {"version":3,"file":"transports.js","names":[],"sources":["../../src/shared/transports.ts"],"sourcesContent":["import { createConnectTransport } from \"@connectrpc/connect-web\";\nimport type { Transport, Interceptor } from \"@connectrpc/connect\";\nimport { toBinary, toJsonString } from \"@bufbuild/protobuf\";\nimport { signAsync } from \"@noble/ed25519\";\nimport { createErrorMappingTransport } from \"./connect-error-mapping.js\";\nimport {\n AuthenticationError,\n ConfigurationError,\n isAbortError,\n NetworkError,\n PolyesterError,\n} from \"./errors.js\";\n\nexport { isAbortError };\n\nexport type ConnectWireFormat = \"binary\" | \"json\";\n\nexport const POLYESTER_MOCK_HEADER = \"x-polyester-mock\";\n\nexport interface TransportConfig {\n apiUrl: string;\n interceptors?: Interceptor[];\n auth?: JwtAuthProvider | ApiKeyEd25519AuthProvider;\n /**\n * Connect wire format. Defaults to binary for production performance.\n * Use `json` for the API Playground visualization.\n */\n wireFormat?: ConnectWireFormat;\n}\n\nexport interface Transports {\n authApi: Transport;\n publicApi: Transport;\n}\n\n/** Connect transports available to services that call authenticated APIs. */\nexport type AuthApiTransports = Pick<Transports, \"authApi\">;\n\n/** Connect transports available to services that call public APIs. */\nexport type PublicApiTransports = Pick<Transports, \"publicApi\">;\n\n/** Connect transports available to services that call both public and authenticated APIs. */\nexport type AuthAndPublicApiTransports = Pick<Transports, \"authApi\" | \"publicApi\">;\n\n/**\n * Generic JWT auth for HTTP/Connect endpoints that follow the Bearer token contract.\n */\nexport interface JwtAuthProvider {\n kind: \"jwt\";\n /**\n * Typically wraps the configured browser auth token storage. The SDK reads\n * the current value for every request and for every realtime auth check, so\n * keep this cheap and return the freshest credential rather than caching.\n */\n getToken: () => string | null | Promise<string | null>;\n}\n\n/**\n * Generic Ed25519 API key auth for HTTP/Connect endpoints that follow the\n * X-API-KEY-ID / X-API-TIMESTAMP / X-API-SIGNATURE contract.\n */\nexport interface ApiKeyEd25519AuthProvider {\n kind: \"api-key-ed25519\";\n getKeyId: () => string | null | Promise<string | null>;\n /** Ed25519 secret key bytes (not hex) for signing. */\n getSecretKey: () => Uint8Array | null | Promise<Uint8Array | null>;\n}\n\nexport interface ApiKeyEd25519SigningRequest {\n url: string | URL;\n method: string;\n body?: Uint8Array;\n timestamp?: string;\n}\n\n/**\n * Returns the fetch implementation used by SDK transports.\n */\nexport function makeFetch(): typeof fetch {\n const wrappedFetch = Object.assign(\n async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n // Normalize headers into a mutable Headers object\n const headers = new Headers(init?.headers);\n\n try {\n const res = await fetch(input, {\n ...init,\n headers,\n redirect: \"manual\",\n });\n\n return res;\n } catch (err) {\n if (isAbortError(err)) throw err;\n throw new NetworkError(\"Transport request failed\", { cause: err });\n }\n },\n fetch,\n );\n\n return wrappedFetch;\n}\n\n/**\n * Creates Connect transports for SDK service clients.\n */\nexport function createTransports(config: TransportConfig): Transports {\n const { apiUrl, interceptors = [], auth, wireFormat = \"binary\" } = config;\n const useBinaryFormat = wireFormat === \"binary\";\n const publicApi = createErrorMappingTransport(\n createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors,\n fetch: makeFetch(),\n }),\n );\n\n const authInterceptors = auth\n ? auth.kind === \"jwt\"\n ? [createAuthInterceptor(auth, { wireFormat }), ...interceptors]\n : [...interceptors, createAuthInterceptor(auth, { wireFormat })]\n : interceptors;\n const authApi = createErrorMappingTransport(\n createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors: authInterceptors,\n fetch: makeFetch(),\n }),\n );\n\n return { authApi, publicApi };\n}\n\n/**\n * Creates an interceptor that enables mock transport behavior.\n */\nexport function createMockInterceptor(getEnabled: () => boolean): Interceptor {\n return (next) => async (req) => {\n if (getEnabled()) req.header.set(POLYESTER_MOCK_HEADER, \"true\");\n return next(req);\n };\n}\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n if (typeof crypto === \"undefined\" || !crypto.subtle) {\n throw new ConfigurationError(\"SHA-256 not available in this environment\");\n }\n const hash = await crypto.subtle.digest(\"SHA-256\", bytes.slice());\n return Array.from(new Uint8Array(hash), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nlet lastTimestamp = 0;\nfunction nextTimestamp(): string {\n lastTimestamp = Math.max(lastTimestamp + 1, Date.now());\n return String(lastTimestamp);\n}\n\nfunction canonicalQueryString(params: URLSearchParams): string {\n const pairs: string[] = [];\n for (const [k, v] of params.entries()) {\n pairs.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`);\n }\n pairs.sort();\n return pairs.join(\"&\");\n}\n\n/**\n * Creates API-key authentication headers for endpoints using the Polyester Ed25519 signing contract.\n */\nexport async function createApiKeyEd25519AuthHeaders(\n auth: ApiKeyEd25519AuthProvider,\n request: ApiKeyEd25519SigningRequest,\n): Promise<Record<string, string>> {\n let keyId: string | null;\n let secretKey: Uint8Array | null;\n try {\n [keyId, secretKey] = await Promise.all([auth.getKeyId(), auth.getSecretKey()]);\n } catch (cause) {\n if (cause instanceof PolyesterError) throw cause;\n throw new ConfigurationError(\"API key credential provider failed\", { cause });\n }\n if (!keyId || !secretKey) throw new ConfigurationError(\"Missing API key ID or secret key\");\n if (!(secretKey instanceof Uint8Array) || secretKey.byteLength !== 32) {\n throw new ConfigurationError(\"API key secret key must contain exactly 32 bytes\");\n }\n\n const urlObj = new URL(request.url);\n const timestamp = request.timestamp ?? nextTimestamp();\n const bodyHash = await sha256Hex(request.body ?? new Uint8Array(0));\n const canonicalQuery = canonicalQueryString(urlObj.searchParams);\n const canonical = `${timestamp}\\n${request.method}\\n${urlObj.pathname}\\n${canonicalQuery}\\n${bodyHash}`;\n const msgBytes = new TextEncoder().encode(canonical);\n const sig = await signAsync(msgBytes, secretKey);\n const signatureHex = Array.from(sig, (b: number) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\n return {\n \"X-API-KEY-ID\": keyId,\n \"X-API-TIMESTAMP\": timestamp,\n \"X-API-SIGNATURE\": signatureHex,\n };\n}\n\n/**\n * Resolves a JWT credential and translates provider failures or invalid values\n * into stable SDK errors.\n */\nexport async function resolveJwtToken(auth: JwtAuthProvider): Promise<string | null> {\n let token: string | null;\n try {\n token = await auth.getToken();\n } catch (cause) {\n if (cause instanceof PolyesterError) throw cause;\n throw new AuthenticationError(\"JWT token provider failed\", { cause });\n }\n if (token !== null && typeof token !== \"string\") {\n throw new ConfigurationError(\"JWT token provider must return a string or null\");\n }\n return token;\n}\n\n/**\n * Creates an interceptor that attaches SDK authentication headers.\n */\nexport function createAuthInterceptor(\n auth: JwtAuthProvider | ApiKeyEd25519AuthProvider,\n options?: { wireFormat?: ConnectWireFormat },\n): Interceptor {\n return (next) => async (req) => {\n const wireFormat = options?.wireFormat ?? \"binary\";\n if (auth.kind === \"jwt\") {\n const token = await resolveJwtToken(auth);\n if (token) {\n req.header.set(\"Authorization\", `Bearer ${token}`);\n }\n } else if (auth.kind === \"api-key-ed25519\") {\n if (req.stream) {\n throw new ConfigurationError(\n \"API key authentication does not support streaming Connect RPCs\",\n );\n }\n // Unary request: serialize the message using the method's input schema.\n const inputSchema = req.method.input;\n const bodyBytes =\n wireFormat === \"json\"\n ? new TextEncoder().encode(toJsonString(inputSchema, req.message))\n : toBinary(inputSchema, req.message);\n\n const headers = await createApiKeyEd25519AuthHeaders(auth, {\n url: req.url,\n method: req.requestMethod,\n body: bodyBytes,\n });\n for (const [key, value] of Object.entries(headers)) {\n req.header.set(key, value);\n }\n }\n return next(req);\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/utils/errors.ts"],"mappings":";;;;;;iBAqBgB,wBAAwB;;iBAaxB,wBAAwB;;iBAsBxB,mBAAmB;;iBAKnB,oBAAoB;;iBAKpB,2BAA2B;;;;;;iBAS3B,iBAAiB;;;;;;;;;;;iBAuBjB,mBACZ,cACA;iBA0CY,sBAAsB,gBAAgB"}
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/utils/errors.ts"],"mappings":";;;;;;iBAqBgB,wBAAwB;;iBAaxB,wBAAwB;;iBAsBxB,mBAAmB;;iBAKnB,oBAAoB;;iBAKpB,2BAA2B;;;;;;iBAS3B,iBAAiB;;;;;;;;;;;iBAuBjB,mBACZ,cACA;iBA2CY,sBAAsB,gBAAgB"}
@@ -71,6 +71,7 @@ function formatConnectError(err, fallback = "Request failed. Please try again.")
71
71
  * returns the caller-owned fallback.
72
72
  */
73
73
  function userFacingTransportMessage(error) {
74
+ if (isAbortError(error)) return "Request canceled.";
74
75
  if (error instanceof RateLimitError) return "You've made too many requests. Wait a moment and try again.";
75
76
  if (error instanceof TimeoutError) return "This is taking longer than expected. Try again.";
76
77
  if (error instanceof ServiceUnavailableError) return "This service is temporarily unavailable. Try again in a few minutes.";
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/utils/errors.ts"],"sourcesContent":["import { Code, ConnectError } from \"@connectrpc/connect\";\nimport { getNormalizedConnectMessage, toPolyesterError } from \"../shared/connect-error-mapping.js\";\nimport {\n isAbortError,\n NetworkError,\n PolicyInUseError,\n PolicyLockedError,\n PolicyScopeMismatchError,\n PolyesterError,\n RateLimitError,\n ResourceNotFoundError,\n RevisionConflictError,\n ServiceUnavailableError,\n TimeoutError,\n} from \"../shared/errors.js\";\n\n/**\n * Whether the backend signalled that the requested resource does not exist.\n * Prefer `err instanceof ResourceNotFoundError`; this predicate also covers\n * raw `ConnectError`s (NotFound or the auth resource-not-found detail).\n */\nexport function isResourceNotFoundError(err: unknown): boolean {\n // Connect can re-wrap interceptor errors as an Unknown ConnectError whose\n // cause is the typed SDK error. Normalize first to recover that cause.\n const mapped = toPolyesterError(err);\n return (\n mapped instanceof ResourceNotFoundError ||\n (mapped instanceof PolyesterError &&\n mapped.detail?.service === \"auth\" &&\n mapped.detail.code === \"AUTH_RESOURCE_NOT_FOUND\")\n );\n}\n\n/** Whether an optimistic-concurrency update used a stale resource revision. */\nexport function isRevisionConflictError(err: unknown): boolean {\n const seen = new Set<unknown>();\n let current = err;\n while (current !== undefined && current !== null && !seen.has(current)) {\n seen.add(current);\n if (toPolyesterError(current) instanceof RevisionConflictError) return true;\n const connectError = ConnectError.from(current);\n if (\n (connectError.code === Code.Unknown || connectError.code === Code.Aborted) &&\n /\\brevision conflict\\b/i.test(getNormalizedConnectMessage(connectError))\n ) {\n return true;\n }\n current =\n typeof current === \"object\" && \"cause\" in current\n ? (current as { cause?: unknown }).cause\n : undefined;\n }\n return false;\n}\n\n/** Whether a policy mutation failed because the policy is still attached to a resource. */\nexport function isPolicyInUseError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyInUseError;\n}\n\n/** Whether a policy mutation failed because the policy is locked. */\nexport function isPolicyLockedError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyLockedError;\n}\n\n/** Whether the policy and target account belong to different scopes. */\nexport function isPolicyScopeMismatchError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyScopeMismatchError;\n}\n\n/**\n * Whether an error is retryable (network/timeout) for idempotent operations.\n * Uses same requestId on retry; backend dedupes within 2min.\n * Prefer `err instanceof TransientError` or `err.retryable` on typed errors.\n */\nexport function isRetryableError(err: unknown): boolean {\n if (isAbortError(err)) return false;\n const mapped = toPolyesterError(err);\n if (mapped instanceof PolyesterError) return mapped.retryable;\n const ce = ConnectError.from(mapped);\n return (\n ce.code === Code.Unavailable ||\n ce.code === Code.DeadlineExceeded ||\n ce.code === Code.ResourceExhausted ||\n ce.code === Code.Aborted\n );\n}\n\n/**\n * Diagnostic formatter for SDK and ConnectRPC errors.\n * Typed SDK errors already carry normalized messages; for raw ConnectErrors\n * this strips leading \"[CODE]\" prefixes. Falls back to a friendly default.\n * The returned message may contain backend implementation details. Never render\n * it to a user; use {@link formatUserFacingError} at presentation boundaries.\n * @param err - The error to format.\n * @param fallback - The fallback message when no message is available.\n * @returns The formatted error message.\n */\nexport function formatConnectError(\n err: unknown,\n fallback = \"Request failed. Please try again.\",\n): string {\n if (err == null) return fallback;\n if (err instanceof PolyesterError) return err.message || fallback;\n const withoutCode = getNormalizedConnectMessage(err);\n return withoutCode || fallback;\n}\n\n/**\n * Formats an untrusted failure for direct display to a user.\n *\n * This function never returns an exception or backend message. A small allowlist\n * of typed transport conditions receives SDK-owned copy; every other failure\n * returns the caller-owned fallback.\n */\nfunction userFacingTransportMessage(error: unknown): string | undefined {\n if (error instanceof RateLimitError) {\n return \"You've made too many requests. Wait a moment and try again.\";\n }\n if (error instanceof TimeoutError) return \"This is taking longer than expected. Try again.\";\n if (error instanceof ServiceUnavailableError) {\n return \"This service is temporarily unavailable. Try again in a few minutes.\";\n }\n if (error instanceof NetworkError) {\n return \"We couldn't connect. Check your internet connection and try again.\";\n }\n\n if (error instanceof ConnectError) {\n if (error.code === Code.ResourceExhausted) {\n return \"You've made too many requests. Wait a moment and try again.\";\n }\n if (error.code === Code.DeadlineExceeded) {\n return \"This is taking longer than expected. Try again.\";\n }\n if (error.code === Code.Unavailable) {\n return \"This service is temporarily unavailable. Try again in a few minutes.\";\n }\n }\n\n return undefined;\n}\n\nexport function formatUserFacingError(error: unknown, fallback: string): string {\n // Walk the cause chain and normalize ConnectErrors so wrapped submit failures\n // (e.g. Error → ConnectError[unknown] \"Service temporarily unavailable.\")\n // still hit the transport allowlist.\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth++) {\n const mapped = toPolyesterError(current);\n const fromMapped = userFacingTransportMessage(mapped);\n if (fromMapped !== undefined) return fromMapped;\n const fromCurrent = userFacingTransportMessage(current);\n if (fromCurrent !== undefined) return fromCurrent;\n\n current =\n typeof current === \"object\" && current !== null && \"cause\" in current\n ? (current as { cause?: unknown }).cause\n : undefined;\n }\n\n return fallback;\n}\n"],"mappings":";;;;;;;;;AAqBA,SAAgB,wBAAwB,KAAuB;CAG3D,MAAM,SAAS,iBAAiB,GAAG;CACnC,OACI,kBAAkB,yBACjB,kBAAkB,kBACf,OAAO,QAAQ,YAAY,UAC3B,OAAO,OAAO,SAAS;AAEnC;;AAGA,SAAgB,wBAAwB,KAAuB;CAC3D,MAAM,uBAAO,IAAI,IAAa;CAC9B,IAAI,UAAU;CACd,OAAO,YAAY,KAAA,KAAa,YAAY,QAAQ,CAAC,KAAK,IAAI,OAAO,GAAG;EACpE,KAAK,IAAI,OAAO;EAChB,IAAI,iBAAiB,OAAO,aAAa,uBAAuB,OAAO;EACvE,MAAM,eAAe,aAAa,KAAK,OAAO;EAC9C,KACK,aAAa,SAAS,KAAK,WAAW,aAAa,SAAS,KAAK,YAClE,yBAAyB,KAAK,4BAA4B,YAAY,CAAC,GAEvE,OAAO;EAEX,UACI,OAAO,YAAY,YAAY,WAAW,UACnC,QAAgC,QACjC,KAAA;CACd;CACA,OAAO;AACX;;AAGA,SAAgB,mBAAmB,KAAuB;CACtD,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;AAGA,SAAgB,oBAAoB,KAAuB;CACvD,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;AAGA,SAAgB,2BAA2B,KAAuB;CAC9D,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;;;;;AAOA,SAAgB,iBAAiB,KAAuB;CACpD,IAAI,aAAa,GAAG,GAAG,OAAO;CAC9B,MAAM,SAAS,iBAAiB,GAAG;CACnC,IAAI,kBAAkB,gBAAgB,OAAO,OAAO;CACpD,MAAM,KAAK,aAAa,KAAK,MAAM;CACnC,OACI,GAAG,SAAS,KAAK,eACjB,GAAG,SAAS,KAAK,oBACjB,GAAG,SAAS,KAAK,qBACjB,GAAG,SAAS,KAAK;AAEzB;;;;;;;;;;;AAYA,SAAgB,mBACZ,KACA,WAAW,qCACL;CACN,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,eAAe,gBAAgB,OAAO,IAAI,WAAW;CAEzD,OADoB,4BAA4B,GAC/B,KAAK;AAC1B;;;;;;;;AASA,SAAS,2BAA2B,OAAoC;CACpE,IAAI,iBAAiB,gBACjB,OAAO;CAEX,IAAI,iBAAiB,cAAc,OAAO;CAC1C,IAAI,iBAAiB,yBACjB,OAAO;CAEX,IAAI,iBAAiB,cACjB,OAAO;CAGX,IAAI,iBAAiB,cAAc;EAC/B,IAAI,MAAM,SAAS,KAAK,mBACpB,OAAO;EAEX,IAAI,MAAM,SAAS,KAAK,kBACpB,OAAO;EAEX,IAAI,MAAM,SAAS,KAAK,aACpB,OAAO;CAEf;AAGJ;AAEA,SAAgB,sBAAsB,OAAgB,UAA0B;CAI5E,IAAI,UAAmB;CACvB,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,WAAW,MAAM,SAAS;EAEvD,MAAM,aAAa,2BADJ,iBAAiB,OACmB,CAAC;EACpD,IAAI,eAAe,KAAA,GAAW,OAAO;EACrC,MAAM,cAAc,2BAA2B,OAAO;EACtD,IAAI,gBAAgB,KAAA,GAAW,OAAO;EAEtC,UACI,OAAO,YAAY,YAAY,YAAY,QAAQ,WAAW,UACvD,QAAgC,QACjC,KAAA;CACd;CAEA,OAAO;AACX"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/utils/errors.ts"],"sourcesContent":["import { Code, ConnectError } from \"@connectrpc/connect\";\nimport { getNormalizedConnectMessage, toPolyesterError } from \"../shared/connect-error-mapping.js\";\nimport {\n isAbortError,\n NetworkError,\n PolicyInUseError,\n PolicyLockedError,\n PolicyScopeMismatchError,\n PolyesterError,\n RateLimitError,\n ResourceNotFoundError,\n RevisionConflictError,\n ServiceUnavailableError,\n TimeoutError,\n} from \"../shared/errors.js\";\n\n/**\n * Whether the backend signalled that the requested resource does not exist.\n * Prefer `err instanceof ResourceNotFoundError`; this predicate also covers\n * raw `ConnectError`s (NotFound or the auth resource-not-found detail).\n */\nexport function isResourceNotFoundError(err: unknown): boolean {\n // Connect can re-wrap interceptor errors as an Unknown ConnectError whose\n // cause is the typed SDK error. Normalize first to recover that cause.\n const mapped = toPolyesterError(err);\n return (\n mapped instanceof ResourceNotFoundError ||\n (mapped instanceof PolyesterError &&\n mapped.detail?.service === \"auth\" &&\n mapped.detail.code === \"AUTH_RESOURCE_NOT_FOUND\")\n );\n}\n\n/** Whether an optimistic-concurrency update used a stale resource revision. */\nexport function isRevisionConflictError(err: unknown): boolean {\n const seen = new Set<unknown>();\n let current = err;\n while (current !== undefined && current !== null && !seen.has(current)) {\n seen.add(current);\n if (toPolyesterError(current) instanceof RevisionConflictError) return true;\n const connectError = ConnectError.from(current);\n if (\n (connectError.code === Code.Unknown || connectError.code === Code.Aborted) &&\n /\\brevision conflict\\b/i.test(getNormalizedConnectMessage(connectError))\n ) {\n return true;\n }\n current =\n typeof current === \"object\" && \"cause\" in current\n ? (current as { cause?: unknown }).cause\n : undefined;\n }\n return false;\n}\n\n/** Whether a policy mutation failed because the policy is still attached to a resource. */\nexport function isPolicyInUseError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyInUseError;\n}\n\n/** Whether a policy mutation failed because the policy is locked. */\nexport function isPolicyLockedError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyLockedError;\n}\n\n/** Whether the policy and target account belong to different scopes. */\nexport function isPolicyScopeMismatchError(err: unknown): boolean {\n return toPolyesterError(err) instanceof PolicyScopeMismatchError;\n}\n\n/**\n * Whether an error is retryable (network/timeout) for idempotent operations.\n * Uses same requestId on retry; backend dedupes within 2min.\n * Prefer `err instanceof TransientError` or `err.retryable` on typed errors.\n */\nexport function isRetryableError(err: unknown): boolean {\n if (isAbortError(err)) return false;\n const mapped = toPolyesterError(err);\n if (mapped instanceof PolyesterError) return mapped.retryable;\n const ce = ConnectError.from(mapped);\n return (\n ce.code === Code.Unavailable ||\n ce.code === Code.DeadlineExceeded ||\n ce.code === Code.ResourceExhausted ||\n ce.code === Code.Aborted\n );\n}\n\n/**\n * Diagnostic formatter for SDK and ConnectRPC errors.\n * Typed SDK errors already carry normalized messages; for raw ConnectErrors\n * this strips leading \"[CODE]\" prefixes. Falls back to a friendly default.\n * The returned message may contain backend implementation details. Never render\n * it to a user; use {@link formatUserFacingError} at presentation boundaries.\n * @param err - The error to format.\n * @param fallback - The fallback message when no message is available.\n * @returns The formatted error message.\n */\nexport function formatConnectError(\n err: unknown,\n fallback = \"Request failed. Please try again.\",\n): string {\n if (err == null) return fallback;\n if (err instanceof PolyesterError) return err.message || fallback;\n const withoutCode = getNormalizedConnectMessage(err);\n return withoutCode || fallback;\n}\n\n/**\n * Formats an untrusted failure for direct display to a user.\n *\n * This function never returns an exception or backend message. A small allowlist\n * of typed transport conditions receives SDK-owned copy; every other failure\n * returns the caller-owned fallback.\n */\nfunction userFacingTransportMessage(error: unknown): string | undefined {\n if (isAbortError(error)) return \"Request canceled.\";\n if (error instanceof RateLimitError) {\n return \"You've made too many requests. Wait a moment and try again.\";\n }\n if (error instanceof TimeoutError) return \"This is taking longer than expected. Try again.\";\n if (error instanceof ServiceUnavailableError) {\n return \"This service is temporarily unavailable. Try again in a few minutes.\";\n }\n if (error instanceof NetworkError) {\n return \"We couldn't connect. Check your internet connection and try again.\";\n }\n\n if (error instanceof ConnectError) {\n if (error.code === Code.ResourceExhausted) {\n return \"You've made too many requests. Wait a moment and try again.\";\n }\n if (error.code === Code.DeadlineExceeded) {\n return \"This is taking longer than expected. Try again.\";\n }\n if (error.code === Code.Unavailable) {\n return \"This service is temporarily unavailable. Try again in a few minutes.\";\n }\n }\n\n return undefined;\n}\n\nexport function formatUserFacingError(error: unknown, fallback: string): string {\n // Walk the cause chain and normalize ConnectErrors so wrapped submit failures\n // (e.g. Error → ConnectError[unknown] \"Service temporarily unavailable.\")\n // still hit the transport allowlist.\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth++) {\n const mapped = toPolyesterError(current);\n const fromMapped = userFacingTransportMessage(mapped);\n if (fromMapped !== undefined) return fromMapped;\n const fromCurrent = userFacingTransportMessage(current);\n if (fromCurrent !== undefined) return fromCurrent;\n\n current =\n typeof current === \"object\" && current !== null && \"cause\" in current\n ? (current as { cause?: unknown }).cause\n : undefined;\n }\n\n return fallback;\n}\n"],"mappings":";;;;;;;;;AAqBA,SAAgB,wBAAwB,KAAuB;CAG3D,MAAM,SAAS,iBAAiB,GAAG;CACnC,OACI,kBAAkB,yBACjB,kBAAkB,kBACf,OAAO,QAAQ,YAAY,UAC3B,OAAO,OAAO,SAAS;AAEnC;;AAGA,SAAgB,wBAAwB,KAAuB;CAC3D,MAAM,uBAAO,IAAI,IAAa;CAC9B,IAAI,UAAU;CACd,OAAO,YAAY,KAAA,KAAa,YAAY,QAAQ,CAAC,KAAK,IAAI,OAAO,GAAG;EACpE,KAAK,IAAI,OAAO;EAChB,IAAI,iBAAiB,OAAO,aAAa,uBAAuB,OAAO;EACvE,MAAM,eAAe,aAAa,KAAK,OAAO;EAC9C,KACK,aAAa,SAAS,KAAK,WAAW,aAAa,SAAS,KAAK,YAClE,yBAAyB,KAAK,4BAA4B,YAAY,CAAC,GAEvE,OAAO;EAEX,UACI,OAAO,YAAY,YAAY,WAAW,UACnC,QAAgC,QACjC,KAAA;CACd;CACA,OAAO;AACX;;AAGA,SAAgB,mBAAmB,KAAuB;CACtD,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;AAGA,SAAgB,oBAAoB,KAAuB;CACvD,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;AAGA,SAAgB,2BAA2B,KAAuB;CAC9D,OAAO,iBAAiB,GAAG,aAAa;AAC5C;;;;;;AAOA,SAAgB,iBAAiB,KAAuB;CACpD,IAAI,aAAa,GAAG,GAAG,OAAO;CAC9B,MAAM,SAAS,iBAAiB,GAAG;CACnC,IAAI,kBAAkB,gBAAgB,OAAO,OAAO;CACpD,MAAM,KAAK,aAAa,KAAK,MAAM;CACnC,OACI,GAAG,SAAS,KAAK,eACjB,GAAG,SAAS,KAAK,oBACjB,GAAG,SAAS,KAAK,qBACjB,GAAG,SAAS,KAAK;AAEzB;;;;;;;;;;;AAYA,SAAgB,mBACZ,KACA,WAAW,qCACL;CACN,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,eAAe,gBAAgB,OAAO,IAAI,WAAW;CAEzD,OADoB,4BAA4B,GAC/B,KAAK;AAC1B;;;;;;;;AASA,SAAS,2BAA2B,OAAoC;CACpE,IAAI,aAAa,KAAK,GAAG,OAAO;CAChC,IAAI,iBAAiB,gBACjB,OAAO;CAEX,IAAI,iBAAiB,cAAc,OAAO;CAC1C,IAAI,iBAAiB,yBACjB,OAAO;CAEX,IAAI,iBAAiB,cACjB,OAAO;CAGX,IAAI,iBAAiB,cAAc;EAC/B,IAAI,MAAM,SAAS,KAAK,mBACpB,OAAO;EAEX,IAAI,MAAM,SAAS,KAAK,kBACpB,OAAO;EAEX,IAAI,MAAM,SAAS,KAAK,aACpB,OAAO;CAEf;AAGJ;AAEA,SAAgB,sBAAsB,OAAgB,UAA0B;CAI5E,IAAI,UAAmB;CACvB,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,WAAW,MAAM,SAAS;EAEvD,MAAM,aAAa,2BADJ,iBAAiB,OACmB,CAAC;EACpD,IAAI,eAAe,KAAA,GAAW,OAAO;EACrC,MAAM,cAAc,2BAA2B,OAAO;EACtD,IAAI,gBAAgB,KAAA,GAAW,OAAO;EAEtC,UACI,OAAO,YAAY,YAAY,YAAY,QAAQ,WAAW,UACvD,QAAgC,QACjC,KAAA;CACd;CAEA,OAAO;AACX"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polyester/sdk",
3
- "version": "0.23.1",
3
+ "version": "0.24.1",
4
4
  "private": false,
5
5
  "description": "TypeScript SDK providing access to APIs on Polyester Exchange.",
6
6
  "homepage": "https://github.com/Fabric-Labs/polyester-sdk-typescript#readme",