@doswiftly/storefront-sdk 15.1.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +239 -0
- package/README.md +28 -0
- package/dist/core/cart/types.d.ts +1 -1
- package/dist/core/cart/types.d.ts.map +1 -1
- package/dist/core/format.d.ts +81 -46
- package/dist/core/format.d.ts.map +1 -1
- package/dist/core/format.js +116 -94
- package/dist/core/generated/operation-types.d.ts +75 -17
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +11 -0
- package/dist/react/components/Money.d.ts +22 -8
- package/dist/react/components/Money.d.ts.map +1 -1
- package/dist/react/components/Money.js +16 -9
- package/dist/react/hooks/use-format.d.ts +85 -0
- package/dist/react/hooks/use-format.d.ts.map +1 -0
- package/dist/react/hooks/use-format.js +141 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,244 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 16.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- ca67b92: **BREAKING** — the formatting utilities switch from a hardcoded 13-currency map to runtime-driven `Intl.NumberFormat` resolution. Every ISO 4217 currency known to the runtime is now supported, with the locale-correct symbol and separators.
|
|
8
|
+
|
|
9
|
+
**API changes**
|
|
10
|
+
- `formatDate(date, locale)` — `locale` is now a required argument. The previous hardcoded `'en-US'` default is gone.
|
|
11
|
+
- `formatDateTime(date, locale)` — `locale` required.
|
|
12
|
+
- `formatNumber(num, locale)` — `locale` required.
|
|
13
|
+
- `formatPrice(price, locale?)` — `locale` is now optional. When omitted, the runtime default (`Intl.NumberFormat().resolvedOptions().locale`) is used. The previous `CURRENCY_LOCALES`-keyed auto-selection is gone.
|
|
14
|
+
- `formatAmount(amount, currencyCode, locale?)` — third argument added (optional).
|
|
15
|
+
- `formatPriceRange(min, max, locale?)` — third argument added (optional).
|
|
16
|
+
- `getCurrencySymbol(code, locale?)` — second argument added (optional). The symbol is derived from `Intl.NumberFormat.formatToParts()`; output depends on the locale (`getCurrencySymbol('PLN', 'pl-PL') === 'zł'`, `getCurrencySymbol('PLN', 'en-US') === 'PLN'`).
|
|
17
|
+
|
|
18
|
+
**Removed exports**
|
|
19
|
+
- `CURRENCY_SYMBOLS` — the 13-entry map is gone. Use `getCurrencySymbol(code, locale)` instead, or read the symbol from `Intl.NumberFormat.formatToParts()` directly.
|
|
20
|
+
- `CURRENCY_LOCALES` — the locale-to-currency map is gone. Pick the locale from the storefront's i18n context (or read `shop.localeToCurrencyMap` from the API for per-shop overrides) and pass it to `formatPrice` / `formatAmount`.
|
|
21
|
+
|
|
22
|
+
**Why**
|
|
23
|
+
- The hardcoded 13-currency map covered ~7% of the ISO 4217 currencies the API now ships in `CurrencyCode` (~180 entries). Every currency outside that list silently fell back to `en-US` formatting — a Brazilian (BRL) or Indian (INR) storefront had to either write its own formatter or accept US-style output.
|
|
24
|
+
- Locale↔currency is a **per-shop** decision (`shop.localeToCurrencyMap` in the schema is explicitly marked SSOT). A globally-hardcoded map in the SDK is the wrong place for that knowledge — it makes Polish customers of a multi-locale shop unable to see PLN in `'en-PL'` even when the merchant configured it.
|
|
25
|
+
- Money precision: `formatPrice` and `formatAmount` no longer apply `parseFloat` to `Money.amount`. Decimal strings are forwarded to `Intl.NumberFormat.format()` verbatim, preserving precision across locales and unusual subunit currencies (JPY/KRW zero-decimal, BHD/JOD/KWD three-decimal, ISK rounding).
|
|
26
|
+
|
|
27
|
+
**Migration**
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// Before
|
|
31
|
+
import {
|
|
32
|
+
formatDate,
|
|
33
|
+
formatPrice,
|
|
34
|
+
CURRENCY_LOCALES,
|
|
35
|
+
CURRENCY_SYMBOLS,
|
|
36
|
+
} from "@doswiftly/storefront-sdk";
|
|
37
|
+
|
|
38
|
+
formatDate(order.createdAt); // hardcoded "Dec 9, 2025"
|
|
39
|
+
formatPrice({ amount: "12.50", currencyCode: "PLN" }); // auto-picked pl-PL → "12,50 zł"
|
|
40
|
+
CURRENCY_LOCALES.PLN; // "pl-PL"
|
|
41
|
+
CURRENCY_SYMBOLS.PLN; // "zł"
|
|
42
|
+
|
|
43
|
+
// After (Client Components)
|
|
44
|
+
import { useLocale } from "next-intl";
|
|
45
|
+
import {
|
|
46
|
+
formatDate,
|
|
47
|
+
formatPrice,
|
|
48
|
+
getCurrencySymbol,
|
|
49
|
+
} from "@doswiftly/storefront-sdk";
|
|
50
|
+
|
|
51
|
+
const locale = useLocale(); // e.g. "pl-PL"
|
|
52
|
+
formatDate(order.createdAt, locale);
|
|
53
|
+
formatPrice({ amount: "12.50", currencyCode: "PLN" }, locale);
|
|
54
|
+
getCurrencySymbol("PLN", locale); // "zł"
|
|
55
|
+
|
|
56
|
+
// After (Server Components / Route Handlers)
|
|
57
|
+
import { getLocale } from "next-intl/server";
|
|
58
|
+
const locale = await getLocale();
|
|
59
|
+
formatDate(order.createdAt, locale);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For per-shop locale↔currency overrides, read `shop.localeToCurrencyMap` from the Storefront API and resolve the locale yourself before calling `formatPrice` / `formatAmount`.
|
|
63
|
+
|
|
64
|
+
**New: Context-driven format hooks**
|
|
65
|
+
|
|
66
|
+
`@doswiftly/storefront-sdk/react` now ships convenience hooks that pull the active language from `useLanguageStore` (inside `<StorefrontProvider>`) and return a memoised, locale-bound formatter. Use them when you don't want to pass `locale` to every call:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import {
|
|
70
|
+
useFormatPrice,
|
|
71
|
+
useFormatAmount,
|
|
72
|
+
useFormatPriceRange,
|
|
73
|
+
useFormatDate,
|
|
74
|
+
useFormatDateTime,
|
|
75
|
+
useFormatNumber,
|
|
76
|
+
useGetCurrencySymbol,
|
|
77
|
+
} from '@doswiftly/storefront-sdk/react';
|
|
78
|
+
|
|
79
|
+
function Cart() {
|
|
80
|
+
const formatPrice = useFormatPrice();
|
|
81
|
+
return <span>{formatPrice(item.price)}</span>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function OrderRow() {
|
|
85
|
+
const formatDate = useFormatDate();
|
|
86
|
+
return <span>{formatDate(order.processedAt)}</span>;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Each hook accepts an optional last `localeOverride` argument that wins over the store value — useful for a "show in US format" toggle on a single element:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const formatPrice = useFormatPrice();
|
|
94
|
+
return <span>{formatPrice(item.price, 'en-US')}</span>;
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Resolution per call: `localeOverride` → `useLanguageStore().language` → runtime default.
|
|
98
|
+
|
|
99
|
+
Use the vanilla `formatPrice` / `formatDate` / etc. from `@doswiftly/storefront-sdk` (no hook) with an explicit `locale` for server components, e-mail templates, or any code path outside a provider.
|
|
100
|
+
|
|
101
|
+
`formatPercentage` is unchanged.
|
|
102
|
+
|
|
103
|
+
`@doswiftly/storefront-operations` bumped to keep linked parity — no operations changes.
|
|
104
|
+
|
|
105
|
+
### Minor Changes
|
|
106
|
+
|
|
107
|
+
- 885c011: Re-export checkout types from the public API. `CartClient` methods added in 15.1.0 (`getAvailablePaymentMethods`, `getAvailableShippingMethods`) returned typed payloads, but the named types were not part of the public surface — component props and function signatures touching these payloads required `Awaited<ReturnType<...>>` workarounds. This change closes that gap.
|
|
108
|
+
|
|
109
|
+
**Newly exported types:**
|
|
110
|
+
- `PaymentMethod`, `AvailablePaymentMethods` — shape returned by `CartClient.getAvailablePaymentMethods()`
|
|
111
|
+
- `AvailableShippingMethod`, `AvailableShippingMethodsPayload`, `FreeShippingProgress`, `DeliveryEstimate`, `ShippingCarrier`, `DeliveryType` — shape returned by `CartClient.getAvailableShippingMethods()`
|
|
112
|
+
- `PickupPoint`, `PickupPointInput` — locker / pickup-point delivery (surfaced via `MailingAddress.pickupPoint` and `CartAddressInput.pickupPoint`)
|
|
113
|
+
- `CartAttributeInput` — input shape for `CartClient.updateAttributes()`
|
|
114
|
+
- `ShippingAddressInput` — input shape for the `availableShippingMethods` standalone query
|
|
115
|
+
|
|
116
|
+
**Example:**
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import type {
|
|
120
|
+
AvailableShippingMethodsPayload,
|
|
121
|
+
AvailableShippingMethod,
|
|
122
|
+
DeliveryType,
|
|
123
|
+
} from "@doswiftly/storefront-sdk";
|
|
124
|
+
|
|
125
|
+
function isPickup(method: AvailableShippingMethod): boolean {
|
|
126
|
+
return method.deliveryType === "PICKUP_POINT";
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
No runtime changes — types already existed internally; this change only adds them to the published surface.
|
|
131
|
+
|
|
132
|
+
`@doswiftly/storefront-operations` bumped to keep linked parity — no operations changes.
|
|
133
|
+
|
|
134
|
+
- fd3d199: Expose `cart.cost.totalDiscount` and `cart.cost.totalShipping` through the `CartCost` fragment.
|
|
135
|
+
|
|
136
|
+
The schema already exposed `CartCost.totalDiscount: Money!` (aggregate of every entry in `cart.discountAllocations`) and `CartCost.totalShipping: Money` (cost of the currently selected shipping method, `null` until one is selected), but the shared `CartCost` fragment did not select them — so they were not part of the typed `Cart.cost` returned by `CartClient`. Storefronts wanting to render a single "Discounts: -X" row or a shipping summary had to either sum `discountAllocations` client-side (precision-sensitive across currencies) or query the schema directly and bypass the typed surface.
|
|
137
|
+
|
|
138
|
+
After this release, both fields are part of `Cart.cost` returned by every `CartClient` operation — `get`, `create`, `addItems`, `updateItems`, `removeItems`, `setShippingAddress`, `setBillingAddress`, `selectShippingMethod`, `selectPaymentMethod`, `updateBuyerIdentity`, `updateDiscountCodes`, `updateNote`, `updateAttributes`, `applyGiftCard`, `removeGiftCard`, `updateGiftCardRecipient`.
|
|
139
|
+
|
|
140
|
+
**Example:**
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const cart = await cartClient.get(cartId);
|
|
144
|
+
|
|
145
|
+
const summary = {
|
|
146
|
+
subtotal: cart.cost.subtotal,
|
|
147
|
+
discount: cart.cost.totalDiscount, // Money — defaults to amount 0
|
|
148
|
+
shipping: cart.cost.totalShipping, // Money | null — null until selectShippingMethod()
|
|
149
|
+
tax: cart.cost.totalTax,
|
|
150
|
+
total: cart.cost.total, // grand total — use directly on checkout summary
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`totalDiscount` is required (defaults to amount 0 when no discount applies). `totalShipping` is nullable — `null` means no shipping method has been selected yet, an amount of 0 means a free-shipping method was selected.
|
|
155
|
+
|
|
156
|
+
Additive — existing consumers keep every field they had before, no breaking change.
|
|
157
|
+
|
|
158
|
+
`@doswiftly/storefront-operations` bumped to keep linked parity (fragment update).
|
|
159
|
+
|
|
160
|
+
- 51091df: Expose `Cart.status` and `Cart.completedOrder` so storefronts can detect a completed (or expired / abandoned) cart on read, without having to attempt a mutation first and react to its `userErrors[].code`.
|
|
161
|
+
|
|
162
|
+
**New fields**
|
|
163
|
+
- `Cart.status: CartStatus!` — lifecycle status (`ACTIVE`, `ABANDONED`, `CONVERTED`, `RECOVERED`, `EXPIRED`). Only `ACTIVE` carts accept mutations; any other status rejects subsequent mutations with `CartErrorCode.ALREADY_COMPLETED`.
|
|
164
|
+
- `Cart.completedOrder: Order` — the order this cart converted into. Populated only when `status === CONVERTED`; null on every other status.
|
|
165
|
+
|
|
166
|
+
**Why**
|
|
167
|
+
|
|
168
|
+
When a buyer returned to the checkout page after completing their order (SSR re-render, deep link, "back" button after redirect), the SDK could only ask `cart(id)` for the cart and got the full pre-completion state back — every form value still there, the "Pay" button still active. The first mutation then failed with `ALREADY_COMPLETED`, after the buyer had already filled out fields. With `status` exposed, the storefront detects the terminal state on initial render and redirects to the order confirmation directly — using the `accessToken` on `completedOrder` for guest tracking, no extra `orderByToken` round-trip.
|
|
169
|
+
|
|
170
|
+
**Example**
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
const cart = await cartClient.get(cartId);
|
|
174
|
+
if (!cart) {
|
|
175
|
+
// Cart not found — guide the buyer to create a new one
|
|
176
|
+
return redirect("/cart");
|
|
177
|
+
}
|
|
178
|
+
if (cart.status !== "ACTIVE") {
|
|
179
|
+
if (cart.completedOrder) {
|
|
180
|
+
// Render the order confirmation page off the data you already have
|
|
181
|
+
return redirect(`/order/${cart.completedOrder.accessToken}`);
|
|
182
|
+
}
|
|
183
|
+
// Abandoned / expired — start a fresh cart
|
|
184
|
+
return redirect("/cart/new");
|
|
185
|
+
}
|
|
186
|
+
// Render the checkout form normally
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Additive — every existing query that selects the shared `Cart` fragment now sees the two new fields automatically. No breaking change.
|
|
190
|
+
|
|
191
|
+
`@doswiftly/storefront-operations` bumped to keep linked parity — schema sync delivers the new fields and the `CartStatus` enum.
|
|
192
|
+
|
|
193
|
+
### Patch Changes
|
|
194
|
+
|
|
195
|
+
- 7ce8ac4: Clarify how `apiUrl` and `shopSlug` are configured.
|
|
196
|
+
|
|
197
|
+
`createStorefrontClient` and `<StorefrontProvider>` take `apiUrl` and `shopSlug` as **explicit `config`** — the SDK does not read environment variables, sniff hostnames, or inspect request headers. The storefront supplies the values; the SDK uses them verbatim.
|
|
198
|
+
|
|
199
|
+
Scaffolded storefronts ship a config helper (`lib/graphql/config.ts`) that resolves the two values from these sources, in order:
|
|
200
|
+
1. `doswiftly.config.ts` (preferred — committed file generated at `doswiftly init`)
|
|
201
|
+
2. `NEXT_PUBLIC_API_URL` + `NEXT_PUBLIC_SHOP_SLUG` (fallback, used for local development)
|
|
202
|
+
3. `http://localhost:8000` + `demo-shop` (defaults — smoke test only)
|
|
203
|
+
|
|
204
|
+
Scratch-built storefronts can skip the helper and pass values into `config={}` directly.
|
|
205
|
+
|
|
206
|
+
**What's new**
|
|
207
|
+
- `@doswiftly/storefront-sdk` README: new `## Configuration` section between `## Installation` and `## Quick Start`. Documents the explicit-config requirement, the three-source resolver shipped with scaffolded storefronts, and when env-var wiring actually matters.
|
|
208
|
+
- `@doswiftly/storefront-operations` `AGENTS.md`: new `### Configuration sources` convention inside `## Critical conventions — DO NOT hallucinate`. AI assistants now prefer `doswiftly.config.ts` and only fall back to the canonical env-var names.
|
|
209
|
+
|
|
210
|
+
Documentation only — no code change.
|
|
211
|
+
|
|
212
|
+
- f4efab9: Add `ShopConfigFields` fragment + `query ShopConfig` for `<StorefrontProvider>` setup.
|
|
213
|
+
|
|
214
|
+
`<StorefrontProvider shopData={...}>` from `@doswiftly/storefront-sdk/react` expects a `ShopConfig` payload with a specific shape: currency setup (including `localeToCurrencyMap`), language setup, and bot protection. Until now the storefront had to hand-write the field selection, and it was easy to miss `localeToCurrencyMap` (used internally by the SDK for browser-locale-based currency detection) or to add an extra field that didn't match the `ShopConfig` interface.
|
|
215
|
+
|
|
216
|
+
**New**
|
|
217
|
+
- `fragment ShopConfigFields on Shop` — minimal selection that matches the `ShopConfig` interface 1:1.
|
|
218
|
+
- `query ShopConfig { shop { ...ShopConfigFields } }` — ready-to-use query for the provider.
|
|
219
|
+
|
|
220
|
+
**Example**
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const SHOP_CONFIG_QUERY = /* GraphQL */ `
|
|
224
|
+
query ShopConfig {
|
|
225
|
+
shop {
|
|
226
|
+
...ShopConfigFields
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
|
|
231
|
+
// In a Server Component:
|
|
232
|
+
const { data } = await execute(SHOP_CONFIG_QUERY);
|
|
233
|
+
return <StorefrontProvider shopData={data.shop}>{children}</StorefrontProvider>;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Use the larger `Shop` fragment + `query Shop` when you also need branding / contact / business hours for your UI; use `ShopConfig` when you only need to bootstrap the provider.
|
|
237
|
+
|
|
238
|
+
Additive — no breaking change.
|
|
239
|
+
|
|
240
|
+
`@doswiftly/storefront-sdk` bumped to keep linked parity — no code change.
|
|
241
|
+
|
|
3
242
|
## 15.1.0
|
|
4
243
|
|
|
5
244
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -24,6 +24,34 @@ Layered runtime SDK for DoSwiftly Commerce storefronts. Framework-agnostic core
|
|
|
24
24
|
pnpm add @doswiftly/storefront-sdk
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
`createStorefrontClient` and `<StorefrontProvider>` take `apiUrl` and `shopSlug` as **explicit `config`** — the SDK does not read environment variables, sniff hostnames, or inspect request headers. The storefront supplies the values; the SDK uses them verbatim.
|
|
30
|
+
|
|
31
|
+
Scaffolded storefronts (`doswiftly init`) ship a `graphqlConfig` helper (`lib/graphql/config.ts`) that resolves both values from three sources in order:
|
|
32
|
+
|
|
33
|
+
| Source | When | What it gives you |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| **`doswiftly.config.ts`** (preferred) | `doswiftly init` storefronts | A committed config file with both values. No env wiring needed in normal use. |
|
|
36
|
+
| `NEXT_PUBLIC_API_URL` + `NEXT_PUBLIC_SHOP_SLUG` (fallback) | Local development; storefronts scaffolded outside `doswiftly init` | Standard Next.js public env vars. `doswiftly dev` rewrites `NEXT_PUBLIC_API_URL` to a local CORS proxy at runtime so client-side calls don't hit production CORS headers. |
|
|
37
|
+
| `http://localhost:8000` + `demo-shop` (defaults) | Empty smoke test | Last-resort placeholders so the project boots before any config is written. |
|
|
38
|
+
|
|
39
|
+
If you go the env-var route, use **exactly these names** — `doswiftly dev` keys off them when overriding. Inventing `API_URL`, `STOREFRONT_URL`, or `TENANT_SLUG` means the dev proxy starts, but your storefront still calls the production API directly and you only learn about it on the first client-side mutation (build and SSR pass silently).
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// app/layout.tsx — Next.js App Router, template-generated wiring
|
|
43
|
+
import { graphqlConfig } from '@/lib/graphql/config';
|
|
44
|
+
|
|
45
|
+
<StorefrontProvider
|
|
46
|
+
config={{ apiUrl: graphqlConfig.apiUrl, shopSlug: graphqlConfig.shopSlug }}
|
|
47
|
+
shopData={shopData}
|
|
48
|
+
>
|
|
49
|
+
{children}
|
|
50
|
+
</StorefrontProvider>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Scratch-built storefronts can read `process.env.NEXT_PUBLIC_*` directly and pass the values into `config={}` — the resolution helper is a convenience, not a requirement.
|
|
54
|
+
|
|
27
55
|
## Quick Start
|
|
28
56
|
|
|
29
57
|
### Core (framework-agnostic)
|
|
@@ -93,7 +93,7 @@ export type PaymentSession = PaymentSessionFragment;
|
|
|
93
93
|
export type DiscountValidationResult = CartValidateDiscountCodeQuery['cartValidateDiscountCode'];
|
|
94
94
|
export type DiscountInfo = NonNullable<DiscountValidationResult['discount']>;
|
|
95
95
|
export type DiscountValidationError = NonNullable<DiscountValidationResult['error']>;
|
|
96
|
-
export type { CartCreateInput, CartLineInput, CartLineUpdateInput, CartBuyerIdentityInput, CartAddressInput, CartAttributeInput, CartCompleteInput, CartApplyGiftCardInput, CartRemoveGiftCardInput, CartSelectPaymentMethodInput, CartSelectShippingMethodInput, CartSetBillingAddressInput, CartSetShippingAddressInput, CartUpdateGiftCardRecipientInput, PaymentCreateInput, ShippingAddressInput, DeliveryType, AttributeSelectionInput as CartAttributeSelectionInput, PaymentMethodType, PaymentInitiationFlow, DiscountApplicationType, DiscountErrorCode, CurrencyCode, CountryCode, LanguageCode, ProductTypeEnum, WeightUnit, CartWarningCode, AttributeType, AttributeFillingMode, AttributeBillingMode, AttributeOptionSurchargeType, StorefrontOrderStatus, OrderPaymentStatus, OrderFulfillmentStatus, } from '../generated/operation-types';
|
|
96
|
+
export type { CartCreateInput, CartLineInput, CartLineUpdateInput, CartBuyerIdentityInput, CartAddressInput, CartAttributeInput, CartCompleteInput, CartApplyGiftCardInput, CartRemoveGiftCardInput, CartSelectPaymentMethodInput, CartSelectShippingMethodInput, CartSetBillingAddressInput, CartSetShippingAddressInput, CartUpdateGiftCardRecipientInput, PaymentCreateInput, ShippingAddressInput, PickupPointInput, DeliveryType, DeliveryEstimate, ShippingCarrier, FreeShippingProgress, PickupPoint, AttributeSelectionInput as CartAttributeSelectionInput, PaymentMethodType, PaymentInitiationFlow, DiscountApplicationType, DiscountErrorCode, CurrencyCode, CountryCode, LanguageCode, ProductTypeEnum, WeightUnit, CartWarningCode, AttributeType, AttributeFillingMode, AttributeBillingMode, AttributeOptionSurchargeType, StorefrontOrderStatus, OrderPaymentStatus, OrderFulfillmentStatus, } from '../generated/operation-types';
|
|
97
97
|
/**
|
|
98
98
|
* Machine-readable error code surfaced when `createPayment` fails. The call
|
|
99
99
|
* throws a `StorefrontError` on `userErrors` — read `.userErrors[0].code` off
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/cart/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/cart/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,0BAA0B,EAC1B,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,EAC3B,iCAAiC,EACjC,aAAa,EACb,sBAAsB,EACtB,6BAA6B,EAC7B,+BAA+B,EAC/B,+BAA+B,EAC/B,qBAAqB,EACrB,iBAAiB,EACjB,+BAA+B,IAAI,qCAAqC,EACzE,MAAM,8BAA8B,CAAC;AAMtC,MAAM,MAAM,KAAK,GAAG,aAAa,CAAC;AAClC,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AACpD,MAAM,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AACxC,MAAM,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AACxC,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAChD,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AACpD,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAC5D,MAAM,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AACxC,0FAA0F;AAC1F,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AACvD,MAAM,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AACxD,MAAM,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AACpE,MAAM,MAAM,IAAI,GAAG,YAAY,CAAC;AAChC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAC9C,wFAAwF;AACxF,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAC5D,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG,2BAA2B,CAAC;AAC9D,kEAAkE;AAClE,MAAM,MAAM,yBAAyB,GAAG,iCAAiC,CAAC;AAC1E;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAClD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,+BAA+B,CAAC;AACtE;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,+BAA+B,CAAC;AACtE;;;;;;;;GAQG;AACH,MAAM,MAAM,+BAA+B,GAAG,qCAAqC,CAAC;AACpF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAC1C;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,aAAa,CAAC;AAClC;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAMpD,gFAAgF;AAChF,MAAM,MAAM,wBAAwB,GAAG,6BAA6B,CAAC,0BAA0B,CAAC,CAAC;AACjG,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAAC;AAC7E,MAAM,MAAM,uBAAuB,GAAG,WAAW,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;AAMrF,YAAY,EACV,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,gCAAgC,EAChC,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EAIZ,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EAEpB,WAAW,EAEX,uBAAuB,IAAI,2BAA2B,EAEtD,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AAMtC;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,oBAAoB,GACpB,mBAAmB,GACnB,iCAAiC,GACjC,oBAAoB,GACpB,mBAAmB,GACnB,gBAAgB,CAAC"}
|
package/dist/core/format.d.ts
CHANGED
|
@@ -3,90 +3,125 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pure functions for formatting prices, dates, numbers.
|
|
5
5
|
* 0 runtime dependencies — works in Node.js, Edge, Deno, Bun.
|
|
6
|
+
*
|
|
7
|
+
* Locale handling:
|
|
8
|
+
* - Every formatter takes an optional `locale: string` argument. When omitted,
|
|
9
|
+
* the runtime default (`Intl.NumberFormat().resolvedOptions().locale`) is
|
|
10
|
+
* used — in browsers this resolves from `navigator.language`, in Node from
|
|
11
|
+
* `LANG` / system settings.
|
|
12
|
+
* - For deterministic output (typical in a storefront with explicit i18n) the
|
|
13
|
+
* caller should pass `locale` explicitly (`useLocale()` in Client Components,
|
|
14
|
+
* `getLocale()` in Server Components, `next-intl`).
|
|
15
|
+
* - For per-shop locale↔currency overrides (e.g. PLN displayed in `'en-PL'`
|
|
16
|
+
* for an English-speaking customer of a Polish shop), the storefront reads
|
|
17
|
+
* `shop.localeToCurrencyMap` from the API and passes the chosen locale.
|
|
18
|
+
*
|
|
19
|
+
* Money precision:
|
|
20
|
+
* - `Money.amount` is a string (Decimal scalar) — values are forwarded to
|
|
21
|
+
* `Intl.NumberFormat.format()` verbatim, without `parseFloat`. This preserves
|
|
22
|
+
* decimal precision exactly as returned by the GraphQL API, including
|
|
23
|
+
* currencies with non-2-digit subunits (JPY/KRW, BHD/JOD, ISK, etc.).
|
|
24
|
+
*
|
|
25
|
+
* Symbol resolution:
|
|
26
|
+
* - `getCurrencySymbol(code, locale?)` derives the symbol via
|
|
27
|
+
* `Intl.NumberFormat.formatToParts()`. The SDK no longer ships a hardcoded
|
|
28
|
+
* subset of currencies — every ISO 4217 currency known to the runtime is
|
|
29
|
+
* supported, with the locale-correct symbol (`'zł'` in pl-PL, `'PLN'` in
|
|
30
|
+
* en-US, `'€'` in de-DE, etc.).
|
|
6
31
|
*/
|
|
32
|
+
declare global {
|
|
33
|
+
namespace Intl {
|
|
34
|
+
interface NumberFormat {
|
|
35
|
+
format(value: string): string;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
7
39
|
export interface PriceMoney {
|
|
8
40
|
amount: string;
|
|
9
41
|
currencyCode: string;
|
|
10
42
|
}
|
|
11
|
-
/** Currency symbols mapping */
|
|
12
|
-
export declare const CURRENCY_SYMBOLS: Record<string, string>;
|
|
13
|
-
/** Currency locale mapping for proper formatting */
|
|
14
|
-
export declare const CURRENCY_LOCALES: Record<string, string>;
|
|
15
43
|
/**
|
|
16
|
-
* Get currency symbol
|
|
44
|
+
* Get the currency symbol for an ISO 4217 code in the requested locale. Derived
|
|
45
|
+
* from `Intl.NumberFormat.formatToParts()` — every currency known to the
|
|
46
|
+
* runtime is supported, with the locale-correct symbol.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* getCurrencySymbol('PLN', 'pl-PL') // => "zł"
|
|
50
|
+
* getCurrencySymbol('PLN', 'en-US') // => "PLN" (en-US has no narrow symbol for PLN)
|
|
51
|
+
* getCurrencySymbol('EUR', 'de-DE') // => "€"
|
|
52
|
+
* getCurrencySymbol('USD') // depends on the runtime locale
|
|
17
53
|
*/
|
|
18
|
-
export declare function getCurrencySymbol(code: string): string;
|
|
54
|
+
export declare function getCurrencySymbol(code: string, locale?: string): string;
|
|
19
55
|
/**
|
|
20
|
-
* Format
|
|
56
|
+
* Format a `Money` value in the requested locale. `amount` is passed to
|
|
57
|
+
* `Intl.NumberFormat` as a string — no `parseFloat`, so decimal precision is
|
|
58
|
+
* preserved exactly as returned by the GraphQL API.
|
|
21
59
|
*
|
|
22
60
|
* @example
|
|
23
|
-
*
|
|
24
|
-
* formatPrice({ amount: "
|
|
25
|
-
* // => "
|
|
26
|
-
* ```
|
|
61
|
+
* formatPrice({ amount: "99.99", currencyCode: "USD" }, 'en-US') // => "$99.99"
|
|
62
|
+
* formatPrice({ amount: "12.50", currencyCode: "PLN" }, 'pl-PL') // => "12,50 zł"
|
|
63
|
+
* formatPrice({ amount: "115.20", currencyCode: "EUR" }, 'de-DE') // => "115,20 €"
|
|
27
64
|
*/
|
|
28
|
-
export declare function formatPrice(price: PriceMoney | null | undefined): string;
|
|
65
|
+
export declare function formatPrice(price: PriceMoney | null | undefined, locale?: string): string;
|
|
29
66
|
/**
|
|
30
|
-
* Format price range
|
|
67
|
+
* Format a price range (`min - max`). Returns a single price when `min` equals
|
|
68
|
+
* `max` by string comparison (no numeric conversion).
|
|
31
69
|
*
|
|
32
70
|
* @example
|
|
33
|
-
* ```typescript
|
|
34
71
|
* formatPriceRange(
|
|
35
72
|
* { amount: "10.00", currencyCode: "USD" },
|
|
36
|
-
* { amount: "50.00", currencyCode: "USD" }
|
|
73
|
+
* { amount: "50.00", currencyCode: "USD" },
|
|
74
|
+
* 'en-US'
|
|
37
75
|
* )
|
|
38
76
|
* // => "$10.00 - $50.00"
|
|
39
|
-
* ```
|
|
40
77
|
*/
|
|
41
|
-
export declare function formatPriceRange(minPrice: PriceMoney, maxPrice: PriceMoney): string;
|
|
78
|
+
export declare function formatPriceRange(minPrice: PriceMoney, maxPrice: PriceMoney, locale?: string): string;
|
|
42
79
|
/**
|
|
43
|
-
* Format amount with currency
|
|
80
|
+
* Format an amount with currency. Accepts a string (recommended — precision
|
|
81
|
+
* preserved) or a number. String values are forwarded to `Intl.NumberFormat`
|
|
82
|
+
* verbatim; number values pass through the standard number path.
|
|
44
83
|
*
|
|
45
84
|
* @example
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* // => "115,20 €"
|
|
49
|
-
* ```
|
|
85
|
+
* formatAmount("115.20", "EUR", 'de-DE') // => "115,20 €"
|
|
86
|
+
* formatAmount(50, "USD", 'en-US') // => "$50.00"
|
|
50
87
|
*/
|
|
51
|
-
export declare function formatAmount(amount: string | number, currencyCode: string): string;
|
|
88
|
+
export declare function formatAmount(amount: string | number, currencyCode: string, locale?: string): string;
|
|
52
89
|
/**
|
|
53
|
-
* Format date
|
|
90
|
+
* Format a date in the requested locale using a `MMM d, y`-style pattern
|
|
91
|
+
* (locale-specific month abbreviation and ordering).
|
|
54
92
|
*
|
|
55
93
|
* @example
|
|
56
|
-
*
|
|
57
|
-
* formatDate(new Date())
|
|
58
|
-
* // => "
|
|
59
|
-
* ```
|
|
94
|
+
* formatDate(new Date(2025, 11, 9), 'en-US') // => "Dec 9, 2025"
|
|
95
|
+
* formatDate(new Date(2025, 11, 9), 'pl-PL') // => "9 gru 2025"
|
|
96
|
+
* formatDate('2025-12-09T12:00:00Z', 'de-DE') // => "9. Dez. 2025"
|
|
60
97
|
*/
|
|
61
|
-
export declare function formatDate(date: Date | string): string;
|
|
98
|
+
export declare function formatDate(date: Date | string, locale: string): string;
|
|
62
99
|
/**
|
|
63
|
-
* Format date with time
|
|
100
|
+
* Format a date with time in the requested locale (month-abbreviated date plus
|
|
101
|
+
* hour and minute, 12- or 24-hour depending on locale convention).
|
|
64
102
|
*
|
|
65
103
|
* @example
|
|
66
|
-
*
|
|
67
|
-
* formatDateTime(new Date())
|
|
68
|
-
* // => "Dec 9, 2025, 10:30 PM"
|
|
69
|
-
* ```
|
|
104
|
+
* formatDateTime(new Date(), 'en-US') // => "Dec 9, 2025, 10:30 PM"
|
|
105
|
+
* formatDateTime(new Date(), 'pl-PL') // => "9 gru 2025, 22:30"
|
|
70
106
|
*/
|
|
71
|
-
export declare function formatDateTime(date: Date | string): string;
|
|
107
|
+
export declare function formatDateTime(date: Date | string, locale: string): string;
|
|
72
108
|
/**
|
|
73
|
-
* Format number with thousands separator
|
|
109
|
+
* Format a number with the locale-appropriate thousands separator and decimal
|
|
110
|
+
* mark.
|
|
74
111
|
*
|
|
75
112
|
* @example
|
|
76
|
-
*
|
|
77
|
-
* formatNumber(1234567)
|
|
78
|
-
* // => "1
|
|
79
|
-
* ```
|
|
113
|
+
* formatNumber(1234567, 'en-US') // => "1,234,567"
|
|
114
|
+
* formatNumber(1234567, 'pl-PL') // => "1 234 567" (NBSP separator)
|
|
115
|
+
* formatNumber(1234.5, 'de-DE') // => "1.234,5"
|
|
80
116
|
*/
|
|
81
|
-
export declare function formatNumber(num: number): string;
|
|
117
|
+
export declare function formatNumber(num: number, locale: string): string;
|
|
82
118
|
/**
|
|
83
|
-
* Format percentage
|
|
119
|
+
* Format a 0-1 ratio as an integer percentage. Locale-independent — uses
|
|
120
|
+
* `Math.round` and a literal `%` suffix.
|
|
84
121
|
*
|
|
85
122
|
* @example
|
|
86
|
-
*
|
|
87
|
-
* formatPercentage(0.
|
|
88
|
-
* // => "15%"
|
|
89
|
-
* ```
|
|
123
|
+
* formatPercentage(0.15) // => "15%"
|
|
124
|
+
* formatPercentage(0.125) // => "13%" (Math.round half-up)
|
|
90
125
|
*/
|
|
91
126
|
export declare function formatPercentage(value: number): string;
|
|
92
127
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/core/format.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/core/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAOH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI,CAAC;QACb,UAAU,YAAY;YACpB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;SAC/B;KACF;CACF;AAMD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AA+DD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAYvE;AAMD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CASzF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,UAAU,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAMR;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAaR;AAMD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQtE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAU1E;AAMD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|