@managesales/storefront 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +274 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,77 +1,315 @@
|
|
|
1
1
|
# @managesales/storefront
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@managesales/storefront)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](#typescript-support)
|
|
6
|
+
[](#browser--node-support)
|
|
7
|
+
|
|
3
8
|
Resource-based TypeScript client for building online storefronts on the **ManageSales Storefront
|
|
4
|
-
API** —
|
|
5
|
-
|
|
9
|
+
API** — think Shopify's Storefront API client, for ManageSales. Browse products, run checkout, and
|
|
10
|
+
manage customer accounts with a typed, ergonomic client instead of hand-rolled `fetch` calls.
|
|
11
|
+
|
|
12
|
+
- 🧩 **Resource namespaces** — `client.products`, `client.checkout`, `client.customer`, …
|
|
13
|
+
- 🔐 **Auth built in** — customer login + automatic access-token refresh
|
|
14
|
+
- 📦 **Zero runtime dependencies** — one small file, uses the platform `fetch`
|
|
15
|
+
- 🟦 **Fully typed** — ships `.d.ts`; responses and params are typed end to end
|
|
16
|
+
- 🌐 **Runs everywhere** — dual ESM + CommonJS, browser / Node 18+ / Deno / Bun / edge
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Table of contents
|
|
21
|
+
|
|
22
|
+
- [What is this?](#what-is-this)
|
|
23
|
+
- [Installation](#installation)
|
|
24
|
+
- [Quick start](#quick-start-30-seconds)
|
|
25
|
+
- [Create a client](#create-a-client)
|
|
26
|
+
- [Products](#products)
|
|
27
|
+
- [Collections](#collections)
|
|
28
|
+
- [Cart & checkout](#cart--checkout)
|
|
29
|
+
- [Authentication](#authentication)
|
|
30
|
+
- [Customer account](#customer-account)
|
|
31
|
+
- [Error handling](#error-handling)
|
|
32
|
+
- [More resources](#more-resources)
|
|
33
|
+
- [TypeScript support](#typescript-support)
|
|
34
|
+
- [Browser & Node support](#browser--node-support)
|
|
35
|
+
- [No-npm alternative](#no-npm-alternative)
|
|
36
|
+
- [License](#license)
|
|
37
|
+
|
|
38
|
+
---
|
|
6
39
|
|
|
7
|
-
|
|
8
|
-
> `GET /api/v1/sdk/storefront.ts`, or download it from **Developers → SDKs** in the app. All three
|
|
9
|
-
> surfaces are generated from one source, so they're always identical.
|
|
40
|
+
## What is this?
|
|
10
41
|
|
|
11
|
-
|
|
42
|
+
`@managesales/storefront` is the official client SDK for the **ManageSales Storefront API** — the
|
|
43
|
+
public, customer-facing API behind a ManageSales store. Use it to build a custom storefront
|
|
44
|
+
(product pages, search, cart, checkout, customer login) in any JavaScript/TypeScript framework,
|
|
45
|
+
while the SDK handles request headers, workspace scoping, error parsing, pagination, and token
|
|
46
|
+
refresh for you.
|
|
47
|
+
|
|
48
|
+
It talks to the same API you can also reach directly over HTTP (`/storefront-api/*`) — the SDK is
|
|
49
|
+
just the typed, batteries-included way to do it.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
12
52
|
|
|
13
53
|
```bash
|
|
14
54
|
npm install @managesales/storefront
|
|
15
|
-
#
|
|
55
|
+
# pnpm add @managesales/storefront
|
|
56
|
+
# yarn add @managesales/storefront
|
|
57
|
+
# bun add @managesales/storefront
|
|
16
58
|
```
|
|
17
59
|
|
|
18
|
-
##
|
|
60
|
+
## Quick start (30 seconds)
|
|
19
61
|
|
|
20
62
|
```ts
|
|
21
63
|
import { createStorefrontClient } from "@managesales/storefront";
|
|
22
64
|
|
|
23
65
|
const client = createStorefrontClient({
|
|
24
|
-
workspaceId: "ws_123", //
|
|
66
|
+
workspaceId: "ws_123", // your store's workspace ID — Settings → API
|
|
25
67
|
});
|
|
26
68
|
|
|
27
|
-
|
|
69
|
+
// Browse products — no authentication required
|
|
70
|
+
const { data: products, total } = await client.products.list({ limit: 12 });
|
|
71
|
+
console.log(`${total} products`, products);
|
|
28
72
|
```
|
|
29
73
|
|
|
30
|
-
|
|
31
|
-
|
|
74
|
+
That's it — public catalog data needs no auth. Add [authentication](#authentication) only when
|
|
75
|
+
customers log in.
|
|
76
|
+
|
|
77
|
+
## Create a client
|
|
32
78
|
|
|
33
79
|
```ts
|
|
80
|
+
import { createStorefrontClient } from "@managesales/storefront";
|
|
81
|
+
|
|
34
82
|
const client = createStorefrontClient({
|
|
35
83
|
workspaceId: "ws_123",
|
|
36
|
-
apiUrl: "https://your-backend.example.com/api/v1",
|
|
37
84
|
});
|
|
38
85
|
```
|
|
39
86
|
|
|
40
|
-
|
|
87
|
+
| Option | Type | Required | Description |
|
|
88
|
+
|--------|------|----------|-------------|
|
|
89
|
+
| `workspaceId` | `string` | ✅ | Identifies your store. Found in **Settings → API**. |
|
|
90
|
+
| `apiUrl` | `string` | — | Backend base URL **including** the `/api/v1` prefix. Defaults to ManageSales cloud; override for self-hosted/staging/local. |
|
|
91
|
+
| `customFetch` | `typeof fetch` | — | Inject a `fetch` implementation for SSR/edge runtimes or Node < 18. |
|
|
92
|
+
| `locale` | `string` | — | Default locale for localized content (e.g. `"en"`). |
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// Point at your own backend and inject a custom fetch:
|
|
96
|
+
const client = createStorefrontClient({
|
|
97
|
+
workspaceId: "ws_123",
|
|
98
|
+
apiUrl: "https://api.mystore.com/api/v1",
|
|
99
|
+
customFetch: fetch,
|
|
100
|
+
locale: "en",
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Products
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// List with pagination, search, and sorting
|
|
108
|
+
const { data: products, total } = await client.products.list({
|
|
109
|
+
page: 1,
|
|
110
|
+
limit: 20,
|
|
111
|
+
search: "red shoes",
|
|
112
|
+
sort: "price",
|
|
113
|
+
order: "asc",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Product details — by ID or slug
|
|
117
|
+
const product = await client.products.get("leather-jacket");
|
|
118
|
+
console.log(product.name, product.price, product.variants);
|
|
119
|
+
|
|
120
|
+
// Full-text search
|
|
121
|
+
const { data: results } = await client.products.search("organic cotton");
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Collections
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
// List collections
|
|
128
|
+
const { data: collections } = await client.collections.list();
|
|
129
|
+
|
|
130
|
+
// Get a collection with its products
|
|
131
|
+
const summer = await client.collections.get("summer-sale");
|
|
132
|
+
console.log(summer.name, summer.products.length);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Cart & checkout
|
|
136
|
+
|
|
137
|
+
The SDK models a cart as a set of checkout line items. Assemble items in your UI, create a checkout
|
|
138
|
+
session, optionally apply a coupon, then complete it.
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
// 1. Create a checkout from cart line items
|
|
142
|
+
const session = await client.checkout.create([
|
|
143
|
+
{ productId: "prod_123", variantId: "var_456", quantity: 2 },
|
|
144
|
+
{ productId: "prod_789", quantity: 1 },
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
// 2. Re-fetch a session (e.g. after a page reload)
|
|
148
|
+
const current = await client.checkout.get(session.id);
|
|
149
|
+
|
|
150
|
+
// 3. Apply a coupon
|
|
151
|
+
const discounted = await client.checkout.applyCoupon(session.id, "SAVE10");
|
|
152
|
+
console.log("Discount:", discounted.discount, "Total:", discounted.total);
|
|
153
|
+
|
|
154
|
+
// 4. Complete the purchase
|
|
155
|
+
const order = await client.checkout.complete(session.id, {
|
|
156
|
+
paymentMethod: "card",
|
|
157
|
+
token: "tok_visa_xxx",
|
|
158
|
+
});
|
|
159
|
+
console.log("Order placed:", order.orderNumber);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Abandoned-cart recovery** — turn a recovery link back into a checkout session:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// URL: https://yourstore.com/recover?token=abc123
|
|
166
|
+
const token = new URLSearchParams(location.search).get("token")!;
|
|
167
|
+
const recovered = await client.cart.recover(token);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Authentication
|
|
171
|
+
|
|
172
|
+
Most storefront pages need **no auth**. When a customer logs in, the SDK stores the access + refresh
|
|
173
|
+
tokens internally and refreshes them automatically on `401` — you never handle tokens by hand.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// Register
|
|
177
|
+
const session = await client.auth.register({
|
|
178
|
+
email: "jane@example.com",
|
|
179
|
+
password: "SecurePass123!",
|
|
180
|
+
name: "Jane Doe",
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Login
|
|
184
|
+
await client.auth.login("jane@example.com", "SecurePass123!");
|
|
185
|
+
|
|
186
|
+
// Google OAuth (pass a Google ID token)
|
|
187
|
+
await client.auth.loginWithGoogle(googleIdToken);
|
|
188
|
+
|
|
189
|
+
// Check state / log out
|
|
190
|
+
if (client.auth.isAuthenticated()) {
|
|
191
|
+
/* show account menu */
|
|
192
|
+
}
|
|
193
|
+
await client.auth.logout();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Server-side (recommended)
|
|
197
|
+
|
|
198
|
+
For production, run the SDK on your server (Next.js route handlers, Express, etc.) with httpOnly
|
|
199
|
+
cookies so tokens never reach the browser. Restore a session from cookies with `setTokens`:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// app/api/storefront/[...path]/route.ts
|
|
203
|
+
import { createStorefrontClient } from "@managesales/storefront";
|
|
204
|
+
import { cookies } from "next/headers";
|
|
205
|
+
|
|
206
|
+
export async function GET() {
|
|
207
|
+
const client = createStorefrontClient({ workspaceId: "ws_123" });
|
|
208
|
+
|
|
209
|
+
const access = cookies().get("sf_access_token")?.value;
|
|
210
|
+
const refresh = cookies().get("sf_refresh_token")?.value;
|
|
211
|
+
if (access && refresh) client.auth.setTokens(access, refresh);
|
|
212
|
+
|
|
213
|
+
const products = await client.products.list({ limit: 20 });
|
|
214
|
+
return Response.json(products);
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Customer account
|
|
219
|
+
|
|
220
|
+
Requires a logged-in session (see [Authentication](#authentication)).
|
|
41
221
|
|
|
42
222
|
```ts
|
|
43
|
-
|
|
223
|
+
const me = await client.customer.me(); // profile
|
|
224
|
+
const { data: orders } = await client.customer.orders({ page: 1 }); // order history
|
|
225
|
+
const addresses = await client.customer.addresses(); // saved addresses
|
|
44
226
|
```
|
|
45
227
|
|
|
46
|
-
|
|
47
|
-
|
|
228
|
+
## Error handling
|
|
229
|
+
|
|
230
|
+
Every non-2xx response throws a `StorefrontError` with structured fields, so you can branch
|
|
231
|
+
precisely:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
import { StorefrontError } from "@managesales/storefront";
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
await client.products.get("does-not-exist");
|
|
238
|
+
} catch (err) {
|
|
239
|
+
if (err instanceof StorefrontError) {
|
|
240
|
+
console.log(err.status); // 404
|
|
241
|
+
console.log(err.code); // "NOT_FOUND"
|
|
242
|
+
console.log(err.message); // "Product not found"
|
|
243
|
+
console.log(err.details); // full error body from the API
|
|
244
|
+
} else {
|
|
245
|
+
throw err; // network / unexpected
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## More resources
|
|
251
|
+
|
|
252
|
+
The client also exposes `client.blog`, `client.bookings`, and `client.forms`:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
const { data: posts } = await client.blog.list({ limit: 10 });
|
|
256
|
+
const post = await client.blog.get("how-to-style-leather");
|
|
257
|
+
|
|
258
|
+
const services = await client.bookings.services();
|
|
259
|
+
const slots = await client.bookings.availability({ serviceId: "svc_1", date: "2026-08-15" });
|
|
260
|
+
const booking = await client.bookings.book({
|
|
261
|
+
serviceId: "svc_1",
|
|
262
|
+
date: "2026-08-15",
|
|
263
|
+
startTime: "10:00",
|
|
264
|
+
customer: { name: "Jane Doe", email: "jane@example.com" },
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const form = await client.forms.get("contact-us");
|
|
268
|
+
await client.forms.submit(form.id, { name: "Jane", email: "jane@example.com", message: "Hi!" });
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## TypeScript support
|
|
272
|
+
|
|
273
|
+
Written in TypeScript and shipped with declaration files — no `@types/*` package needed. Params and
|
|
274
|
+
responses are fully typed, including generics like `PaginatedResponse<Product>`:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import {
|
|
278
|
+
createStorefrontClient,
|
|
279
|
+
StorefrontError,
|
|
280
|
+
type StorefrontConfig,
|
|
281
|
+
type Product,
|
|
282
|
+
type PaginatedResponse,
|
|
283
|
+
} from "@managesales/storefront";
|
|
284
|
+
|
|
285
|
+
const config: StorefrontConfig = { workspaceId: "ws_123" };
|
|
286
|
+
const client = createStorefrontClient(config);
|
|
287
|
+
|
|
288
|
+
const page: PaginatedResponse<Product> = await client.products.list();
|
|
289
|
+
```
|
|
48
290
|
|
|
49
|
-
##
|
|
291
|
+
## Browser & Node support
|
|
50
292
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
293
|
+
- **Zero dependencies** — uses the platform's global `fetch`.
|
|
294
|
+
- **Node.js ≥ 18** (global `fetch`). On older Node, pass `customFetch` (e.g. `undici`).
|
|
295
|
+
- **Browsers** — all modern evergreen browsers.
|
|
296
|
+
- **Deno, Bun, and edge runtimes** (Cloudflare Workers, Vercel Edge) — supported; inject
|
|
297
|
+
`customFetch` where a global isn't available.
|
|
298
|
+
- **Module formats** — ships both **ESM** (`import`) and **CommonJS** (`require`).
|
|
54
299
|
|
|
55
|
-
##
|
|
300
|
+
## No-npm alternative
|
|
56
301
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
(`backend/src/modules/storefront/sdk/storefront-sdk-source.ts`) — the exact same function that
|
|
60
|
-
serves `GET /api/v1/sdk/storefront.ts`. This guarantees the npm package, the curl endpoint, and the
|
|
61
|
-
in-app Download never drift.
|
|
302
|
+
Prefer not to add a dependency? The exact same client is served as a single file — download it from
|
|
303
|
+
**Developers → SDKs** in the app, or curl it:
|
|
62
304
|
|
|
63
305
|
```bash
|
|
64
|
-
|
|
65
|
-
|
|
306
|
+
curl -o managesales-storefront.ts \
|
|
307
|
+
"https://managesales-backend-phase1test.up.railway.app/api/v1/sdk/storefront.ts"
|
|
66
308
|
```
|
|
67
309
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- Override the baked default backend URL at build time with `PUBLIC_API_URL` (must include
|
|
71
|
-
`/api/v1`).
|
|
72
|
-
- The build imports the generator across the monorepo. If this package is ever extracted to its own
|
|
73
|
-
repo, vendor `storefront-sdk-source.ts` into `scripts/` instead.
|
|
310
|
+
Then `import { createStorefrontClient } from "./managesales-storefront"`. The npm package, the curl
|
|
311
|
+
endpoint, and the in-app download are all generated from one source, so they're always identical.
|
|
74
312
|
|
|
75
313
|
## License
|
|
76
314
|
|
|
77
|
-
Apache-2.0
|
|
315
|
+
[Apache-2.0](./LICENSE) © ManageSales
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@managesales/storefront",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Resource-based TypeScript client for building storefronts on the ManageSales Storefront API. Zero runtime dependencies, built-in auth and token refresh.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|