@commercengine/storefront-sdk-nextjs 0.3.0 → 0.4.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/MIGRATION.md CHANGED
@@ -1,89 +1,197 @@
1
1
  # Storefront SDK Next.js Migration Guide
2
2
 
3
- This guide covers the breaking API changes in
4
- `@commercengine/storefront-sdk-nextjs`.
3
+ This package is now a **frozen legacy wrapper**. The supported migration target
4
+ is:
5
5
 
6
- ## Summary
6
+ ```bash
7
+ pnpm add @commercengine/storefront
8
+ ```
9
+
10
+ Then move your Next.js imports to:
7
11
 
8
- - `storefront()` was replaced by explicit `storefront.public()` and
9
- `storefront.session(...)`
10
- - `isRootLayout` was removed
11
- - root layouts and public server reads now use `storefront.public()`
12
- - server-side session usage now always uses `storefront.session(await cookies())`
13
- - client-side session usage uses `storefront.session()`
12
+ ```typescript
13
+ import { Environment } from "@commercengine/storefront";
14
+ import {
15
+ createNextjsStorefront,
16
+ type NextjsStorefrontConfig,
17
+ } from "@commercengine/storefront/nextjs";
18
+ ```
19
+
20
+ ## What Changes
21
+
22
+ - package install changes from `@commercengine/storefront-sdk-nextjs` to
23
+ `@commercengine/storefront`
24
+ - `createStorefront(...)` becomes `createNextjsStorefront(...)`
25
+ - `storefront.public()` becomes `storefront.publicStorefront()`
26
+ - `storefront.session()` becomes `storefront.clientStorefront()` in browser code
27
+ - `storefront.session(await cookies())` becomes
28
+ `await storefront.serverStorefront()` in server code
29
+ - SDK-provided `StorefrontSDKInitializer` is no longer the primary path
30
+ - eager bootstrap moves to an explicit app-local client component that calls
31
+ `storefront.bootstrap()`
14
32
 
15
33
  ## Before / After
16
34
 
35
+ ### Package imports
36
+
37
+ Before:
38
+
39
+ ```typescript
40
+ import {
41
+ createStorefront,
42
+ type StorefrontRuntimeConfig,
43
+ } from "@commercengine/storefront-sdk-nextjs";
44
+ ```
45
+
46
+ After:
47
+
48
+ ```typescript
49
+ import { Environment } from "@commercengine/storefront";
50
+ import {
51
+ createNextjsStorefront,
52
+ type NextjsStorefrontConfig,
53
+ } from "@commercengine/storefront/nextjs";
54
+ ```
55
+
56
+ ### App config
57
+
58
+ Before:
59
+
60
+ ```typescript
61
+ import {
62
+ createStorefront,
63
+ type StorefrontRuntimeConfig,
64
+ } from "@commercengine/storefront-sdk-nextjs";
65
+
66
+ const storefrontConfig: StorefrontRuntimeConfig = {
67
+ debug: true,
68
+ timeout: 15000,
69
+ };
70
+
71
+ export const storefront = createStorefront(storefrontConfig);
72
+ ```
73
+
74
+ After:
75
+
76
+ ```typescript
77
+ import { Environment } from "@commercengine/storefront";
78
+ import {
79
+ createNextjsStorefront,
80
+ type NextjsStorefrontConfig,
81
+ } from "@commercengine/storefront/nextjs";
82
+
83
+ const storefrontConfig: NextjsStorefrontConfig = {
84
+ storeId: process.env.NEXT_PUBLIC_STORE_ID!,
85
+ apiKey: process.env.NEXT_PUBLIC_API_KEY!,
86
+ environment: Environment.Staging,
87
+ debug: true,
88
+ timeout: 15000,
89
+ };
90
+
91
+ export const storefront = createNextjsStorefront(storefrontConfig);
92
+ ```
93
+
17
94
  ### Public server reads
18
95
 
19
96
  Before:
20
97
 
21
98
  ```typescript
22
- const sdk = storefront({ isRootLayout: true });
99
+ const sdk = storefront.public();
23
100
  const { data } = await sdk.catalog.listProducts();
24
101
  ```
25
102
 
26
103
  After:
27
104
 
28
105
  ```typescript
29
- const sdk = storefront.public();
106
+ const sdk = storefront.publicStorefront();
30
107
  const { data } = await sdk.catalog.listProducts();
31
108
  ```
32
109
 
33
- ### Server components, server actions, and route handlers
110
+ ### Client session usage
34
111
 
35
112
  Before:
36
113
 
37
114
  ```typescript
38
- const sdk = storefront(await cookies());
115
+ const sdk = storefront.session();
39
116
  ```
40
117
 
41
118
  After:
42
119
 
43
120
  ```typescript
44
- const sdk = storefront.session(await cookies());
121
+ const sdk = storefront.clientStorefront();
45
122
  ```
46
123
 
47
- ### Client components
124
+ ### Server session usage
48
125
 
49
126
  Before:
50
127
 
51
128
  ```typescript
52
- const sdk = storefront();
129
+ import { cookies } from "next/headers";
130
+
131
+ const sdk = storefront.session(await cookies());
53
132
  ```
54
133
 
