@ordersail/storefront-sdk 0.1.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/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @ordersail/storefront-sdk
2
+
3
+ A typed TypeScript client for OrderSail's public `storefront-api`. This is
4
+ the thing a merchant (or their developer) uses to build and host their
5
+ **own** storefront against OrderSail's catalog, cart, checkout, and customer
6
+ account data — `storefront-web` is just the worked reference example of
7
+ doing that.
8
+
9
+ Generated types come straight from `storefront-api`'s OpenAPI spec
10
+ (`src/types.gen.ts`); everything else is a thin, hand-written wrapper for
11
+ ergonomics around [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/).
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @ordersail/storefront-sdk
17
+ ```
18
+
19
+ Inside this monorepo it's consumed via the npm workspace protocol instead
20
+ (see `apps/storefront-web/package.json`).
21
+
22
+ ## Quickstart
23
+
24
+ ```ts
25
+ import { StorefrontClient, ApiError } from "@ordersail/storefront-sdk";
26
+
27
+ const storefrontApi = new StorefrontClient(
28
+ "https://api.your-storefront-api-host.com",
29
+ "sfk_...", // your account's app key — see "Auth model" below
30
+ );
31
+
32
+ // reads return the data directly, or undefined if not found
33
+ const products = await storefrontApi.products.list({ limit: 20 });
34
+
35
+ // mutations throw a typed ApiError on failure
36
+ try {
37
+ await storefrontApi.cart.addItem({ variantId: 123, quantity: 1 });
38
+ } catch (error) {
39
+ if (error instanceof ApiError) {
40
+ console.error(`${error.status}: ${error.message}`);
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Resources
46
+
47
+ | Resource | Method | Throws `ApiError`? |
48
+ | ------------------------------ | ---------------------------------------- | ------------------- |
49
+ | `storefrontApi.products` | `list(query?)` | no |
50
+ | | `getById(id)` | no |
51
+ | `storefrontApi.cart` | `get()` | no |
52
+ | | `addItem(body)` | **yes** |
53
+ | | `updateItem(variantId, body)` | **yes** |
54
+ | | `removeItem(variantId)` | **yes** |
55
+ | | `clear()` | **yes** |
56
+ | `storefrontApi.checkout` | `getConfig()` | no |
57
+ | | `createSession(body)` | **yes** |
58
+ | | `getSessionStatus(sessionId)` | no |
59
+ | | `getShippingOptions(body)` | no |
60
+ | `storefrontApi.customer` | `get()` | no |
61
+ | | `update(params)` | **yes** |
62
+ | `storefrontApi` (top level) | `signUp(dto)` | **yes** |
63
+ | | `signIn(credentials)` | **yes** |
64
+ | | `refreshAccessToken()` | no |
65
+ | | `logout()` | no |
66
+
67
+ The convention throughout: a read returns the response body directly (or
68
+ `undefined` on a non-2xx response), while a mutation throws `ApiError` so a
69
+ failure can't be silently ignored.
70
+
71
+ Not yet supported: **order history** for customers (`storefront-api` has no
72
+ customer-facing order endpoints yet — see Storefront Builder M5) and
73
+ **webhooks/real-time events** (no plans yet).
74
+
75
+ ## Error handling
76
+
77
+ Every mutation throws `ApiError` (from `@ordersail/storefront-sdk`) on a
78
+ non-2xx response:
79
+
80
+ ```ts
81
+ export class ApiError extends Error {
82
+ readonly status: number; // the HTTP status code
83
+ readonly message: string; // the server's message, when it sends one
84
+ }
85
+ ```
86
+
87
+ `error.message` is the API's own message when the response body has one
88
+ (most validation and conflict errors do); otherwise it falls back to
89
+ `` `Request failed (${status})` ``. Two exceptions worth knowing: `signIn`'s
90
+ `401` and `signUp`'s `409` currently carry no response body at all, so
91
+ `error.message` for those two is always the generic fallback — write your
92
+ own copy for those cases rather than surfacing it (see
93
+ `apps/storefront-web/src/routes/signin.tsx` for the pattern).
94
+
95
+ ## Auth model
96
+
97
+ Two independent layers, both handled for you by `StorefrontClient`:
98
+
99
+ - **Tenant scoping** — every request carries an `x-app-key` header (your
100
+ account's app key, created in `merchant-web` under Settings → Developer
101
+ API keys). Set once in the constructor; re-assign `client.appKey` later if
102
+ you ever need to switch accounts.
103
+ - **Customer auth** — a bearer JWT (`accessToken`), held in memory only (it
104
+ doesn't survive a page reload), plus an httpOnly `customer_refresh_token`
105
+ cookie the browser sends automatically (`credentials: "include"`). Call
106
+ `refreshAccessToken()` on app start to restore a session from that cookie.
107
+
108
+ **Known gap**: only `customer.get()`/`customer.update()` currently retry
109
+ once on a `401` by calling `refreshAccessToken()` and re-issuing the
110
+ request. `cart` and `checkout` methods do not — if you're calling them a
111
+ long time after the last customer request, a stale in-memory token can
112
+ produce an unhandled `401`. Call `refreshAccessToken()` proactively if this
113
+ matters for your integration, or treat it as a signed-out state and prompt
114
+ sign-in again.
115
+
116
+ ## Regenerating after an API change
117
+
118
+ ```bash
119
+ npm run generate:openapi -w storefront-api # refresh storefront-api's openapi.json
120
+ npm run generate -w @ordersail/storefront-sdk # regenerate types.gen.ts from it
121
+ ```
122
+
123
+ Both steps are manual and their output is committed — there's no watch mode
124
+ or CI auto-regen.
package/dist/http.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ export type DoRequest<T> = () => Promise<{
2
+ data?: T;
3
+ error?: unknown;
4
+ response: Response;
5
+ }>;
6
+ export type DoFn = <T>(request: DoRequest<T>) => Promise<{
7
+ data?: T;
8
+ error?: unknown;
9
+ response: Response;
10
+ }>;
11
+ export declare class ApiError extends Error {
12
+ readonly status: number;
13
+ constructor(message: string, status: number);
14
+ }
15
+ export declare function unwrap<T>(result: {
16
+ data?: T;
17
+ error?: unknown;
18
+ response: Response;
19
+ }): T;
20
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC;IACvC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC,CAAC;AAKH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,EACnB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,KAClB,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAIhE,qBAAa,QAAS,SAAQ,KAAK;IAG/B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM;CAK1B;AAKD,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE;IAChC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;CACpB,GAAG,CAAC,CAaJ"}
package/dist/http.js ADDED
@@ -0,0 +1,28 @@
1
+ // A non-2xx response from the API. `message` is the server's message when it
2
+ // sends one (NestJS `{ message }`, string or string[]), otherwise a fallback.
3
+ export class ApiError extends Error {
4
+ status;
5
+ constructor(message, status) {
6
+ super(message);
7
+ this.status = status;
8
+ this.name = "ApiError";
9
+ }
10
+ }
11
+ // openapi-fetch resolves non-2xx as { error } rather than throwing. Resource
12
+ // methods that mutate use this so callers can `try/catch` and show the API's
13
+ // message instead of a generic string.
14
+ export function unwrap(result) {
15
+ if (result.data !== undefined)
16
+ return result.data;
17
+ const body = result.error;
18
+ const raw = body && typeof body === "object" && "message" in body
19
+ ? body.message
20
+ : undefined;
21
+ const message = Array.isArray(raw)
22
+ ? raw.join(", ")
23
+ : typeof raw === "string" && raw
24
+ ? raw
25
+ : `Request failed (${result.response.status})`;
26
+ throw new ApiError(message, result.response.status);
27
+ }
28
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAaA,6EAA6E;AAC7E,8EAA8E;AAC9E,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGtB;IAFX,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,6EAA6E;AAC7E,6EAA6E;AAC7E,uCAAuC;AACvC,MAAM,UAAU,MAAM,CAAI,MAIzB;IACC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1B,MAAM,GAAG,GACP,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,SAAS,IAAI,IAAI;QACnD,CAAC,CAAE,IAA6B,CAAC,OAAO;QACxC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAChC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QAChB,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG;YAC9B,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,mBAAmB,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;IACnD,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { type Client } from "openapi-fetch";
2
+ import type { paths, components } from "./types.gen.js";
3
+ export { ApiError } from "./http.js";
4
+ import { createProductsResource } from "./resources/products.js";
5
+ import { createCartResource } from "./resources/cart.js";
6
+ import { createCheckoutResource } from "./resources/checkout.js";
7
+ import { createCustomerResource } from "./resources/customer.js";
8
+ export type ProductListItem = components["schemas"]["ProductListItem"];
9
+ export type PaginatedProducts = components["schemas"]["PaginatedProducts"];
10
+ export type ProductDetail = components["schemas"]["ProductDetail"];
11
+ export type ProductDetailOption = components["schemas"]["ProductDetailOption"];
12
+ export type ProductDetailVariant = components["schemas"]["ProductDetailVariant"];
13
+ export type Cart = components["schemas"]["Cart"];
14
+ export type CartItem = components["schemas"]["CartItem"];
15
+ export type CheckoutSession = components["schemas"]["CheckoutSession"];
16
+ export type CheckoutConfig = components["schemas"]["CheckoutConfig"];
17
+ export type CheckoutSessionStatus = components["schemas"]["CheckoutSessionStatus"];
18
+ export type Customer = components["schemas"]["Customer"];
19
+ export type CustomerSignUpDto = components["schemas"]["CustomerSignUpDto"];
20
+ export type CustomerSignInDto = components["schemas"]["CustomerSignInDto"];
21
+ export type UpdateCustomerDto = components["schemas"]["UpdateCustomerDto"];
22
+ export declare class StorefrontClient {
23
+ appKey: string;
24
+ cartToken: string | undefined;
25
+ accessToken: string | undefined;
26
+ client: Client<paths>;
27
+ products: ReturnType<typeof createProductsResource>;
28
+ cart: ReturnType<typeof createCartResource>;
29
+ checkout: ReturnType<typeof createCheckoutResource>;
30
+ customer: ReturnType<typeof createCustomerResource>;
31
+ private authMiddleware;
32
+ constructor(baseUrl: string, appKey: string, cartToken?: string);
33
+ signUp(signup: CustomerSignUpDto): Promise<string>;
34
+ signIn(credentials: CustomerSignInDto): Promise<string>;
35
+ refreshAccessToken(): Promise<string | undefined>;
36
+ logout(): Promise<void>;
37
+ private do;
38
+ }
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAqB,EAAE,KAAK,MAAM,EAAmB,MAAM,eAAe,CAAC;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAC3E,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AACnE,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC;AAC/E,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,CAAC;AACjF,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AACjD,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;AACzD,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC,CAAC;AACrE,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC,CAAC;AACnF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;AACzD,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAC3E,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAC3E,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAI3E,qBAAa,gBAAgB;IAC3B,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAG9B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtB,QAAQ,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACpD,IAAI,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAC5C,QAAQ,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACpD,QAAQ,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IAKpD,OAAO,CAAC,cAAc,CAKpB;gBAEU,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IA6BzD,MAAM,CAAC,MAAM,EAAE,iBAAiB;IAQhC,MAAM,CAAC,WAAW,EAAE,iBAAiB;IASrC,kBAAkB;IAQlB,MAAM;YAME,EAAE;CAUjB"}
package/dist/index.js ADDED
@@ -0,0 +1,89 @@
1
+ import createClient, {} from "openapi-fetch";
2
+ import { unwrap } from "./http.js";
3
+ export { ApiError } from "./http.js";
4
+ import { createProductsResource } from "./resources/products.js";
5
+ import { createCartResource } from "./resources/cart.js";
6
+ import { createCheckoutResource } from "./resources/checkout.js";
7
+ import { createCustomerResource } from "./resources/customer.js";
8
+ const APP_KEY_HEADER = "x-app-key";
9
+ export class StorefrontClient {
10
+ appKey;
11
+ // set automatically the first time cart.addItem() creates a cart — or
12
+ // pass one in up front (e.g. restored from localStorage) to resume a cart
13
+ cartToken;
14
+ // in-memory only, like merchant-sdk — a page refresh re-derives it from the
15
+ // httpOnly customer_refresh_token cookie via refreshAccessToken()
16
+ accessToken;
17
+ client;
18
+ products;
19
+ cart;
20
+ checkout;
21
+ customer;
22
+ // every authenticated request needs the bearer token and the cross-origin
23
+ // cookie (for customer_refresh_token) — centralized here instead of at
24
+ // each call site, same pattern as merchant-sdk's AdminClient
25
+ authMiddleware = {
26
+ onRequest: ({ request }) => {
27
+ request.headers.set("Authorization", `Bearer ${this.accessToken}`);
28
+ return new Request(request, { credentials: "include" });
29
+ },
30
+ };
31
+ constructor(baseUrl, appKey, cartToken) {
32
+ this.appKey = appKey;
33
+ this.cartToken = cartToken;
34
+ this.client = createClient({ baseUrl });
35
+ // the app key identifies the tenant on every request — read off `this`
36
+ // rather than captured at construction, so reassigning `appKey` later
37
+ // (e.g. switching storefronts) takes effect immediately
38
+ this.client.use({
39
+ onRequest: ({ request }) => {
40
+ request.headers.set(APP_KEY_HEADER, this.appKey);
41
+ return request;
42
+ },
43
+ });
44
+ this.client.use(this.authMiddleware);
45
+ const doRequest = (request) => this.do(request);
46
+ this.products = createProductsResource(this.client);
47
+ this.cart = createCartResource(this.client, () => this.cartToken, (token) => {
48
+ this.cartToken = token;
49
+ });
50
+ this.checkout = createCheckoutResource(this.client, () => this.cartToken);
51
+ this.customer = createCustomerResource(this.client, doRequest);
52
+ }
53
+ async signUp(signup) {
54
+ const result = await this.client.POST("/auth/signup", { body: signup });
55
+ this.accessToken = unwrap(result).access_token;
56
+ return this.accessToken;
57
+ }
58
+ // sends the current cart token (if any) so the backend can claim the
59
+ // guest cart into the newly-signed-in customer's account
60
+ async signIn(credentials) {
61
+ const result = await this.client.POST("/auth/signin", {
62
+ body: credentials,
63
+ headers: this.cartToken ? { "x-cart-token": this.cartToken } : {},
64
+ });
65
+ this.accessToken = unwrap(result).access_token;
66
+ return this.accessToken;
67
+ }
68
+ async refreshAccessToken() {
69
+ const { data } = await this.client.GET("/auth/token/refresh");
70
+ this.accessToken = data?.access_token;
71
+ return this.accessToken;
72
+ }
73
+ // clears the httpOnly customer_refresh_token cookie server-side — the
74
+ // client can't delete it itself — then drops the in-memory access token
75
+ async logout() {
76
+ await this.client.POST("/auth/logout");
77
+ this.accessToken = undefined;
78
+ }
79
+ // request is a thunk so the retry rebuilds headers off the refreshed accessToken, not a stale one
80
+ async do(request) {
81
+ const result = await request();
82
+ if (result.response.status === 401) {
83
+ await this.refreshAccessToken();
84
+ return await request();
85
+ }
86
+ return result;
87
+ }
88
+ }
89
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { components, paths } from "../types.gen.js";
3
+ export declare function createCartResource(client: Client<paths>, getCartToken: () => string | undefined, setCartToken: (token: string) => void): {
4
+ addItem: (body: components["schemas"]["AddCartItemDto"]) => Promise<{
5
+ token: string;
6
+ items: components["schemas"]["CartItem"][];
7
+ subtotalCents: number;
8
+ itemCount: number;
9
+ }>;
10
+ get: () => Promise<{
11
+ token: string;
12
+ items: {
13
+ variantId: number;
14
+ productId: number;
15
+ productName: string;
16
+ sku: string | null;
17
+ priceCents: number;
18
+ quantity: number;
19
+ stock: number;
20
+ optionValues: {
21
+ optionName: string;
22
+ value: string;
23
+ }[];
24
+ }[];
25
+ subtotalCents: number;
26
+ itemCount: number;
27
+ } | undefined>;
28
+ updateItem: (variantId: number, body: components["schemas"]["UpdateCartItemDto"]) => Promise<{
29
+ token: string;
30
+ items: {
31
+ variantId: number;
32
+ productId: number;
33
+ productName: string;
34
+ sku: string | null;
35
+ priceCents: number;
36
+ quantity: number;
37
+ stock: number;
38
+ optionValues: {
39
+ optionName: string;
40
+ value: string;
41
+ }[];
42
+ }[];
43
+ subtotalCents: number;
44
+ itemCount: number;
45
+ }>;
46
+ removeItem: (variantId: number) => Promise<{
47
+ token: string;
48
+ items: {
49
+ variantId: number;
50
+ productId: number;
51
+ productName: string;
52
+ sku: string | null;
53
+ priceCents: number;
54
+ quantity: number;
55
+ stock: number;
56
+ optionValues: {
57
+ optionName: string;
58
+ value: string;
59
+ }[];
60
+ }[];
61
+ subtotalCents: number;
62
+ itemCount: number;
63
+ }>;
64
+ clear: () => Promise<{
65
+ token: string;
66
+ items: {
67
+ variantId: number;
68
+ productId: number;
69
+ productName: string;
70
+ sku: string | null;
71
+ priceCents: number;
72
+ quantity: number;
73
+ stock: number;
74
+ optionValues: {
75
+ optionName: string;
76
+ value: string;
77
+ }[];
78
+ }[];
79
+ subtotalCents: number;
80
+ itemCount: number;
81
+ }>;
82
+ };
83
+ //# sourceMappingURL=cart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../src/resources/cart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAKzD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EACrB,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,EACtC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;oBAoBb,UAAU,CAAC,SAAS,CAAC,CAAC,gBAAgB,CAAC;;eA2CmrN,qBAAsB;;;;;;;;;;;;;;;;;;;;;;4BA7BzvN,MAAM,QACX,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC;;;;;;;;;;;;;;;;;;4BAYpB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevC"}
@@ -0,0 +1,54 @@
1
+ import { unwrap } from "../http.js";
2
+ const CART_TOKEN_HEADER = "x-cart-token";
3
+ export function createCartResource(client, getCartToken, setCartToken) {
4
+ // x-cart-token isn't a documented OpenAPI header parameter (it's read via
5
+ // a plain decorator server-side, not @ApiHeader), so it's sent as a raw
6
+ // fetch header rather than through the typed params.header slot
7
+ function cartHeaders() {
8
+ const token = getCartToken();
9
+ return token ? { [CART_TOKEN_HEADER]: token } : {};
10
+ }
11
+ // addItem may create a cart server-side and hand back a new token — this
12
+ // captures it so the caller doesn't have to wire that up by hand. addItem
13
+ // always calls this with unwrap()'s result, which is defined or throws —
14
+ // never undefined — so this stays non-optional rather than re-widening it.
15
+ function captureToken(cart) {
16
+ setCartToken(cart.token);
17
+ return cart;
18
+ }
19
+ return {
20
+ addItem: async (body) => {
21
+ const result = await client.POST("/cart/items", {
22
+ body,
23
+ headers: cartHeaders(),
24
+ });
25
+ return captureToken(unwrap(result));
26
+ },
27
+ get: async () => {
28
+ const { data } = await client.GET("/cart", { headers: cartHeaders() });
29
+ return data;
30
+ },
31
+ updateItem: async (variantId, body) => {
32
+ const path = { variantId: String(variantId) };
33
+ const result = await client.PATCH("/cart/items/{variantId}", {
34
+ params: { path },
35
+ body,
36
+ headers: cartHeaders(),
37
+ });
38
+ return unwrap(result);
39
+ },
40
+ removeItem: async (variantId) => {
41
+ const path = { variantId: String(variantId) };
42
+ const result = await client.DELETE("/cart/items/{variantId}", {
43
+ params: { path },
44
+ headers: cartHeaders(),
45
+ });
46
+ return unwrap(result);
47
+ },
48
+ clear: async () => {
49
+ const result = await client.DELETE("/cart", { headers: cartHeaders() });
50
+ return unwrap(result);
51
+ },
52
+ };
53
+ }
54
+ //# sourceMappingURL=cart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart.js","sourceRoot":"","sources":["../../src/resources/cart.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,UAAU,kBAAkB,CAChC,MAAqB,EACrB,YAAsC,EACtC,YAAqC;IAErC,0EAA0E;IAC1E,wEAAwE;IACxE,gEAAgE;IAChE,SAAS,WAAW;QAClB,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,SAAS,YAAY,CAAC,IAAmC;QACvD,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK,EAAE,IAA6C,EAAE,EAAE;YAC/D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE;gBAC9C,IAAI;gBACJ,OAAO,EAAE,WAAW,EAAE;aACvB,CAAC,CAAC;YACH,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YACvE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,UAAU,EAAE,KAAK,EACf,SAAiB,EACjB,IAAgD,EAChD,EAAE;YACF,MAAM,IAAI,GACR,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE;gBAC3D,MAAM,EAAE,EAAE,IAAI,EAAE;gBAChB,IAAI;gBACJ,OAAO,EAAE,WAAW,EAAE;aACvB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,UAAU,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE;YACtC,MAAM,IAAI,GACR,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,yBAAyB,EAAE;gBAC5D,MAAM,EAAE,EAAE,IAAI,EAAE;gBAChB,OAAO,EAAE,WAAW,EAAE;aACvB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YACxE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { components, paths } from "../types.gen.js";
3
+ export declare function createCheckoutResource(client: Client<paths>, getCartToken: () => string | undefined): {
4
+ getConfig: () => Promise<{
5
+ ready: boolean;
6
+ stripeAccountId: string | null;
7
+ } | undefined>;
8
+ createSession: (body: components["schemas"]["CreateCheckoutSessionDto"]) => Promise<{
9
+ clientSecret: string;
10
+ }>;
11
+ getSessionStatus: (sessionId: string) => Promise<{
12
+ status: string;
13
+ paymentStatus: string;
14
+ customerEmail: string | null;
15
+ } | undefined>;
16
+ getShippingOptions: (body: components["schemas"]["GetShippingOptionsDto"]) => Promise<{
17
+ ok: boolean;
18
+ errorMessage?: string;
19
+ } | undefined>;
20
+ };
21
+ //# sourceMappingURL=checkout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/resources/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAKzD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EACrB,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS;;;;;0BAaR,UAAU,CAAC,SAAS,CAAC,CAAC,0BAA0B,CAAC;;;kCAQzC,MAAM;;;;;+BAUlC,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC;;;;EAMzD"}
@@ -0,0 +1,33 @@
1
+ import { unwrap } from "../http.js";
2
+ const CART_TOKEN_HEADER = "x-cart-token";
3
+ export function createCheckoutResource(client, getCartToken) {
4
+ function cartHeaders() {
5
+ const token = getCartToken();
6
+ return token ? { [CART_TOKEN_HEADER]: token } : {};
7
+ }
8
+ return {
9
+ getConfig: async () => {
10
+ const { data } = await client.GET("/checkout/config");
11
+ return data;
12
+ },
13
+ createSession: async (body) => {
14
+ const result = await client.POST("/checkout/session", {
15
+ body,
16
+ headers: cartHeaders(),
17
+ });
18
+ return unwrap(result);
19
+ },
20
+ getSessionStatus: async (sessionId) => {
21
+ const path = { sessionId };
22
+ const { data } = await client.GET("/checkout/session/{sessionId}", {
23
+ params: { path },
24
+ });
25
+ return data;
26
+ },
27
+ getShippingOptions: async (body) => {
28
+ const { data } = await client.POST("/checkout/shipping-options", { body });
29
+ return data;
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=checkout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/resources/checkout.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,UAAU,sBAAsB,CACpC,MAAqB,EACrB,YAAsC;IAEtC,SAAS,WAAW;QAClB,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,CAAC;IAED,OAAO;QACL,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,aAAa,EAAE,KAAK,EAAE,IAAuD,EAAE,EAAE;YAC/E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;gBACpD,IAAI;gBACJ,OAAO,EAAE,WAAW,EAAE;aACvB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,gBAAgB,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE;YAC5C,MAAM,IAAI,GACR,EAAE,SAAS,EAAE,CAAC;YAChB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,+BAA+B,EAAE;gBACjE,MAAM,EAAE,EAAE,IAAI,EAAE;aACjB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,kBAAkB,EAAE,KAAK,EACvB,IAAoD,EACpD,EAAE;YACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { components, paths } from "../types.gen.js";
3
+ import { type DoFn } from "../http.js";
4
+ export declare function createCustomerResource(client: Client<paths>, doRequest: DoFn): {
5
+ get: () => Promise<{
6
+ id: number;
7
+ accountId: number;
8
+ firstName: string;
9
+ lastName: string;
10
+ email: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ } | undefined>;
14
+ update: (params: components["schemas"]["UpdateCustomerDto"]) => Promise<{
15
+ id: number;
16
+ accountId: number;
17
+ firstName: string;
18
+ lastName: string;
19
+ email: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ }>;
23
+ };
24
+ //# sourceMappingURL=customer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer.d.ts","sourceRoot":"","sources":["../../src/resources/customer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAU,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI;;;;;;;;;;qBAOlD,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC;;;;;;;;;EAOpE"}
@@ -0,0 +1,14 @@
1
+ import { unwrap } from "../http.js";
2
+ export function createCustomerResource(client, doRequest) {
3
+ return {
4
+ get: async () => {
5
+ const { data } = await doRequest(() => client.GET("/customer"));
6
+ return data;
7
+ },
8
+ update: async (params) => {
9
+ const result = await doRequest(() => client.PATCH("/customer", { body: params }));
10
+ return unwrap(result);
11
+ },
12
+ };
13
+ }
14
+ //# sourceMappingURL=customer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer.js","sourceRoot":"","sources":["../../src/resources/customer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAa,MAAM,YAAY,CAAC;AAE/C,MAAM,UAAU,sBAAsB,CAAC,MAAqB,EAAE,SAAe;IAC3E,OAAO;QACL,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,MAAkD,EAAE,EAAE;YACnE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAClC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAC5C,CAAC;YACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,67 @@
1
+ import type { Client } from "openapi-fetch";
2
+ import type { paths } from "../types.gen.js";
3
+ export declare function createProductsResource(client: Client<paths>): {
4
+ list: (query?: paths["/products"]["get"]["parameters"]["query"]) => Promise<{
5
+ items: {
6
+ id: number;
7
+ name: string;
8
+ description: string | null;
9
+ brand: {
10
+ id: number;
11
+ name: string;
12
+ } | null;
13
+ categories: {
14
+ id: number;
15
+ name: string;
16
+ }[];
17
+ minPriceCents: number | null;
18
+ maxPriceCents: number | null;
19
+ thumbnailUrl: string | null;
20
+ }[];
21
+ total: number;
22
+ limit: number;
23
+ offset: number;
24
+ } | undefined>;
25
+ getById: (id: number) => Promise<{
26
+ id: number;
27
+ name: string;
28
+ description: string | null;
29
+ brand: {
30
+ id: number;
31
+ name: string;
32
+ } | null;
33
+ categories: {
34
+ id: number;
35
+ name: string;
36
+ }[];
37
+ options: {
38
+ id: number;
39
+ name: string;
40
+ values: {
41
+ id: number;
42
+ value: string;
43
+ }[];
44
+ }[];
45
+ variants: {
46
+ id: number;
47
+ sku: string | null;
48
+ priceCents: number;
49
+ stock: number;
50
+ optionValues: {
51
+ optionName: string;
52
+ value: string;
53
+ }[];
54
+ images: {
55
+ id: number;
56
+ url: string;
57
+ position: number;
58
+ }[];
59
+ }[];
60
+ images: {
61
+ id: number;
62
+ url: string;
63
+ position: number;
64
+ }[];
65
+ } | undefined>;
66
+ };
67
+ //# sourceMappingURL=products.d.ts.map