@commercengine/storefront-sdk-nextjs 0.1.0-alpha.0 → 1.0.0-alpha.2
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 +515 -139
- package/dist/client.cjs +405 -0
- package/dist/client.d.cts +121 -0
- package/dist/client.d.ts +121 -0
- package/dist/client.js +378 -0
- package/dist/index.cjs +229 -140
- package/dist/index.d.cts +27 -102
- package/dist/index.d.ts +27 -102
- package/dist/index.js +230 -132
- package/dist/middleware.cjs +66 -0
- package/dist/middleware.d.cts +38 -0
- package/dist/middleware.d.ts +38 -0
- package/dist/middleware.js +39 -0
- package/dist/server-ByBPoXJG.d.cts +182 -0
- package/dist/server-ByBPoXJG.d.ts +182 -0
- package/dist/server-CwxgXezP.d.cts +115 -0
- package/dist/server-CwxgXezP.d.ts +115 -0
- package/dist/server-D-pFrx8J.d.cts +105 -0
- package/dist/server-DaDfTjsO.d.cts +103 -0
- package/dist/server-DaDfTjsO.d.ts +103 -0
- package/dist/server-DjlQVC11.d.ts +105 -0
- package/dist/server.cjs +385 -0
- package/dist/server.d.cts +3 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +358 -0
- package/dist/storefront.cjs +474 -0
- package/dist/storefront.d.cts +2 -0
- package/dist/storefront.d.ts +2 -0
- package/dist/storefront.js +448 -0
- package/package.json +18 -8
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CommerceEngine Next.js SDK
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Production-ready Next.js wrapper** for the CommerceEngine Storefront SDK. Provides the perfect developer experience with automatic context detection, universal API, and zero configuration complexity.
|
|
4
4
|
|
|
5
|
-
**✨
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
5
|
+
**✨ Perfect DX Pattern:**
|
|
6
|
+
- **🎯 One Config File** - Single `lib/storefront.ts` using `createStorefront()`
|
|
7
|
+
- **🌍 Universal API** - Same `storefront()` import works everywhere
|
|
8
|
+
- **🔥 Automatic Tokens** - Creates and manages tokens automatically
|
|
9
|
+
- **🧠 Smart Context Detection** - Detects Server vs Client vs Build contexts
|
|
10
|
+
- **🍪 Cookie-based State** - Shared authentication via Next.js cookies
|
|
11
|
+
- **⚡ Request Isolation** - Proper per-request SDK instances on server
|
|
12
|
+
- **🛠 Zero Complexity** - Environment variables + one lib file = done
|
|
10
13
|
|
|
11
14
|
## Installation
|
|
12
15
|
|
|
@@ -18,23 +21,79 @@ pnpm add @commercengine/storefront-sdk-nextjs
|
|
|
18
21
|
|
|
19
22
|
## Quick Start
|
|
20
23
|
|
|
21
|
-
### 1.
|
|
24
|
+
### 1. Environment Variables (Required)
|
|
25
|
+
|
|
26
|
+
Add your store configuration to `.env.local`:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
NEXT_PUBLIC_STORE_ID=your-store-id
|
|
30
|
+
NEXT_PUBLIC_API_KEY=your-api-key
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Optional environment variables:**
|
|
34
|
+
```bash
|
|
35
|
+
# Environment (defaults to "staging")
|
|
36
|
+
NEXT_PUBLIC_ENVIRONMENT=staging # or "production"
|
|
37
|
+
|
|
38
|
+
# Custom API endpoint (overrides environment default)
|
|
39
|
+
NEXT_PUBLIC_API_BASE_URL=https://your-custom-api.example.com
|
|
40
|
+
|
|
41
|
+
# Request timeout in milliseconds
|
|
42
|
+
NEXT_PUBLIC_API_TIMEOUT=10000
|
|
43
|
+
|
|
44
|
+
# Debug mode (defaults to false)
|
|
45
|
+
NEXT_PUBLIC_DEBUG_MODE=true
|
|
46
|
+
|
|
47
|
+
# Default customer group for pricing and promotions
|
|
48
|
+
NEXT_PUBLIC_DEFAULT_CUSTOMER_GROUP_ID=01JHS28V83KDWTRBXXJQRTEKA0
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Create Your Storefront Configuration
|
|
52
|
+
|
|
53
|
+
Create `lib/storefront.ts` in your project:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// lib/storefront.ts
|
|
57
|
+
import {
|
|
58
|
+
createStorefront,
|
|
59
|
+
type StorefrontRuntimeConfig,
|
|
60
|
+
} from "@commercengine/storefront-sdk-nextjs";
|
|
61
|
+
|
|
62
|
+
// Optional advanced configuration (everything not in environment variables)
|
|
63
|
+
const storefrontConfig: StorefrontRuntimeConfig = {
|
|
64
|
+
debug: true,
|
|
65
|
+
timeout: 15000,
|
|
66
|
+
logger: (msg: string, ...args: any[]) =>
|
|
67
|
+
console.log("[STOREFRONT]", msg, ...args),
|
|
68
|
+
onTokensUpdated: (access: string, refresh: string) => {
|
|
69
|
+
console.log("🔥 TOKENS UPDATED:", {
|
|
70
|
+
access: access.slice(0, 20) + "...",
|
|
71
|
+
refresh: refresh.slice(0, 20) + "...",
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
onTokensCleared: () => {
|
|
75
|
+
console.log("🔄 TOKENS CLEARED");
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Create the configured storefront function
|
|
80
|
+
export const storefront = createStorefront(storefrontConfig);
|
|
81
|
+
|
|
82
|
+
// Re-export types for convenience
|
|
83
|
+
export type { StorefrontRuntimeConfig };
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 3. Initialize in Root Layout
|
|
22
87
|
|
|
23
88
|
```typescript
|
|
24
89
|
// app/layout.tsx
|
|
25
|
-
import { StorefrontSDKInitializer
|
|
90
|
+
import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
|
|
26
91
|
|
|
27
92
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
28
93
|
return (
|
|
29
|
-
<html>
|
|
94
|
+
<html lang="en">
|
|
30
95
|
<body>
|
|
31
|
-
<StorefrontSDKInitializer
|
|
32
|
-
config={{
|
|
33
|
-
storeId: process.env.NEXT_PUBLIC_STORE_ID!,
|
|
34
|
-
environment: Environment.Production,
|
|
35
|
-
apiKey: process.env.NEXT_PUBLIC_API_KEY,
|
|
36
|
-
}}
|
|
37
|
-
/>
|
|
96
|
+
<StorefrontSDKInitializer />
|
|
38
97
|
{children}
|
|
39
98
|
</body>
|
|
40
99
|
</html>
|
|
@@ -42,198 +101,515 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
42
101
|
}
|
|
43
102
|
```
|
|
44
103
|
|
|
45
|
-
###
|
|
104
|
+
### 4. Use Anywhere with Universal Import
|
|
46
105
|
|
|
47
106
|
```typescript
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
import {
|
|
107
|
+
// Import your configured storefront everywhere
|
|
108
|
+
import { storefront } from "@/lib/storefront";
|
|
109
|
+
import { cookies } from "next/headers"; // Only for server contexts
|
|
51
110
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
111
|
+
// ✅ Client Component - No cookies needed
|
|
112
|
+
const products = await storefront().catalog.listProducts();
|
|
113
|
+
|
|
114
|
+
// ✅ Server Component, Server Action, or API Route - MUST pass cookies
|
|
115
|
+
const products = await storefront(cookies()).catalog.listProducts();
|
|
116
|
+
|
|
117
|
+
// ✅ Root Layout - Special exception with explicit flag
|
|
118
|
+
const products = await storefront({ isRootLayout: true }).catalog.listProducts();
|
|
119
|
+
|
|
120
|
+
// ✅ SSG/ISR (build contexts) - Automatic fallback to memory storage
|
|
121
|
+
// (NEXT_BUILD_CACHE_TOKENS=true enables this)
|
|
122
|
+
const products = await storefront().catalog.listProducts();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Usage in Different Next.js Contexts
|
|
62
126
|
|
|
63
|
-
|
|
127
|
+
### Client Components
|
|
128
|
+
|
|
129
|
+
Client Components run in the browser and can persist tokens via cookies:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// components/ProductList.tsx
|
|
133
|
+
"use client";
|
|
134
|
+
|
|
135
|
+
import { useState, useEffect } from "react";
|
|
136
|
+
import { storefront } from "@/lib/storefront";
|
|
137
|
+
|
|
138
|
+
export default function ProductList() {
|
|
139
|
+
const [products, setProducts] = useState([]);
|
|
140
|
+
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
async function loadProducts() {
|
|
143
|
+
const sdk = storefront(); // No cookies() needed on client-side
|
|
144
|
+
|
|
145
|
+
// Tokens are automatically managed by StorefrontSDKInitializer
|
|
146
|
+
const { data } = await sdk.catalog.listProducts();
|
|
147
|
+
if (data) setProducts(data.products);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
loadProducts();
|
|
151
|
+
}, []);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<div>
|
|
155
|
+
{products.map(product => (
|
|
156
|
+
<div key={product.id}>{product.name}</div>
|
|
157
|
+
))}
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
64
160
|
}
|
|
65
161
|
```
|
|
66
162
|
|
|
163
|
+
### Server Components
|
|
164
|
+
|
|
165
|
+
Server Components run on the server and can read cookies:
|
|
166
|
+
|
|
67
167
|
```typescript
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
import { cookies } from
|
|
71
|
-
import { getStorefrontSDK } from '@commercengine/storefront-sdk-nextjs';
|
|
168
|
+
// app/products/page.tsx
|
|
169
|
+
import { storefront } from "@/lib/storefront";
|
|
170
|
+
import { cookies } from "next/headers";
|
|
72
171
|
|
|
73
|
-
export async function
|
|
74
|
-
const sdk =
|
|
172
|
+
export default async function ProductsPage() {
|
|
173
|
+
const sdk = storefront(cookies());
|
|
75
174
|
|
|
76
|
-
|
|
77
|
-
const { data } = await sdk.cart.addToCart({
|
|
78
|
-
product_id: productId,
|
|
79
|
-
quantity: 1,
|
|
80
|
-
});
|
|
175
|
+
const { data: products } = await sdk.catalog.listProducts();
|
|
81
176
|
|
|
82
|
-
return
|
|
177
|
+
return (
|
|
178
|
+
<div>
|
|
179
|
+
{products?.products.map(product => (
|
|
180
|
+
<div key={product.id}>{product.name}</div>
|
|
181
|
+
))}
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
83
184
|
}
|
|
84
185
|
```
|
|
85
186
|
|
|
187
|
+
### Server Actions
|
|
188
|
+
|
|
189
|
+
Server Actions can both read and write cookies, perfect for authentication:
|
|
190
|
+
|
|
86
191
|
```typescript
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
192
|
+
// app/actions.ts
|
|
193
|
+
"use server";
|
|
194
|
+
|
|
195
|
+
import { storefront } from "@/lib/storefront";
|
|
196
|
+
import { cookies } from "next/headers";
|
|
90
197
|
|
|
91
|
-
export
|
|
92
|
-
const sdk =
|
|
198
|
+
export async function loginWithEmail(email: string, password: string) {
|
|
199
|
+
const sdk = storefront(cookies());
|
|
93
200
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
201
|
+
const { data, error } = await sdk.auth.loginWithPassword({ email, password });
|
|
202
|
+
|
|
203
|
+
if (data) {
|
|
204
|
+
// Tokens are automatically saved to cookies
|
|
205
|
+
return { success: true, user: data.user };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return { success: false, error: error?.message };
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### API Routes
|
|
213
|
+
|
|
214
|
+
API Routes work identically to Server Actions:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
// app/api/products/route.ts
|
|
218
|
+
import { storefront } from "@/lib/storefront";
|
|
219
|
+
import { cookies } from "next/headers";
|
|
220
|
+
import { NextResponse } from "next/server";
|
|
221
|
+
|
|
222
|
+
export async function GET() {
|
|
223
|
+
try {
|
|
224
|
+
const sdk = storefront(cookies());
|
|
225
|
+
const { data, error } = await sdk.catalog.listProducts();
|
|
226
|
+
|
|
227
|
+
if (error) {
|
|
228
|
+
return NextResponse.json({ error: error.message }, { status: 400 });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return NextResponse.json(data);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
return NextResponse.json(
|
|
234
|
+
{ error: "Internal server error" },
|
|
235
|
+
{ status: 500 }
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Root Layout (Special Case)
|
|
242
|
+
|
|
243
|
+
Root Layout requires explicit flag since it's outside request context:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
// app/layout.tsx
|
|
247
|
+
import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
|
|
248
|
+
import { storefront } from "@/lib/storefront";
|
|
98
249
|
|
|
99
|
-
|
|
250
|
+
// Root Layout requires explicit flag - no request context available
|
|
251
|
+
const sdk = storefront({ isRootLayout: true });
|
|
252
|
+
const { data: storeConfig } = await sdk.store.getStoreConfig();
|
|
253
|
+
|
|
254
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
255
|
+
return (
|
|
256
|
+
<html lang="en">
|
|
257
|
+
<body>
|
|
258
|
+
<StorefrontSDKInitializer />
|
|
259
|
+
<h1>Welcome to {storeConfig?.store_config?.brand.name}</h1>
|
|
260
|
+
{children}
|
|
261
|
+
</body>
|
|
262
|
+
</html>
|
|
263
|
+
);
|
|
100
264
|
}
|
|
101
265
|
```
|
|
102
266
|
|
|
267
|
+
## Static Site Generation (SSG) & Build-Time Optimization
|
|
103
268
|
|
|
104
|
-
|
|
269
|
+
The SDK provides powerful build-time optimizations through intelligent token caching.
|
|
105
270
|
|
|
106
|
-
###
|
|
271
|
+
### Enable Build-Time Token Caching
|
|
107
272
|
|
|
108
|
-
|
|
273
|
+
```bash
|
|
274
|
+
# Enable caching during builds
|
|
275
|
+
NEXT_BUILD_CACHE_TOKENS=true pnpm build
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### SSG with generateStaticParams
|
|
109
279
|
|
|
110
280
|
```typescript
|
|
111
|
-
//
|
|
112
|
-
|
|
281
|
+
// app/products/[slug]/page.tsx
|
|
282
|
+
import { storefront } from "@/lib/storefront";
|
|
283
|
+
import { notFound } from "next/navigation";
|
|
284
|
+
|
|
285
|
+
interface ProductPageProps {
|
|
286
|
+
params: Promise<{ slug: string }>;
|
|
287
|
+
}
|
|
113
288
|
|
|
114
|
-
|
|
115
|
-
const
|
|
289
|
+
export default async function ProductPage({ params }: ProductPageProps) {
|
|
290
|
+
const { slug } = await params;
|
|
291
|
+
const sdk = storefront(); // No cookies() - uses build-time storage
|
|
292
|
+
|
|
293
|
+
const { data, error } = await sdk.catalog.getProductDetail({
|
|
294
|
+
product_id_or_slug: slug
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
if (error || !data) {
|
|
298
|
+
notFound();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<div>
|
|
303
|
+
<h1>{data.product.name}</h1>
|
|
304
|
+
<p>SKU: {data.product.sku}</p>
|
|
305
|
+
<p>Description: {data.product.short_description}</p>
|
|
306
|
+
</div>
|
|
307
|
+
);
|
|
308
|
+
}
|
|
116
309
|
|
|
117
|
-
//
|
|
118
|
-
|
|
310
|
+
// Generate static params from real API data
|
|
311
|
+
export async function generateStaticParams() {
|
|
312
|
+
const sdk = storefront(); // Token will be cached and reused
|
|
313
|
+
|
|
314
|
+
const { data: productsData, error } = await sdk.catalog.listProducts({
|
|
315
|
+
limit: 100
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
if (error || !productsData) {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return productsData.products.map(product => ({
|
|
323
|
+
slug: product.slug || product.id
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
119
326
|
```
|
|
120
327
|
|
|
121
|
-
###
|
|
328
|
+
### Build Performance Benefits
|
|
122
329
|
|
|
123
|
-
|
|
330
|
+
With token caching enabled:
|
|
331
|
+
- ✅ Token created once and reused across all pages
|
|
332
|
+
- ✅ 100 pages = ~1 anonymous token API call total
|
|
333
|
+
- ✅ Faster builds, dramatically lower API usage
|
|
334
|
+
|
|
335
|
+
## Authentication Patterns
|
|
336
|
+
|
|
337
|
+
### Anonymous Users
|
|
338
|
+
|
|
339
|
+
The SDK automatically creates anonymous tokens:
|
|
124
340
|
|
|
125
341
|
```typescript
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
342
|
+
// This works everywhere - creates anonymous token automatically
|
|
343
|
+
const { data: products } = await storefront(cookies()).catalog.listProducts();
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Email/Password Login
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// Server Action
|
|
350
|
+
"use server";
|
|
351
|
+
export async function loginUser(email: string, password: string) {
|
|
352
|
+
const sdk = storefront(cookies());
|
|
353
|
+
|
|
354
|
+
const { data, error } = await sdk.auth.loginWithPassword({ email, password });
|
|
355
|
+
|
|
356
|
+
if (data) {
|
|
357
|
+
// Tokens automatically saved to cookies
|
|
358
|
+
redirect('/dashboard');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return { error: error?.message };
|
|
362
|
+
}
|
|
141
363
|
```
|
|
142
364
|
|
|
143
|
-
|
|
365
|
+
### Phone/OTP Login
|
|
144
366
|
|
|
145
|
-
|
|
367
|
+
```typescript
|
|
368
|
+
// Server Action - Step 1: Send OTP
|
|
369
|
+
export async function sendOTP(phone: string, country_code: string) {
|
|
370
|
+
const sdk = storefront(await cookies());
|
|
371
|
+
|
|
372
|
+
return await sdk.auth.loginWithPhone({
|
|
373
|
+
phone,
|
|
374
|
+
country_code,
|
|
375
|
+
register_if_not_exists: true
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Server Action - Step 2: Verify OTP
|
|
380
|
+
export async function verifyOTP(otp: string, otp_token: string, otp_action: string) {
|
|
381
|
+
const sdk = storefront(await cookies());
|
|
382
|
+
|
|
383
|
+
const { data, error } = await sdk.auth.verifyOtp({
|
|
384
|
+
otp,
|
|
385
|
+
otp_token,
|
|
386
|
+
otp_action
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
if (data) {
|
|
390
|
+
// Tokens automatically saved to cookies
|
|
391
|
+
return { success: true, user: data.user };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return { success: false, error: error?.message };
|
|
395
|
+
}
|
|
396
|
+
```
|
|
146
397
|
|
|
147
|
-
|
|
398
|
+
## API Reference
|
|
148
399
|
|
|
149
|
-
|
|
150
|
-
2. **Token Expiry**: Refreshes tokens transparently
|
|
151
|
-
3. **Token Corruption**: Cleans up orphaned tokens
|
|
152
|
-
4. **User Login**: Upgrades from anonymous to authenticated tokens
|
|
153
|
-
5. **User Logout**: Downgrades gracefully with continuity
|
|
154
|
-
6. **Page Refresh**: Tokens persist via cookies across server/client
|
|
400
|
+
### `createStorefront(config?)`
|
|
155
401
|
|
|
156
|
-
|
|
402
|
+
Creates a configured storefront function that works universally across all Next.js contexts.
|
|
157
403
|
|
|
158
404
|
```typescript
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const
|
|
405
|
+
import { createStorefront } from "@commercengine/storefront-sdk-nextjs";
|
|
406
|
+
|
|
407
|
+
export const storefront = createStorefront({
|
|
408
|
+
debug: true,
|
|
409
|
+
logger: (msg, ...args) => console.log('[DEBUG]', msg, ...args)
|
|
410
|
+
});
|
|
162
411
|
```
|
|
163
412
|
|
|
164
|
-
|
|
413
|
+
**Parameters:**
|
|
414
|
+
- `config` (optional): `StorefrontRuntimeConfig` - Advanced configuration options
|
|
415
|
+
|
|
416
|
+
**Returns:**
|
|
417
|
+
- Universal `storefront()` function that works in all Next.js contexts
|
|
418
|
+
|
|
419
|
+
### `StorefrontRuntimeConfig`
|
|
165
420
|
|
|
166
|
-
|
|
421
|
+
Optional configuration object for `createStorefront()`:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
interface StorefrontRuntimeConfig {
|
|
425
|
+
// Override environment variables
|
|
426
|
+
storeId?: string;
|
|
427
|
+
apiKey?: string;
|
|
428
|
+
environment?: Environment;
|
|
429
|
+
baseUrl?: string;
|
|
430
|
+
timeout?: number;
|
|
431
|
+
debug?: boolean;
|
|
432
|
+
|
|
433
|
+
// Advanced options (not available via environment variables)
|
|
434
|
+
accessToken?: string;
|
|
435
|
+
refreshToken?: string;
|
|
436
|
+
defaultHeaders?: SupportedDefaultHeaders;
|
|
437
|
+
logger?: (message: string, ...args: any[]) => void;
|
|
438
|
+
onTokensUpdated?: (accessToken: string, refreshToken: string) => void;
|
|
439
|
+
onTokensCleared?: () => void;
|
|
440
|
+
tokenStorageOptions?: NextJSTokenStorageOptions;
|
|
441
|
+
}
|
|
167
442
|
```
|
|
168
|
-
🚨 Server Environment Detected!
|
|
169
443
|
|
|
170
|
-
|
|
171
|
-
Please pass the Next.js cookie store:
|
|
444
|
+
### Universal `storefront()` Function
|
|
172
445
|
|
|
173
|
-
|
|
174
|
-
import { cookies } from 'next/headers';
|
|
446
|
+
The function returned by `createStorefront()` works in all contexts with strict enforcement:
|
|
175
447
|
|
|
176
|
-
|
|
177
|
-
|
|
448
|
+
```typescript
|
|
449
|
+
// Client-side (browser)
|
|
450
|
+
const sdk = storefront();
|
|
178
451
|
|
|
179
|
-
//
|
|
180
|
-
const sdk =
|
|
452
|
+
// Server-side (requires cookies for user continuity)
|
|
453
|
+
const sdk = storefront(cookies());
|
|
454
|
+
|
|
455
|
+
// Root Layout (special exception with explicit flag)
|
|
456
|
+
const sdk = storefront({ isRootLayout: true });
|
|
181
457
|
|
|
182
|
-
|
|
183
|
-
const sdk =
|
|
458
|
+
// Server-side without cookies - throws helpful error to protect user sessions
|
|
459
|
+
const sdk = storefront(); // ❌ Throws error in server contexts
|
|
184
460
|
```
|
|
185
461
|
|
|
186
|
-
|
|
462
|
+
### Function Signatures
|
|
187
463
|
|
|
188
|
-
**Before (Base SDK):**
|
|
189
464
|
```typescript
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
465
|
+
function storefront(): StorefrontSDK;
|
|
466
|
+
function storefront(cookieStore: NextCookieStore): StorefrontSDK;
|
|
467
|
+
function storefront(options: { isRootLayout: true }): StorefrontSDK;
|
|
468
|
+
function storefront(cookieStore: NextCookieStore, options: { isRootLayout?: boolean }): StorefrontSDK;
|
|
193
469
|
```
|
|
194
470
|
|
|
195
|
-
|
|
471
|
+
### `StorefrontSDKInitializer`
|
|
472
|
+
|
|
473
|
+
Client-side initializer component (must be imported from `/client`):
|
|
474
|
+
|
|
196
475
|
```typescript
|
|
197
|
-
|
|
198
|
-
|
|
476
|
+
import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
|
|
477
|
+
|
|
478
|
+
<StorefrontSDKInitializer />
|
|
199
479
|
```
|
|
200
480
|
|
|
201
|
-
|
|
481
|
+
No props needed - configuration comes from environment variables and your `lib/storefront.ts` file.
|
|
482
|
+
|
|
483
|
+
## Error Handling
|
|
202
484
|
|
|
203
|
-
|
|
485
|
+
All SDK methods return a consistent error structure:
|
|
204
486
|
|
|
205
487
|
```typescript
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
488
|
+
const { data, error, response } = await storefront(cookies()).catalog.listProducts();
|
|
489
|
+
|
|
490
|
+
if (error) {
|
|
491
|
+
console.error("API Error:", error.message, error.code);
|
|
492
|
+
console.log("Status:", response.status);
|
|
493
|
+
} else {
|
|
494
|
+
console.log("Products:", data.products);
|
|
495
|
+
}
|
|
211
496
|
```
|
|
212
497
|
|
|
213
498
|
## Best Practices
|
|
214
499
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
500
|
+
### ✅ Do's
|
|
501
|
+
|
|
502
|
+
- **Set required environment variables**: `NEXT_PUBLIC_STORE_ID` and `NEXT_PUBLIC_API_KEY` are mandatory
|
|
503
|
+
- **Create one lib/storefront.ts file**: Use `createStorefront()` to configure advanced options
|
|
504
|
+
- **Initialize once**: Call `StorefrontSDKInitializer` only in your root layout
|
|
505
|
+
- **Use `storefront(cookies())`**: Always pass cookies in server contexts
|
|
506
|
+
- **Handle errors**: Always check the error property in responses
|
|
507
|
+
- **Use Server Actions**: For authentication flows that need to persist tokens
|
|
508
|
+
|
|
509
|
+
### ❌ Don'ts
|
|
510
|
+
|
|
511
|
+
- **Don't call `cookies()` in Client Components**: It will throw an error
|
|
512
|
+
- **Don't initialize multiple times**: The SDK handles singleton behavior
|
|
513
|
+
- **Don't forget error handling**: API calls can fail for various reasons
|
|
514
|
+
- **Don't skip environment variables**: Missing required variables will cause errors
|
|
515
|
+
|
|
516
|
+
## Troubleshooting
|
|
517
|
+
|
|
518
|
+
### Common Issues
|
|
519
|
+
|
|
520
|
+
1. **"Server context requires cookies for user continuity!"**
|
|
521
|
+
```typescript
|
|
522
|
+
// ❌ Wrong - server context without cookies (breaks user sessions)
|
|
523
|
+
storefront()
|
|
524
|
+
|
|
525
|
+
// ✅ Correct - server context with cookies
|
|
526
|
+
storefront(cookies())
|
|
527
|
+
|
|
528
|
+
// ✅ Root Layout exception
|
|
529
|
+
storefront({ isRootLayout: true })
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
2. **Missing Environment Variables**
|
|
533
|
+
```bash
|
|
534
|
+
# Ensure your .env.local has the required variables:
|
|
535
|
+
NEXT_PUBLIC_STORE_ID=your-store-id
|
|
536
|
+
NEXT_PUBLIC_API_KEY=your-api-key
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
3. **"Cookie store passed in client environment"**
|
|
540
|
+
```typescript
|
|
541
|
+
// ❌ Wrong - client component with cookies
|
|
542
|
+
storefront(cookies())
|
|
543
|
+
|
|
544
|
+
// ✅ Correct - client component without cookies
|
|
545
|
+
storefront()
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
4. **Server Actions and async cookies()**
|
|
549
|
+
```typescript
|
|
550
|
+
// ✅ Correct - Server Actions need await cookies()
|
|
551
|
+
const sdk = storefront(await cookies());
|
|
552
|
+
|
|
553
|
+
// ✅ Server Components and API Routes use cookies() directly
|
|
554
|
+
const sdk = storefront(cookies());
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Migration Guide
|
|
558
|
+
|
|
559
|
+
### From Core SDK
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
// Before (core SDK)
|
|
563
|
+
import { StorefrontSDK } from "@commercengine/storefront-sdk";
|
|
564
|
+
const sdk = new StorefrontSDK({
|
|
565
|
+
storeId: "...",
|
|
566
|
+
tokenStorage: new BrowserTokenStorage()
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// After (Next.js SDK)
|
|
570
|
+
import { storefront } from "@/lib/storefront";
|
|
571
|
+
const sdk = storefront(cookies());
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### From Previous SDK Versions
|
|
220
575
|
|
|
221
|
-
|
|
576
|
+
```typescript
|
|
577
|
+
// Before (old pattern)
|
|
578
|
+
import { getStorefrontSDK, storefront } from "@commercengine/storefront-sdk-nextjs";
|
|
579
|
+
const sdk = getStorefrontSDK(cookies());
|
|
580
|
+
const sdk2 = storefront(cookies(), { debug: true });
|
|
581
|
+
|
|
582
|
+
// After (createStorefront pattern)
|
|
583
|
+
import { storefront } from "@/lib/storefront"; // Your configured function
|
|
584
|
+
const sdk = storefront(cookies());
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Why This Pattern?
|
|
588
|
+
|
|
589
|
+
**The Perfect DX Pattern provides:**
|
|
590
|
+
- **One Config File**: All advanced configuration in `lib/storefront.ts`
|
|
591
|
+
- **Environment Variables**: Basic config (storeId, apiKey) via env vars
|
|
592
|
+
- **Universal Import**: Same `storefront()` import everywhere
|
|
593
|
+
- **Strict User Continuity**: Enforces cookie passing to protect user sessions and analytics
|
|
594
|
+
- **Explicit Exceptions**: Clear patterns for special cases like Root Layout
|
|
595
|
+
- **Zero Guesswork**: Helpful errors guide developers to correct patterns
|
|
596
|
+
|
|
597
|
+
**Result: Production-ready e-commerce with bulletproof user session management!** 🛡️
|
|
598
|
+
|
|
599
|
+
## API Reference
|
|
222
600
|
|
|
223
|
-
|
|
224
|
-
- Manual token storage setup
|
|
225
|
-
- Server/client environment handling
|
|
226
|
-
- Cookie configuration for SSR
|
|
227
|
-
- Token lifecycle management
|
|
601
|
+
For complete API documentation of all available endpoints, visit [docs.commercengine.io/api-reference](https://docs.commercengine.io/api-reference)
|
|
228
602
|
|
|
229
|
-
|
|
230
|
-
- Zero configuration token management
|
|
231
|
-
- Automatic environment detection
|
|
232
|
-
- Cookie-based persistence works out of the box
|
|
233
|
-
- One API that works everywhere
|
|
603
|
+
The Next.js SDK provides access to all the same endpoints as the core SDK:
|
|
234
604
|
|
|
235
|
-
|
|
605
|
+
- `sdk.auth.*` - Authentication and user management
|
|
606
|
+
- `sdk.customer.*` - Customer profiles and preferences
|
|
607
|
+
- `sdk.catalog.*` - Products, categories, and search
|
|
608
|
+
- `sdk.cart.*` - Shopping cart management
|
|
609
|
+
- `sdk.order.*` - Order creation and tracking
|
|
610
|
+
- `sdk.shipping.*` - Shipping methods and rates
|
|
611
|
+
- `sdk.helpers.*` - Countries, currencies, utilities
|
|
236
612
|
|
|
237
613
|
## License
|
|
238
614
|
|
|
239
|
-
All
|
|
615
|
+
All Rights Reserved
|