55
134
  After:
56
135
 
57
136
  ```typescript
58
- const sdk = storefront.session();
137
+ const sdk = await storefront.serverStorefront();
59
138
  ```
60
139
 
61
- ## New Mental Model
140
+ ## Bootstrap
62
141
 
63
- Use `storefront.public()` for:
142
+ The new wrapper does not require an SDK-provided initializer component, but the
143
+ recommended framework pattern is still to bootstrap eagerly in app code.
64
144
 
65
- - root layouts
66
- - static generation
67
- - ISR pages
68
- - public server-rendered catalog or helper reads
145
+ Why this matters:
69
146
 
70
- Use `storefront.session()` / `storefront.session(await cookies())` for:
147
+ - the browser can lazily bootstrap, but that is not the documented pattern
148
+ - server actions and route handlers can also establish a session
149
+ - but a cold Server Component request cannot be relied on to persist a newly
150
+ created anonymous session before later server reads depend on it
71
151
 
72
- - auth flows
73
- - cart reads and mutations
74
- - customer reads and mutations
75
- - order and payment flows
76
- - any request that should participate in anonymous or authenticated session
77
- continuity
152
+ Recommended bootstrap:
78
153
 
79
- ## Root Layouts
154
+ ```tsx
155
+ "use client";
80
156
 
81
- There is no special root-layout escape hatch anymore.
157
+ import { useEffect } from "react";
158
+ import { storefront } from "@/lib/storefront";
82
159
 
83
- Root layouts should:
160
+ export function StorefrontBootstrap() {
161
+ useEffect(() => {
162
+ storefront.bootstrap().catch(console.error);
163
+ }, []);
84
164
 
85
- - use `storefront.public()` for public reads
86
- - mount `StorefrontSDKInitializer` to eagerly bootstrap the browser session
165
+ return null;
166
+ }
167
+ ```
168
+
169
+ Mount this once near the root of your app.
170
+
171
+ ## Mental Model
172
+
173
+ Use:
174
+
175
+ - `storefront.publicStorefront()` for build-safe public reads
176
+ - `storefront.clientStorefront()` for browser session usage
177
+ - `await storefront.serverStorefront()` for server components, route handlers,
178
+ and server actions
179
+ - `storefront.bootstrap()` in a small app-local client component so session
180
+ continuity is established eagerly and explicitly
181
+
182
+ The new wrapper still keeps the SDK core separate:
183
+
184
+ - app/framework consumers use `@commercengine/storefront`
185
+ - low-level advanced/custom users can still use `@commercengine/storefront-sdk`
186
+
187
+ ## Advanced Token Storage
188
+
189
+ If you were manually wiring low-level server token storage before, prefer the
190
+ high-level server accessor now:
191
+
192
+ ```typescript
193
+ const sdk = await storefront.serverStorefront();
194
+ ```
87
195
 
88
- If a server component needs request-bound session continuity, move that call to a
89
- request-aware boundary and use `storefront.session(await cookies())`.
196
+ If you still need low-level storage wiring, use `@commercengine/ssr-utils`
197
+ directly rather than depending on this frozen package for new integrations.
package/README.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # CommerceEngine Next.js SDK
2
2
 
3
+ > **Deprecated** — This package is superseded by
4
+ > [`@commercengine/storefront/nextjs`](../storefront).
5
+ >
6
+ > This package is now on its **final legacy release line**. It is frozen for
7
+ > migration only and will not receive new DX or framework work.
8
+ >
9
+ > Migrate to `@commercengine/storefront/nextjs`, which provides the actively
10
+ > maintained Next.js API:
11
+ >
12
+ > - `storefront.publicStorefront()`
13
+ > - `storefront.clientStorefront()`
14
+ > - `await storefront.serverStorefront()`
15
+ > - explicit app-local `storefront.bootstrap()` for eager session priming
16
+ >
17
+ > ```bash
18
+ > pnpm add @commercengine/storefront
19
+ > ```
20
+ >
21
+ > See the [`@commercengine/storefront` README](../storefront/README.md) and
22
+ > [`MIGRATION.md`](./MIGRATION.md) for the direct migration path.
23
+
24
+ ---
25
+
26
+ _The legacy documentation below is preserved only for teams that are still
27
+ finishing migration from this frozen package._
28
+
29
+ ---
30
+
3
31
  Production-ready Next.js wrapper for the CommerceEngine Storefront SDK.
4
32
 
5
33
  Breaking changes from the previous wrapper API are documented in
@@ -12,8 +40,9 @@ explicit access patterns:
12
40
  - `storefront.session()` / `storefront.session(await cookies())` for live user
13
41
  session flows
14
42
 
15
- It builds on [`@commercengine/ssr-utils`](../ssr-utils) for cookie-backed server
16
- storage, but the primary DX is the Next.js-specific `createStorefront()` API.
43
+ It builds on [`@commercengine/ssr-utils`](../ssr-utils) and its `createSSRFactory`
44
+ for cookie-backed storage, singleton scoping, and bootstrap coordination. The
45
+ primary DX is the Next.js-specific `createStorefront()` API.
17
46
 
18
47
  ## Installation
19
48
 
