@polyester/sdk 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +63 -17
- package/dist/_virtual/_rolldown/runtime.js +15 -1
- package/dist/account-signer/types.d.ts.map +1 -1
- package/dist/account-signer/types.js +6 -3
- package/dist/account-signer/types.js.map +1 -1
- package/dist/browser-client.d.ts +4 -2
- package/dist/browser-client.d.ts.map +1 -1
- package/dist/browser-client.js +3 -4
- package/dist/browser-client.js.map +1 -1
- package/dist/catalogs/client-catalog.d.ts.map +1 -1
- package/dist/catalogs/client-catalog.js +11 -4
- package/dist/catalogs/client-catalog.js.map +1 -1
- package/dist/catalogs/index.js +1 -1
- package/dist/catalogs/readers.d.ts.map +1 -1
- package/dist/catalogs/readers.js +3 -1
- package/dist/catalogs/readers.js.map +1 -1
- package/dist/catalogs/snapshot-validation.js +132 -0
- package/dist/catalogs/snapshot-validation.js.map +1 -0
- package/dist/catalogs/snapshot.d.ts.map +1 -1
- package/dist/catalogs/snapshot.js +16 -7
- package/dist/catalogs/snapshot.js.map +1 -1
- package/dist/catalogs/zipper-supply.d.ts.map +1 -1
- package/dist/catalogs/zipper-supply.js +10 -7
- package/dist/catalogs/zipper-supply.js.map +1 -1
- package/dist/core-client.d.ts +24 -17
- package/dist/core-client.d.ts.map +1 -1
- package/dist/core-client.js +21 -3
- package/dist/core-client.js.map +1 -1
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js +32 -1
- package/dist/environment.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/realtime/client.js +13 -2
- package/dist/realtime/client.js.map +1 -1
- package/dist/realtime/snapshot-then-stream.js +1 -1
- package/dist/realtime/snapshot-then-stream.js.map +1 -1
- package/dist/realtime/types.d.ts +2 -0
- package/dist/realtime/types.d.ts.map +1 -1
- package/dist/server-client.d.ts +17 -8
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +8 -11
- package/dist/server-client.js.map +1 -1
- package/dist/services/accounts/accounts.js +3 -3
- package/dist/services/accounts/accounts.js.map +1 -1
- package/dist/services/accounts/accounts.schemas.d.ts +13 -13
- package/dist/services/accounts/accounts.schemas.d.ts.map +1 -1
- package/dist/services/accounts/accounts.schemas.js +11 -11
- package/dist/services/accounts/accounts.schemas.js.map +1 -1
- package/dist/services/address-book/address-book.js +28 -28
- package/dist/services/address-book/address-book.js.map +1 -1
- package/dist/services/address-book/address-book.schemas.d.ts +751 -751
- package/dist/services/address-book/address-book.schemas.d.ts.map +1 -1
- package/dist/services/address-book/address-book.schemas.js +160 -160
- package/dist/services/address-book/address-book.schemas.js.map +1 -1
- package/dist/services/api-keys/api-keys.d.ts +6 -6
- package/dist/services/api-keys/api-keys.d.ts.map +1 -1
- package/dist/services/api-keys/api-keys.js +12 -12
- package/dist/services/api-keys/api-keys.js.map +1 -1
- package/dist/services/api-keys/api-keys.schemas.d.ts +62 -62
- package/dist/services/api-keys/api-keys.schemas.d.ts.map +1 -1
- package/dist/services/api-keys/api-keys.schemas.js +34 -34
- package/dist/services/api-keys/api-keys.schemas.js.map +1 -1
- package/dist/services/auth/auth.d.ts +46 -40
- package/dist/services/auth/auth.d.ts.map +1 -1
- package/dist/services/auth/auth.js +28 -25
- package/dist/services/auth/auth.js.map +1 -1
- package/dist/services/auth/profile/profile.d.ts +2 -2
- package/dist/services/auth/profile/profile.d.ts.map +1 -1
- package/dist/services/auth/profile/profile.js +7 -7
- package/dist/services/auth/profile/profile.js.map +1 -1
- package/dist/services/auth/profile/profile.schemas.d.ts +41 -41
- package/dist/services/auth/profile/profile.schemas.d.ts.map +1 -1
- package/dist/services/auth/profile/profile.schemas.js +27 -27
- package/dist/services/auth/profile/profile.schemas.js.map +1 -1
- package/dist/services/auth/session.d.ts +1 -1
- package/dist/services/auth/session.d.ts.map +1 -1
- package/dist/services/auth/session.js +6 -2
- package/dist/services/auth/session.js.map +1 -1
- package/dist/services/auth/session.schemas.js +17 -17
- package/dist/services/auth/session.schemas.js.map +1 -1
- package/dist/services/auth/session.types.d.ts +3 -2
- package/dist/services/auth/session.types.d.ts.map +1 -1
- package/dist/services/balances/balances.d.ts +1 -1
- package/dist/services/balances/balances.js +9 -9
- package/dist/services/balances/balances.js.map +1 -1
- package/dist/services/balances/balances.schemas.d.ts +95 -95
- package/dist/services/balances/balances.schemas.d.ts.map +1 -1
- package/dist/services/balances/balances.schemas.js +61 -61
- package/dist/services/balances/balances.schemas.js.map +1 -1
- package/dist/services/candles/candles.js +12 -12
- package/dist/services/candles/candles.js.map +1 -1
- package/dist/services/candles/candles.schemas.d.ts +70 -70
- package/dist/services/candles/candles.schemas.d.ts.map +1 -1
- package/dist/services/candles/candles.schemas.js +47 -48
- package/dist/services/candles/candles.schemas.js.map +1 -1
- package/dist/services/chain-analytics/chain-analytics.js +7 -7
- package/dist/services/chain-analytics/chain-analytics.js.map +1 -1
- package/dist/services/chain-analytics/chain-analytics.schemas.d.ts +68 -68
- package/dist/services/chain-analytics/chain-analytics.schemas.d.ts.map +1 -1
- package/dist/services/chain-analytics/chain-analytics.schemas.js +29 -29
- package/dist/services/chain-analytics/chain-analytics.schemas.js.map +1 -1
- package/dist/services/deposit/deposit.js +5 -5
- package/dist/services/deposit/deposit.js.map +1 -1
- package/dist/services/deposit/deposit.schemas.d.ts +17 -17
- package/dist/services/deposit/deposit.schemas.d.ts.map +1 -1
- package/dist/services/deposit/deposit.schemas.js +11 -11
- package/dist/services/deposit/deposit.schemas.js.map +1 -1
- package/dist/services/guard-signer/guard-signer.js +13 -13
- package/dist/services/guard-signer/guard-signer.js.map +1 -1
- package/dist/services/guard-signer/guard-signer.schemas.d.ts +75 -75
- package/dist/services/guard-signer/guard-signer.schemas.d.ts.map +1 -1
- package/dist/services/guard-signer/guard-signer.schemas.js +42 -42
- package/dist/services/guard-signer/guard-signer.schemas.js.map +1 -1
- package/dist/services/heatmap/heatmap.js +9 -9
- package/dist/services/heatmap/heatmap.js.map +1 -1
- package/dist/services/heatmap/heatmap.schemas.d.ts +144 -144
- package/dist/services/heatmap/heatmap.schemas.d.ts.map +1 -1
- package/dist/services/heatmap/heatmap.schemas.js +47 -47
- package/dist/services/heatmap/heatmap.schemas.js.map +1 -1
- package/dist/services/internal-transfers/internal-transfers.js +3 -3
- package/dist/services/internal-transfers/internal-transfers.js.map +1 -1
- package/dist/services/internal-transfers/internal-transfers.schemas.d.ts +53 -53
- package/dist/services/internal-transfers/internal-transfers.schemas.d.ts.map +1 -1
- package/dist/services/internal-transfers/internal-transfers.schemas.js +27 -27
- package/dist/services/internal-transfers/internal-transfers.schemas.js.map +1 -1
- package/dist/services/lifecycle/lifecycle.js +10 -10
- package/dist/services/lifecycle/lifecycle.js.map +1 -1
- package/dist/services/lifecycle/lifecycle.schemas.d.ts +614 -614
- package/dist/services/lifecycle/lifecycle.schemas.d.ts.map +1 -1
- package/dist/services/lifecycle/lifecycle.schemas.js +146 -146
- package/dist/services/lifecycle/lifecycle.schemas.js.map +1 -1
- package/dist/services/market-data/market-data.js +6 -6
- package/dist/services/market-data/market-data.js.map +1 -1
- package/dist/services/market-data/market-data.schemas.d.ts +20 -20
- package/dist/services/market-data/market-data.schemas.d.ts.map +1 -1
- package/dist/services/market-data/market-data.schemas.js +51 -55
- package/dist/services/market-data/market-data.schemas.js.map +1 -1
- package/dist/services/market-overview/market-overview.js +4 -4
- package/dist/services/market-overview/market-overview.js.map +1 -1
- package/dist/services/market-overview/market-overview.schemas.d.ts +38 -38
- package/dist/services/market-overview/market-overview.schemas.d.ts.map +1 -1
- package/dist/services/market-overview/market-overview.schemas.js +33 -33
- package/dist/services/market-overview/market-overview.schemas.js.map +1 -1
- package/dist/services/mfa/mfa.js +27 -27
- package/dist/services/mfa/mfa.js.map +1 -1
- package/dist/services/mfa/mfa.schemas.d.ts +206 -206
- package/dist/services/mfa/mfa.schemas.d.ts.map +1 -1
- package/dist/services/mfa/mfa.schemas.js +83 -83
- package/dist/services/mfa/mfa.schemas.js.map +1 -1
- package/dist/services/orderbook/orderbook.d.ts +2 -2
- package/dist/services/orderbook/orderbook.d.ts.map +1 -1
- package/dist/services/orderbook/orderbook.js +5 -5
- package/dist/services/orderbook/orderbook.js.map +1 -1
- package/dist/services/orderbook/orderbook.schemas.d.ts +22 -22
- package/dist/services/orderbook/orderbook.schemas.d.ts.map +1 -1
- package/dist/services/orderbook/orderbook.schemas.js +15 -15
- package/dist/services/orderbook/orderbook.schemas.js.map +1 -1
- package/dist/services/orders/order-errors.schemas.d.ts +18 -18
- package/dist/services/orders/order-errors.schemas.d.ts.map +1 -1
- package/dist/services/orders/order-errors.schemas.js +8 -8
- package/dist/services/orders/order-errors.schemas.js.map +1 -1
- package/dist/services/orders/orders-batch.schemas.d.ts +492 -492
- package/dist/services/orders/orders-batch.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-batch.schemas.js +118 -118
- package/dist/services/orders/orders-batch.schemas.js.map +1 -1
- package/dist/services/orders/orders-identifiers.schemas.js +5 -5
- package/dist/services/orders/orders-identifiers.schemas.js.map +1 -1
- package/dist/services/orders/orders-input.schemas.d.ts +657 -648
- package/dist/services/orders/orders-input.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-input.schemas.js +100 -96
- package/dist/services/orders/orders-input.schemas.js.map +1 -1
- package/dist/services/orders/orders-modify.schemas.d.ts +370 -351
- package/dist/services/orders/orders-modify.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-modify.schemas.js +48 -44
- package/dist/services/orders/orders-modify.schemas.js.map +1 -1
- package/dist/services/orders/orders-output.schemas.d.ts +183 -183
- package/dist/services/orders/orders-output.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-output.schemas.js +49 -49
- package/dist/services/orders/orders-output.schemas.js.map +1 -1
- package/dist/services/orders/orders-risk.schemas.d.ts +226 -226
- package/dist/services/orders/orders-risk.schemas.d.ts.map +1 -1
- package/dist/services/orders/orders-risk.schemas.js +69 -69
- package/dist/services/orders/orders-risk.schemas.js.map +1 -1
- package/dist/services/orders/orders.d.ts +8 -8
- package/dist/services/orders/orders.d.ts.map +1 -1
- package/dist/services/orders/orders.js +44 -32
- package/dist/services/orders/orders.js.map +1 -1
- package/dist/services/policies/api-key-policies/api-key-policies.d.ts +6 -6
- package/dist/services/policies/api-key-policies/api-key-policies.d.ts.map +1 -1
- package/dist/services/policies/api-key-policies/api-key-policies.js +11 -11
- package/dist/services/policies/api-key-policies/api-key-policies.js.map +1 -1
- package/dist/services/policies/api-key-policies/api-key-policies.schemas.d.ts +105 -105
- package/dist/services/policies/api-key-policies/api-key-policies.schemas.d.ts.map +1 -1
- package/dist/services/policies/api-key-policies/api-key-policies.schemas.js +49 -49
- package/dist/services/policies/api-key-policies/api-key-policies.schemas.js.map +1 -1
- package/dist/services/policies/shared.d.ts +5 -5
- package/dist/services/policies/shared.d.ts.map +1 -1
- package/dist/services/policies/shared.js +10 -10
- package/dist/services/policies/shared.js.map +1 -1
- package/dist/services/policies/subaccount-policies/subaccount-policies.d.ts +6 -6
- package/dist/services/policies/subaccount-policies/subaccount-policies.d.ts.map +1 -1
- package/dist/services/policies/subaccount-policies/subaccount-policies.js +13 -13
- package/dist/services/policies/subaccount-policies/subaccount-policies.js.map +1 -1
- package/dist/services/policies/subaccount-policies/subaccount-policies.schemas.d.ts +124 -124
- package/dist/services/policies/subaccount-policies/subaccount-policies.schemas.d.ts.map +1 -1
- package/dist/services/policies/subaccount-policies/subaccount-policies.schemas.js +75 -75
- package/dist/services/policies/subaccount-policies/subaccount-policies.schemas.js.map +1 -1
- package/dist/services/shared.js +11 -11
- package/dist/services/shared.js.map +1 -1
- package/dist/services/social-verification/social-verification.d.ts +3 -3
- package/dist/services/social-verification/social-verification.d.ts.map +1 -1
- package/dist/services/social-verification/social-verification.js +7 -7
- package/dist/services/social-verification/social-verification.js.map +1 -1
- package/dist/services/social-verification/social-verification.schemas.d.ts +54 -54
- package/dist/services/social-verification/social-verification.schemas.d.ts.map +1 -1
- package/dist/services/social-verification/social-verification.schemas.js +28 -28
- package/dist/services/social-verification/social-verification.schemas.js.map +1 -1
- package/dist/services/subaccount-resolver.js +5 -3
- package/dist/services/subaccount-resolver.js.map +1 -1
- package/dist/services/subaccounts/subaccounts.d.ts +15 -15
- package/dist/services/subaccounts/subaccounts.d.ts.map +1 -1
- package/dist/services/subaccounts/subaccounts.js +35 -35
- package/dist/services/subaccounts/subaccounts.js.map +1 -1
- package/dist/services/subaccounts/subaccounts.schemas.d.ts +135 -135
- package/dist/services/subaccounts/subaccounts.schemas.d.ts.map +1 -1
- package/dist/services/subaccounts/subaccounts.schemas.js +72 -72
- package/dist/services/subaccounts/subaccounts.schemas.js.map +1 -1
- package/dist/services/trades/trades.d.ts +2 -2
- package/dist/services/trades/trades.d.ts.map +1 -1
- package/dist/services/trades/trades.js +5 -5
- package/dist/services/trades/trades.js.map +1 -1
- package/dist/services/trades/trades.schemas.d.ts +31 -31
- package/dist/services/trades/trades.schemas.d.ts.map +1 -1
- package/dist/services/trades/trades.schemas.js +24 -24
- package/dist/services/trades/trades.schemas.js.map +1 -1
- package/dist/services/trading-withdraws/trading-withdraws.js +8 -8
- package/dist/services/trading-withdraws/trading-withdraws.js.map +1 -1
- package/dist/services/trading-withdraws/trading-withdraws.schemas.d.ts +45 -45
- package/dist/services/trading-withdraws/trading-withdraws.schemas.d.ts.map +1 -1
- package/dist/services/trading-withdraws/trading-withdraws.schemas.js +36 -36
- package/dist/services/trading-withdraws/trading-withdraws.schemas.js.map +1 -1
- package/dist/services/transfers/transfers.d.ts +1 -1
- package/dist/services/transfers/transfers.d.ts.map +1 -1
- package/dist/services/transfers/transfers.js +5 -5
- package/dist/services/transfers/transfers.js.map +1 -1
- package/dist/services/transfers/transfers.schemas.d.ts +42 -42
- package/dist/services/transfers/transfers.schemas.d.ts.map +1 -1
- package/dist/services/transfers/transfers.schemas.js +30 -30
- package/dist/services/transfers/transfers.schemas.js.map +1 -1
- package/dist/services/triggers/trigger-child-order.schemas.js +23 -23
- package/dist/services/triggers/trigger-child-order.schemas.js.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.d.ts +226 -226
- package/dist/services/triggers/trigger-input.schemas.d.ts.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.js +53 -53
- package/dist/services/triggers/trigger-input.schemas.js.map +1 -1
- package/dist/services/triggers/triggers-output.schemas.d.ts +210 -210
- package/dist/services/triggers/triggers-output.schemas.d.ts.map +1 -1
- package/dist/services/triggers/triggers-output.schemas.js +152 -152
- package/dist/services/triggers/triggers-output.schemas.js.map +1 -1
- package/dist/services/triggers/triggers.js +21 -21
- package/dist/services/triggers/triggers.js.map +1 -1
- package/dist/services/whiteboard/whiteboard.js +15 -15
- package/dist/services/whiteboard/whiteboard.js.map +1 -1
- package/dist/services/whiteboard/whiteboard.schemas.d.ts +379 -379
- package/dist/services/whiteboard/whiteboard.schemas.d.ts.map +1 -1
- package/dist/services/whiteboard/whiteboard.schemas.js +71 -71
- package/dist/services/whiteboard/whiteboard.schemas.js.map +1 -1
- package/dist/services/zipper/zipper.js +3 -3
- package/dist/services/zipper/zipper.js.map +1 -1
- package/dist/services/zipper/zipper.schemas.d.ts +1 -1
- package/dist/services/zipper/zipper.schemas.js +54 -54
- package/dist/services/zipper/zipper.schemas.js.map +1 -1
- package/dist/shared/account-scope.d.ts +6 -6
- package/dist/shared/account-scope.d.ts.map +1 -1
- package/dist/shared/account-scope.js +3 -3
- package/dist/shared/account-scope.js.map +1 -1
- package/dist/shared/connect-error-mapping.d.ts +1 -1
- package/dist/shared/connect-error-mapping.js +29 -3
- package/dist/shared/connect-error-mapping.js.map +1 -1
- package/dist/shared/rate-limit.schemas.d.ts +12 -12
- package/dist/shared/rate-limit.schemas.d.ts.map +1 -1
- package/dist/shared/rate-limit.schemas.js +7 -7
- package/dist/shared/rate-limit.schemas.js.map +1 -1
- package/dist/shared/schemas.js +26 -26
- package/dist/shared/schemas.js.map +1 -1
- package/dist/shared/transports.js +7 -12
- package/dist/shared/transports.js.map +1 -1
- package/dist/shared/types.d.ts +12 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/validation.d.ts +14 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +24 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/utils/connect-order-errors.js +2 -2
- package/dist/utils/connect-order-errors.js.map +1 -1
- package/dist/utils/cookies.d.ts +8 -3
- package/dist/utils/cookies.d.ts.map +1 -1
- package/dist/utils/cookies.js +7 -1
- package/dist/utils/cookies.js.map +1 -1
- package/dist/utils/event-emitter.d.ts +1 -1
- package/dist/utils/event-emitter.d.ts.map +1 -1
- package/dist/utils/event-emitter.js +4 -2
- package/dist/utils/event-emitter.js.map +1 -1
- package/dist/utils/evm.js +2 -2
- package/dist/utils/evm.js.map +1 -1
- package/dist/utils/jwt.d.ts +2 -2
- package/dist/utils/jwt.d.ts.map +1 -1
- package/dist/utils/jwt.js +2 -2
- package/dist/utils/jwt.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PolyesterError } from "./errors.js";
|
|
2
|
-
import { ConnectError, Interceptor } from "@connectrpc/connect";
|
|
2
|
+
import { ConnectError, Interceptor, Transport } from "@connectrpc/connect";
|
|
3
3
|
//#region src/shared/connect-error-mapping.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Maps a `ConnectError` from the Polyester backend onto the typed
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AlreadyExistsError, AuthenticationError, InternalServerError, MfaEnrollmentRequiredError, MfaLastFactorRequiredError, MfaVerificationError, PermissionError, PolicyInUseError, PolicyLockedError, PolicyScopeMismatchError, PolyesterError, PreconditionFailedError, RateLimitError, ResourceNotFoundError, RevisionConflictError, ServiceUnavailableError, SessionElevationRequiredError, StaleQuoteError, StepUpRequiredError, TimeoutError, TransientError, ValidationError, isAbortError, normalizeErrorMessage } from "./errors.js";
|
|
2
|
+
import { validation_exports } from "./validation.js";
|
|
2
3
|
import { AuthErrorDetailSchema } from "../gen/auth/v1/auth_pb.js";
|
|
3
4
|
import { ErrorDetailSchema } from "../gen/orders/v1/orders_pb.js";
|
|
4
5
|
import { RateLimitDetailSchema } from "./rate-limit.schemas.js";
|
|
5
6
|
import { Code, ConnectError } from "@connectrpc/connect";
|
|
6
|
-
import * as v from "valibot";
|
|
7
7
|
//#region src/shared/connect-error-mapping.ts
|
|
8
8
|
function getAuthErrorDetails(err) {
|
|
9
9
|
return ConnectError.from(err).findDetails(AuthErrorDetailSchema);
|
|
@@ -20,7 +20,7 @@ function getOrderErrorDetails(err) {
|
|
|
20
20
|
function getRateLimitDetail(err) {
|
|
21
21
|
for (const orderDetail of getOrderErrorDetails(err)) {
|
|
22
22
|
if (!orderDetail.rateLimit) continue;
|
|
23
|
-
const result =
|
|
23
|
+
const result = validation_exports.safeParse(RateLimitDetailSchema, orderDetail.rateLimit);
|
|
24
24
|
if (result.success) return result.output;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -164,7 +164,33 @@ function createErrorMappingInterceptor() {
|
|
|
164
164
|
}
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Wraps a Connect transport so errors are translated after Connect's call
|
|
169
|
+
* runner has applied its own error normalization.
|
|
170
|
+
*/
|
|
171
|
+
function createErrorMappingTransport(transport) {
|
|
172
|
+
return {
|
|
173
|
+
async unary(method, signal, timeoutMs, header, input, contextValues) {
|
|
174
|
+
try {
|
|
175
|
+
return await transport.unary(method, signal, timeoutMs, header, input, contextValues);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw toPolyesterError(error);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
async stream(method, signal, timeoutMs, header, input, contextValues) {
|
|
181
|
+
try {
|
|
182
|
+
const response = await transport.stream(method, signal, timeoutMs, header, input, contextValues);
|
|
183
|
+
return {
|
|
184
|
+
...response,
|
|
185
|
+
message: mapStreamErrors(response.message)
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw toPolyesterError(error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
167
193
|
//#endregion
|
|
168
|
-
export { connectErrorToPolyesterError, createErrorMappingInterceptor, detectMfaErrorKind, getNormalizedConnectMessage, toPolyesterError };
|
|
194
|
+
export { connectErrorToPolyesterError, createErrorMappingInterceptor, createErrorMappingTransport, detectMfaErrorKind, getNormalizedConnectMessage, toPolyesterError };
|
|
169
195
|
|
|
170
196
|
//# sourceMappingURL=connect-error-mapping.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect-error-mapping.js","names":["OrderErrorDetailSchema"],"sources":["../../src/shared/connect-error-mapping.ts"],"sourcesContent":["import { Code, ConnectError, type Interceptor } from \"@connectrpc/connect\";\nimport * as v from \"valibot\";\nimport { AuthErrorCode, AuthErrorDetailSchema } from \"../gen/auth/v1/auth_pb.js\";\nimport {\n ErrorCode as OrderErrorCode,\n ErrorDetailSchema as OrderErrorDetailSchema,\n} from \"../gen/orders/v1/orders_pb.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 { RateLimitDetailSchema, type RateLimitDetail } from \"./rate-limit.schemas.js\";\n\nfunction getAuthErrorDetails(err: unknown) {\n return ConnectError.from(err).findDetails(AuthErrorDetailSchema);\n}\n\nfunction hasAuthErrorCode(err: unknown, code: AuthErrorCode): boolean {\n return getAuthErrorDetails(err).some((detail) => detail.code === code);\n}\n\nfunction hasOrderErrorCode(err: unknown, code: OrderErrorCode): boolean {\n return getOrderErrorDetails(err).some((detail) => detail.code === code);\n}\n\nfunction getOrderErrorDetails(err: unknown) {\n return ConnectError.from(err).findDetails(OrderErrorDetailSchema);\n}\n\nfunction getRateLimitDetail(err: unknown): RateLimitDetail | undefined {\n for (const orderDetail of getOrderErrorDetails(err)) {\n if (!orderDetail.rateLimit) continue;\n const result = v.safeParse(RateLimitDetailSchema, orderDetail.rateLimit);\n if (result.success) return result.output;\n }\n return undefined;\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\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 if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_ELEVATION_REQUIRED)) {\n return \"session-elevation\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_STEP_UP_REQUIRED)) return \"step-up\";\n if (hasAuthErrorCode(err, AuthErrorCode.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 const seconds = Number(value);\n if (Number.isFinite(seconds)) return Math.max(0, Math.round(seconds * 1000));\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 options: PolyesterErrorOptions = { cause: ce };\n const withFallback = (fallback: string) => message || fallback;\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_RESOURCE_NOT_FOUND)) {\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n }\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_REVISION_CONFLICT)) {\n return new RevisionConflictError(\n withFallback(\"Resource changed since it was last read.\"),\n options,\n );\n }\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_POLICY_IN_USE)) {\n return new PolicyInUseError(withFallback(\"Policy is still in use.\"), options);\n }\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_POLICY_LOCKED)) {\n return new PolicyLockedError(withFallback(\"Policy is locked.\"), options);\n }\n if (hasAuthErrorCode(ce, AuthErrorCode.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 (hasAuthErrorCode(ce, AuthErrorCode.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\n const mfaVerificationReason = getMfaVerificationFailureReason(ce);\n if (mfaVerificationReason) {\n return new MfaVerificationError(\n withFallback(\"MFA verification failed.\"),\n mfaVerificationReason,\n options,\n );\n }\n\n const mfaKind = detectMfaErrorKind(ce);\n if (mfaKind) {\n return new MFA_ERROR_CLASSES[mfaKind](\n withFallback(\"Multi-factor authentication required.\"),\n options,\n );\n }\n\n if (hasOrderErrorCode(ce, OrderErrorCode.STALE_QUOTE)) {\n return new StaleQuoteError(withFallback(\"The submitted market quote is stale.\"), options);\n }\n\n const rateLimit = getRateLimitDetail(ce);\n if (rateLimit || hasOrderErrorCode(ce, OrderErrorCode.RATE_LIMIT_EXCEEDED)) {\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n rateLimit,\n retryAfterMs: safeRetryAfterMs(rateLimit) ?? parseRetryAfterMs(ce),\n });\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(err: unknown): MfaVerificationFailureReason | null {\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_CHALLENGE_INVALID)) {\n return \"challenge-invalid\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_CHALLENGE_LOCKED)) {\n return \"challenge-locked\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_OTP_INVALID)) return \"otp-invalid\";\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_RECOVERY_INVALID)) {\n return \"recovery-code-invalid\";\n }\n if (\n hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_PASSKEY_CREDENTIAL_INVALID) ||\n hasAuthErrorCode(err, AuthErrorCode.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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connect-error-mapping.js","names":["OrderErrorDetailSchema","v"],"sources":["../../src/shared/connect-error-mapping.ts"],"sourcesContent":["import { Code, ConnectError, type Interceptor, type Transport } from \"@connectrpc/connect\";\nimport * as v from \"./validation.js\";\nimport { AuthErrorCode, AuthErrorDetailSchema } from \"../gen/auth/v1/auth_pb.js\";\nimport {\n ErrorCode as OrderErrorCode,\n ErrorDetailSchema as OrderErrorDetailSchema,\n} from \"../gen/orders/v1/orders_pb.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 { RateLimitDetailSchema, type RateLimitDetail } from \"./rate-limit.schemas.js\";\n\nfunction getAuthErrorDetails(err: unknown) {\n return ConnectError.from(err).findDetails(AuthErrorDetailSchema);\n}\n\nfunction hasAuthErrorCode(err: unknown, code: AuthErrorCode): boolean {\n return getAuthErrorDetails(err).some((detail) => detail.code === code);\n}\n\nfunction hasOrderErrorCode(err: unknown, code: OrderErrorCode): boolean {\n return getOrderErrorDetails(err).some((detail) => detail.code === code);\n}\n\nfunction getOrderErrorDetails(err: unknown) {\n return ConnectError.from(err).findDetails(OrderErrorDetailSchema);\n}\n\nfunction getRateLimitDetail(err: unknown): RateLimitDetail | undefined {\n for (const orderDetail of getOrderErrorDetails(err)) {\n if (!orderDetail.rateLimit) continue;\n const result = v.safeParse(RateLimitDetailSchema, orderDetail.rateLimit);\n if (result.success) return result.output;\n }\n return undefined;\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\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 if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_ELEVATION_REQUIRED)) {\n return \"session-elevation\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_STEP_UP_REQUIRED)) return \"step-up\";\n if (hasAuthErrorCode(err, AuthErrorCode.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 const seconds = Number(value);\n if (Number.isFinite(seconds)) return Math.max(0, Math.round(seconds * 1000));\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 options: PolyesterErrorOptions = { cause: ce };\n const withFallback = (fallback: string) => message || fallback;\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_RESOURCE_NOT_FOUND)) {\n return new ResourceNotFoundError(withFallback(\"Resource not found.\"), options);\n }\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_REVISION_CONFLICT)) {\n return new RevisionConflictError(\n withFallback(\"Resource changed since it was last read.\"),\n options,\n );\n }\n\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_POLICY_IN_USE)) {\n return new PolicyInUseError(withFallback(\"Policy is still in use.\"), options);\n }\n if (hasAuthErrorCode(ce, AuthErrorCode.AUTH_POLICY_LOCKED)) {\n return new PolicyLockedError(withFallback(\"Policy is locked.\"), options);\n }\n if (hasAuthErrorCode(ce, AuthErrorCode.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 (hasAuthErrorCode(ce, AuthErrorCode.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\n const mfaVerificationReason = getMfaVerificationFailureReason(ce);\n if (mfaVerificationReason) {\n return new MfaVerificationError(\n withFallback(\"MFA verification failed.\"),\n mfaVerificationReason,\n options,\n );\n }\n\n const mfaKind = detectMfaErrorKind(ce);\n if (mfaKind) {\n return new MFA_ERROR_CLASSES[mfaKind](\n withFallback(\"Multi-factor authentication required.\"),\n options,\n );\n }\n\n if (hasOrderErrorCode(ce, OrderErrorCode.STALE_QUOTE)) {\n return new StaleQuoteError(withFallback(\"The submitted market quote is stale.\"), options);\n }\n\n const rateLimit = getRateLimitDetail(ce);\n if (rateLimit || hasOrderErrorCode(ce, OrderErrorCode.RATE_LIMIT_EXCEEDED)) {\n return new RateLimitError(withFallback(\"Rate limit exceeded.\"), {\n ...options,\n rateLimit,\n retryAfterMs: safeRetryAfterMs(rateLimit) ?? parseRetryAfterMs(ce),\n });\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(err: unknown): MfaVerificationFailureReason | null {\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_CHALLENGE_INVALID)) {\n return \"challenge-invalid\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_CHALLENGE_LOCKED)) {\n return \"challenge-locked\";\n }\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_OTP_INVALID)) return \"otp-invalid\";\n if (hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_RECOVERY_INVALID)) {\n return \"recovery-code-invalid\";\n }\n if (\n hasAuthErrorCode(err, AuthErrorCode.AUTH_MFA_PASSKEY_CREDENTIAL_INVALID) ||\n hasAuthErrorCode(err, AuthErrorCode.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":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { validation_d_exports } from "./validation.js";
|
|
1
2
|
import { FailureReason, LimiterScope, PolicyClass, RefillModel } from "../gen/polyester/ratelimit/v1/types_pb.js";
|
|
2
|
-
import * as v from "valibot";
|
|
3
3
|
//#region src/shared/rate-limit.schemas.d.ts
|
|
4
4
|
declare const RATE_LIMIT_FAILURE_REASON_VALUES: readonly ["unspecified", "quota_exceeded", "authority_unavailable"];
|
|
5
5
|
declare const RATE_LIMIT_POLICY_CLASS_VALUES: readonly ["unspecified", "auth_public", "trading_place", "trading_cancel", "trading_read", "account_admin", "public_read", "account_security", "deposit_create", "internal_transfer", "withdraw_submit", "withdraw_validate", "guard_sign", "social_provider"];
|
|
@@ -14,19 +14,19 @@ type RateLimitScope = (typeof RATE_LIMIT_SCOPE_VALUES)[number];
|
|
|
14
14
|
/** Refill behavior for the exhausted quota. */
|
|
15
15
|
type RateLimitRefillModel = (typeof RATE_LIMIT_REFILL_MODEL_VALUES)[number];
|
|
16
16
|
/** Parses protobuf quota state into the stable SDK rate-limit detail shape. */
|
|
17
|
-
declare const RateLimitDetailSchema:
|
|
18
|
-
readonly reason:
|
|
19
|
-
readonly limit:
|
|
20
|
-
readonly remaining:
|
|
21
|
-
readonly retryAfterMs:
|
|
22
|
-
readonly policyVersion:
|
|
23
|
-
readonly operationId:
|
|
24
|
-
readonly policyClass:
|
|
25
|
-
readonly scope:
|
|
26
|
-
readonly refillModel:
|
|
17
|
+
declare const RateLimitDetailSchema: validation_d_exports.ObjectSchema<{
|
|
18
|
+
readonly reason: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.EnumSchema<typeof FailureReason, undefined>, validation_d_exports.TransformAction<FailureReason, "unspecified" | "quota_exceeded" | "authority_unavailable">]>;
|
|
19
|
+
readonly limit: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.OptionalSchema<validation_d_exports.BigintSchema<undefined>, undefined>, validation_d_exports.TransformAction<bigint | undefined, string | undefined>]>;
|
|
20
|
+
readonly remaining: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.OptionalSchema<validation_d_exports.BigintSchema<undefined>, undefined>, validation_d_exports.TransformAction<bigint | undefined, string | undefined>]>;
|
|
21
|
+
readonly retryAfterMs: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.OptionalSchema<validation_d_exports.BigintSchema<undefined>, undefined>, validation_d_exports.TransformAction<bigint | undefined, string | undefined>]>;
|
|
22
|
+
readonly policyVersion: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.OptionalSchema<validation_d_exports.BigintSchema<undefined>, undefined>, validation_d_exports.TransformAction<bigint | undefined, string | undefined>]>;
|
|
23
|
+
readonly operationId: validation_d_exports.StringSchema<undefined>;
|
|
24
|
+
readonly policyClass: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.EnumSchema<typeof PolicyClass, undefined>, validation_d_exports.TransformAction<PolicyClass, "unspecified" | "auth_public" | "trading_place" | "trading_cancel" | "trading_read" | "account_admin" | "public_read" | "account_security" | "deposit_create" | "internal_transfer" | "withdraw_submit" | "withdraw_validate" | "guard_sign" | "social_provider">]>;
|
|
25
|
+
readonly scope: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.EnumSchema<typeof LimiterScope, undefined>, validation_d_exports.TransformAction<LimiterScope, "symbol" | "unspecified" | "client_ip" | "api_key" | "account" | "subaccount" | "connection" | "service" | "region" | "auth_subject">]>;
|
|
26
|
+
readonly refillModel: validation_d_exports.SchemaWithPipe<readonly [validation_d_exports.EnumSchema<typeof RefillModel, undefined>, validation_d_exports.TransformAction<RefillModel, "unspecified" | "continuous" | "fixed_window" | "rolling_window">]>;
|
|
27
27
|
}, undefined>;
|
|
28
28
|
/** Structured quota state exposed by order rejections and {@link RateLimitError}. */
|
|
29
|
-
type RateLimitDetail =
|
|
29
|
+
type RateLimitDetail = validation_d_exports.InferOutput<typeof RateLimitDetailSchema>;
|
|
30
30
|
//#endregion
|
|
31
31
|
export { RateLimitDetail, RateLimitDetailSchema, RateLimitFailureReason, RateLimitPolicyClass, RateLimitRefillModel, RateLimitScope };
|
|
32
32
|
//# sourceMappingURL=rate-limit.schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.schemas.d.ts","names":[],"sources":["../../src/shared/rate-limit.schemas.ts"],"mappings":";;;cAMM;cAMA;cAiBA;cAaA;;KAQM,iCAAiC;;KAEjC,+BAA+B;;KAE/B,yBAAyB;;KAEzB,+BAA+B;;cAsD9B,uBAAqB,
|
|
1
|
+
{"version":3,"file":"rate-limit.schemas.d.ts","names":[],"sources":["../../src/shared/rate-limit.schemas.ts"],"mappings":";;;cAMM;cAMA;cAiBA;cAaA;;KAQM,iCAAiC;;KAEjC,+BAA+B;;KAE/B,yBAAyB;;KAEzB,+BAA+B;;cAsD9B,uBAAqB,qBAAA;;;;;;;;;;;;KAqDtB,kBAAkB,qBAAE,mBAAmB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { validation_exports } from "./validation.js";
|
|
1
2
|
import { FailureReason, LimiterScope, PolicyClass, RefillModel } from "../gen/polyester/ratelimit/v1/types_pb.js";
|
|
2
3
|
import { requiredEnumLabel } from "./proto-enum-codec.js";
|
|
3
4
|
import { OptionalBigIntStringSchema } from "./schemas.js";
|
|
4
|
-
import * as v from "valibot";
|
|
5
5
|
//#region src/shared/rate-limit.schemas.ts
|
|
6
6
|
const RateLimitFailureReasonCodec = { protoToOutput: {
|
|
7
7
|
[0]: "unspecified",
|
|
@@ -43,16 +43,16 @@ const RateLimitRefillModelCodec = { protoToOutput: {
|
|
|
43
43
|
[3]: "rolling_window"
|
|
44
44
|
} };
|
|
45
45
|
/** Parses protobuf quota state into the stable SDK rate-limit detail shape. */
|
|
46
|
-
const RateLimitDetailSchema =
|
|
47
|
-
reason:
|
|
46
|
+
const RateLimitDetailSchema = validation_exports.object({
|
|
47
|
+
reason: validation_exports.pipe(validation_exports.enum(FailureReason), validation_exports.transform((reason) => requiredEnumLabel(RateLimitFailureReasonCodec.protoToOutput, reason, "RateLimitDetailSchema", "reason"))),
|
|
48
48
|
limit: OptionalBigIntStringSchema,
|
|
49
49
|
remaining: OptionalBigIntStringSchema,
|
|
50
50
|
retryAfterMs: OptionalBigIntStringSchema,
|
|
51
51
|
policyVersion: OptionalBigIntStringSchema,
|
|
52
|
-
operationId:
|
|
53
|
-
policyClass:
|
|
54
|
-
scope:
|
|
55
|
-
refillModel:
|
|
52
|
+
operationId: validation_exports.string(),
|
|
53
|
+
policyClass: validation_exports.pipe(validation_exports.enum(PolicyClass), validation_exports.transform((policyClass) => requiredEnumLabel(RateLimitPolicyClassCodec.protoToOutput, policyClass, "RateLimitDetailSchema", "policyClass"))),
|
|
54
|
+
scope: validation_exports.pipe(validation_exports.enum(LimiterScope), validation_exports.transform((scope) => requiredEnumLabel(RateLimitScopeCodec.protoToOutput, scope, "RateLimitDetailSchema", "scope"))),
|
|
55
|
+
refillModel: validation_exports.pipe(validation_exports.enum(RefillModel), validation_exports.transform((refillModel) => requiredEnumLabel(RateLimitRefillModelCodec.protoToOutput, refillModel, "RateLimitDetailSchema", "refillModel")))
|
|
56
56
|
});
|
|
57
57
|
//#endregion
|
|
58
58
|
export { RateLimitDetailSchema };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.schemas.js","names":["Proto.FailureReason","Proto.PolicyClass","Proto.LimiterScope","Proto.RefillModel"],"sources":["../../src/shared/rate-limit.schemas.ts"],"sourcesContent":["import * as v from \"
|
|
1
|
+
{"version":3,"file":"rate-limit.schemas.js","names":["v","Proto.FailureReason","Proto.PolicyClass","Proto.LimiterScope","Proto.RefillModel"],"sources":["../../src/shared/rate-limit.schemas.ts"],"sourcesContent":["import * as v from \"./validation.js\";\nimport * as Proto from \"../gen/polyester/ratelimit/v1/types_pb.js\";\nimport type { ProtoToOutput } from \"../utils/types.js\";\nimport { requiredEnumLabel } from \"./proto-enum-codec.js\";\nimport { OptionalBigIntStringSchema } from \"./schemas.js\";\n\nconst RATE_LIMIT_FAILURE_REASON_VALUES = [\n \"unspecified\",\n \"quota_exceeded\",\n \"authority_unavailable\",\n] as const;\n\nconst RATE_LIMIT_POLICY_CLASS_VALUES = [\n \"unspecified\",\n \"auth_public\",\n \"trading_place\",\n \"trading_cancel\",\n \"trading_read\",\n \"account_admin\",\n \"public_read\",\n \"account_security\",\n \"deposit_create\",\n \"internal_transfer\",\n \"withdraw_submit\",\n \"withdraw_validate\",\n \"guard_sign\",\n \"social_provider\",\n] as const;\n\nconst RATE_LIMIT_SCOPE_VALUES = [\n \"unspecified\",\n \"client_ip\",\n \"api_key\",\n \"account\",\n \"subaccount\",\n \"connection\",\n \"service\",\n \"region\",\n \"symbol\",\n \"auth_subject\",\n] as const;\n\nconst RATE_LIMIT_REFILL_MODEL_VALUES = [\n \"unspecified\",\n \"continuous\",\n \"fixed_window\",\n \"rolling_window\",\n] as const;\n\n/** Machine-readable reason for a rate-limit rejection. */\nexport type RateLimitFailureReason = (typeof RATE_LIMIT_FAILURE_REASON_VALUES)[number];\n/** Quota policy family used for a rate-limit decision. */\nexport type RateLimitPolicyClass = (typeof RATE_LIMIT_POLICY_CLASS_VALUES)[number];\n/** Caller dimension that owns the exhausted capacity. */\nexport type RateLimitScope = (typeof RATE_LIMIT_SCOPE_VALUES)[number];\n/** Refill behavior for the exhausted quota. */\nexport type RateLimitRefillModel = (typeof RATE_LIMIT_REFILL_MODEL_VALUES)[number];\n\nconst RateLimitFailureReasonCodec = {\n protoToOutput: {\n [Proto.FailureReason.REASON_UNSPECIFIED]: \"unspecified\",\n [Proto.FailureReason.QUOTA_EXCEEDED]: \"quota_exceeded\",\n [Proto.FailureReason.AUTHORITY_UNAVAILABLE]: \"authority_unavailable\",\n } satisfies ProtoToOutput<Proto.FailureReason, RateLimitFailureReason>,\n} as const;\n\nconst RateLimitPolicyClassCodec = {\n protoToOutput: {\n [Proto.PolicyClass.CLASS_UNSPECIFIED]: \"unspecified\",\n [Proto.PolicyClass.AUTH_PUBLIC]: \"auth_public\",\n [Proto.PolicyClass.TRADING_PLACE]: \"trading_place\",\n [Proto.PolicyClass.TRADING_CANCEL]: \"trading_cancel\",\n [Proto.PolicyClass.TRADING_READ]: \"trading_read\",\n [Proto.PolicyClass.ACCOUNT_ADMIN]: \"account_admin\",\n [Proto.PolicyClass.PUBLIC_READ]: \"public_read\",\n [Proto.PolicyClass.ACCOUNT_SECURITY]: \"account_security\",\n [Proto.PolicyClass.DEPOSIT_CREATE]: \"deposit_create\",\n [Proto.PolicyClass.INTERNAL_TRANSFER]: \"internal_transfer\",\n [Proto.PolicyClass.WITHDRAW_SUBMIT]: \"withdraw_submit\",\n [Proto.PolicyClass.WITHDRAW_VALIDATE]: \"withdraw_validate\",\n [Proto.PolicyClass.GUARD_SIGN]: \"guard_sign\",\n [Proto.PolicyClass.SOCIAL_PROVIDER]: \"social_provider\",\n } satisfies ProtoToOutput<Proto.PolicyClass, RateLimitPolicyClass>,\n} as const;\n\nconst RateLimitScopeCodec = {\n protoToOutput: {\n [Proto.LimiterScope.SCOPE_UNSPECIFIED]: \"unspecified\",\n [Proto.LimiterScope.CLIENT_IP]: \"client_ip\",\n [Proto.LimiterScope.API_KEY]: \"api_key\",\n [Proto.LimiterScope.ACCOUNT]: \"account\",\n [Proto.LimiterScope.SUBACCOUNT]: \"subaccount\",\n [Proto.LimiterScope.CONNECTION]: \"connection\",\n [Proto.LimiterScope.SERVICE]: \"service\",\n [Proto.LimiterScope.REGION]: \"region\",\n [Proto.LimiterScope.SYMBOL]: \"symbol\",\n [Proto.LimiterScope.AUTH_SUBJECT]: \"auth_subject\",\n } satisfies ProtoToOutput<Proto.LimiterScope, RateLimitScope>,\n} as const;\n\nconst RateLimitRefillModelCodec = {\n protoToOutput: {\n [Proto.RefillModel.REFILL_UNSPECIFIED]: \"unspecified\",\n [Proto.RefillModel.CONTINUOUS]: \"continuous\",\n [Proto.RefillModel.FIXED_WINDOW]: \"fixed_window\",\n [Proto.RefillModel.ROLLING_WINDOW]: \"rolling_window\",\n } satisfies ProtoToOutput<Proto.RefillModel, RateLimitRefillModel>,\n} as const;\n\n/** Parses protobuf quota state into the stable SDK rate-limit detail shape. */\nexport const RateLimitDetailSchema = v.object({\n reason: v.pipe(\n v.enum(Proto.FailureReason),\n v.transform((reason) =>\n requiredEnumLabel(\n RateLimitFailureReasonCodec.protoToOutput,\n reason,\n \"RateLimitDetailSchema\",\n \"reason\",\n ),\n ),\n ),\n limit: OptionalBigIntStringSchema,\n remaining: OptionalBigIntStringSchema,\n retryAfterMs: OptionalBigIntStringSchema,\n policyVersion: OptionalBigIntStringSchema,\n operationId: v.string(),\n policyClass: v.pipe(\n v.enum(Proto.PolicyClass),\n v.transform((policyClass) =>\n requiredEnumLabel(\n RateLimitPolicyClassCodec.protoToOutput,\n policyClass,\n \"RateLimitDetailSchema\",\n \"policyClass\",\n ),\n ),\n ),\n scope: v.pipe(\n v.enum(Proto.LimiterScope),\n v.transform((scope) =>\n requiredEnumLabel(\n RateLimitScopeCodec.protoToOutput,\n scope,\n \"RateLimitDetailSchema\",\n \"scope\",\n ),\n ),\n ),\n refillModel: v.pipe(\n v.enum(Proto.RefillModel),\n v.transform((refillModel) =>\n requiredEnumLabel(\n RateLimitRefillModelCodec.protoToOutput,\n refillModel,\n \"RateLimitDetailSchema\",\n \"refillModel\",\n ),\n ),\n ),\n});\n\n/** Structured quota state exposed by order rejections and {@link RateLimitError}. */\nexport type RateLimitDetail = v.InferOutput<typeof RateLimitDetailSchema>;\n"],"mappings":";;;;;AA0DA,MAAM,8BAA8B,EAChC,eAAe;EAC+B,IAAA;EACJ,IAAA;EACO,IAAA;AACjD,EACJ;AAEA,MAAM,4BAA4B,EAC9B,eAAe;EAC4B,IAAA;EACN,IAAA;EACE,IAAA;EACC,IAAA;EACF,IAAA;EACC,IAAA;EACF,IAAA;EACK,IAAA;EACF,IAAA;EACG,IAAA;EACF,KAAA;EACE,KAAA;EACP,KAAA;EACK,KAAA;AACzC,EACJ;AAEA,MAAM,sBAAsB,EACxB,eAAe;EAC6B,IAAA;EACR,IAAA;EACF,IAAA;EACA,IAAA;EACG,IAAA;EACA,IAAA;EACH,IAAA;EACD,IAAA;EACA,IAAA;EACM,IAAA;AACvC,EACJ;AAEA,MAAM,4BAA4B,EAC9B,eAAe;EAC6B,IAAA;EACR,IAAA;EACE,IAAA;EACE,IAAA;AACxC,EACJ;;AAGA,MAAa,wBAAwBA,mBAAE,OAAO;CAC1C,QAAQA,mBAAE,KACNA,mBAAE,KAAKC,aAAmB,GAC1BD,mBAAE,WAAW,WACT,kBACI,4BAA4B,eAC5B,QACA,yBACA,QACJ,CACJ,CACJ;CACA,OAAO;CACP,WAAW;CACX,cAAc;CACd,eAAe;CACf,aAAaA,mBAAE,OAAO;CACtB,aAAaA,mBAAE,KACXA,mBAAE,KAAKE,WAAiB,GACxBF,mBAAE,WAAW,gBACT,kBACI,0BAA0B,eAC1B,aACA,yBACA,aACJ,CACJ,CACJ;CACA,OAAOA,mBAAE,KACLA,mBAAE,KAAKG,YAAkB,GACzBH,mBAAE,WAAW,UACT,kBACI,oBAAoB,eACpB,OACA,yBACA,OACJ,CACJ,CACJ;CACA,aAAaA,mBAAE,KACXA,mBAAE,KAAKI,WAAiB,GACxBJ,mBAAE,WAAW,gBACT,kBACI,0BAA0B,eAC1B,aACA,yBACA,aACJ,CACJ,CACJ;AACJ,CAAC"}
|
package/dist/shared/schemas.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
+
import { validation_exports } from "./validation.js";
|
|
1
2
|
import { formatId, idToBigInt } from "../utils/base58-id.js";
|
|
2
3
|
import { parseOptionalUint64DecimalStrict, toBigIntOrZero, toBpsOrZero, toIntOrZero } from "../utils/numbers.js";
|
|
3
4
|
import { tsNsToMs, tsObjToMs } from "../utils/time.js";
|
|
4
|
-
import * as v from "valibot";
|
|
5
5
|
//#region src/shared/schemas.ts
|
|
6
6
|
const UINT64_MAX = (1n << 64n) - 1n;
|
|
7
7
|
const MS_TO_US = 1000n;
|
|
8
8
|
const MS_TO_NS = 1000000n;
|
|
9
9
|
const MAX_UINT64_TIMESTAMP_MS_US = Number(UINT64_MAX / MS_TO_US);
|
|
10
10
|
const MAX_UINT64_TIMESTAMP_MS = Number(UINT64_MAX / MS_TO_NS);
|
|
11
|
-
const TimestampSchema =
|
|
12
|
-
seconds:
|
|
13
|
-
nanos:
|
|
11
|
+
const TimestampSchema = validation_exports.object({
|
|
12
|
+
seconds: validation_exports.bigint(),
|
|
13
|
+
nanos: validation_exports.optional(validation_exports.number(), 0)
|
|
14
14
|
});
|
|
15
|
-
const TimestampMsSchema =
|
|
16
|
-
const OptionalTimestampMsSchema =
|
|
17
|
-
const OptionalNumberDefaultNullSchema =
|
|
18
|
-
const OptionalNumberToBigIntOrZeroSchema =
|
|
19
|
-
const OptionalNumberToIntOrZeroSchema =
|
|
20
|
-
const OptionalNumberToBpsOrZeroSchema =
|
|
21
|
-
|
|
22
|
-
const BigIntStringSchema =
|
|
23
|
-
const OptionalBigIntStringSchema =
|
|
24
|
-
|
|
25
|
-
const OptionalTimestampMsToUsInputSchema =
|
|
26
|
-
const OptionalTimestampSecondsInputSchema =
|
|
27
|
-
const PublicIdSchema =
|
|
28
|
-
const OptionalPublicIdSchema =
|
|
29
|
-
const TrimmedStringSchema =
|
|
30
|
-
const OptionalTrimmedStringSchema =
|
|
15
|
+
const TimestampMsSchema = validation_exports.pipe(TimestampSchema, validation_exports.transform((value) => tsObjToMs(value)));
|
|
16
|
+
const OptionalTimestampMsSchema = validation_exports.pipe(validation_exports.optional(TimestampSchema), validation_exports.transform((value) => tsObjToMs(value)));
|
|
17
|
+
const OptionalNumberDefaultNullSchema = validation_exports.optional(validation_exports.nullable(validation_exports.number()), null);
|
|
18
|
+
const OptionalNumberToBigIntOrZeroSchema = validation_exports.pipe(OptionalNumberDefaultNullSchema, validation_exports.transform((value) => toBigIntOrZero(value)));
|
|
19
|
+
const OptionalNumberToIntOrZeroSchema = validation_exports.pipe(OptionalNumberDefaultNullSchema, validation_exports.transform((value) => toIntOrZero(value)));
|
|
20
|
+
const OptionalNumberToBpsOrZeroSchema = validation_exports.pipe(OptionalNumberDefaultNullSchema, validation_exports.transform((value) => toBpsOrZero(value)));
|
|
21
|
+
validation_exports.pipe(validation_exports.bigint(), validation_exports.transform((value) => tsNsToMs(value)));
|
|
22
|
+
const BigIntStringSchema = validation_exports.pipe(validation_exports.bigint(), validation_exports.transform((value) => value.toString()));
|
|
23
|
+
const OptionalBigIntStringSchema = validation_exports.pipe(validation_exports.optional(validation_exports.bigint()), validation_exports.transform((value) => value === void 0 ? void 0 : value.toString()));
|
|
24
|
+
validation_exports.optional(validation_exports.pipe(validation_exports.number(), validation_exports.integer(), validation_exports.minValue(0), validation_exports.maxValue(MAX_UINT64_TIMESTAMP_MS), validation_exports.transform((value) => BigInt(value) * MS_TO_NS)));
|
|
25
|
+
const OptionalTimestampMsToUsInputSchema = validation_exports.optional(validation_exports.pipe(validation_exports.number(), validation_exports.integer(), validation_exports.minValue(0), validation_exports.maxValue(MAX_UINT64_TIMESTAMP_MS_US), validation_exports.transform((value) => BigInt(value) * MS_TO_US)));
|
|
26
|
+
const OptionalTimestampSecondsInputSchema = validation_exports.optional(validation_exports.pipe(validation_exports.number(), validation_exports.integer(), validation_exports.minValue(0), validation_exports.maxValue(Number.MAX_SAFE_INTEGER), validation_exports.transform((value) => BigInt(value))));
|
|
27
|
+
const PublicIdSchema = validation_exports.pipe(validation_exports.bigint(), validation_exports.transform((value) => formatId(value)));
|
|
28
|
+
const OptionalPublicIdSchema = validation_exports.pipe(validation_exports.optional(validation_exports.bigint()), validation_exports.transform((value) => value ? formatId(value) : void 0));
|
|
29
|
+
const TrimmedStringSchema = validation_exports.pipe(validation_exports.string(), validation_exports.trim());
|
|
30
|
+
const OptionalTrimmedStringSchema = validation_exports.optional(TrimmedStringSchema);
|
|
31
31
|
/**
|
|
32
32
|
* Creates a schema for required public id input.
|
|
33
33
|
*/
|
|
34
34
|
function idInputSchema(fieldName) {
|
|
35
|
-
return
|
|
35
|
+
return validation_exports.pipe(validation_exports.string(), validation_exports.trim(), validation_exports.minLength(1), validation_exports.transform((value) => idToBigInt(value, fieldName)));
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Creates a schema for optional public id input.
|
|
39
39
|
*/
|
|
40
40
|
function optionalIdInputSchema(fieldName) {
|
|
41
|
-
return
|
|
41
|
+
return validation_exports.pipe(OptionalTrimmedStringSchema, validation_exports.transform((value) => value ? idToBigInt(value, fieldName) : void 0));
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Creates a schema for optional subaccount id input.
|
|
@@ -50,15 +50,15 @@ function optionalSubaccountIdInputSchema() {
|
|
|
50
50
|
* Creates a schema for optional uint64 decimal filter input.
|
|
51
51
|
*/
|
|
52
52
|
function optionalUint64DecimalFilterSchema(fieldName) {
|
|
53
|
-
return
|
|
53
|
+
return validation_exports.pipe(OptionalTrimmedStringSchema, validation_exports.transform((value) => parseOptionalUint64DecimalStrict(value, fieldName)));
|
|
54
54
|
}
|
|
55
55
|
function bigintStringInputSchema(fieldName) {
|
|
56
|
-
return
|
|
56
|
+
return validation_exports.pipe(TrimmedStringSchema, validation_exports.regex(/^\d+$/, `${fieldName} must be a decimal integer`), validation_exports.transform((value) => BigInt(value)));
|
|
57
57
|
}
|
|
58
58
|
function positiveBigintStringInputSchema(fieldName) {
|
|
59
|
-
return
|
|
59
|
+
return validation_exports.pipe(bigintStringInputSchema(fieldName), validation_exports.check((value) => value > 0n, `${fieldName} must be greater than 0`));
|
|
60
60
|
}
|
|
61
|
-
const JsonObjectSchema =
|
|
61
|
+
const JsonObjectSchema = validation_exports.custom((input) => typeof input === "object" && input !== null && !Array.isArray(input));
|
|
62
62
|
//#endregion
|
|
63
63
|
export { BigIntStringSchema, JsonObjectSchema, OptionalBigIntStringSchema, OptionalNumberDefaultNullSchema, OptionalNumberToBigIntOrZeroSchema, OptionalNumberToBpsOrZeroSchema, OptionalNumberToIntOrZeroSchema, OptionalPublicIdSchema, OptionalTimestampMsSchema, OptionalTimestampMsToUsInputSchema, OptionalTimestampSecondsInputSchema, PublicIdSchema, TimestampMsSchema, TimestampSchema, bigintStringInputSchema, idInputSchema, optionalIdInputSchema, optionalSubaccountIdInputSchema, optionalUint64DecimalFilterSchema, positiveBigintStringInputSchema };
|
|
64
64
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","names":[],"sources":["../../src/shared/schemas.ts"],"sourcesContent":["import * as v from \"
|
|
1
|
+
{"version":3,"file":"schemas.js","names":["v"],"sources":["../../src/shared/schemas.ts"],"sourcesContent":["import * as v from \"./validation.js\";\nimport { formatId, idToBigInt } from \"../utils/base58-id.js\";\nimport {\n parseOptionalUint64DecimalStrict,\n toBigIntOrZero,\n toBpsOrZero,\n toIntOrZero,\n} from \"../utils/numbers.js\";\nimport { tsNsToMs, tsObjToMs } from \"../utils/time.js\";\nimport type { JsonObject } from \"@bufbuild/protobuf\";\n\nconst UINT64_MAX = (1n << 64n) - 1n;\nconst MS_TO_US = 1_000n;\nconst MS_TO_NS = 1_000_000n;\nconst MAX_UINT64_TIMESTAMP_MS_US = Number(UINT64_MAX / MS_TO_US);\nconst MAX_UINT64_TIMESTAMP_MS = Number(UINT64_MAX / MS_TO_NS);\n\nexport const TimestampSchema = v.object({\n seconds: v.bigint(),\n nanos: v.optional(v.number(), 0),\n});\n\nexport const TimestampMsSchema = v.pipe(\n TimestampSchema,\n v.transform((value) => tsObjToMs(value)),\n);\n\nexport const OptionalTimestampMsSchema = v.pipe(\n v.optional(TimestampSchema),\n v.transform((value) => tsObjToMs(value)),\n);\n\nexport const OptionalNumberDefaultNullSchema = v.optional(v.nullable(v.number()), null);\n\nexport const OptionalNumberToBigIntOrZeroSchema = v.pipe(\n OptionalNumberDefaultNullSchema,\n v.transform((value) => toBigIntOrZero(value)),\n);\n\nexport const OptionalNumberToIntOrZeroSchema = v.pipe(\n OptionalNumberDefaultNullSchema,\n v.transform((value) => toIntOrZero(value)),\n);\n\nexport const OptionalNumberToBpsOrZeroSchema = v.pipe(\n OptionalNumberDefaultNullSchema,\n v.transform((value) => toBpsOrZero(value)),\n);\n\nexport const TimestampNsMsSchema = v.pipe(\n v.bigint(),\n v.transform((value) => tsNsToMs(value)),\n);\n\nexport const BigIntStringSchema = v.pipe(\n v.bigint(),\n v.transform((value) => value.toString()),\n);\n\nexport const OptionalBigIntStringSchema = v.pipe(\n v.optional(v.bigint()),\n v.transform((value) => (value === undefined ? undefined : value.toString())),\n);\n\nexport const OptionalTimestampMsToNsInputSchema = v.optional(\n v.pipe(\n v.number(),\n v.integer(),\n v.minValue(0),\n v.maxValue(MAX_UINT64_TIMESTAMP_MS),\n v.transform((value) => BigInt(value) * MS_TO_NS),\n ),\n);\n\nexport const OptionalTimestampMsToUsInputSchema = v.optional(\n v.pipe(\n v.number(),\n v.integer(),\n v.minValue(0),\n v.maxValue(MAX_UINT64_TIMESTAMP_MS_US),\n v.transform((value) => BigInt(value) * MS_TO_US),\n ),\n);\n\nexport const OptionalTimestampSecondsInputSchema = v.optional(\n v.pipe(\n v.number(),\n v.integer(),\n v.minValue(0),\n v.maxValue(Number.MAX_SAFE_INTEGER),\n v.transform((value) => BigInt(value)),\n ),\n);\n\nexport const PublicIdSchema = v.pipe(\n v.bigint(),\n v.transform((value) => formatId(value)),\n);\n\nexport const OptionalPublicIdSchema = v.pipe(\n v.optional(v.bigint()),\n v.transform((value) => (value ? formatId(value) : undefined)),\n);\n\nconst TrimmedStringSchema = v.pipe(v.string(), v.trim());\n\nconst OptionalTrimmedStringSchema = v.optional(TrimmedStringSchema);\n\n/**\n * Creates a schema for required public id input.\n */\nexport function idInputSchema(fieldName: string) {\n return v.pipe(\n v.string(),\n v.trim(),\n v.minLength(1),\n v.transform((value) => idToBigInt(value, fieldName)),\n );\n}\n\n/**\n * Creates a schema for optional public id input.\n */\nexport function optionalIdInputSchema(fieldName: string) {\n return v.pipe(\n OptionalTrimmedStringSchema,\n v.transform((value) => (value ? idToBigInt(value, fieldName) : undefined)),\n );\n}\n\n/**\n * Creates a schema for optional subaccount id input.\n */\nexport function optionalSubaccountIdInputSchema() {\n return optionalIdInputSchema(\"subaccountId\");\n}\n\n/**\n * Creates a schema for optional uint64 decimal filter input.\n */\nexport function optionalUint64DecimalFilterSchema(fieldName: string) {\n return v.pipe(\n OptionalTrimmedStringSchema,\n v.transform((value) => parseOptionalUint64DecimalStrict(value, fieldName)),\n );\n}\n\n/**\n * Creates a schema for positive bigint-like input.\n */\nexport function positiveBigintLikeSchema(message: string) {\n return v.pipe(\n v.union([\n v.bigint(),\n v.pipe(\n TrimmedStringSchema,\n v.regex(/^\\d+$/),\n v.transform((value) => BigInt(value)),\n ),\n ]),\n v.check((value) => value > 0n, message),\n );\n}\n\nexport function bigintStringInputSchema(fieldName: string) {\n return v.pipe(\n TrimmedStringSchema,\n v.regex(/^\\d+$/, `${fieldName} must be a decimal integer`),\n v.transform((value) => BigInt(value)),\n );\n}\n\nexport function positiveBigintStringInputSchema(fieldName: string) {\n return v.pipe(\n bigintStringInputSchema(fieldName),\n v.check((value) => value > 0n, `${fieldName} must be greater than 0`),\n );\n}\n\nexport const JsonObjectSchema = v.custom<JsonObject>(\n (input): input is JsonObject =>\n typeof input === \"object\" && input !== null && !Array.isArray(input),\n);\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConfigurationError, NetworkError, isAbortError } from "./errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { createErrorMappingTransport } from "./connect-error-mapping.js";
|
|
3
3
|
import { createConnectTransport } from "@connectrpc/connect-web";
|
|
4
4
|
import { toBinary, toJsonString } from "@bufbuild/protobuf";
|
|
5
5
|
import { signAsync } from "@noble/ed25519";
|
|
@@ -28,25 +28,20 @@ function makeFetch() {
|
|
|
28
28
|
function createTransports(config) {
|
|
29
29
|
const { apiUrl, interceptors = [], auth, wireFormat = "binary" } = config;
|
|
30
30
|
const useBinaryFormat = wireFormat === "binary";
|
|
31
|
-
const
|
|
32
|
-
const publicApi = createConnectTransport({
|
|
31
|
+
const publicApi = createErrorMappingTransport(createConnectTransport({
|
|
33
32
|
baseUrl: apiUrl,
|
|
34
33
|
useBinaryFormat,
|
|
35
|
-
interceptors
|
|
34
|
+
interceptors,
|
|
36
35
|
fetch: makeFetch()
|
|
37
|
-
});
|
|
38
|
-
const authInterceptors = auth ? [
|
|
39
|
-
errorMapping,
|
|
40
|
-
createAuthInterceptor(auth, { wireFormat }),
|
|
41
|
-
...interceptors
|
|
42
|
-
] : [errorMapping, ...interceptors];
|
|
36
|
+
}));
|
|
37
|
+
const authInterceptors = auth ? [createAuthInterceptor(auth, { wireFormat }), ...interceptors] : interceptors;
|
|
43
38
|
return {
|
|
44
|
-
authApi: createConnectTransport({
|
|
39
|
+
authApi: createErrorMappingTransport(createConnectTransport({
|
|
45
40
|
baseUrl: apiUrl,
|
|
46
41
|
useBinaryFormat,
|
|
47
42
|
interceptors: authInterceptors,
|
|
48
43
|
fetch: makeFetch()
|
|
49
|
-
}),
|
|
44
|
+
})),
|
|
50
45
|
publicApi
|
|
51
46
|
};
|
|
52
47
|
}
|
|
@@ -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 { createErrorMappingInterceptor } from \"./connect-error-mapping.js\";\nimport { ConfigurationError, isAbortError, NetworkError } 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/**\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 // Outermost so every RPC failure surfaces as a typed PolyesterError.\n const errorMapping = createErrorMappingInterceptor();\n\n const publicApi = createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors: [errorMapping, ...interceptors],\n fetch: makeFetch(),\n });\n\n const authInterceptors = auth\n ? [errorMapping, createAuthInterceptor(auth, { wireFormat }), ...interceptors]\n : [errorMapping, ...interceptors];\n const authApi = createConnectTransport({\n baseUrl: apiUrl,\n useBinaryFormat,\n interceptors: authInterceptors,\n fetch: makeFetch(),\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\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 const [keyId, secretKey] = await Promise.all([auth.getKeyId(), auth.getSecretKey()]);\n if (!keyId || !secretKey) throw new ConfigurationError(\"Missing API key ID or secret key\");\n\n const urlObj = new URL(request.url);\n const timestamp = request.timestamp ?? String(Date.now());\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 * 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 auth.getToken();\n if (token) {\n req.header.set(\"Authorization\", `Bearer ${token}`);\n }\n } else if (auth.kind === \"api-key-ed25519\") {\n let bodyBytes: Uint8Array;\n if (!req.stream) {\n // unary request - serialize the message using the method's input schema\n const inputSchema = req.method.input;\n bodyBytes =\n wireFormat === \"json\"\n ? new TextEncoder().encode(toJsonString(inputSchema, req.message))\n : toBinary(inputSchema, req.message);\n } else {\n // stream request - empty body for signing (streams don't have a single body)\n bodyBytes = new Uint8Array(0);\n }\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
|
+
{"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 { ConfigurationError, isAbortError, NetworkError } 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/**\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 ? [createAuthInterceptor(auth, { wireFormat }), ...interceptors]\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\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 const [keyId, secretKey] = await Promise.all([auth.getKeyId(), auth.getSecretKey()]);\n if (!keyId || !secretKey) throw new ConfigurationError(\"Missing API key ID or secret key\");\n\n const urlObj = new URL(request.url);\n const timestamp = request.timestamp ?? String(Date.now());\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 * 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 auth.getToken();\n if (token) {\n req.header.set(\"Authorization\", `Bearer ${token}`);\n }\n } else if (auth.kind === \"api-key-ed25519\") {\n let bodyBytes: Uint8Array;\n if (!req.stream) {\n // unary request - serialize the message using the method's input schema\n const inputSchema = req.method.input;\n bodyBytes =\n wireFormat === \"json\"\n ? new TextEncoder().encode(toJsonString(inputSchema, req.message))\n : toBinary(inputSchema, req.message);\n } else {\n // stream request - empty body for signing (streams don't have a single body)\n bodyBytes = new Uint8Array(0);\n }\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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"}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { SdkSubscriptionErrorContext } from "./subscription-errors.js";
|
|
2
2
|
//#region src/shared/types.d.ts
|
|
3
3
|
interface BaseSubscribeInput<T> {
|
|
4
|
+
/**
|
|
5
|
+
* Called after the channel subscription is confirmed. The unsubscribe function
|
|
6
|
+
* returned by subscribe only starts the connection; wait for the first onOpen
|
|
7
|
+
* call before issuing writes whose events must be observed. Called again after
|
|
8
|
+
* a successful resubscription.
|
|
9
|
+
*/
|
|
4
10
|
onOpen?: () => void;
|
|
11
|
+
/** Called when an active channel subscription closes. */
|
|
5
12
|
onClose?: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Called when the subscription or an event handler reports an error. When omitted,
|
|
15
|
+
* a synchronously detected missing-authentication failure throws instead.
|
|
16
|
+
*/
|
|
6
17
|
onError?: (ctx: SdkSubscriptionErrorContext) => void;
|
|
18
|
+
/** Called for each event received while the channel subscription is active. */
|
|
7
19
|
onEvent: (c: T) => void;
|
|
8
20
|
}
|
|
9
21
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/shared/types.ts"],"mappings":";;UAEiB,mBAAmB
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/shared/types.ts"],"mappings":";;UAEiB,mBAAmB;;;;;;;EAOhC;;EAEA;;;;;EAKA,WAAW,KAAK;;EAEhB,UAAU,GAAG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
export * from "valibot";
|
|
3
|
+
declare namespace validation_d_exports {
|
|
4
|
+
export { parse };
|
|
5
|
+
}
|
|
6
|
+
import * as import_valibot from "valibot";
|
|
7
|
+
/**
|
|
8
|
+
* Parses a value with Valibot and translates schema failures into the SDK's
|
|
9
|
+
* public error hierarchy.
|
|
10
|
+
*/
|
|
11
|
+
declare function parse<const TSchema extends v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>>(schema: TSchema, input: unknown, config?: v.Config<v.InferIssue<TSchema>>): v.InferOutput<TSchema>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { parse, validation_d_exports };
|
|
14
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","names":[],"sources":["../../src/shared/validation.ts"],"mappings":";;;;;;;;;;iBASgB,YAAY,gBAAgB,EAAE,6BAA6B,EAAE,qBACzE,QAAQ,SACR,gBACA,SAAS,EAAE,OAAO,EAAE,WAAW,YAChC,EAAE,YAAY"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { ValidationError } from "./errors.js";
|
|
3
|
+
import * as v from "valibot";
|
|
4
|
+
export * from "valibot";
|
|
5
|
+
//#region src/shared/validation.ts
|
|
6
|
+
var validation_exports = /* @__PURE__ */ __exportAll({ parse: () => parse });
|
|
7
|
+
import * as import_valibot from "valibot";
|
|
8
|
+
__reExport(validation_exports, import_valibot);
|
|
9
|
+
/**
|
|
10
|
+
* Parses a value with Valibot and translates schema failures into the SDK's
|
|
11
|
+
* public error hierarchy.
|
|
12
|
+
*/
|
|
13
|
+
function parse(schema, input, config) {
|
|
14
|
+
try {
|
|
15
|
+
return v.parse(schema, input, config);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (v.isValiError(error)) throw new ValidationError(error.message, { cause: error });
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { parse, validation_exports };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../src/shared/validation.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport { ValidationError } from \"./errors.js\";\n\nexport * from \"valibot\";\n\n/**\n * Parses a value with Valibot and translates schema failures into the SDK's\n * public error hierarchy.\n */\nexport function parse<const TSchema extends v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>>(\n schema: TSchema,\n input: unknown,\n config?: v.Config<v.InferIssue<TSchema>>,\n): v.InferOutput<TSchema> {\n try {\n return v.parse(schema, input, config);\n } catch (error) {\n if (v.isValiError(error)) {\n throw new ValidationError(error.message, { cause: error });\n }\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;;AASA,SAAgB,MACZ,QACA,OACA,QACsB;CACtB,IAAI;EACA,OAAO,EAAE,MAAM,QAAQ,OAAO,MAAM;CACxC,SAAS,OAAO;EACZ,IAAI,EAAE,YAAY,KAAK,GACnB,MAAM,IAAI,gBAAgB,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAE7D,MAAM;CACV;AACJ"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { StaleQuoteError } from "../shared/errors.js";
|
|
2
|
+
import { validation_exports } from "../shared/validation.js";
|
|
2
3
|
import { ErrorDetailSchema } from "../gen/orders/v1/orders_pb.js";
|
|
3
4
|
import { toPolyesterError } from "../shared/connect-error-mapping.js";
|
|
4
5
|
import { OrderErrorDetailSchema } from "../services/orders/order-errors.schemas.js";
|
|
5
6
|
import { ConnectError } from "@connectrpc/connect";
|
|
6
|
-
import * as v from "valibot";
|
|
7
7
|
//#region src/utils/connect-order-errors.ts
|
|
8
8
|
/**
|
|
9
9
|
* Returns the first structured Orders API rejection detail in an error cause chain.
|
|
@@ -16,7 +16,7 @@ function getOrderErrorDetail(error) {
|
|
|
16
16
|
seen.add(current);
|
|
17
17
|
const details = ConnectError.from(current).findDetails(ErrorDetailSchema);
|
|
18
18
|
for (const detail of details) {
|
|
19
|
-
const parsed =
|
|
19
|
+
const parsed = validation_exports.safeParse(OrderErrorDetailSchema, detail);
|
|
20
20
|
if (parsed.success) return parsed.output;
|
|
21
21
|
}
|
|
22
22
|
current = current instanceof Error ? current.cause : void 0;
|