@01.software/sdk 0.48.0 → 0.49.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +64 -7
  3. package/dist/client.cjs +189 -26
  4. package/dist/client.cjs.map +1 -1
  5. package/dist/client.d.cts +7 -6
  6. package/dist/client.d.ts +7 -6
  7. package/dist/client.js +189 -26
  8. package/dist/client.js.map +1 -1
  9. package/dist/{collection-client-D3ExJU-7.d.ts → collection-client-DnDt6EQz.d.ts} +4 -4
  10. package/dist/{collection-client-CBup9yOx.d.cts → collection-client-XfGLPuTf.d.cts} +4 -4
  11. package/dist/{const-BXEi1Kix.d.cts → const-CBba4lDo.d.cts} +1 -1
  12. package/dist/{const-k9gHylYa.d.ts → const-DCNV5Kq7.d.ts} +1 -1
  13. package/dist/errors.cjs +63 -15
  14. package/dist/errors.cjs.map +1 -1
  15. package/dist/errors.d.cts +10 -1
  16. package/dist/errors.d.ts +10 -1
  17. package/dist/errors.js +63 -15
  18. package/dist/errors.js.map +1 -1
  19. package/dist/{index-BCM9CTL7.d.cts → index-CbKyoEzy.d.cts} +3 -3
  20. package/dist/{index-CHGGkcLj.d.ts → index-DUuIqUS8.d.ts} +3 -3
  21. package/dist/index.cjs +152 -48
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +8 -8
  24. package/dist/index.d.ts +8 -8
  25. package/dist/index.js +152 -48
  26. package/dist/index.js.map +1 -1
  27. package/dist/{payload-types-B6AZQcB7.d.cts → payload-types-MKbx5MuJ.d.cts} +133 -3
  28. package/dist/{payload-types-B6AZQcB7.d.ts → payload-types-MKbx5MuJ.d.ts} +133 -3
  29. package/dist/query.cjs +21 -0
  30. package/dist/query.cjs.map +1 -1
  31. package/dist/query.d.cts +5 -5
  32. package/dist/query.d.ts +5 -5
  33. package/dist/query.js +21 -0
  34. package/dist/query.js.map +1 -1
  35. package/dist/realtime.d.cts +2 -2
  36. package/dist/realtime.d.ts +2 -2
  37. package/dist/server.cjs +189 -26
  38. package/dist/server.cjs.map +1 -1
  39. package/dist/server.d.cts +8 -7
  40. package/dist/server.d.ts +8 -7
  41. package/dist/server.js +189 -26
  42. package/dist/server.js.map +1 -1
  43. package/dist/storefront-cache.cjs +21 -0
  44. package/dist/storefront-cache.cjs.map +1 -1
  45. package/dist/storefront-cache.js +21 -0
  46. package/dist/storefront-cache.js.map +1 -1
  47. package/dist/{types-DbA5V3mt.d.ts → types-1UeOk1Uy.d.cts} +31 -6
  48. package/dist/{types-8us-_C-Q.d.cts → types-BKr_2avj.d.cts} +2 -2
  49. package/dist/{types-CM2je9Kw.d.cts → types-Du4s5anw.d.ts} +31 -6
  50. package/dist/{types-ByD2zii1.d.ts → types-L_nh-ED7.d.ts} +2 -2
  51. package/dist/ui/form.d.cts +1 -1
  52. package/dist/ui/form.d.ts +1 -1
  53. package/dist/ui/video.d.cts +1 -1
  54. package/dist/ui/video.d.ts +1 -1
  55. package/dist/webhook.d.cts +4 -4
  56. package/dist/webhook.d.ts +4 -4
  57. package/package.json +5 -4