@@ -52,6 +81,11 @@ export const storefront = createStorefront(storefrontConfig);
52
81
  export type { StorefrontRuntimeConfig };
53
82
  ```
54
83
 
84
+ `createStorefront()` stores the runtime config once for the app bundle and
85
+ resets cached `public()` / client-side `session()` SDK instances when that
86
+ config changes. In practice, define it once in `lib/storefront.ts` and reuse it
87
+ everywhere.
88
+
55
89
  ### 3. Initialize once in the root layout
56
90
 
57
91
  ```typescript
@@ -271,9 +305,15 @@ type NextJSStorefront = {
271
305
  (): SessionStorefrontSDK;
272
306
  (cookieStore: NextCookieStore): SessionStorefrontSDK;
273
307
  };
308
+ bootstrap: () => Promise<void>;
274
309
  };
275
310
  ```
276
311
 
312
+ `public()` returns the cached public SDK. `session()` returns the cached default
313
+ client-side session SDK, while `session(await cookies())` creates the
314
+ request-scoped server SDK for that request context. `bootstrap()` is a deduped
315
+ client-side convenience for eagerly establishing an anonymous session.
316
+
277
317
  ### `StorefrontRuntimeConfig`
278
318
 
279
319
  Optional configuration object for `createStorefront()`:
@@ -360,6 +400,29 @@ storefront.session(await cookies());
360
400
  storefront.public();
361
401
  ```
362
402
 
403
+ ### Advanced server token storage
404
+
405
+ For most apps, use `storefront.session(await cookies())` instead of manually
406
+ creating server token storage.
407
+
408
+ If you need the low-level path, `ServerTokenStorage` now expects a
409
+ `CookieAdapter`, not the raw Next.js `cookies()` store:
410
+
411
+ ```typescript
412
+ import {
413
+ ServerTokenStorage,
414
+ createCookieAdapter,
415
+ } from "@commercengine/storefront-sdk-nextjs/server";
416
+ import { cookies } from "next/headers";
417
+
418
+ const tokenStorage = new ServerTokenStorage(
419
+ createCookieAdapter(await cookies())
420
+ );
421
+ ```
422
+
423
+ `bootstrapStorefrontSDK` is a client-side helper and should be imported from
424
+ `@commercengine/storefront-sdk-nextjs/client`, not the `/server` entry.
425
+
363
426
  ### From direct core SDK usage
364
427
 
