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