@@ -25,6 +25,24 @@ __export(storefront_cache_exports, {
25
25
  module.exports = __toCommonJS(storefront_cache_exports);
26
26
 
27
27
  // src/core/errors.ts
28
+ var SDK_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError");
29
+ var SDK_ERROR_TYPE_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError.type");
30
+ function defineSDKErrorBrand(error) {
31
+ Object.defineProperty(error, SDK_ERROR_BRAND, {
32
+ value: true,
33
+ enumerable: false,
34
+ configurable: false,
35
+ writable: false
36
+ });
37
+ }
38
+ function defineSDKErrorType(error, type) {
39
+ Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {
40
+ value: type,
41
+ enumerable: false,
42
+ configurable: false,
43
+ writable: false
44
+ });
45
+ }
28
46
  var SDKError = class extends Error {
29
47
  constructor(code, message, status, details, userMessage, suggestion, requestId) {
30
48
  super(message);
@@ -35,6 +53,7 @@ var SDKError = class extends Error {
35
53
  this.userMessage = userMessage;
36
54
  this.suggestion = suggestion;
37
55
  this.requestId = requestId;
56
+ defineSDKErrorBrand(this);
38
57
  if (Error.captureStackTrace) {
39
58
  Error.captureStackTrace(this, new.target);
40
59
  }
@@ -55,6 +74,7 @@ var SDKError = class extends Error {
55
74
  ...this.kind !== void 0 && { kind: this.kind },
56
75
  ...this.reason !== void 0 && { reason: this.reason },
57
76
  ...this.rawReason !== void 0 && { rawReason: this.rawReason },
77
+ ...this.apiReason !== void 0 && { apiReason: this.apiReason },
58
78
  ...this.retryable !== void 0 && { retryable: this.retryable },
59
79
  ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
60
80
  };
@@ -171,6 +191,7 @@ var ValidationError = class extends SDKError {
171
191
  constructor(message, details, userMessage, suggestion, status = 400) {
172
192
  super("VALIDATION_ERROR", message, status, details, userMessage, suggestion);
173
193
  this.name = "ValidationError";
194
+ defineSDKErrorType(this, "ValidationError");
174
195
  }
175
196
  };
176
197
  var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/storefront-cache.ts","../src/core/errors.ts","../src/utils/storefront-cache.ts"],"sourcesContent":["export * from './utils/storefront-cache'\n","export class SDKError extends Error {\n readonly code: string\n readonly status?: number\n readonly details?: unknown\n readonly userMessage?: string\n readonly suggestion?: string\n readonly requestId?: string\n readonly kind?: 'commerce'\n readonly reason?: CommerceErrorCode | 'unknown_commerce_error'\n readonly rawReason?: string\n readonly retryable?: boolean\n readonly retryAfter?: number\n\n constructor(\n code: string,\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n this.code = code\n this.status = status\n this.details = details\n this.userMessage = userMessage\n this.suggestion = suggestion\n this.requestId = requestId\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, new.target)\n }\n }\n\n getUserMessage(): string {\n return this.userMessage || this.message\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n status: this.status,\n details: this.details,\n userMessage: this.userMessage,\n suggestion: this.suggestion,\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n ...(this.kind !== undefined && { kind: this.kind }),\n ...(this.reason !== undefined && { reason: this.reason }),\n ...(this.rawReason !== undefined && { rawReason: this.rawReason }),\n ...(this.retryable !== undefined && { retryable: this.retryable }),\n ...(this.retryAfter !== undefined && { retryAfter: this.retryAfter }),\n }\n }\n}\n\n/**\n * Canonical Cart/Checkout/PaymentSession error reasons. This public SDK mirror\n * intentionally does not import the private contracts package; parity is\n * enforced by a type test.\n */\nexport const COMMERCE_ERROR_CODES = [\n 'validation_failed',\n 'bad_request',\n 'unauthorized',\n 'forbidden',\n 'account_suspended',\n 'key_invalid',\n 'pat_tenant_header_forbidden',\n 'tenant_mismatch',\n 'test_tenant_expired',\n 'token_invalid',\n 'token_expired',\n 'origin_not_allowed',\n 'server_credentials_required',\n 'role_denied',\n 'scope_denied',\n 'feature_disabled',\n 'not_found',\n 'conflict',\n 'locked',\n 'cart_revision_conflict',\n 'rate_limit_exceeded',\n 'usage_limit_exceeded',\n 'service_unavailable',\n 'idempotency_conflict',\n 'idempotency_in_progress',\n 'idempotency_key_required',\n 'invalid_idempotency_key',\n 'cart_not_active',\n 'cart_locked',\n 'cart_empty',\n 'cart_market_unavailable',\n 'cart_market_mismatch',\n 'checkout_not_open',\n 'checkout_already_open',\n 'payment_slot_held',\n 'reservation_expired',\n 'payment_session_not_cancelable',\n 'payment_session_conflict',\n 'provider_identity_mismatch',\n 'payment_method_unavailable',\n 'provider_unavailable',\n 'lock_timeout',\n 'price_changed',\n 'pricing_fact_in_use',\n 'insufficient_stock',\n 'reservation_conflict',\n 'stock_lock_unavailable',\n 'variant_not_found',\n 'variant_stock_write_failed',\n 'stock_invariant_violation',\n 'payment_confirmation_in_flight',\n 'checkout_reservation_release_requires_transaction',\n 'admission_metadata_invalid',\n 'admission_metadata_required',\n 'capacity_exceeded',\n 'occurrence_lock_unavailable',\n 'occurrence_not_open',\n 'admission_type_capacity_exceeded',\n 'admission_type_occurrence_mismatch',\n 'admission_hold_expired',\n 'admission_hold_checkout_item_conflict',\n 'admission_hold_checkout_conflict',\n 'admission_hold_quantity_mismatch',\n 'admission_hold_unbound',\n 'admission_hold_missing',\n 'admission_hold_checkout_item_missing',\n 'admission_hold_expiry_failed',\n 'admission_hold_expiry_requires_transaction',\n 'admission_hold_line_item_mismatch',\n 'admission_materialization_failed',\n 'variant_inactive',\n 'variant_product_mismatch',\n 'product_not_public',\n 'market_not_found',\n 'market_shipping_currency_unsupported',\n 'missing_market_rate',\n 'missing_shipping_amount',\n 'no_enabled_payment_provider',\n 'product_market_unavailable',\n 'unsupported_currency',\n 'missing_price_row',\n 'payment_provider_currency_unsupported',\n 'discount_code_not_found',\n 'discount_not_started',\n 'discount_expired',\n 'discount_usage_limit',\n 'discount_per_customer_limit',\n 'discount_customer_required',\n 'discount_first_order_only',\n 'discount_customer_not_eligible',\n 'discount_customer_excluded',\n 'discount_items_required',\n 'discount_product_not_eligible',\n 'discount_product_excluded',\n 'discount_min_order_amount',\n 'discount_currency_scope_required',\n 'discount_allocation_method_unsupported',\n 'currency_mismatch',\n 'customer_token_required',\n 'market_required',\n 'server_derived',\n 'internal_error',\n] as const\n\nexport type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number]\n\ntype CommerceSDKErrorBase = SDKError & {\n readonly kind: 'commerce'\n readonly requestId: string\n readonly retryable: boolean\n readonly retryAfter?: number\n readonly details?: Record<string, unknown>\n}\n\nexport type CommerceSDKError = CommerceSDKErrorBase &\n (\n | { readonly reason: CommerceErrorCode; readonly rawReason?: never }\n | {\n readonly reason: 'unknown_commerce_error'\n readonly rawReason: string\n }\n )\n\nconst COMMERCE_ERROR_CODE_SET: ReadonlySet<string> = new Set(\n COMMERCE_ERROR_CODES,\n)\nconst COMMERCE_ERROR_ENVELOPE_KEYS = new Set([\n 'error',\n 'reason',\n 'requestId',\n 'retryable',\n 'details',\n])\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport type CommerceErrorEnvelope = {\n error: string\n reason: string\n requestId: string\n retryable: boolean\n details?: Record<string, unknown>\n}\n\nfunction commerceProtocolError(\n issue: string,\n trustedRequestId?: string,\n): SDKError {\n return createApiError(\n 'Invalid canonical commerce error response.',\n 502,\n { protocol: 'commerce-error-envelope', issue },\n 'The server returned an incompatible commerce error response.',\n 'Verify that the Console commerce contract is deployed before using this SDK version.',\n trustedRequestId,\n )\n}\n\n/** @internal Strictly parse a canonical commerce error without retaining its raw body. */\nexport function parseCommerceErrorEnvelope(\n body: unknown,\n headerRequestId?: string,\n): CommerceErrorEnvelope {\n if (headerRequestId === undefined) {\n throw commerceProtocolError('missing_request_id_header')\n }\n if (headerRequestId.length === 0) {\n throw commerceProtocolError('empty_request_id_header')\n }\n if (!isPlainRecord(body)) {\n throw commerceProtocolError('expected_object', headerRequestId)\n }\n if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {\n throw commerceProtocolError('unexpected_field', headerRequestId)\n }\n if (\n typeof body.error !== 'string' ||\n body.error.length === 0 ||\n typeof body.reason !== 'string' ||\n body.reason.length === 0 ||\n typeof body.requestId !== 'string' ||\n body.requestId.length === 0 ||\n (body.retryable !== undefined && typeof body.retryable !== 'boolean') ||\n (body.details !== undefined && !isPlainRecord(body.details))\n ) {\n throw commerceProtocolError('invalid_field', headerRequestId)\n }\n\n if (headerRequestId !== undefined && headerRequestId !== body.requestId) {\n throw commerceProtocolError('request_id_mismatch', headerRequestId)\n }\n\n return {\n error: body.error,\n reason: body.reason,\n requestId: body.requestId,\n retryable: body.retryable === true,\n ...(body.details === undefined ? {} : { details: body.details }),\n }\n}\n\n/** @internal Validate and apply the canonical commerce error envelope. */\nexport function enhanceCommerceError(\n error: SDKError,\n body: unknown,\n headerRequestId?: string,\n): SDKError {\n const envelope = parseCommerceErrorEnvelope(body, headerRequestId)\n\n const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason)\n Object.assign(error, {\n code: envelope.reason,\n kind: 'commerce' as const,\n reason: known\n ? (envelope.reason as CommerceErrorCode)\n : 'unknown_commerce_error',\n ...(known ? {} : { rawReason: envelope.reason }),\n requestId: envelope.requestId,\n retryable: envelope.retryable,\n details: envelope.details,\n })\n return error\n}\n\nexport function isCommerceSDKError(error: unknown): error is CommerceSDKError {\n if (!(error instanceof SDKError) || error.kind !== 'commerce') return false\n if (\n typeof error.requestId !== 'string' ||\n typeof error.retryable !== 'boolean' ||\n (error.retryAfter !== undefined &&\n (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0)) ||\n typeof error.reason !== 'string'\n ) {\n return false\n }\n return error.reason === 'unknown_commerce_error'\n ? typeof error.rawReason === 'string'\n : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === undefined\n}\n\nexport class NetworkError extends SDKError {\n constructor(\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('NETWORK_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'NetworkError'\n }\n}\n\nexport class ValidationError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status = 400,\n ) {\n super('VALIDATION_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'ValidationError'\n }\n}\n\nexport class ApiError extends SDKError {\n constructor(\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'API_ERROR',\n message,\n status,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'ApiError'\n }\n}\n\nexport class ConfigError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('CONFIG_ERROR', message, undefined, details, userMessage, suggestion)\n this.name = 'ConfigError'\n }\n}\n\nexport class TimeoutError extends SDKError {\n constructor(\n message = 'Request timed out.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('TIMEOUT_ERROR', message, 408, details, userMessage, suggestion)\n this.name = 'TimeoutError'\n }\n}\n\nexport class GoneError extends SDKError {\n constructor(\n message = 'The requested resource is no longer available.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('GONE_ERROR', message, 410, details, userMessage, suggestion)\n this.name = 'GoneError'\n }\n}\n\nexport class ServiceUnavailableError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message = 'Service temporarily unavailable.',\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super(\n 'SERVICE_UNAVAILABLE_ERROR',\n message,\n 503,\n details,\n userMessage,\n suggestion,\n )\n this.name = 'ServiceUnavailableError'\n this.retryAfter = retryAfter\n }\n}\n\nexport class UsageLimitError extends SDKError {\n readonly usage: { limit: number; current: number; remaining: number }\n\n constructor(\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('USAGE_LIMIT_ERROR', message, 429, details, userMessage, suggestion)\n this.name = 'UsageLimitError'\n this.usage = usage\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n usage: this.usage,\n }\n }\n}\n\nexport class AuthError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'auth_error',\n message,\n 401,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'AuthError'\n }\n}\n\nexport class PermissionError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'permission_error',\n message,\n 403,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'PermissionError'\n }\n}\n\nexport class NotFoundError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'not_found',\n message,\n 404,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'NotFoundError'\n }\n}\n\nexport class ConflictError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super('conflict', message, 409, details, userMessage, suggestion, requestId)\n this.name = 'ConflictError'\n }\n}\n\nexport class RateLimitError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'rate_limit_exceeded',\n message,\n 429,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'RateLimitError'\n this.retryAfter = retryAfter\n }\n}\n\nexport function isSDKError(error: unknown): error is SDKError {\n return error instanceof SDKError\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n if (error instanceof ValidationError) return true\n if (error == null || typeof error !== 'object') return false\n\n const candidate = error as {\n code?: unknown\n name?: unknown\n message?: unknown\n getUserMessage?: unknown\n toJSON?: unknown\n }\n return (\n candidate.name === 'ValidationError' &&\n candidate.code === 'VALIDATION_ERROR' &&\n typeof candidate.message === 'string' &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError\n}\n\nexport function isConfigError(error: unknown): error is ConfigError {\n return error instanceof ConfigError\n}\n\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return error instanceof TimeoutError\n}\n\nexport function isGoneError(error: unknown): error is GoneError {\n return error instanceof GoneError\n}\n\nexport function isServiceUnavailableError(\n error: unknown,\n): error is ServiceUnavailableError {\n return error instanceof ServiceUnavailableError\n}\n\nexport function isUsageLimitError(error: unknown): error is UsageLimitError {\n return error instanceof UsageLimitError\n}\n\nexport function isAuthError(error: unknown): error is AuthError {\n return error instanceof AuthError\n}\n\nexport function isPermissionError(error: unknown): error is PermissionError {\n return error instanceof PermissionError\n}\n\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return error instanceof NotFoundError\n}\n\nexport function isConflictError(error: unknown): error is ConflictError {\n return error instanceof ConflictError\n}\n\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return error instanceof RateLimitError\n}\n\nexport const createNetworkError = (\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new NetworkError(message, status, details, userMessage, suggestion)\n\nexport const createValidationError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status?: number,\n) => new ValidationError(message, details, userMessage, suggestion, status)\n\nexport const createApiError = (\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ApiError(message, status, details, userMessage, suggestion, requestId)\n\nexport const createConfigError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new ConfigError(message, details, userMessage, suggestion)\n\nexport const createTimeoutError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new TimeoutError(message, details, userMessage, suggestion)\n\nexport const createGoneError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new GoneError(message, details, userMessage, suggestion)\n\nexport const createServiceUnavailableError = (\n message?: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) =>\n new ServiceUnavailableError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n )\n\nexport const createUsageLimitError = (\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new UsageLimitError(message, usage, details, userMessage, suggestion)\n\nexport const createAuthError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new AuthError(message, details, userMessage, suggestion, requestId)\n\nexport const createPermissionError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new PermissionError(message, details, userMessage, suggestion, requestId)\n\nexport const createNotFoundError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new NotFoundError(message, details, userMessage, suggestion, requestId)\n\nexport const createConflictError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ConflictError(message, details, userMessage, suggestion, requestId)\n\nexport const createRateLimitError = (\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) =>\n new RateLimitError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n","import { createValidationError } from '../errors'\n\nconst CACHE_RESOURCE_VERSION = 'storefront:v1'\n\nexport type StorefrontCacheScope = {\n /**\n * Tenant identifier for the public storefront read.\n */\n tenantId: string | number\n /**\n * Stable, non-secret scope for publishable-key variance. Use a short key id,\n * key fingerprint, or \"default\" when a tenant has one public cache view.\n */\n publishableKeyScope?: string | number\n}\n\nexport type StorefrontCacheProductDetailIdentity =\n | { id: string | number; slug?: never }\n | { id?: never; slug: string }\n\nfunction invalidResourceInput(message: string) {\n return createValidationError(message)\n}\n\nfunction encodeResourceSegment(value: unknown, label: string): string {\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw invalidResourceInput(`${label} must be a string or number`)\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw invalidResourceInput(`${label} must be a finite number`)\n }\n const segment = String(value).trim()\n if (!segment) {\n throw invalidResourceInput(`${label} must not be empty`)\n }\n return encodeURIComponent(segment)\n}\n\nfunction scopedResource(scope: StorefrontCacheScope, resource: string): string {\n if (scope == null || typeof scope !== 'object') {\n throw invalidResourceInput('cache scope must be an object')\n }\n const candidate = scope as {\n tenantId?: unknown\n publishableKeyScope?: unknown\n }\n const tenantId = encodeResourceSegment(candidate.tenantId, 'tenantId')\n const publishableKeyScopeValue =\n candidate.publishableKeyScope === undefined\n ? 'default'\n : candidate.publishableKeyScope\n const publishableKeyScope = encodeResourceSegment(\n publishableKeyScopeValue,\n 'publishableKeyScope',\n )\n\n return `${CACHE_RESOURCE_VERSION}:tenant:${tenantId}:key:${publishableKeyScope}:resource:${resource}`\n}\n\nfunction listResource(scope: StorefrontCacheScope, collection: string): string {\n return scopedResource(scope, `${collection}:list`)\n}\n\nfunction idDetailResource(\n scope: StorefrontCacheScope,\n collection: string,\n id: string | number,\n): string {\n return scopedResource(\n scope,\n `${collection}:detail:id:${encodeResourceSegment(id, 'resource id')}`,\n )\n}\n\nfunction productDetailResource(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n): string {\n const candidate = (identity ?? {}) as {\n id?: unknown\n slug?: unknown\n }\n const hasIdField = candidate.id !== undefined\n const hasSlugField = candidate.slug !== undefined\n\n if (hasIdField === hasSlugField) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n\n if (hasIdField) {\n if (\n (typeof candidate.id !== 'string' && typeof candidate.id !== 'number') ||\n String(candidate.id).trim() === ''\n ) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return idDetailResource(scope, 'products', candidate.id as string | number)\n }\n if (typeof candidate.slug !== 'string' || candidate.slug.trim() === '') {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return scopedResource(\n scope,\n `products:detail:slug:${encodeResourceSegment(\n candidate.slug as string,\n 'resource slug',\n )}`,\n )\n}\n\nexport const storefrontCacheResources = {\n productListing(scope: StorefrontCacheScope): string {\n return listResource(scope, 'products')\n },\n productDetail(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n ): string {\n return productDetailResource(scope, identity)\n },\n} as const\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/storefront-cache.ts","../src/core/errors.ts","../src/utils/storefront-cache.ts"],"sourcesContent":["export * from './utils/storefront-cache'\n","const SDK_ERROR_BRAND = Symbol.for('@01.software/sdk/SDKError')\nconst SDK_ERROR_TYPE_BRAND = Symbol.for('@01.software/sdk/SDKError.type')\n\ntype SDKErrorType =\n | 'NetworkError'\n | 'ValidationError'\n | 'ApiError'\n | 'ConfigError'\n | 'TimeoutError'\n | 'GoneError'\n | 'ServiceUnavailableError'\n | 'UsageLimitError'\n | 'AuthError'\n | 'PermissionError'\n | 'NotFoundError'\n | 'ConflictError'\n | 'RateLimitError'\n\nfunction defineSDKErrorBrand(error: SDKError): void {\n Object.defineProperty(error, SDK_ERROR_BRAND, {\n value: true,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n}\n\nfunction defineSDKErrorType(error: SDKError, type: SDKErrorType): void {\n Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {\n value: type,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n}\n\nexport class SDKError extends Error {\n readonly code: string\n readonly status?: number\n readonly details?: unknown\n readonly userMessage?: string\n readonly suggestion?: string\n readonly requestId?: string\n readonly kind?: 'commerce'\n readonly reason?: CommerceErrorCode | 'unknown_commerce_error'\n readonly rawReason?: string\n /** Machine-readable reason from a non-commerce API response. */\n readonly apiReason?: string\n readonly retryable?: boolean\n readonly retryAfter?: number\n\n constructor(\n code: string,\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n this.code = code\n this.status = status\n this.details = details\n this.userMessage = userMessage\n this.suggestion = suggestion\n this.requestId = requestId\n defineSDKErrorBrand(this)\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, new.target)\n }\n }\n\n getUserMessage(): string {\n return this.userMessage || this.message\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n status: this.status,\n details: this.details,\n userMessage: this.userMessage,\n suggestion: this.suggestion,\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n ...(this.kind !== undefined && { kind: this.kind }),\n ...(this.reason !== undefined && { reason: this.reason }),\n ...(this.rawReason !== undefined && { rawReason: this.rawReason }),\n ...(this.apiReason !== undefined && { apiReason: this.apiReason }),\n ...(this.retryable !== undefined && { retryable: this.retryable }),\n ...(this.retryAfter !== undefined && { retryAfter: this.retryAfter }),\n }\n }\n}\n\n/**\n * Canonical Cart/Checkout/PaymentSession error reasons. This public SDK mirror\n * intentionally does not import the private contracts package; parity is\n * enforced by a type test.\n */\nexport const COMMERCE_ERROR_CODES = [\n 'validation_failed',\n 'bad_request',\n 'unauthorized',\n 'forbidden',\n 'account_suspended',\n 'key_invalid',\n 'pat_tenant_header_forbidden',\n 'tenant_mismatch',\n 'test_tenant_expired',\n 'token_invalid',\n 'token_expired',\n 'origin_not_allowed',\n 'server_credentials_required',\n 'role_denied',\n 'scope_denied',\n 'feature_disabled',\n 'not_found',\n 'conflict',\n 'locked',\n 'cart_revision_conflict',\n 'rate_limit_exceeded',\n 'usage_limit_exceeded',\n 'service_unavailable',\n 'idempotency_conflict',\n 'idempotency_in_progress',\n 'idempotency_key_required',\n 'invalid_idempotency_key',\n 'cart_not_active',\n 'cart_locked',\n 'cart_empty',\n 'cart_market_unavailable',\n 'cart_market_mismatch',\n 'checkout_not_open',\n 'checkout_already_open',\n 'payment_slot_held',\n 'reservation_expired',\n 'payment_session_not_cancelable',\n 'payment_session_conflict',\n 'provider_identity_mismatch',\n 'payment_method_unavailable',\n 'provider_unavailable',\n 'lock_timeout',\n 'price_changed',\n 'pricing_fact_in_use',\n 'insufficient_stock',\n 'reservation_conflict',\n 'stock_lock_unavailable',\n 'variant_not_found',\n 'variant_stock_write_failed',\n 'stock_invariant_violation',\n 'payment_confirmation_in_flight',\n 'checkout_reservation_release_requires_transaction',\n 'admission_metadata_invalid',\n 'admission_metadata_required',\n 'capacity_exceeded',\n 'occurrence_lock_unavailable',\n 'occurrence_not_open',\n 'admission_type_capacity_exceeded',\n 'admission_type_occurrence_mismatch',\n 'admission_hold_expired',\n 'admission_hold_checkout_item_conflict',\n 'admission_hold_checkout_conflict',\n 'admission_hold_quantity_mismatch',\n 'admission_hold_unbound',\n 'admission_hold_missing',\n 'admission_hold_checkout_item_missing',\n 'admission_hold_expiry_failed',\n 'admission_hold_expiry_requires_transaction',\n 'admission_hold_line_item_mismatch',\n 'admission_materialization_failed',\n 'variant_inactive',\n 'variant_product_mismatch',\n 'product_not_public',\n 'market_not_found',\n 'market_shipping_currency_unsupported',\n 'missing_market_rate',\n 'missing_shipping_amount',\n 'no_enabled_payment_provider',\n 'product_market_unavailable',\n 'unsupported_currency',\n 'missing_price_row',\n 'payment_provider_currency_unsupported',\n 'discount_code_not_found',\n 'discount_not_started',\n 'discount_expired',\n 'discount_usage_limit',\n 'discount_per_customer_limit',\n 'discount_customer_required',\n 'discount_first_order_only',\n 'discount_customer_not_eligible',\n 'discount_customer_excluded',\n 'discount_items_required',\n 'discount_product_not_eligible',\n 'discount_product_excluded',\n 'discount_min_order_amount',\n 'discount_currency_scope_required',\n 'discount_allocation_method_unsupported',\n 'currency_mismatch',\n 'customer_token_required',\n 'market_required',\n 'server_derived',\n 'internal_error',\n] as const\n\nexport type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number]\n\ntype CommerceSDKErrorBase = SDKError & {\n readonly kind: 'commerce'\n readonly requestId: string\n readonly retryable: boolean\n readonly retryAfter?: number\n readonly details?: Record<string, unknown>\n}\n\nexport type CommerceSDKError = CommerceSDKErrorBase &\n (\n | { readonly reason: CommerceErrorCode; readonly rawReason?: never }\n | {\n readonly reason: 'unknown_commerce_error'\n readonly rawReason: string\n }\n )\n\nconst COMMERCE_ERROR_CODE_SET: ReadonlySet<string> = new Set(\n COMMERCE_ERROR_CODES,\n)\nconst COMMERCE_ERROR_ENVELOPE_KEYS = new Set([\n 'error',\n 'reason',\n 'requestId',\n 'retryable',\n 'details',\n])\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport type CommerceErrorEnvelope = {\n error: string\n reason: string\n requestId: string\n retryable: boolean\n details?: Record<string, unknown>\n}\n\nfunction commerceProtocolError(\n issue: string,\n trustedRequestId?: string,\n): SDKError {\n return createApiError(\n 'Invalid canonical commerce error response.',\n 502,\n { protocol: 'commerce-error-envelope', issue },\n 'The server returned an incompatible commerce error response.',\n 'Verify that the Console commerce contract is deployed before using this SDK version.',\n trustedRequestId,\n )\n}\n\n/** @internal Strictly parse a canonical commerce error without retaining its raw body. */\nexport function parseCommerceErrorEnvelope(\n body: unknown,\n headerRequestId?: string,\n): CommerceErrorEnvelope {\n if (headerRequestId === undefined) {\n throw commerceProtocolError('missing_request_id_header')\n }\n if (headerRequestId.length === 0) {\n throw commerceProtocolError('empty_request_id_header')\n }\n if (!isPlainRecord(body)) {\n throw commerceProtocolError('expected_object', headerRequestId)\n }\n if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {\n throw commerceProtocolError('unexpected_field', headerRequestId)\n }\n if (\n typeof body.error !== 'string' ||\n body.error.length === 0 ||\n typeof body.reason !== 'string' ||\n body.reason.length === 0 ||\n typeof body.requestId !== 'string' ||\n body.requestId.length === 0 ||\n (body.retryable !== undefined && typeof body.retryable !== 'boolean') ||\n (body.details !== undefined && !isPlainRecord(body.details))\n ) {\n throw commerceProtocolError('invalid_field', headerRequestId)\n }\n\n if (headerRequestId !== undefined && headerRequestId !== body.requestId) {\n throw commerceProtocolError('request_id_mismatch', headerRequestId)\n }\n\n return {\n error: body.error,\n reason: body.reason,\n requestId: body.requestId,\n retryable: body.retryable === true,\n ...(body.details === undefined ? {} : { details: body.details }),\n }\n}\n\n/** @internal Validate and apply the canonical commerce error envelope. */\nexport function enhanceCommerceError(\n error: SDKError,\n body: unknown,\n headerRequestId?: string,\n): SDKError {\n const envelope = parseCommerceErrorEnvelope(body, headerRequestId)\n\n const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason)\n Object.assign(error, {\n code: envelope.reason,\n kind: 'commerce' as const,\n reason: known\n ? (envelope.reason as CommerceErrorCode)\n : 'unknown_commerce_error',\n ...(known ? {} : { rawReason: envelope.reason }),\n requestId: envelope.requestId,\n retryable: envelope.retryable,\n details: envelope.details,\n })\n return error\n}\n\n/** @internal Apply a non-commerce reason without canonical-commerce validation. */\nexport function enhanceNonCommerceError(\n error: SDKError,\n reason: unknown,\n): SDKError {\n if (typeof reason === 'string') Object.assign(error, { apiReason: reason })\n return error\n}\n\n/**\n * Read the server-provided machine reason across strict commerce and\n * non-commerce SDK errors. Unknown commerce reasons are returned verbatim.\n */\nexport function getSDKErrorReason(error: SDKError): string | undefined {\n if (error.kind !== 'commerce') return error.apiReason\n return error.reason === 'unknown_commerce_error'\n ? error.rawReason\n : error.reason\n}\n\nexport function isCommerceSDKError(error: unknown): error is CommerceSDKError {\n if (!isSDKError(error) || error.kind !== 'commerce') return false\n if (\n typeof error.requestId !== 'string' ||\n typeof error.retryable !== 'boolean' ||\n (error.retryAfter !== undefined &&\n (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0)) ||\n typeof error.reason !== 'string'\n ) {\n return false\n }\n return error.reason === 'unknown_commerce_error'\n ? typeof error.rawReason === 'string'\n : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === undefined\n}\n\nexport class NetworkError extends SDKError {\n constructor(\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('NETWORK_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'NetworkError'\n defineSDKErrorType(this, 'NetworkError')\n }\n}\n\nexport class ValidationError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status = 400,\n ) {\n super('VALIDATION_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'ValidationError'\n defineSDKErrorType(this, 'ValidationError')\n }\n}\n\nexport class ApiError extends SDKError {\n constructor(\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'API_ERROR',\n message,\n status,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'ApiError'\n defineSDKErrorType(this, 'ApiError')\n }\n}\n\nexport class ConfigError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('CONFIG_ERROR', message, undefined, details, userMessage, suggestion)\n this.name = 'ConfigError'\n defineSDKErrorType(this, 'ConfigError')\n }\n}\n\nexport class TimeoutError extends SDKError {\n constructor(\n message = 'Request timed out.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('TIMEOUT_ERROR', message, 408, details, userMessage, suggestion)\n this.name = 'TimeoutError'\n defineSDKErrorType(this, 'TimeoutError')\n }\n}\n\nexport class GoneError extends SDKError {\n constructor(\n message = 'The requested resource is no longer available.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('GONE_ERROR', message, 410, details, userMessage, suggestion)\n this.name = 'GoneError'\n defineSDKErrorType(this, 'GoneError')\n }\n}\n\nexport class ServiceUnavailableError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message = 'Service temporarily unavailable.',\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super(\n 'SERVICE_UNAVAILABLE_ERROR',\n message,\n 503,\n details,\n userMessage,\n suggestion,\n )\n this.name = 'ServiceUnavailableError'\n this.retryAfter = retryAfter\n defineSDKErrorType(this, 'ServiceUnavailableError')\n }\n}\n\nexport class UsageLimitError extends SDKError {\n readonly usage: { limit: number; current: number; remaining: number }\n\n constructor(\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('USAGE_LIMIT_ERROR', message, 429, details, userMessage, suggestion)\n this.name = 'UsageLimitError'\n this.usage = usage\n defineSDKErrorType(this, 'UsageLimitError')\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n usage: this.usage,\n }\n }\n}\n\nexport class AuthError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'auth_error',\n message,\n 401,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'AuthError'\n defineSDKErrorType(this, 'AuthError')\n }\n}\n\nexport class PermissionError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'permission_error',\n message,\n 403,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'PermissionError'\n defineSDKErrorType(this, 'PermissionError')\n }\n}\n\nexport class NotFoundError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'not_found',\n message,\n 404,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'NotFoundError'\n defineSDKErrorType(this, 'NotFoundError')\n }\n}\n\nexport class ConflictError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super('conflict', message, 409, details, userMessage, suggestion, requestId)\n this.name = 'ConflictError'\n defineSDKErrorType(this, 'ConflictError')\n }\n}\n\nexport class RateLimitError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'rate_limit_exceeded',\n message,\n 429,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'RateLimitError'\n this.retryAfter = retryAfter\n defineSDKErrorType(this, 'RateLimitError')\n }\n}\n\nfunction hasBrandedSDKErrorShape(error: unknown): error is SDKError {\n if (error === null || typeof error !== 'object') return false\n\n const candidate = error as Record<PropertyKey, unknown>\n return (\n candidate[SDK_ERROR_BRAND] === true &&\n typeof candidate.name === 'string' &&\n typeof candidate.code === 'string' &&\n typeof candidate.message === 'string' &&\n (candidate.status === undefined || typeof candidate.status === 'number') &&\n (candidate.userMessage === undefined ||\n typeof candidate.userMessage === 'string') &&\n (candidate.suggestion === undefined ||\n typeof candidate.suggestion === 'string') &&\n (candidate.requestId === undefined ||\n typeof candidate.requestId === 'string') &&\n (candidate.kind === undefined || candidate.kind === 'commerce') &&\n (candidate.reason === undefined || typeof candidate.reason === 'string') &&\n (candidate.rawReason === undefined ||\n typeof candidate.rawReason === 'string') &&\n (candidate.apiReason === undefined ||\n typeof candidate.apiReason === 'string') &&\n (candidate.retryable === undefined ||\n typeof candidate.retryable === 'boolean') &&\n (candidate.retryAfter === undefined ||\n typeof candidate.retryAfter === 'number') &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nfunction hasSDKErrorType(error: unknown, type: SDKErrorType): boolean {\n return (\n hasBrandedSDKErrorShape(error) &&\n (error as unknown as Record<PropertyKey, unknown>)[SDK_ERROR_TYPE_BRAND] ===\n type\n )\n}\n\nexport function isSDKError(error: unknown): error is SDKError {\n return error instanceof SDKError || hasBrandedSDKErrorShape(error)\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError || hasSDKErrorType(error, 'NetworkError')\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n if (\n error instanceof ValidationError ||\n hasSDKErrorType(error, 'ValidationError')\n ) {\n return true\n }\n if (error == null || typeof error !== 'object') return false\n\n const candidate = error as {\n code?: unknown\n name?: unknown\n message?: unknown\n getUserMessage?: unknown\n toJSON?: unknown\n }\n return (\n candidate.name === 'ValidationError' &&\n candidate.code === 'VALIDATION_ERROR' &&\n typeof candidate.message === 'string' &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError || hasSDKErrorType(error, 'ApiError')\n}\n\nexport function isConfigError(error: unknown): error is ConfigError {\n return error instanceof ConfigError || hasSDKErrorType(error, 'ConfigError')\n}\n\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return error instanceof TimeoutError || hasSDKErrorType(error, 'TimeoutError')\n}\n\nexport function isGoneError(error: unknown): error is GoneError {\n return error instanceof GoneError || hasSDKErrorType(error, 'GoneError')\n}\n\nexport function isServiceUnavailableError(\n error: unknown,\n): error is ServiceUnavailableError {\n return (\n error instanceof ServiceUnavailableError ||\n hasSDKErrorType(error, 'ServiceUnavailableError')\n )\n}\n\nexport function isUsageLimitError(error: unknown): error is UsageLimitError {\n return (\n error instanceof UsageLimitError ||\n hasSDKErrorType(error, 'UsageLimitError')\n )\n}\n\nexport function isAuthError(error: unknown): error is AuthError {\n return error instanceof AuthError || hasSDKErrorType(error, 'AuthError')\n}\n\nexport function isPermissionError(error: unknown): error is PermissionError {\n return (\n error instanceof PermissionError ||\n hasSDKErrorType(error, 'PermissionError')\n )\n}\n\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return (\n error instanceof NotFoundError || hasSDKErrorType(error, 'NotFoundError')\n )\n}\n\nexport function isConflictError(error: unknown): error is ConflictError {\n return (\n error instanceof ConflictError || hasSDKErrorType(error, 'ConflictError')\n )\n}\n\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return (\n error instanceof RateLimitError || hasSDKErrorType(error, 'RateLimitError')\n )\n}\n\nexport const createNetworkError = (\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new NetworkError(message, status, details, userMessage, suggestion)\n\nexport const createValidationError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status?: number,\n) => new ValidationError(message, details, userMessage, suggestion, status)\n\nexport const createApiError = (\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ApiError(message, status, details, userMessage, suggestion, requestId)\n\nexport const createConfigError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new ConfigError(message, details, userMessage, suggestion)\n\nexport const createTimeoutError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new TimeoutError(message, details, userMessage, suggestion)\n\nexport const createGoneError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new GoneError(message, details, userMessage, suggestion)\n\nexport const createServiceUnavailableError = (\n message?: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) =>\n new ServiceUnavailableError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n )\n\nexport const createUsageLimitError = (\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new UsageLimitError(message, usage, details, userMessage, suggestion)\n\nexport const createAuthError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new AuthError(message, details, userMessage, suggestion, requestId)\n\nexport const createPermissionError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new PermissionError(message, details, userMessage, suggestion, requestId)\n\nexport const createNotFoundError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new NotFoundError(message, details, userMessage, suggestion, requestId)\n\nexport const createConflictError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ConflictError(message, details, userMessage, suggestion, requestId)\n\nexport const createRateLimitError = (\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) =>\n new RateLimitError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n","import { createValidationError } from '../errors'\n\nconst CACHE_RESOURCE_VERSION = 'storefront:v1'\n\nexport type StorefrontCacheScope = {\n /**\n * Tenant identifier for the public storefront read.\n */\n tenantId: string | number\n /**\n * Stable, non-secret scope for publishable-key variance. Use a short key id,\n * key fingerprint, or \"default\" when a tenant has one public cache view.\n */\n publishableKeyScope?: string | number\n}\n\nexport type StorefrontCacheProductDetailIdentity =\n | { id: string | number; slug?: never }\n | { id?: never; slug: string }\n\nfunction invalidResourceInput(message: string) {\n return createValidationError(message)\n}\n\nfunction encodeResourceSegment(value: unknown, label: string): string {\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw invalidResourceInput(`${label} must be a string or number`)\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw invalidResourceInput(`${label} must be a finite number`)\n }\n const segment = String(value).trim()\n if (!segment) {\n throw invalidResourceInput(`${label} must not be empty`)\n }\n return encodeURIComponent(segment)\n}\n\nfunction scopedResource(scope: StorefrontCacheScope, resource: string): string {\n if (scope == null || typeof scope !== 'object') {\n throw invalidResourceInput('cache scope must be an object')\n }\n const candidate = scope as {\n tenantId?: unknown\n publishableKeyScope?: unknown\n }\n const tenantId = encodeResourceSegment(candidate.tenantId, 'tenantId')\n const publishableKeyScopeValue =\n candidate.publishableKeyScope === undefined\n ? 'default'\n : candidate.publishableKeyScope\n const publishableKeyScope = encodeResourceSegment(\n publishableKeyScopeValue,\n 'publishableKeyScope',\n )\n\n return `${CACHE_RESOURCE_VERSION}:tenant:${tenantId}:key:${publishableKeyScope}:resource:${resource}`\n}\n\nfunction listResource(scope: StorefrontCacheScope, collection: string): string {\n return scopedResource(scope, `${collection}:list`)\n}\n\nfunction idDetailResource(\n scope: StorefrontCacheScope,\n collection: string,\n id: string | number,\n): string {\n return scopedResource(\n scope,\n `${collection}:detail:id:${encodeResourceSegment(id, 'resource id')}`,\n )\n}\n\nfunction productDetailResource(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n): string {\n const candidate = (identity ?? {}) as {\n id?: unknown\n slug?: unknown\n }\n const hasIdField = candidate.id !== undefined\n const hasSlugField = candidate.slug !== undefined\n\n if (hasIdField === hasSlugField) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n\n if (hasIdField) {\n if (\n (typeof candidate.id !== 'string' && typeof candidate.id !== 'number') ||\n String(candidate.id).trim() === ''\n ) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return idDetailResource(scope, 'products', candidate.id as string | number)\n }\n if (typeof candidate.slug !== 'string' || candidate.slug.trim() === '') {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return scopedResource(\n scope,\n `products:detail:slug:${encodeResourceSegment(\n candidate.slug as string,\n 'resource slug',\n )}`,\n )\n}\n\nexport const storefrontCacheResources = {\n productListing(scope: StorefrontCacheScope): string {\n return listResource(scope, 'products')\n },\n productDetail(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n ): string {\n return productDetailResource(scope, identity)\n },\n} as const\n"],"mappings":"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","names":[]}
@@ -1,4 +1,22 @@
1
1
  // src/core/errors.ts
2
+ var SDK_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError");
3
+ var SDK_ERROR_TYPE_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError.type");
4
+ function defineSDKErrorBrand(error) {
5
+ Object.defineProperty(error, SDK_ERROR_BRAND, {
6
+ value: true,
7
+ enumerable: false,
8
+ configurable: false,
9
+ writable: false
10
+ });
11
+ }
12
+ function defineSDKErrorType(error, type) {
13
+ Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {
14
+ value: type,
15
+ enumerable: false,
16
+ configurable: false,
17
+ writable: false
18
+ });
19
+ }
2
20
  var SDKError = class extends Error {
3
21
  constructor(code, message, status, details, userMessage, suggestion, requestId) {
4
22
  super(message);
@@ -9,6 +27,7 @@ var SDKError = class extends Error {
9
27
  this.userMessage = userMessage;
10
28
  this.suggestion = suggestion;
11
29
  this.requestId = requestId;
30
+ defineSDKErrorBrand(this);
12
31
  if (Error.captureStackTrace) {
13
32
  Error.captureStackTrace(this, new.target);
14
33
  }
@@ -29,6 +48,7 @@ var SDKError = class extends Error {
29
48
  ...this.kind !== void 0 && { kind: this.kind },
30
49
  ...this.reason !== void 0 && { reason: this.reason },
31
50
  ...this.rawReason !== void 0 && { rawReason: this.rawReason },
51
+ ...this.apiReason !== void 0 && { apiReason: this.apiReason },
32
52
  ...this.retryable !== void 0 && { retryable: this.retryable },
33
53
  ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
34
54
  };
@@ -145,6 +165,7 @@ var ValidationError = class extends SDKError {
145
165
  constructor(message, details, userMessage, suggestion, status = 400) {
146
166
  super("VALIDATION_ERROR", message, status, details, userMessage, suggestion);
147
167
  this.name = "ValidationError";
168
+ defineSDKErrorType(this, "ValidationError");
148
169
  }
149
170
  };
150
171
  var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/errors.ts","../src/utils/storefront-cache.ts"],"sourcesContent":["export class SDKError extends Error {\n readonly code: string\n readonly status?: number\n readonly details?: unknown\n readonly userMessage?: string\n readonly suggestion?: string\n readonly requestId?: string\n readonly kind?: 'commerce'\n readonly reason?: CommerceErrorCode | 'unknown_commerce_error'\n readonly rawReason?: string\n readonly retryable?: boolean\n readonly retryAfter?: number\n\n constructor(\n code: string,\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n this.code = code\n this.status = status\n this.details = details\n this.userMessage = userMessage\n this.suggestion = suggestion\n this.requestId = requestId\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, new.target)\n }\n }\n\n getUserMessage(): string {\n return this.userMessage || this.message\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n status: this.status,\n details: this.details,\n userMessage: this.userMessage,\n suggestion: this.suggestion,\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n ...(this.kind !== undefined && { kind: this.kind }),\n ...(this.reason !== undefined && { reason: this.reason }),\n ...(this.rawReason !== undefined && { rawReason: this.rawReason }),\n ...(this.retryable !== undefined && { retryable: this.retryable }),\n ...(this.retryAfter !== undefined && { retryAfter: this.retryAfter }),\n }\n }\n}\n\n/**\n * Canonical Cart/Checkout/PaymentSession error reasons. This public SDK mirror\n * intentionally does not import the private contracts package; parity is\n * enforced by a type test.\n */\nexport const COMMERCE_ERROR_CODES = [\n 'validation_failed',\n 'bad_request',\n 'unauthorized',\n 'forbidden',\n 'account_suspended',\n 'key_invalid',\n 'pat_tenant_header_forbidden',\n 'tenant_mismatch',\n 'test_tenant_expired',\n 'token_invalid',\n 'token_expired',\n 'origin_not_allowed',\n 'server_credentials_required',\n 'role_denied',\n 'scope_denied',\n 'feature_disabled',\n 'not_found',\n 'conflict',\n 'locked',\n 'cart_revision_conflict',\n 'rate_limit_exceeded',\n 'usage_limit_exceeded',\n 'service_unavailable',\n 'idempotency_conflict',\n 'idempotency_in_progress',\n 'idempotency_key_required',\n 'invalid_idempotency_key',\n 'cart_not_active',\n 'cart_locked',\n 'cart_empty',\n 'cart_market_unavailable',\n 'cart_market_mismatch',\n 'checkout_not_open',\n 'checkout_already_open',\n 'payment_slot_held',\n 'reservation_expired',\n 'payment_session_not_cancelable',\n 'payment_session_conflict',\n 'provider_identity_mismatch',\n 'payment_method_unavailable',\n 'provider_unavailable',\n 'lock_timeout',\n 'price_changed',\n 'pricing_fact_in_use',\n 'insufficient_stock',\n 'reservation_conflict',\n 'stock_lock_unavailable',\n 'variant_not_found',\n 'variant_stock_write_failed',\n 'stock_invariant_violation',\n 'payment_confirmation_in_flight',\n 'checkout_reservation_release_requires_transaction',\n 'admission_metadata_invalid',\n 'admission_metadata_required',\n 'capacity_exceeded',\n 'occurrence_lock_unavailable',\n 'occurrence_not_open',\n 'admission_type_capacity_exceeded',\n 'admission_type_occurrence_mismatch',\n 'admission_hold_expired',\n 'admission_hold_checkout_item_conflict',\n 'admission_hold_checkout_conflict',\n 'admission_hold_quantity_mismatch',\n 'admission_hold_unbound',\n 'admission_hold_missing',\n 'admission_hold_checkout_item_missing',\n 'admission_hold_expiry_failed',\n 'admission_hold_expiry_requires_transaction',\n 'admission_hold_line_item_mismatch',\n 'admission_materialization_failed',\n 'variant_inactive',\n 'variant_product_mismatch',\n 'product_not_public',\n 'market_not_found',\n 'market_shipping_currency_unsupported',\n 'missing_market_rate',\n 'missing_shipping_amount',\n 'no_enabled_payment_provider',\n 'product_market_unavailable',\n 'unsupported_currency',\n 'missing_price_row',\n 'payment_provider_currency_unsupported',\n 'discount_code_not_found',\n 'discount_not_started',\n 'discount_expired',\n 'discount_usage_limit',\n 'discount_per_customer_limit',\n 'discount_customer_required',\n 'discount_first_order_only',\n 'discount_customer_not_eligible',\n 'discount_customer_excluded',\n 'discount_items_required',\n 'discount_product_not_eligible',\n 'discount_product_excluded',\n 'discount_min_order_amount',\n 'discount_currency_scope_required',\n 'discount_allocation_method_unsupported',\n 'currency_mismatch',\n 'customer_token_required',\n 'market_required',\n 'server_derived',\n 'internal_error',\n] as const\n\nexport type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number]\n\ntype CommerceSDKErrorBase = SDKError & {\n readonly kind: 'commerce'\n readonly requestId: string\n readonly retryable: boolean\n readonly retryAfter?: number\n readonly details?: Record<string, unknown>\n}\n\nexport type CommerceSDKError = CommerceSDKErrorBase &\n (\n | { readonly reason: CommerceErrorCode; readonly rawReason?: never }\n | {\n readonly reason: 'unknown_commerce_error'\n readonly rawReason: string\n }\n )\n\nconst COMMERCE_ERROR_CODE_SET: ReadonlySet<string> = new Set(\n COMMERCE_ERROR_CODES,\n)\nconst COMMERCE_ERROR_ENVELOPE_KEYS = new Set([\n 'error',\n 'reason',\n 'requestId',\n 'retryable',\n 'details',\n])\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport type CommerceErrorEnvelope = {\n error: string\n reason: string\n requestId: string\n retryable: boolean\n details?: Record<string, unknown>\n}\n\nfunction commerceProtocolError(\n issue: string,\n trustedRequestId?: string,\n): SDKError {\n return createApiError(\n 'Invalid canonical commerce error response.',\n 502,\n { protocol: 'commerce-error-envelope', issue },\n 'The server returned an incompatible commerce error response.',\n 'Verify that the Console commerce contract is deployed before using this SDK version.',\n trustedRequestId,\n )\n}\n\n/** @internal Strictly parse a canonical commerce error without retaining its raw body. */\nexport function parseCommerceErrorEnvelope(\n body: unknown,\n headerRequestId?: string,\n): CommerceErrorEnvelope {\n if (headerRequestId === undefined) {\n throw commerceProtocolError('missing_request_id_header')\n }\n if (headerRequestId.length === 0) {\n throw commerceProtocolError('empty_request_id_header')\n }\n if (!isPlainRecord(body)) {\n throw commerceProtocolError('expected_object', headerRequestId)\n }\n if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {\n throw commerceProtocolError('unexpected_field', headerRequestId)\n }\n if (\n typeof body.error !== 'string' ||\n body.error.length === 0 ||\n typeof body.reason !== 'string' ||\n body.reason.length === 0 ||\n typeof body.requestId !== 'string' ||\n body.requestId.length === 0 ||\n (body.retryable !== undefined && typeof body.retryable !== 'boolean') ||\n (body.details !== undefined && !isPlainRecord(body.details))\n ) {\n throw commerceProtocolError('invalid_field', headerRequestId)\n }\n\n if (headerRequestId !== undefined && headerRequestId !== body.requestId) {\n throw commerceProtocolError('request_id_mismatch', headerRequestId)\n }\n\n return {\n error: body.error,\n reason: body.reason,\n requestId: body.requestId,\n retryable: body.retryable === true,\n ...(body.details === undefined ? {} : { details: body.details }),\n }\n}\n\n/** @internal Validate and apply the canonical commerce error envelope. */\nexport function enhanceCommerceError(\n error: SDKError,\n body: unknown,\n headerRequestId?: string,\n): SDKError {\n const envelope = parseCommerceErrorEnvelope(body, headerRequestId)\n\n const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason)\n Object.assign(error, {\n code: envelope.reason,\n kind: 'commerce' as const,\n reason: known\n ? (envelope.reason as CommerceErrorCode)\n : 'unknown_commerce_error',\n ...(known ? {} : { rawReason: envelope.reason }),\n requestId: envelope.requestId,\n retryable: envelope.retryable,\n details: envelope.details,\n })\n return error\n}\n\nexport function isCommerceSDKError(error: unknown): error is CommerceSDKError {\n if (!(error instanceof SDKError) || error.kind !== 'commerce') return false\n if (\n typeof error.requestId !== 'string' ||\n typeof error.retryable !== 'boolean' ||\n (error.retryAfter !== undefined &&\n (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0)) ||\n typeof error.reason !== 'string'\n ) {\n return false\n }\n return error.reason === 'unknown_commerce_error'\n ? typeof error.rawReason === 'string'\n : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === undefined\n}\n\nexport class NetworkError extends SDKError {\n constructor(\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('NETWORK_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'NetworkError'\n }\n}\n\nexport class ValidationError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status = 400,\n ) {\n super('VALIDATION_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'ValidationError'\n }\n}\n\nexport class ApiError extends SDKError {\n constructor(\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'API_ERROR',\n message,\n status,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'ApiError'\n }\n}\n\nexport class ConfigError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('CONFIG_ERROR', message, undefined, details, userMessage, suggestion)\n this.name = 'ConfigError'\n }\n}\n\nexport class TimeoutError extends SDKError {\n constructor(\n message = 'Request timed out.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('TIMEOUT_ERROR', message, 408, details, userMessage, suggestion)\n this.name = 'TimeoutError'\n }\n}\n\nexport class GoneError extends SDKError {\n constructor(\n message = 'The requested resource is no longer available.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('GONE_ERROR', message, 410, details, userMessage, suggestion)\n this.name = 'GoneError'\n }\n}\n\nexport class ServiceUnavailableError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message = 'Service temporarily unavailable.',\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super(\n 'SERVICE_UNAVAILABLE_ERROR',\n message,\n 503,\n details,\n userMessage,\n suggestion,\n )\n this.name = 'ServiceUnavailableError'\n this.retryAfter = retryAfter\n }\n}\n\nexport class UsageLimitError extends SDKError {\n readonly usage: { limit: number; current: number; remaining: number }\n\n constructor(\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('USAGE_LIMIT_ERROR', message, 429, details, userMessage, suggestion)\n this.name = 'UsageLimitError'\n this.usage = usage\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n usage: this.usage,\n }\n }\n}\n\nexport class AuthError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'auth_error',\n message,\n 401,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'AuthError'\n }\n}\n\nexport class PermissionError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'permission_error',\n message,\n 403,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'PermissionError'\n }\n}\n\nexport class NotFoundError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'not_found',\n message,\n 404,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'NotFoundError'\n }\n}\n\nexport class ConflictError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super('conflict', message, 409, details, userMessage, suggestion, requestId)\n this.name = 'ConflictError'\n }\n}\n\nexport class RateLimitError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'rate_limit_exceeded',\n message,\n 429,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'RateLimitError'\n this.retryAfter = retryAfter\n }\n}\n\nexport function isSDKError(error: unknown): error is SDKError {\n return error instanceof SDKError\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n if (error instanceof ValidationError) return true\n if (error == null || typeof error !== 'object') return false\n\n const candidate = error as {\n code?: unknown\n name?: unknown\n message?: unknown\n getUserMessage?: unknown\n toJSON?: unknown\n }\n return (\n candidate.name === 'ValidationError' &&\n candidate.code === 'VALIDATION_ERROR' &&\n typeof candidate.message === 'string' &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError\n}\n\nexport function isConfigError(error: unknown): error is ConfigError {\n return error instanceof ConfigError\n}\n\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return error instanceof TimeoutError\n}\n\nexport function isGoneError(error: unknown): error is GoneError {\n return error instanceof GoneError\n}\n\nexport function isServiceUnavailableError(\n error: unknown,\n): error is ServiceUnavailableError {\n return error instanceof ServiceUnavailableError\n}\n\nexport function isUsageLimitError(error: unknown): error is UsageLimitError {\n return error instanceof UsageLimitError\n}\n\nexport function isAuthError(error: unknown): error is AuthError {\n return error instanceof AuthError\n}\n\nexport function isPermissionError(error: unknown): error is PermissionError {\n return error instanceof PermissionError\n}\n\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return error instanceof NotFoundError\n}\n\nexport function isConflictError(error: unknown): error is ConflictError {\n return error instanceof ConflictError\n}\n\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return error instanceof RateLimitError\n}\n\nexport const createNetworkError = (\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new NetworkError(message, status, details, userMessage, suggestion)\n\nexport const createValidationError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status?: number,\n) => new ValidationError(message, details, userMessage, suggestion, status)\n\nexport const createApiError = (\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ApiError(message, status, details, userMessage, suggestion, requestId)\n\nexport const createConfigError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new ConfigError(message, details, userMessage, suggestion)\n\nexport const createTimeoutError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new TimeoutError(message, details, userMessage, suggestion)\n\nexport const createGoneError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new GoneError(message, details, userMessage, suggestion)\n\nexport const createServiceUnavailableError = (\n message?: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) =>\n new ServiceUnavailableError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n )\n\nexport const createUsageLimitError = (\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new UsageLimitError(message, usage, details, userMessage, suggestion)\n\nexport const createAuthError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new AuthError(message, details, userMessage, suggestion, requestId)\n\nexport const createPermissionError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new PermissionError(message, details, userMessage, suggestion, requestId)\n\nexport const createNotFoundError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new NotFoundError(message, details, userMessage, suggestion, requestId)\n\nexport const createConflictError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ConflictError(message, details, userMessage, suggestion, requestId)\n\nexport const createRateLimitError = (\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) =>\n new RateLimitError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n","import { createValidationError } from '../errors'\n\nconst CACHE_RESOURCE_VERSION = 'storefront:v1'\n\nexport type StorefrontCacheScope = {\n /**\n * Tenant identifier for the public storefront read.\n */\n tenantId: string | number\n /**\n * Stable, non-secret scope for publishable-key variance. Use a short key id,\n * key fingerprint, or \"default\" when a tenant has one public cache view.\n */\n publishableKeyScope?: string | number\n}\n\nexport type StorefrontCacheProductDetailIdentity =\n | { id: string | number; slug?: never }\n | { id?: never; slug: string }\n\nfunction invalidResourceInput(message: string) {\n return createValidationError(message)\n}\n\nfunction encodeResourceSegment(value: unknown, label: string): string {\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw invalidResourceInput(`${label} must be a string or number`)\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw invalidResourceInput(`${label} must be a finite number`)\n }\n const segment = String(value).trim()\n if (!segment) {\n throw invalidResourceInput(`${label} must not be empty`)\n }\n return encodeURIComponent(segment)\n}\n\nfunction scopedResource(scope: StorefrontCacheScope, resource: string): string {\n if (scope == null || typeof scope !== 'object') {\n throw invalidResourceInput('cache scope must be an object')\n }\n const candidate = scope as {\n tenantId?: unknown\n publishableKeyScope?: unknown\n }\n const tenantId = encodeResourceSegment(candidate.tenantId, 'tenantId')\n const publishableKeyScopeValue =\n candidate.publishableKeyScope === undefined\n ? 'default'\n : candidate.publishableKeyScope\n const publishableKeyScope = encodeResourceSegment(\n publishableKeyScopeValue,\n 'publishableKeyScope',\n )\n\n return `${CACHE_RESOURCE_VERSION}:tenant:${tenantId}:key:${publishableKeyScope}:resource:${resource}`\n}\n\nfunction listResource(scope: StorefrontCacheScope, collection: string): string {\n return scopedResource(scope, `${collection}:list`)\n}\n\nfunction idDetailResource(\n scope: StorefrontCacheScope,\n collection: string,\n id: string | number,\n): string {\n return scopedResource(\n scope,\n `${collection}:detail:id:${encodeResourceSegment(id, 'resource id')}`,\n )\n}\n\nfunction productDetailResource(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n): string {\n const candidate = (identity ?? {}) as {\n id?: unknown\n slug?: unknown\n }\n const hasIdField = candidate.id !== undefined\n const hasSlugField = candidate.slug !== undefined\n\n if (hasIdField === hasSlugField) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n\n if (hasIdField) {\n if (\n (typeof candidate.id !== 'string' && typeof candidate.id !== 'number') ||\n String(candidate.id).trim() === ''\n ) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return idDetailResource(scope, 'products', candidate.id as string | number)\n }\n if (typeof candidate.slug !== 'string' || candidate.slug.trim() === '') {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return scopedResource(\n scope,\n `products:detail:slug:${encodeResourceSegment(\n candidate.slug as string,\n 'resource slug',\n )}`,\n )\n}\n\nexport const storefrontCacheResources = {\n productListing(scope: StorefrontCacheScope): string {\n return listResource(scope, 'products')\n },\n productDetail(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n ): string {\n return productDetailResource(scope, identity)\n },\n} as const\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core/errors.ts","../src/utils/storefront-cache.ts"],"sourcesContent":["const SDK_ERROR_BRAND = Symbol.for('@01.software/sdk/SDKError')\nconst SDK_ERROR_TYPE_BRAND = Symbol.for('@01.software/sdk/SDKError.type')\n\ntype SDKErrorType =\n | 'NetworkError'\n | 'ValidationError'\n | 'ApiError'\n | 'ConfigError'\n | 'TimeoutError'\n | 'GoneError'\n | 'ServiceUnavailableError'\n | 'UsageLimitError'\n | 'AuthError'\n | 'PermissionError'\n | 'NotFoundError'\n | 'ConflictError'\n | 'RateLimitError'\n\nfunction defineSDKErrorBrand(error: SDKError): void {\n Object.defineProperty(error, SDK_ERROR_BRAND, {\n value: true,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n}\n\nfunction defineSDKErrorType(error: SDKError, type: SDKErrorType): void {\n Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {\n value: type,\n enumerable: false,\n configurable: false,\n writable: false,\n })\n}\n\nexport class SDKError extends Error {\n readonly code: string\n readonly status?: number\n readonly details?: unknown\n readonly userMessage?: string\n readonly suggestion?: string\n readonly requestId?: string\n readonly kind?: 'commerce'\n readonly reason?: CommerceErrorCode | 'unknown_commerce_error'\n readonly rawReason?: string\n /** Machine-readable reason from a non-commerce API response. */\n readonly apiReason?: string\n readonly retryable?: boolean\n readonly retryAfter?: number\n\n constructor(\n code: string,\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n this.code = code\n this.status = status\n this.details = details\n this.userMessage = userMessage\n this.suggestion = suggestion\n this.requestId = requestId\n defineSDKErrorBrand(this)\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, new.target)\n }\n }\n\n getUserMessage(): string {\n return this.userMessage || this.message\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n status: this.status,\n details: this.details,\n userMessage: this.userMessage,\n suggestion: this.suggestion,\n ...(this.requestId !== undefined && { requestId: this.requestId }),\n ...(this.kind !== undefined && { kind: this.kind }),\n ...(this.reason !== undefined && { reason: this.reason }),\n ...(this.rawReason !== undefined && { rawReason: this.rawReason }),\n ...(this.apiReason !== undefined && { apiReason: this.apiReason }),\n ...(this.retryable !== undefined && { retryable: this.retryable }),\n ...(this.retryAfter !== undefined && { retryAfter: this.retryAfter }),\n }\n }\n}\n\n/**\n * Canonical Cart/Checkout/PaymentSession error reasons. This public SDK mirror\n * intentionally does not import the private contracts package; parity is\n * enforced by a type test.\n */\nexport const COMMERCE_ERROR_CODES = [\n 'validation_failed',\n 'bad_request',\n 'unauthorized',\n 'forbidden',\n 'account_suspended',\n 'key_invalid',\n 'pat_tenant_header_forbidden',\n 'tenant_mismatch',\n 'test_tenant_expired',\n 'token_invalid',\n 'token_expired',\n 'origin_not_allowed',\n 'server_credentials_required',\n 'role_denied',\n 'scope_denied',\n 'feature_disabled',\n 'not_found',\n 'conflict',\n 'locked',\n 'cart_revision_conflict',\n 'rate_limit_exceeded',\n 'usage_limit_exceeded',\n 'service_unavailable',\n 'idempotency_conflict',\n 'idempotency_in_progress',\n 'idempotency_key_required',\n 'invalid_idempotency_key',\n 'cart_not_active',\n 'cart_locked',\n 'cart_empty',\n 'cart_market_unavailable',\n 'cart_market_mismatch',\n 'checkout_not_open',\n 'checkout_already_open',\n 'payment_slot_held',\n 'reservation_expired',\n 'payment_session_not_cancelable',\n 'payment_session_conflict',\n 'provider_identity_mismatch',\n 'payment_method_unavailable',\n 'provider_unavailable',\n 'lock_timeout',\n 'price_changed',\n 'pricing_fact_in_use',\n 'insufficient_stock',\n 'reservation_conflict',\n 'stock_lock_unavailable',\n 'variant_not_found',\n 'variant_stock_write_failed',\n 'stock_invariant_violation',\n 'payment_confirmation_in_flight',\n 'checkout_reservation_release_requires_transaction',\n 'admission_metadata_invalid',\n 'admission_metadata_required',\n 'capacity_exceeded',\n 'occurrence_lock_unavailable',\n 'occurrence_not_open',\n 'admission_type_capacity_exceeded',\n 'admission_type_occurrence_mismatch',\n 'admission_hold_expired',\n 'admission_hold_checkout_item_conflict',\n 'admission_hold_checkout_conflict',\n 'admission_hold_quantity_mismatch',\n 'admission_hold_unbound',\n 'admission_hold_missing',\n 'admission_hold_checkout_item_missing',\n 'admission_hold_expiry_failed',\n 'admission_hold_expiry_requires_transaction',\n 'admission_hold_line_item_mismatch',\n 'admission_materialization_failed',\n 'variant_inactive',\n 'variant_product_mismatch',\n 'product_not_public',\n 'market_not_found',\n 'market_shipping_currency_unsupported',\n 'missing_market_rate',\n 'missing_shipping_amount',\n 'no_enabled_payment_provider',\n 'product_market_unavailable',\n 'unsupported_currency',\n 'missing_price_row',\n 'payment_provider_currency_unsupported',\n 'discount_code_not_found',\n 'discount_not_started',\n 'discount_expired',\n 'discount_usage_limit',\n 'discount_per_customer_limit',\n 'discount_customer_required',\n 'discount_first_order_only',\n 'discount_customer_not_eligible',\n 'discount_customer_excluded',\n 'discount_items_required',\n 'discount_product_not_eligible',\n 'discount_product_excluded',\n 'discount_min_order_amount',\n 'discount_currency_scope_required',\n 'discount_allocation_method_unsupported',\n 'currency_mismatch',\n 'customer_token_required',\n 'market_required',\n 'server_derived',\n 'internal_error',\n] as const\n\nexport type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number]\n\ntype CommerceSDKErrorBase = SDKError & {\n readonly kind: 'commerce'\n readonly requestId: string\n readonly retryable: boolean\n readonly retryAfter?: number\n readonly details?: Record<string, unknown>\n}\n\nexport type CommerceSDKError = CommerceSDKErrorBase &\n (\n | { readonly reason: CommerceErrorCode; readonly rawReason?: never }\n | {\n readonly reason: 'unknown_commerce_error'\n readonly rawReason: string\n }\n )\n\nconst COMMERCE_ERROR_CODE_SET: ReadonlySet<string> = new Set(\n COMMERCE_ERROR_CODES,\n)\nconst COMMERCE_ERROR_ENVELOPE_KEYS = new Set([\n 'error',\n 'reason',\n 'requestId',\n 'retryable',\n 'details',\n])\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport type CommerceErrorEnvelope = {\n error: string\n reason: string\n requestId: string\n retryable: boolean\n details?: Record<string, unknown>\n}\n\nfunction commerceProtocolError(\n issue: string,\n trustedRequestId?: string,\n): SDKError {\n return createApiError(\n 'Invalid canonical commerce error response.',\n 502,\n { protocol: 'commerce-error-envelope', issue },\n 'The server returned an incompatible commerce error response.',\n 'Verify that the Console commerce contract is deployed before using this SDK version.',\n trustedRequestId,\n )\n}\n\n/** @internal Strictly parse a canonical commerce error without retaining its raw body. */\nexport function parseCommerceErrorEnvelope(\n body: unknown,\n headerRequestId?: string,\n): CommerceErrorEnvelope {\n if (headerRequestId === undefined) {\n throw commerceProtocolError('missing_request_id_header')\n }\n if (headerRequestId.length === 0) {\n throw commerceProtocolError('empty_request_id_header')\n }\n if (!isPlainRecord(body)) {\n throw commerceProtocolError('expected_object', headerRequestId)\n }\n if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {\n throw commerceProtocolError('unexpected_field', headerRequestId)\n }\n if (\n typeof body.error !== 'string' ||\n body.error.length === 0 ||\n typeof body.reason !== 'string' ||\n body.reason.length === 0 ||\n typeof body.requestId !== 'string' ||\n body.requestId.length === 0 ||\n (body.retryable !== undefined && typeof body.retryable !== 'boolean') ||\n (body.details !== undefined && !isPlainRecord(body.details))\n ) {\n throw commerceProtocolError('invalid_field', headerRequestId)\n }\n\n if (headerRequestId !== undefined && headerRequestId !== body.requestId) {\n throw commerceProtocolError('request_id_mismatch', headerRequestId)\n }\n\n return {\n error: body.error,\n reason: body.reason,\n requestId: body.requestId,\n retryable: body.retryable === true,\n ...(body.details === undefined ? {} : { details: body.details }),\n }\n}\n\n/** @internal Validate and apply the canonical commerce error envelope. */\nexport function enhanceCommerceError(\n error: SDKError,\n body: unknown,\n headerRequestId?: string,\n): SDKError {\n const envelope = parseCommerceErrorEnvelope(body, headerRequestId)\n\n const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason)\n Object.assign(error, {\n code: envelope.reason,\n kind: 'commerce' as const,\n reason: known\n ? (envelope.reason as CommerceErrorCode)\n : 'unknown_commerce_error',\n ...(known ? {} : { rawReason: envelope.reason }),\n requestId: envelope.requestId,\n retryable: envelope.retryable,\n details: envelope.details,\n })\n return error\n}\n\n/** @internal Apply a non-commerce reason without canonical-commerce validation. */\nexport function enhanceNonCommerceError(\n error: SDKError,\n reason: unknown,\n): SDKError {\n if (typeof reason === 'string') Object.assign(error, { apiReason: reason })\n return error\n}\n\n/**\n * Read the server-provided machine reason across strict commerce and\n * non-commerce SDK errors. Unknown commerce reasons are returned verbatim.\n */\nexport function getSDKErrorReason(error: SDKError): string | undefined {\n if (error.kind !== 'commerce') return error.apiReason\n return error.reason === 'unknown_commerce_error'\n ? error.rawReason\n : error.reason\n}\n\nexport function isCommerceSDKError(error: unknown): error is CommerceSDKError {\n if (!isSDKError(error) || error.kind !== 'commerce') return false\n if (\n typeof error.requestId !== 'string' ||\n typeof error.retryable !== 'boolean' ||\n (error.retryAfter !== undefined &&\n (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0)) ||\n typeof error.reason !== 'string'\n ) {\n return false\n }\n return error.reason === 'unknown_commerce_error'\n ? typeof error.rawReason === 'string'\n : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === undefined\n}\n\nexport class NetworkError extends SDKError {\n constructor(\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('NETWORK_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'NetworkError'\n defineSDKErrorType(this, 'NetworkError')\n }\n}\n\nexport class ValidationError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status = 400,\n ) {\n super('VALIDATION_ERROR', message, status, details, userMessage, suggestion)\n this.name = 'ValidationError'\n defineSDKErrorType(this, 'ValidationError')\n }\n}\n\nexport class ApiError extends SDKError {\n constructor(\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'API_ERROR',\n message,\n status,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'ApiError'\n defineSDKErrorType(this, 'ApiError')\n }\n}\n\nexport class ConfigError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('CONFIG_ERROR', message, undefined, details, userMessage, suggestion)\n this.name = 'ConfigError'\n defineSDKErrorType(this, 'ConfigError')\n }\n}\n\nexport class TimeoutError extends SDKError {\n constructor(\n message = 'Request timed out.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('TIMEOUT_ERROR', message, 408, details, userMessage, suggestion)\n this.name = 'TimeoutError'\n defineSDKErrorType(this, 'TimeoutError')\n }\n}\n\nexport class GoneError extends SDKError {\n constructor(\n message = 'The requested resource is no longer available.',\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('GONE_ERROR', message, 410, details, userMessage, suggestion)\n this.name = 'GoneError'\n defineSDKErrorType(this, 'GoneError')\n }\n}\n\nexport class ServiceUnavailableError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message = 'Service temporarily unavailable.',\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super(\n 'SERVICE_UNAVAILABLE_ERROR',\n message,\n 503,\n details,\n userMessage,\n suggestion,\n )\n this.name = 'ServiceUnavailableError'\n this.retryAfter = retryAfter\n defineSDKErrorType(this, 'ServiceUnavailableError')\n }\n}\n\nexport class UsageLimitError extends SDKError {\n readonly usage: { limit: number; current: number; remaining: number }\n\n constructor(\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n ) {\n super('USAGE_LIMIT_ERROR', message, 429, details, userMessage, suggestion)\n this.name = 'UsageLimitError'\n this.usage = usage\n defineSDKErrorType(this, 'UsageLimitError')\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n usage: this.usage,\n }\n }\n}\n\nexport class AuthError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'auth_error',\n message,\n 401,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'AuthError'\n defineSDKErrorType(this, 'AuthError')\n }\n}\n\nexport class PermissionError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'permission_error',\n message,\n 403,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'PermissionError'\n defineSDKErrorType(this, 'PermissionError')\n }\n}\n\nexport class NotFoundError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'not_found',\n message,\n 404,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'NotFoundError'\n defineSDKErrorType(this, 'NotFoundError')\n }\n}\n\nexport class ConflictError extends SDKError {\n constructor(\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super('conflict', message, 409, details, userMessage, suggestion, requestId)\n this.name = 'ConflictError'\n defineSDKErrorType(this, 'ConflictError')\n }\n}\n\nexport class RateLimitError extends SDKError {\n readonly retryAfter?: number\n\n constructor(\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n ) {\n super(\n 'rate_limit_exceeded',\n message,\n 429,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n this.name = 'RateLimitError'\n this.retryAfter = retryAfter\n defineSDKErrorType(this, 'RateLimitError')\n }\n}\n\nfunction hasBrandedSDKErrorShape(error: unknown): error is SDKError {\n if (error === null || typeof error !== 'object') return false\n\n const candidate = error as Record<PropertyKey, unknown>\n return (\n candidate[SDK_ERROR_BRAND] === true &&\n typeof candidate.name === 'string' &&\n typeof candidate.code === 'string' &&\n typeof candidate.message === 'string' &&\n (candidate.status === undefined || typeof candidate.status === 'number') &&\n (candidate.userMessage === undefined ||\n typeof candidate.userMessage === 'string') &&\n (candidate.suggestion === undefined ||\n typeof candidate.suggestion === 'string') &&\n (candidate.requestId === undefined ||\n typeof candidate.requestId === 'string') &&\n (candidate.kind === undefined || candidate.kind === 'commerce') &&\n (candidate.reason === undefined || typeof candidate.reason === 'string') &&\n (candidate.rawReason === undefined ||\n typeof candidate.rawReason === 'string') &&\n (candidate.apiReason === undefined ||\n typeof candidate.apiReason === 'string') &&\n (candidate.retryable === undefined ||\n typeof candidate.retryable === 'boolean') &&\n (candidate.retryAfter === undefined ||\n typeof candidate.retryAfter === 'number') &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nfunction hasSDKErrorType(error: unknown, type: SDKErrorType): boolean {\n return (\n hasBrandedSDKErrorShape(error) &&\n (error as unknown as Record<PropertyKey, unknown>)[SDK_ERROR_TYPE_BRAND] ===\n type\n )\n}\n\nexport function isSDKError(error: unknown): error is SDKError {\n return error instanceof SDKError || hasBrandedSDKErrorShape(error)\n}\n\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError || hasSDKErrorType(error, 'NetworkError')\n}\n\nexport function isValidationError(error: unknown): error is ValidationError {\n if (\n error instanceof ValidationError ||\n hasSDKErrorType(error, 'ValidationError')\n ) {\n return true\n }\n if (error == null || typeof error !== 'object') return false\n\n const candidate = error as {\n code?: unknown\n name?: unknown\n message?: unknown\n getUserMessage?: unknown\n toJSON?: unknown\n }\n return (\n candidate.name === 'ValidationError' &&\n candidate.code === 'VALIDATION_ERROR' &&\n typeof candidate.message === 'string' &&\n typeof candidate.getUserMessage === 'function' &&\n typeof candidate.toJSON === 'function'\n )\n}\n\nexport function isApiError(error: unknown): error is ApiError {\n return error instanceof ApiError || hasSDKErrorType(error, 'ApiError')\n}\n\nexport function isConfigError(error: unknown): error is ConfigError {\n return error instanceof ConfigError || hasSDKErrorType(error, 'ConfigError')\n}\n\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return error instanceof TimeoutError || hasSDKErrorType(error, 'TimeoutError')\n}\n\nexport function isGoneError(error: unknown): error is GoneError {\n return error instanceof GoneError || hasSDKErrorType(error, 'GoneError')\n}\n\nexport function isServiceUnavailableError(\n error: unknown,\n): error is ServiceUnavailableError {\n return (\n error instanceof ServiceUnavailableError ||\n hasSDKErrorType(error, 'ServiceUnavailableError')\n )\n}\n\nexport function isUsageLimitError(error: unknown): error is UsageLimitError {\n return (\n error instanceof UsageLimitError ||\n hasSDKErrorType(error, 'UsageLimitError')\n )\n}\n\nexport function isAuthError(error: unknown): error is AuthError {\n return error instanceof AuthError || hasSDKErrorType(error, 'AuthError')\n}\n\nexport function isPermissionError(error: unknown): error is PermissionError {\n return (\n error instanceof PermissionError ||\n hasSDKErrorType(error, 'PermissionError')\n )\n}\n\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return (\n error instanceof NotFoundError || hasSDKErrorType(error, 'NotFoundError')\n )\n}\n\nexport function isConflictError(error: unknown): error is ConflictError {\n return (\n error instanceof ConflictError || hasSDKErrorType(error, 'ConflictError')\n )\n}\n\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return (\n error instanceof RateLimitError || hasSDKErrorType(error, 'RateLimitError')\n )\n}\n\nexport const createNetworkError = (\n message: string,\n status?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new NetworkError(message, status, details, userMessage, suggestion)\n\nexport const createValidationError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n status?: number,\n) => new ValidationError(message, details, userMessage, suggestion, status)\n\nexport const createApiError = (\n message: string,\n status: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ApiError(message, status, details, userMessage, suggestion, requestId)\n\nexport const createConfigError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new ConfigError(message, details, userMessage, suggestion)\n\nexport const createTimeoutError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new TimeoutError(message, details, userMessage, suggestion)\n\nexport const createGoneError = (\n message?: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new GoneError(message, details, userMessage, suggestion)\n\nexport const createServiceUnavailableError = (\n message?: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) =>\n new ServiceUnavailableError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n )\n\nexport const createUsageLimitError = (\n message: string,\n usage: { limit: number; current: number; remaining: number },\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n) => new UsageLimitError(message, usage, details, userMessage, suggestion)\n\nexport const createAuthError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new AuthError(message, details, userMessage, suggestion, requestId)\n\nexport const createPermissionError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new PermissionError(message, details, userMessage, suggestion, requestId)\n\nexport const createNotFoundError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new NotFoundError(message, details, userMessage, suggestion, requestId)\n\nexport const createConflictError = (\n message: string,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) => new ConflictError(message, details, userMessage, suggestion, requestId)\n\nexport const createRateLimitError = (\n message: string,\n retryAfter?: number,\n details?: unknown,\n userMessage?: string,\n suggestion?: string,\n requestId?: string,\n) =>\n new RateLimitError(\n message,\n retryAfter,\n details,\n userMessage,\n suggestion,\n requestId,\n )\n","import { createValidationError } from '../errors'\n\nconst CACHE_RESOURCE_VERSION = 'storefront:v1'\n\nexport type StorefrontCacheScope = {\n /**\n * Tenant identifier for the public storefront read.\n */\n tenantId: string | number\n /**\n * Stable, non-secret scope for publishable-key variance. Use a short key id,\n * key fingerprint, or \"default\" when a tenant has one public cache view.\n */\n publishableKeyScope?: string | number\n}\n\nexport type StorefrontCacheProductDetailIdentity =\n | { id: string | number; slug?: never }\n | { id?: never; slug: string }\n\nfunction invalidResourceInput(message: string) {\n return createValidationError(message)\n}\n\nfunction encodeResourceSegment(value: unknown, label: string): string {\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw invalidResourceInput(`${label} must be a string or number`)\n }\n if (typeof value === 'number' && !Number.isFinite(value)) {\n throw invalidResourceInput(`${label} must be a finite number`)\n }\n const segment = String(value).trim()\n if (!segment) {\n throw invalidResourceInput(`${label} must not be empty`)\n }\n return encodeURIComponent(segment)\n}\n\nfunction scopedResource(scope: StorefrontCacheScope, resource: string): string {\n if (scope == null || typeof scope !== 'object') {\n throw invalidResourceInput('cache scope must be an object')\n }\n const candidate = scope as {\n tenantId?: unknown\n publishableKeyScope?: unknown\n }\n const tenantId = encodeResourceSegment(candidate.tenantId, 'tenantId')\n const publishableKeyScopeValue =\n candidate.publishableKeyScope === undefined\n ? 'default'\n : candidate.publishableKeyScope\n const publishableKeyScope = encodeResourceSegment(\n publishableKeyScopeValue,\n 'publishableKeyScope',\n )\n\n return `${CACHE_RESOURCE_VERSION}:tenant:${tenantId}:key:${publishableKeyScope}:resource:${resource}`\n}\n\nfunction listResource(scope: StorefrontCacheScope, collection: string): string {\n return scopedResource(scope, `${collection}:list`)\n}\n\nfunction idDetailResource(\n scope: StorefrontCacheScope,\n collection: string,\n id: string | number,\n): string {\n return scopedResource(\n scope,\n `${collection}:detail:id:${encodeResourceSegment(id, 'resource id')}`,\n )\n}\n\nfunction productDetailResource(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n): string {\n const candidate = (identity ?? {}) as {\n id?: unknown\n slug?: unknown\n }\n const hasIdField = candidate.id !== undefined\n const hasSlugField = candidate.slug !== undefined\n\n if (hasIdField === hasSlugField) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n\n if (hasIdField) {\n if (\n (typeof candidate.id !== 'string' && typeof candidate.id !== 'number') ||\n String(candidate.id).trim() === ''\n ) {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return idDetailResource(scope, 'products', candidate.id as string | number)\n }\n if (typeof candidate.slug !== 'string' || candidate.slug.trim() === '') {\n throw invalidResourceInput(\n 'product detail identity must include exactly one non-empty id or slug',\n )\n }\n return scopedResource(\n scope,\n `products:detail:slug:${encodeResourceSegment(\n candidate.slug as string,\n 'resource slug',\n )}`,\n )\n}\n\nexport const storefrontCacheResources = {\n productListing(scope: StorefrontCacheScope): string {\n return listResource(scope, 'products')\n },\n productDetail(\n scope: StorefrontCacheScope,\n identity: StorefrontCacheProductDetailIdentity,\n ): string {\n return productDetailResource(scope, identity)\n },\n} as const\n"],"mappings":";AAAA,IAAM,kBAAkB,uBAAO,IAAI,2BAA2B;AAC9D,IAAM,uBAAuB,uBAAO,IAAI,gCAAgC;AAiBxE,SAAS,oBAAoB,OAAuB;AAClD,SAAO,eAAe,OAAO,iBAAiB;AAAA,IAC5C,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,EACZ,CAAC;AACH;AAEA,SAAS,mBAAmB,OAAiB,MAA0B;AACrE,SAAO,eAAe,OAAO,sBAAsB;AAAA,IACjD,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAelC,YACE,MACA,SACA,QACA,SACA,aACA,YACA,WACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,wBAAoB,IAAI;AAExB,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,UAAU;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK,eAAe,KAAK;AAAA,EAClC;AAAA,EAEA,SAAS;AACP,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,GAAI,KAAK,cAAc,UAAa,EAAE,WAAW,KAAK,UAAU;AAAA,MAChE,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK;AAAA,MACjD,GAAI,KAAK,WAAW,UAAa,EAAE,QAAQ,KAAK,OAAO;AAAA,MACvD,GAAI,KAAK,cAAc,UAAa,EAAE,WAAW,KAAK,UAAU;AAAA,MAChE,GAAI,KAAK,cAAc,UAAa,EAAE,WAAW,KAAK,UAAU;AAAA,MAChE,GAAI,KAAK,cAAc,UAAa,EAAE,WAAW,KAAK,UAAU;AAAA,MAChE,GAAI,KAAK,eAAe,UAAa,EAAE,YAAY,KAAK,WAAW;AAAA,IACrE;AAAA,EACF;AACF;AAOO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAqBA,IAAM,0BAA+C,IAAI;AAAA,EACvD;AACF;AAuJO,IAAM,kBAAN,cAA8B,SAAS;AAAA,EAC5C,YACE,SACA,SACA,aACA,YACA,SAAS,KACT;AACA,UAAM,oBAAoB,SAAS,QAAQ,SAAS,aAAa,UAAU;AAC3E,SAAK,OAAO;AACZ,uBAAmB,MAAM,iBAAiB;AAAA,EAC5C;AACF;AAuWO,IAAM,wBAAwB,CACnC,SACA,SACA,aACA,YACA,WACG,IAAI,gBAAgB,SAAS,SAAS,aAAa,YAAY,MAAM;;;ACpvB1E,IAAM,yBAAyB;AAkB/B,SAAS,qBAAqB,SAAiB;AAC7C,SAAO,sBAAsB,OAAO;AACtC;AAEA,SAAS,sBAAsB,OAAgB,OAAuB;AACpE,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,UAAM,qBAAqB,GAAG,KAAK,6BAA6B;AAAA,EAClE;AACA,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;AACxD,UAAM,qBAAqB,GAAG,KAAK,0BAA0B;AAAA,EAC/D;AACA,QAAM,UAAU,OAAO,KAAK,EAAE,KAAK;AACnC,MAAI,CAAC,SAAS;AACZ,UAAM,qBAAqB,GAAG,KAAK,oBAAoB;AAAA,EACzD;AACA,SAAO,mBAAmB,OAAO;AACnC;AAEA,SAAS,eAAe,OAA6B,UAA0B;AAC7E,MAAI,SAAS,QAAQ,OAAO,UAAU,UAAU;AAC9C,UAAM,qBAAqB,+BAA+B;AAAA,EAC5D;AACA,QAAM,YAAY;AAIlB,QAAM,WAAW,sBAAsB,UAAU,UAAU,UAAU;AACrE,QAAM,2BACJ,UAAU,wBAAwB,SAC9B,YACA,UAAU;AAChB,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AAEA,SAAO,GAAG,sBAAsB,WAAW,QAAQ,QAAQ,mBAAmB,aAAa,QAAQ;AACrG;AAEA,SAAS,aAAa,OAA6B,YAA4B;AAC7E,SAAO,eAAe,OAAO,GAAG,UAAU,OAAO;AACnD;AAEA,SAAS,iBACP,OACA,YACA,IACQ;AACR,SAAO;AAAA,IACL;AAAA,IACA,GAAG,UAAU,cAAc,sBAAsB,IAAI,aAAa,CAAC;AAAA,EACrE;AACF;AAEA,SAAS,sBACP,OACA,UACQ;AACR,QAAM,YAAa,YAAY,CAAC;AAIhC,QAAM,aAAa,UAAU,OAAO;AACpC,QAAM,eAAe,UAAU,SAAS;AAExC,MAAI,eAAe,cAAc;AAC/B,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY;AACd,QACG,OAAO,UAAU,OAAO,YAAY,OAAO,UAAU,OAAO,YAC7D,OAAO,UAAU,EAAE,EAAE,KAAK,MAAM,IAChC;AACA,YAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AACA,WAAO,iBAAiB,OAAO,YAAY,UAAU,EAAqB;AAAA,EAC5E;AACA,MAAI,OAAO,UAAU,SAAS,YAAY,UAAU,KAAK,KAAK,MAAM,IAAI;AACtE,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,wBAAwB;AAAA,MACtB,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,IAAM,2BAA2B;AAAA,EACtC,eAAe,OAAqC;AAClD,WAAO,aAAa,OAAO,UAAU;AAAA,EACvC;AAAA,EACA,cACE,OACA,UACQ;AACR,WAAO,sBAAsB,OAAO,QAAQ;AAAA,EAC9C;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
- import { P as PublicCollection, C as Collection, S as ServerCollection } from './const-k9gHylYa.js';
2
- import { C as CollectionType, a as PublicProduct, P as PublicMarket } from './types-ByD2zii1.js';
3
- import { O as Order, k as Transaction, l as Fulfillment, R as Return } from './payload-types-B6AZQcB7.js';
1
+ import { P as PublicCollection, C as Collection, S as ServerCollection } from './const-CBba4lDo.cjs';
2
+ import { C as CollectionType, a as PublicProduct, P as PublicMarket } from './types-BKr_2avj.cjs';
3
+ import { O as Order, k as Transaction, l as Fulfillment, R as Return } from './payload-types-MKbx5MuJ.cjs';
4
4
 
5
5
  declare const operationBrand: unique symbol;
6
6
  type HttpOperation = {
@@ -2206,7 +2206,7 @@ type CheckoutAmounts = {
2206
2206
  };
2207
2207
  type CheckoutPaymentSessionRef = {
2208
2208
  id: string;
2209
- provider: 'toss';
2209
+ provider: 'toss' | 'portone';
2210
2210
  providerStatus: 'requires_payment_method' | 'requires_action' | 'requires_confirmation' | 'initializing' | 'processing' | 'authorized' | 'canceling' | 'unknown' | 'captured' | 'failed' | 'canceled';
2211
2211
  };
2212
2212
  type OpenCheckoutPaymentState = {
@@ -2330,6 +2330,8 @@ type Money = {
2330
2330
  currency: Uppercase<string>;
2331
2331
  };
2332
2332
  type PortOneHostedPaymentMethod = 'CARD_KR' | 'N_PAY' | 'KAKAO_PAY' | 'TOSS_PAY' | 'CARD_INTERNATIONAL' | 'PAY_PAL' | 'UNION_PAY' | 'ALIPAY_CN' | 'ALIPAY_HK' | 'TRUE_MONEY' | 'DANA' | 'TOUCH_N_GO' | 'G_CASH' | 'WE_CHAT_PAY' | 'KLARNA' | 'E_CONTEXT' | 'GRAB_PAY_MY' | 'GRAB_PAY_SG' | 'SHOPEE_PAY_TH' | 'PAY_PAY' | 'BPI' | 'RABBIT_LINE_PAY' | 'CONVENIENCE_STORE_JP' | 'AMAZON_PAY' | 'RAKUTEN_PAY' | 'D_BARAI' | 'AU_PAY' | 'MERPAY';
2333
+ /** Standard Browser SDK methods intentionally do not reuse Hosted methods. */
2334
+ type PortOneStandardPaymentMethod = 'CARD';
2333
2335
  type CreatePaymentSessionParams = {
2334
2336
  checkoutToken: string;
2335
2337
  idempotencyKey: string;
@@ -2345,6 +2347,9 @@ type CreatePortOnePaymentSessionParams = {
2345
2347
  providerOptions: {
2346
2348
  profile: 'hosted_v2';
2347
2349
  paymentMethod: PortOneHostedPaymentMethod;
2350
+ } | {
2351
+ profile: 'standard_v2';
2352
+ paymentMethod: PortOneStandardPaymentMethod;
2348
2353
  };
2349
2354
  };
2350
2355
  type RetrieveBrowserPaymentSessionParams = {
@@ -2413,6 +2418,13 @@ type ConfirmCustomPaymentSessionResponse = {
2413
2418
  orderId: string;
2414
2419
  transactionId: string;
2415
2420
  status: 'paid';
2421
+ /**
2422
+ * `true` when the session was already confirmed at observation time.
2423
+ *
2424
+ * This field is absent from the initial successful confirmation. It does not
2425
+ * prove that this call caused the transition and is not an exactly-once gate;
2426
+ * a lost initial response followed by a retry also returns `true`.
2427
+ */
2416
2428
  alreadyConfirmed?: boolean;
2417
2429
  };
2418
2430
  type CustomPaymentSessionProof = {
@@ -2438,9 +2450,22 @@ type PortOnePaymentNextAction = {
2438
2450
  type: 'portone_checkout';
2439
2451
  checkoutUrl: string;
2440
2452
  };
2453
+ type PortOneSdkPaymentNextAction = {
2454
+ type: 'portone_sdk';
2455
+ version: 'v2';
2456
+ storeId: string;
2457
+ channelKey: string;
2458
+ paymentId: string;
2459
+ orderName: string;
2460
+ totalAmount: number;
2461
+ /** PortOne Browser SDK V2 currency constant, not an ISO 4217 code. */
2462
+ currency: 'CURRENCY_KRW';
2463
+ payMethod: PortOneStandardPaymentMethod;
2464
+ redirectUrl: string;
2465
+ };
2441
2466
  /** Existing Toss action surface retained for source compatibility. */
2442
2467
  type PaymentNextAction = TossPaymentNextAction;
2443
- type ManagedPaymentNextAction = TossPaymentNextAction | PortOnePaymentNextAction;
2468
+ type ManagedPaymentNextAction = TossPaymentNextAction | PortOnePaymentNextAction | PortOneSdkPaymentNextAction;
2444
2469
  type PaymentSessionRole = 'active' | 'canonical_candidate' | 'canonical' | 'residual' | 'historical';
2445
2470
  type PaymentProviderStatus = 'requires_payment_method' | 'requires_action' | 'requires_confirmation' | 'initializing' | 'processing' | 'authorized' | 'canceling' | 'unknown' | 'captured' | 'failed' | 'canceled';
2446
2471
  type PaymentReconciliationReason = 'provider_outcome_unknown' | 'local_commit_ambiguous' | 'amount_mismatch' | 'currency_mismatch' | 'excess_capture_pending_order' | 'inventory_unavailable' | 'admission_unavailable' | 'excess_capture' | 'late_capture' | 'cross_checkout_duplicate';
@@ -2594,7 +2619,7 @@ type PublicPaymentSession = PublicPaymentSessionBase & {
2594
2619
  } & PublicPaymentSessionState<TossPaymentNextAction>;
2595
2620
  type PortOnePublicPaymentSession = PublicPaymentSessionBase & {
2596
2621
  provider: 'portone';
2597
- } & PublicPaymentSessionState<PortOnePaymentNextAction>;
2622
+ } & PublicPaymentSessionState<PortOnePaymentNextAction | PortOneSdkPaymentNextAction>;
2598
2623
  type ManagedPublicPaymentSession = PublicPaymentSession | PortOnePublicPaymentSession;
2599
2624
  declare class PaymentSessionApi extends CustomerScopedApi {
2600
2625
  private readonly serverTransport;
@@ -1,5 +1,5 @@
1
- import { P as Product, a as ProductVariant, M as Market, C as CustomerProfile, b as CustomerProfileStat, c as CustomerProfileList, d as ProductCollection, e as Config } from './payload-types-B6AZQcB7.cjs';
2
- import { C as Collection } from './const-BXEi1Kix.cjs';
1
+ import { P as Product, a as ProductVariant, M as Market, C as CustomerProfile, b as CustomerProfileStat, c as CustomerProfileList, d as ProductCollection, e as Config } from './payload-types-MKbx5MuJ.cjs';
2
+ import { C as Collection } from './const-CBba4lDo.cjs';
3
3
 
4
4
  type PublicCustomerProfile = Omit<CustomerProfile, 'tenant' | 'customer' | 'isPublic' | 'anonymizedAt' | 'metadata'>;
5
5
  type PublicCustomerProfileListEntry = {
@@ -1,6 +1,6 @@
1
- import { P as PublicCollection, C as Collection, S as ServerCollection } from './const-BXEi1Kix.cjs';
2
- import { C as CollectionType, a as PublicProduct, P as PublicMarket } from './types-8us-_C-Q.cjs';
3
- import { O as Order, k as Transaction, l as Fulfillment, R as Return } from './payload-types-B6AZQcB7.cjs';
1
+ import { P as PublicCollection, C as Collection, S as ServerCollection } from './const-DCNV5Kq7.js';
2
+ import { C as CollectionType, a as PublicProduct, P as PublicMarket } from './types-L_nh-ED7.js';
3
+ import { O as Order, k as Transaction, l as Fulfillment, R as Return } from './payload-types-MKbx5MuJ.js';
4
4
 
5
5
  declare const operationBrand: unique symbol;
6
6
  type HttpOperation = {
@@ -2206,7 +2206,7 @@ type CheckoutAmounts = {
2206
2206
  };
2207
2207
  type CheckoutPaymentSessionRef = {
2208
2208
  id: string;
2209
- provider: 'toss';
2209
+ provider: 'toss' | 'portone';
2210
2210
  providerStatus: 'requires_payment_method' | 'requires_action' | 'requires_confirmation' | 'initializing' | 'processing' | 'authorized' | 'canceling' | 'unknown' | 'captured' | 'failed' | 'canceled';
2211
2211
  };
2212
2212
  type OpenCheckoutPaymentState = {
@@ -2330,6 +2330,8 @@ type Money = {
2330
2330
  currency: Uppercase<string>;
2331
2331
  };
2332
2332
  type PortOneHostedPaymentMethod = 'CARD_KR' | 'N_PAY' | 'KAKAO_PAY' | 'TOSS_PAY' | 'CARD_INTERNATIONAL' | 'PAY_PAL' | 'UNION_PAY' | 'ALIPAY_CN' | 'ALIPAY_HK' | 'TRUE_MONEY' | 'DANA' | 'TOUCH_N_GO' | 'G_CASH' | 'WE_CHAT_PAY' | 'KLARNA' | 'E_CONTEXT' | 'GRAB_PAY_MY' | 'GRAB_PAY_SG' | 'SHOPEE_PAY_TH' | 'PAY_PAY' | 'BPI' | 'RABBIT_LINE_PAY' | 'CONVENIENCE_STORE_JP' | 'AMAZON_PAY' | 'RAKUTEN_PAY' | 'D_BARAI' | 'AU_PAY' | 'MERPAY';
2333
+ /** Standard Browser SDK methods intentionally do not reuse Hosted methods. */
2334
+ type PortOneStandardPaymentMethod = 'CARD';
2333
2335
  type CreatePaymentSessionParams = {
2334
2336
  checkoutToken: string;
2335
2337
  idempotencyKey: string;
@@ -2345,6 +2347,9 @@ type CreatePortOnePaymentSessionParams = {
2345
2347
  providerOptions: {
2346
2348
  profile: 'hosted_v2';
2347
2349
  paymentMethod: PortOneHostedPaymentMethod;
2350
+ } | {
2351
+ profile: 'standard_v2';
2352
+ paymentMethod: PortOneStandardPaymentMethod;
2348
2353
  };
2349
2354
  };
2350
2355
  type RetrieveBrowserPaymentSessionParams = {
@@ -2413,6 +2418,13 @@ type ConfirmCustomPaymentSessionResponse = {
2413
2418
  orderId: string;
2414
2419
  transactionId: string;
2415
2420
  status: 'paid';
2421
+ /**
2422
+ * `true` when the session was already confirmed at observation time.
2423
+ *
2424
+ * This field is absent from the initial successful confirmation. It does not
2425
+ * prove that this call caused the transition and is not an exactly-once gate;
2426
+ * a lost initial response followed by a retry also returns `true`.
2427
+ */
2416
2428
  alreadyConfirmed?: boolean;
2417
2429
  };
2418
2430
  type CustomPaymentSessionProof = {
@@ -2438,9 +2450,22 @@ type PortOnePaymentNextAction = {
2438
2450
  type: 'portone_checkout';
2439
2451
  checkoutUrl: string;
2440
2452
  };
2453
+ type PortOneSdkPaymentNextAction = {
2454
+ type: 'portone_sdk';
2455
+ version: 'v2';
2456
+ storeId: string;
2457
+ channelKey: string;
2458
+ paymentId: string;
2459
+ orderName: string;
2460
+ totalAmount: number;
2461
+ /** PortOne Browser SDK V2 currency constant, not an ISO 4217 code. */
2462
+ currency: 'CURRENCY_KRW';
2463
+ payMethod: PortOneStandardPaymentMethod;
2464
+ redirectUrl: string;
2465
+ };
2441
2466
  /** Existing Toss action surface retained for source compatibility. */
2442
2467
  type PaymentNextAction = TossPaymentNextAction;
2443
- type ManagedPaymentNextAction = TossPaymentNextAction | PortOnePaymentNextAction;
2468
+ type ManagedPaymentNextAction = TossPaymentNextAction | PortOnePaymentNextAction | PortOneSdkPaymentNextAction;
2444
2469
  type PaymentSessionRole = 'active' | 'canonical_candidate' | 'canonical' | 'residual' | 'historical';
2445
2470
  type PaymentProviderStatus = 'requires_payment_method' | 'requires_action' | 'requires_confirmation' | 'initializing' | 'processing' | 'authorized' | 'canceling' | 'unknown' | 'captured' | 'failed' | 'canceled';
2446
2471
  type PaymentReconciliationReason = 'provider_outcome_unknown' | 'local_commit_ambiguous' | 'amount_mismatch' | 'currency_mismatch' | 'excess_capture_pending_order' | 'inventory_unavailable' | 'admission_unavailable' | 'excess_capture' | 'late_capture' | 'cross_checkout_duplicate';
@@ -2594,7 +2619,7 @@ type PublicPaymentSession = PublicPaymentSessionBase & {
2594
2619
  } & PublicPaymentSessionState<TossPaymentNextAction>;
2595
2620
  type PortOnePublicPaymentSession = PublicPaymentSessionBase & {
2596
2621
  provider: 'portone';
2597
- } & PublicPaymentSessionState<PortOnePaymentNextAction>;
2622
+ } & PublicPaymentSessionState<PortOnePaymentNextAction | PortOneSdkPaymentNextAction>;
2598
2623
  type ManagedPublicPaymentSession = PublicPaymentSession | PortOnePublicPaymentSession;
2599
2624
  declare class PaymentSessionApi extends CustomerScopedApi {
2600
2625
  private readonly serverTransport;
@@ -1,5 +1,5 @@
1
- import { P as Product, a as ProductVariant, M as Market, C as CustomerProfile, b as CustomerProfileStat, c as CustomerProfileList, d as ProductCollection, e as Config } from './payload-types-B6AZQcB7.js';
2
- import { C as Collection } from './const-k9gHylYa.js';
1
+ import { P as Product, a as ProductVariant, M as Market, C as CustomerProfile, b as CustomerProfileStat, c as CustomerProfileList, d as ProductCollection, e as Config } from './payload-types-MKbx5MuJ.js';
2
+ import { C as Collection } from './const-DCNV5Kq7.js';
3
3
 
4
4
  type PublicCustomerProfile = Omit<CustomerProfile, 'tenant' | 'customer' | 'isPublic' | 'anonymizedAt' | 'metadata'>;
5
5
  type PublicCustomerProfileListEntry = {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { F as Form } from '../payload-types-B6AZQcB7.cjs';
2
+ import { F as Form } from '../payload-types-MKbx5MuJ.cjs';
3
3
  import { RichTextData } from './rich-text.cjs';
4
4
  import '@payloadcms/richtext-lexical';
5
5
  import '@payloadcms/richtext-lexical/lexical';
package/dist/ui/form.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { F as Form } from '../payload-types-B6AZQcB7.js';
2
+ import { F as Form } from '../payload-types-MKbx5MuJ.js';
3
3
  import { RichTextData } from './rich-text.js';
4
4
  import '@payloadcms/richtext-lexical';
5
5
  import '@payloadcms/richtext-lexical/lexical';
@@ -1,7 +1,7 @@
1
1
  import React, { CSSProperties } from 'react';
2
2
  import { MuxPlayerProps, MuxPlayerRefAttributes } from '@mux/mux-player-react';
3
3
  export { MuxPlayerRefAttributes as VideoPlayerRef } from '@mux/mux-player-react';
4
- import { V as Video } from '../payload-types-B6AZQcB7.cjs';
4
+ import { V as Video } from '../payload-types-MKbx5MuJ.cjs';
5
5
  export { V as VideoGifOptions, a as VideoThumbnailOptions, g as getVideoGif, b as getVideoMp4Url, c as getVideoStoryboard, d as getVideoStreamUrl, e as getVideoThumbnail } from '../video-WR_TFO9a.cjs';
6
6
 
7
7
  interface VideoPlayerCSSProperties extends CSSProperties {