365
428
  ```typescript
package/dist/client.d.mts CHANGED
@@ -1,7 +1,26 @@
1
- import { a as initializeStorefrontSDK, i as getSessionStorefrontSDK, l as ClientTokenStorage, n as StorefrontRuntimeConfig, r as getPublicStorefrontSDK, t as NextJSSDKConfig, u as NextJSTokenStorageOptions } from "./manager.mjs";
1
+ import { a as getSessionStorefrontSDK, i as getPublicStorefrontSDK, n as StorefrontRuntimeConfig, o as initializeStorefrontSDK, r as bootstrapStorefrontSDK, t as NextJSSDKConfig } from "./manager.mjs";
2
2
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, SessionStorefrontSDKOptions, StoreConfigClient, TokenStorage } from "@commercengine/storefront-sdk";
3
+ import { ClientTokenStorage, SSRTokenStorageOptions as NextJSTokenStorageOptions } from "@commercengine/ssr-utils";
3
4
 
4
5
  //#region src/initializer.d.ts
6
+
7
+ /**
8
+ * Client-side initialization component
9
+ * Use this in your root layout to initialize the SDK once
10
+ *
11
+ * Configuration is handled via environment variables:
12
+ * - NEXT_PUBLIC_STORE_ID
13
+ * - NEXT_PUBLIC_API_KEY
14
+ * - NEXT_PUBLIC_ENVIRONMENT (optional, defaults to staging)
15
+ *
16
+ * The core SDK middleware automatically handles everything:
17
+ * - Creates anonymous tokens automatically on first API request (if no tokens exist)
18
+ * - Token state assessment and cleanup on first request per page load
19
+ * - Expired token refresh with automatic anonymous fallback
20
+ * - Graceful handling of partial token states
21
+ *
22
+ * No manual token creation needed - just make API calls and everything works!
23
+ */
5
24
  interface StorefrontSDKInitializerProps {
6
25
  /**
7
26
  * Optional runtime configuration overrides for client-side API calls
@@ -13,4 +32,4 @@ declare function StorefrontSDKInitializer({
13
32
  runtimeConfig
14
33
  }?: StorefrontSDKInitializerProps): null;
15
34
  //#endregion
16
- export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, ClientTokenStorage, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, type NextJSSDKConfig, type NextJSTokenStorageOptions, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, type SessionStorefrontSDKOptions, StoreConfigClient, StorefrontSDKInitializer, type TokenStorage, getPublicStorefrontSDK, getSessionStorefrontSDK, initializeStorefrontSDK };
35
+ export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, ClientTokenStorage, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, type NextJSSDKConfig, type NextJSTokenStorageOptions, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, type SessionStorefrontSDKOptions, StoreConfigClient, StorefrontSDKInitializer, type TokenStorage, bootstrapStorefrontSDK, getPublicStorefrontSDK, getSessionStorefrontSDK, initializeStorefrontSDK };
package/dist/client.mjs CHANGED
@@ -1,41 +1,19 @@
1
1
  "use client";
2
2
 
3
- import { i as setGlobalStorefrontConfig, n as getSessionStorefrontSDK, o as ClientTokenStorage, r as initializeStorefrontSDK, t as getPublicStorefrontSDK } from "./manager.mjs";
3
+ import { a as setGlobalStorefrontConfig, i as initializeStorefrontSDK, n as getPublicStorefrontSDK, r as getSessionStorefrontSDK, t as bootstrapStorefrontSDK } from "./manager.mjs";
4
4
  import { useEffect } from "react";
5
5
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient } from "@commercengine/storefront-sdk";
6
+ import { ClientTokenStorage } from "@commercengine/ssr-utils";
6
7
 
7
8
  //#region src/initializer.tsx
8
- /**
9
- * Client-side initialization component
10
- * Use this in your root layout to initialize the SDK once
11
- *
12
- * Configuration is handled via environment variables:
13
- * - NEXT_PUBLIC_STORE_ID
14
- * - NEXT_PUBLIC_API_KEY
15
- * - NEXT_PUBLIC_ENVIRONMENT (optional, defaults to staging)
16
- *
17
- * The core SDK middleware automatically handles everything:
18
- * - Creates anonymous tokens automatically on first API request (if no tokens exist)
19
- * - Token state assessment and cleanup on first request per page load
20
- * - Expired token refresh with automatic anonymous fallback
21
- * - Graceful handling of partial token states
22
- *
23
- * No manual token creation needed - just make API calls and everything works!
24
- */
25
- /**
26
- * Bootstrap the client-side session if no access token exists yet.
27
- */
28
- async function bootstrapSession() {
29
- await getSessionStorefrontSDK().ensureAccessToken();
30
- }
31
9
  function StorefrontSDKInitializer({ runtimeConfig } = {}) {
32
10
  useEffect(() => {
33
11
  if (runtimeConfig) setGlobalStorefrontConfig(runtimeConfig);
34
12
  else initializeStorefrontSDK();
35
- bootstrapSession().catch(console.error);
13
+ bootstrapStorefrontSDK().catch(console.error);
36
14
  }, [runtimeConfig]);
37
15
  return null;
38
16
  }
39
17
 
40
18
  //#endregion
41
- export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, ClientTokenStorage, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient, StorefrontSDKInitializer, getPublicStorefrontSDK, getSessionStorefrontSDK, initializeStorefrontSDK };
19
+ export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, ClientTokenStorage, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient, StorefrontSDKInitializer, bootstrapStorefrontSDK, getPublicStorefrontSDK, getSessionStorefrontSDK, initializeStorefrontSDK };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as StorefrontRuntimeConfig, o as NextCookieStore } from "./manager.mjs";
1
+ import { n as StorefrontRuntimeConfig, s as NextCookieStore } from "./manager.mjs";
2
2
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, PublicStorefrontSDK as PublicStorefrontSDK$1, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, SessionStorefrontSDK as SessionStorefrontSDK$1, StoreConfigClient } from "@commercengine/storefront-sdk";
3
3
  export * from "@commercengine/storefront-sdk";
4
4
 
@@ -11,6 +11,7 @@ export * from "@commercengine/storefront-sdk";
11
11
  * - `storefront.public()` for build/prerender-safe public reads
12
12
  * - `storefront.session()` in Client Components
13
13
  * - `storefront.session(cookies())` in server request contexts
14
+ * - `storefront.bootstrap()` in `StorefrontSDKInitializer` or custom client init
14
15
  */
15
16
  type NextJSStorefront = {
16
17
  public: () => PublicStorefrontSDK$1;
@@ -18,10 +19,15 @@ type NextJSStorefront = {
18
19
  (): SessionStorefrontSDK$1;
19
20
  (cookieStore: NextCookieStore): SessionStorefrontSDK$1;
20
21
  };
22
+ bootstrap: () => Promise<void>;
21
23
  };
22
24
  /**
23
25
  * Creates a configured storefront factory for Next.js.
24
26
  *
27
+ * The provided config is stored as the runtime default for this app instance.
28
+ * Updating that config resets the cached `public()` and client-side
29
+ * `session()` SDK singletons so future calls pick up the latest values.
30
+ *
25
31
  * Usage:
26
32
  * ```typescript
27
33
  * // lib/storefront.ts
package/dist/index.mjs CHANGED
@@ -1,10 +1,14 @@
1
- import { i as setGlobalStorefrontConfig, n as getSessionStorefrontSDK, t as getPublicStorefrontSDK } from "./manager.mjs";
1
+ import { a as setGlobalStorefrontConfig, n as getPublicStorefrontSDK, r as getSessionStorefrontSDK, t as bootstrapStorefrontSDK } from "./manager.mjs";
2
2
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient } from "@commercengine/storefront-sdk";
3
3
 
4
4
  //#region src/storefront.ts
5
5
  /**
6
6
  * Creates a configured storefront factory for Next.js.
7
7
  *
8
+ * The provided config is stored as the runtime default for this app instance.
9
+ * Updating that config resets the cached `public()` and client-side
10
+ * `session()` SDK singletons so future calls pick up the latest values.
11
+ *
8
12
  * Usage:
9
13
  * ```typescript
10
14
  * // lib/storefront.ts
@@ -26,7 +30,8 @@ function createStorefront(config) {
26
30
  }
27
31
  return {
28
32
  public: () => getPublicStorefrontSDK(),
29
- session
33
+ session,
34
+ bootstrap: () => bootstrapStorefrontSDK()
30
35
  };
31
36
  }
32
37
 
@@ -1,49 +1,13 @@
1
- import { DebugLoggerFn, Environment, PublicStorefrontSDK, SessionStorefrontSDK, SessionStorefrontSDKOptions, SupportedDefaultHeaders, TokenStorage } from "@commercengine/storefront-sdk";
2
- import { SSRTokenStorageOptions, ServerTokenStorage } from "@commercengine/ssr-utils";
1
+ import { DebugLoggerFn, Environment, PublicStorefrontSDK, SessionStorefrontSDK, SessionStorefrontSDKOptions, SupportedDefaultHeaders } from "@commercengine/storefront-sdk";
2
+ import { SSRTokenStorageOptions, SSRTokenStorageOptions as NextJSTokenStorageOptions$1, ServerTokenStorage } from "@commercengine/ssr-utils";
3
3
 
4
- //#region src/client-storage.d.ts
4
+ //#region src/server-storage.d.ts
5
5
 
6
6
  /**
7
- * Configuration options for NextJS token storage
8
- * Re-exported from ssr-utils for convenience
9
- */
10
- type NextJSTokenStorageOptions$1 = SSRTokenStorageOptions;
11
- /**
12
- * Client-side token storage that uses document.cookie
13
- *
14
- * This is Next.js specific because it needs to work with the same cookie
15
- * format as the server-side storage for seamless SSR/client hydration.
7
+ * Type for Next.js cookies (from next/headers).
16
8
  *
17
- * @example
18
- * ```typescript
19
- * import { ClientTokenStorage } from '@commercengine/storefront-sdk-nextjs/client';
20
- *
21
- * const storage = new ClientTokenStorage();
22
- * ```
23
- */
24
- declare class ClientTokenStorage implements TokenStorage {
25
- private accessTokenKey;
26
- private refreshTokenKey;
27
- private options;
28
- constructor(options?: NextJSTokenStorageOptions$1);
29
- getAccessToken(): Promise<string | null>;
30
- setAccessToken(token: string): Promise<void>;
31
- getRefreshToken(): Promise<string | null>;
32
- setRefreshToken(token: string): Promise<void>;
33
- clearTokens(): Promise<void>;
34
- private getCookie;
35
- private setCookie;
36
- private deleteCookie;
37
- }
38
- //#endregion
39
- //#region src/server-storage.d.ts
40
- /**
41
- * Configuration options for NextJS token storage
42
- * Re-exported from ssr-utils for convenience
43
- */
44
- type NextJSTokenStorageOptions = SSRTokenStorageOptions;
45
- /**
46
- * Type for Next.js cookies (from next/headers)
9
+ * This type remains local to the Next.js package so the `session(cookies())`
10
+ * overload stays framework-native.
47
11
  */
48
12
  type NextCookieStore = {
49
13
  get: (name: string) => {
@@ -52,22 +16,6 @@ type NextCookieStore = {
52
16
  set: (name: string, value: string, options?: Record<string, unknown>) => void;
53
17
  delete: (name: string) => void;
54
18
  };
55
- /**
56
- * Server-side token storage for Next.js using the cookies() API
57
- *
58
- * This wraps the ssr-utils ServerTokenStorage with a Next.js-specific adapter.
59
- *
60
- * @example
61
- * ```typescript
62
- * import { cookies } from 'next/headers';
63
- * import { ServerTokenStorage } from '@commercengine/storefront-sdk-nextjs/server';
64
- *
65
- * const storage = new ServerTokenStorage(cookies());
66
- * ```
67
- */
68
- declare class ServerTokenStorage$1 extends ServerTokenStorage {
69
- constructor(cookieStore: NextCookieStore, options?: NextJSTokenStorageOptions);
70
- }
71
19
  //#endregion
72
20
  //#region src/manager.d.ts
73
21
  /**
@@ -77,8 +25,12 @@ interface NextJSSDKConfig extends Omit<SessionStorefrontSDKOptions, "tokenStorag
77
25
  /**
78
26
  * Token storage configuration options
79
27
  */
80
- tokenStorageOptions?: NextJSTokenStorageOptions$1;
28
+ tokenStorageOptions?: NextJSTokenStorageOptions;
81
29
  }
30
+ /**
31
+ * Token storage options re-exported from ssr-utils
32
+ */
33
+ type NextJSTokenStorageOptions = SSRTokenStorageOptions;
82
34
  /**
83
35
  * Runtime configuration overrides that can be passed to `createStorefront()`
84
36
  * These override environment variables for that specific app instance.
@@ -105,7 +57,7 @@ interface StorefrontRuntimeConfig {
105
57
  /**
106
58
  * Token storage configuration
107
59
  */
108
- tokenStorageOptions?: NextJSTokenStorageOptions$1;
60
+ tokenStorageOptions?: NextJSTokenStorageOptions;
109
61
  }
110
62
  /**
111
63
  * Get or create the public SDK singleton.
@@ -123,9 +75,15 @@ declare function getPublicStorefrontSDK(): PublicStorefrontSDK;
123
75
  */
124
76
  declare function getSessionStorefrontSDK(): SessionStorefrontSDK;
125
77
  declare function getSessionStorefrontSDK(cookieStore: NextCookieStore): SessionStorefrontSDK;
78
+ /**
79
+ * Bootstrap the client-side session.
80
+ *
81
+ * Delegates to the SSR factory's deduped bootstrap. No-op on the server.
82
+ */
83
+ declare function bootstrapStorefrontSDK(): Promise<void>;
126
84
  /**
127
85
  * Reset instantiated SDK singletons so they pick up current configuration.
128
86
  */
129
87
  declare function initializeStorefrontSDK(): void;
130
88
  //#endregion
131
- export { initializeStorefrontSDK as a, ServerTokenStorage$1 as c, getSessionStorefrontSDK as i, ClientTokenStorage as l, StorefrontRuntimeConfig as n, NextCookieStore as o, getPublicStorefrontSDK as r, NextJSTokenStorageOptions as s, NextJSSDKConfig as t, NextJSTokenStorageOptions$1 as u };
89
+ export { getSessionStorefrontSDK as a, NextJSTokenStorageOptions$1 as c, getPublicStorefrontSDK as i, ServerTokenStorage as l, StorefrontRuntimeConfig as n, initializeStorefrontSDK as o, bootstrapStorefrontSDK as r, NextCookieStore as s, NextJSSDKConfig as t };
package/dist/manager.mjs CHANGED
@@ -1,126 +1,17 @@
1
1
  import { cache } from "react";
2
2
  import { Environment, PublicStorefrontSDK, SessionStorefrontSDK } from "@commercengine/storefront-sdk";
3
- import { ServerTokenStorage } from "@commercengine/ssr-utils";
3
+ import { createSSRFactory } from "@commercengine/ssr-utils";
4
4
 
5
- //#region src/client-storage.ts
6
- /**
7
- * Client-side token storage that uses document.cookie
8
- *
9
- * This is Next.js specific because it needs to work with the same cookie
10
- * format as the server-side storage for seamless SSR/client hydration.
11
- *
12
- * @example
13
- * ```typescript
14
- * import { ClientTokenStorage } from '@commercengine/storefront-sdk-nextjs/client';
15
- *
16
- * const storage = new ClientTokenStorage();
17
- * ```
18
- */
19
- var ClientTokenStorage = class {
20
- accessTokenKey;
21
- refreshTokenKey;
22
- options;
23
- constructor(options = {}) {
24
- const prefix = options.prefix || "ce_";
25
- this.accessTokenKey = `${prefix}access_token`;
26
- this.refreshTokenKey = `${prefix}refresh_token`;
27
- const normalizedSameSite = options.sameSite ? {
28
- strict: "Strict",
29
- lax: "Lax",
30
- none: "None"
31
- }[options.sameSite] : "Lax";
32
- this.options = {
33
- maxAge: options.maxAge || 720 * 60 * 60,
34
- path: options.path || "/",
35
- domain: options.domain,
36
- secure: options.secure ?? (typeof window !== "undefined" && window.location?.protocol === "https:"),
37
- sameSite: normalizedSameSite
38
- };
39
- }
40
- async getAccessToken() {
41
- return this.getCookie(this.accessTokenKey);
42
- }
43
- async setAccessToken(token) {
44
- this.setCookie(this.accessTokenKey, token);
45
- }
46
- async getRefreshToken() {
47
- return this.getCookie(this.refreshTokenKey);
48
- }
49
- async setRefreshToken(token) {
50
- this.setCookie(this.refreshTokenKey, token);
51
- }
52
- async clearTokens() {
53
- this.deleteCookie(this.accessTokenKey);
54
- this.deleteCookie(this.refreshTokenKey);
55
- }
56
- getCookie(name) {
57
- if (typeof document === "undefined") return null;
58
- const parts = `; ${document.cookie}`.split(`; ${name}=`);
59
- if (parts.length === 2) {
60
- const cookieValue = parts.pop()?.split(";").shift();
61
- return cookieValue ? decodeURIComponent(cookieValue) : null;
62
- }
63
- return null;
64
- }
65
- setCookie(name, value) {
66
- if (typeof document === "undefined") return;
67
- let cookieString = `${name}=${encodeURIComponent(value)}`;
68
- if (this.options.maxAge) cookieString += `; Max-Age=${this.options.maxAge}`;
69
- if (this.options.path) cookieString += `; Path=${this.options.path}`;
70
- if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
71
- if (this.options.secure) cookieString += `; Secure`;
72
- if (this.options.sameSite) cookieString += `; SameSite=${this.options.sameSite}`;
73
- document.cookie = cookieString;
74
- }
75
- deleteCookie(name) {
76
- if (typeof document === "undefined") return;
77
- let cookieString = `${name}=; Max-Age=0`;
78
- if (this.options.path) cookieString += `; Path=${this.options.path}`;
79
- if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
80
- document.cookie = cookieString;
81
- }
82
- };
83
-
84
- //#endregion
85
- //#region src/server-storage.ts
86
- /**
87
- * Server-side token storage for Next.js using the cookies() API
88
- *
89
- * This wraps the ssr-utils ServerTokenStorage with a Next.js-specific adapter.
90
- *
91
- * @example
92
- * ```typescript
93
- * import { cookies } from 'next/headers';
94
- * import { ServerTokenStorage } from '@commercengine/storefront-sdk-nextjs/server';
95
- *
96
- * const storage = new ServerTokenStorage(cookies());
97
- * ```
98
- */
99
- var ServerTokenStorage$1 = class extends ServerTokenStorage {
100
- constructor(cookieStore, options = {}) {
101
- super({
102
- get: (name) => cookieStore.get(name)?.value ?? null,
103
- set: (name, value, opts) => cookieStore.set(name, value, opts),
104
- delete: (name) => cookieStore.delete(name)
105
- }, options);
106
- }
107
- };
108
-
109
- //#endregion
110
5
  //#region src/manager.ts
111
6
  /**
112
- * Global runtime configuration storage
7
+ * Global runtime configuration storage.
113
8
  * This gets bundled into both client and server bundles.
114
9
  */
115
10
  let globalStorefrontConfig = null;
116
11
  /**
117
- * Client-side session SDK singleton (only lives in browser)
118
- */
119
- let clientSessionSDK = null;
120
- /**
121
- * Public SDK singleton shared by non-session reads
12
+ * Cached SSR factory invalidated when global config changes.
122
13
  */
123
- let publicSDK = null;
14
+ let ssrFactory = null;
124
15
  /**
125
16
  * Get configuration from environment variables merged with global config.
126
17
  * Precedence order: environment variables < global config
@@ -187,23 +78,45 @@ function buildPublicSDKConfig(config) {
187
78
  if (config.defaultHeaders) publicConfig.defaultHeaders = config.defaultHeaders;
188
79
  return publicConfig;
189
80
  }
190
- function createClientSessionSDK(config) {
191
- return new SessionStorefrontSDK({
192
- ...config,
193
- tokenStorage: new ClientTokenStorage(config.tokenStorageOptions)
194
- });
195
- }
196
- function createServerSessionSDK(cookieStore, config) {
197
- return new SessionStorefrontSDK({
198
- ...config,
199
- tokenStorage: new ServerTokenStorage$1(cookieStore, config.tokenStorageOptions)
200
- });
81
+ /**
82
+ * Get or create the SSR factory.
83
+ *
84
+ * The factory is lazily created on first access and invalidated when
85
+ * global config changes via {@link setGlobalStorefrontConfig} or
86
+ * {@link initializeStorefrontSDK}.
87
+ */
88
+ function getFactory() {
89
+ if (!ssrFactory) {
90
+ const config = getConfig();
91
+ ssrFactory = createSSRFactory({
92
+ createPublicSDK: () => new PublicStorefrontSDK(buildPublicSDKConfig(config)),
93
+ createClientSessionSDK: (tokenStorage) => new SessionStorefrontSDK({
94
+ ...config,
95
+ tokenStorage
96
+ }),
97
+ createServerSessionSDK: (_cookieStore, tokenStorage) => new SessionStorefrontSDK({
98
+ ...config,
99
+ tokenStorage
100
+ }),
101
+ createServerCookieAdapter: (cookieStore) => ({
102
+ get: (name) => cookieStore.get(name)?.value ?? null,
103
+ set: (name, value, opts) => cookieStore.set(name, value, opts),
104
+ delete: (name) => cookieStore.delete(name)
105
+ }),
106
+ bootstrapSession: (sdk) => sdk.ensureAccessToken().then(() => {}),
107
+ tokenStorageOptions: config.tokenStorageOptions
108
+ });
109
+ }
110
+ return ssrFactory;
201
111
  }
202
112
  /**
203
- * Request-scoped server session SDK factory using React cache
113
+ * Request-scoped server session SDK using React cache for dedup.
114
+ *
115
+ * React `cache()` deduplicates calls with the same `cookieStore` reference
116
+ * within a single server request, avoiding redundant SDK instantiation.
204
117
  */
205
118
  const getServerSessionSDKCached = cache((cookieStore) => {
206
- return createServerSessionSDK(cookieStore, getConfig());
119
+ return getFactory().session(cookieStore);
207
120
  });
208
121
  /**
209
122
  * Get or create the public SDK singleton.
@@ -212,48 +125,40 @@ const getServerSessionSDKCached = cache((cookieStore) => {
212
125
  * participate in session bootstrap, refresh, or storage writes.
213
126
  */
214
127
  function getPublicStorefrontSDK() {
215
- const config = getConfig();
216
- if (!publicSDK) publicSDK = new PublicStorefrontSDK(buildPublicSDKConfig(config));
217
- return publicSDK;
128
+ return getFactory().public();
218
129
  }
219
130
  function getSessionStorefrontSDK(cookieStore) {
220
131
  if (typeof window !== "undefined") {
221
132
  if (cookieStore) console.warn("Cookie store passed in client environment - this will be ignored");
222
- const config = getConfig();
223
- if (!clientSessionSDK) clientSessionSDK = createClientSessionSDK(config);
224
- return clientSessionSDK;
133
+ return getFactory().session();
225
134
  }
226
135
  if (cookieStore) return getServerSessionSDKCached(cookieStore);
227
- throw new Error([
228
- "🚨 Server session access requires cookies!",
229
- "",
230
- "You're calling the session SDK on the server without cookies.",
231
- "",
232
- "✅ Correct usage for user/session-aware requests:",
233
- " import { cookies } from 'next/headers'",
234
- " const sdk = storefront.session(cookies())",
235
- "",
236
- "✅ Correct usage for build/prerender-safe public reads:",
237
- " const sdk = storefront.public()",
238
- "",
239
- "This keeps public rendering separate from real user session continuity."
240
- ].join("\n"));
136
+ return getFactory().session();
137
+ }
138
+ /**
139
+ * Bootstrap the client-side session.
140
+ *
141
+ * Delegates to the SSR factory's deduped bootstrap. No-op on the server.
142
+ */
143
+ function bootstrapStorefrontSDK() {
144
+ return getFactory().bootstrap();
241
145
  }
242
146
  /**
243
147
  * Set global storefront configuration that applies to all SDK instances.
148
+ *
149
+ * Resetting the cached factory here keeps `createStorefront(config)`
150
+ * deterministic even though runtime config is stored globally for the bundle.
244
151
  */
245
152
  function setGlobalStorefrontConfig(config) {
246
153
  globalStorefrontConfig = config;
247
- clientSessionSDK = null;
248
- publicSDK = null;
154
+ ssrFactory = null;
249
155
  }
250
156
  /**
251
157
  * Reset instantiated SDK singletons so they pick up current configuration.
252
158
  */
253
159
  function initializeStorefrontSDK() {
254
- clientSessionSDK = null;
255
- publicSDK = null;
160
+ ssrFactory = null;
256
161
  }
257
162
 
258
163
  //#endregion
259
- export { ServerTokenStorage$1 as a, setGlobalStorefrontConfig as i, getSessionStorefrontSDK as n, ClientTokenStorage as o, initializeStorefrontSDK as r, getPublicStorefrontSDK as t };
164
+ export { setGlobalStorefrontConfig as a, initializeStorefrontSDK as i, getPublicStorefrontSDK as n, getSessionStorefrontSDK as r, bootstrapStorefrontSDK as t };
package/dist/server.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as initializeStorefrontSDK, c as ServerTokenStorage, i as getSessionStorefrontSDK, r as getPublicStorefrontSDK, s as NextJSTokenStorageOptions, t as NextJSSDKConfig } from "./manager.mjs";
1
+ import { a as getSessionStorefrontSDK, c as NextJSTokenStorageOptions, i as getPublicStorefrontSDK, l as ServerTokenStorage, o as initializeStorefrontSDK, t as NextJSSDKConfig } from "./manager.mjs";
2
2
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient } from "@commercengine/storefront-sdk";
3
3
  export * from "@commercengine/storefront-sdk";
4
4
  export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, type NextJSSDKConfig, type NextJSTokenStorageOptions, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, ServerTokenStorage, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient, getPublicStorefrontSDK, getSessionStorefrontSDK, initializeStorefrontSDK };
package/dist/server.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { a as ServerTokenStorage, n as getSessionStorefrontSDK, r as initializeStorefrontSDK, t as getPublicStorefrontSDK } from "./manager.mjs";
1
+ import { i as initializeStorefrontSDK, n as getPublicStorefrontSDK, r as getSessionStorefrontSDK } from "./manager.mjs";
2
2
  import { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient } from "@commercengine/storefront-sdk";
3
+ import { ServerTokenStorage } from "@commercengine/ssr-utils";
3
4
 
4
5
  export * from "@commercengine/storefront-sdk"
5
6
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@commercengine/storefront-sdk-nextjs",
3
- "version": "0.3.0",
4
- "description": "Next.js wrapper for the Commerce Engine Storefront SDK",
3
+ "version": "0.4.0",
4
+ "description": "Legacy frozen Next.js wrapper for the Commerce Engine Storefront SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
7
7
  "types": "dist/index.d.mts",
@@ -34,7 +34,9 @@
34
34
  "api",
35
35
  "sdk",
36
36
  "nextjs",
37
- "react"
37
+ "react",
38
+ "legacy",
39
+ "deprecated"
38
40
  ],
39
41
  "author": "Commerce Engine",
40
42
  "license": "All rights reserved",
@@ -44,8 +46,8 @@
44
46
  "react-dom": ">=19.0.0"
45
47
  },
46
48
  "dependencies": {
47
- "@commercengine/storefront-sdk": "0.14.0",
48
- "@commercengine/ssr-utils": "0.2.0"
49
+ "@commercengine/storefront-sdk": "0.14.2",
50
+ "@commercengine/ssr-utils": "0.3.0"
49
51
  },
50
52
  "devDependencies": {
51
53
  "@types/node": "^24.10.4",