@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/dist/index.cjs CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,28 +15,17 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
31
21
  var index_exports = {};
32
22
  __export(index_exports, {
33
- ClientTokenStorage: () => ClientTokenStorage,
34
- Environment: () => import_storefront_sdk2.Environment,
35
- ServerTokenStorage: () => ServerTokenStorage,
36
- StorefrontSDKInitializer: () => StorefrontSDKInitializer,
37
- getStorefrontSDK: () => getStorefrontSDK
23
+ createStorefront: () => createStorefront
38
24
  });
39
25
  module.exports = __toCommonJS(index_exports);
40
26
 
41
27
  // src/sdk-manager.ts
28
+ var import_react = require("react");
42
29
  var import_storefront_sdk = require("@commercengine/storefront-sdk");
43
30
 
44
31
  // src/token-storage.ts
@@ -147,7 +134,7 @@ var ServerTokenStorage = class {
147
134
  secure: this.options.secure,
148
135
  sameSite: this.options.sameSite?.toLowerCase(),
149
136
  httpOnly: false
150
- // Must be false for client-side access
137
+ // Allow client-side access for SDK flexibility
151
138
  });
152
139
  } catch (error) {
153
140
  console.warn(`Could not set access token on server:`, error);
@@ -170,7 +157,7 @@ var ServerTokenStorage = class {
170
157
  secure: this.options.secure,
171
158
  sameSite: this.options.sameSite?.toLowerCase(),
172
159
  httpOnly: false
173
- // Must be false for client-side access
160
+ // Allow client-side access for SDK flexibility
174
161
  });
175
162
  } catch (error) {
176
163
  console.warn(`Could not set refresh token on server:`, error);
@@ -186,152 +173,254 @@ var ServerTokenStorage = class {
186
173
  }
187
174
  };
188
175
 
189
- // src/sdk-manager.ts
190
- var NextJSSDKManager = class _NextJSSDKManager {
191
- constructor() {
192
- this.clientSDK = null;
193
- this.config = null;
194
- }
195
- static getInstance() {
196
- if (!_NextJSSDKManager.instance) {
197
- _NextJSSDKManager.instance = new _NextJSSDKManager();
198
- }
199
- return _NextJSSDKManager.instance;
200
- }
201
- /**
202
- * Initialize the SDK with configuration (should be called once)
203
- */
204
- initialize(config) {
205
- this.config = config;
206
- if (typeof window !== "undefined" && !this.clientSDK) {
207
- this.clientSDK = this.createClientSDK();
208
- }
176
+ // src/build-token-cache.ts
177
+ var store = /* @__PURE__ */ new Map();
178
+ function isExpired(token) {
179
+ if (!token) return true;
180
+ if (!token.expiresAt) return false;
181
+ return Date.now() > token.expiresAt - 3e4;
182
+ }
183
+ function getCachedToken(key) {
184
+ const token = store.get(key);
185
+ return isExpired(token) ? null : token;
186
+ }
187
+ function setCachedToken(key, token) {
188
+ const expiresAt = token.ttlSeconds != null ? Date.now() + token.ttlSeconds * 1e3 : void 0;
189
+ store.set(key, {
190
+ accessToken: token.accessToken,
191
+ refreshToken: token.refreshToken ?? null,
192
+ expiresAt
193
+ });
194
+ }
195
+ function clearCachedToken(key) {
196
+ store.delete(key);
197
+ }
198
+
199
+ // src/build-caching-memory-storage.ts
200
+ var DEFAULT_TTL_SECONDS = 5 * 60;
201
+ var BuildCachingMemoryTokenStorage = class {
202
+ constructor(cacheKey, ttlSeconds = DEFAULT_TTL_SECONDS) {
203
+ this.cacheKey = cacheKey;
204
+ this.ttlSeconds = ttlSeconds;
205
+ this.access = null;
206
+ this.refresh = null;
209
207
  }
210
- /**
211
- * Get SDK instance for client-side usage
212
- */
213
- getClientSDK() {
214
- if (!this.config) {
215
- throw new Error("SDK not initialized. Call initialize() first.");
216
- }
217
- if (!this.clientSDK) {
218
- this.clientSDK = this.createClientSDK();
208
+ async getAccessToken() {
209
+ if (this.access) {
210
+ return this.access;
219
211
  }
220
- return this.clientSDK;
221
- }
222
- /**
223
- * Get SDK instance for server-side usage
224
- */
225
- getServerSDK(cookieStore) {
226
- if (!this.config) {
227
- throw new Error("SDK not initialized. Call initialize() first.");
212
+ const cached = getCachedToken(this.cacheKey);
213
+ if (cached?.accessToken) {
214
+ this.access = cached.accessToken;
215
+ this.refresh = cached.refreshToken ?? null;
216
+ return this.access;
228
217
  }
229
- return new import_storefront_sdk.StorefrontSDK({
230
- ...this.config,
231
- tokenStorage: new ServerTokenStorage(
232
- cookieStore,
233
- this.config.tokenStorageOptions
234
- )
235
- });
218
+ return null;
236
219
  }
237
- createClientSDK() {
238
- if (!this.config) {
239
- throw new Error("SDK not initialized. Call initialize() first.");
240
- }
241
- return new import_storefront_sdk.StorefrontSDK({
242
- ...this.config,
243
- tokenStorage: new ClientTokenStorage(this.config.tokenStorageOptions)
220
+ async setAccessToken(token) {
221
+ this.access = token;
222
+ setCachedToken(this.cacheKey, {
223
+ accessToken: token,
224
+ refreshToken: this.refresh,
225
+ ttlSeconds: this.ttlSeconds
244
226
  });
245
227
  }
246
- /**
247
- * Check if SDK is initialized
248
- */
249
- isInitialized() {
250
- return this.config !== null;
228
+ async getRefreshToken() {
229
+ return this.refresh;
230
+ }
231
+ async setRefreshToken(token) {
232
+ this.refresh = token;
233
+ setCachedToken(this.cacheKey, {
234
+ accessToken: this.access ?? "",
235
+ refreshToken: token,
236
+ ttlSeconds: this.ttlSeconds
237
+ });
251
238
  }
252
- /**
253
- * Reset the SDK (useful for testing)
254
- */
255
- reset() {
256
- this.clientSDK = null;
257
- this.config = null;
239
+ async clearTokens() {
240
+ this.access = null;
241
+ this.refresh = null;
242
+ clearCachedToken(this.cacheKey);
258
243
  }
259
244
  };
245
+
246
+ // src/sdk-manager.ts
247
+ function getConfig() {
248
+ const envStoreId = process.env.NEXT_PUBLIC_STORE_ID;
249
+ const envApiKey = process.env.NEXT_PUBLIC_API_KEY;
250
+ const envEnvironment = process.env.NEXT_PUBLIC_ENVIRONMENT;
251
+ const envBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
252
+ const envTimeout = process.env.NEXT_PUBLIC_API_TIMEOUT ? parseInt(process.env.NEXT_PUBLIC_API_TIMEOUT, 10) : void 0;
253
+ const envDebug = process.env.NEXT_PUBLIC_DEBUG_MODE === "true";
254
+ const envDefaultHeaders = {};
255
+ if (process.env.NEXT_PUBLIC_DEFAULT_CUSTOMER_GROUP_ID) {
256
+ envDefaultHeaders.customer_group_id = process.env.NEXT_PUBLIC_DEFAULT_CUSTOMER_GROUP_ID;
257
+ }
258
+ const storeId = globalStorefrontConfig?.storeId || envStoreId;
259
+ const apiKey = globalStorefrontConfig?.apiKey || envApiKey;
260
+ const environment = globalStorefrontConfig?.environment || (envEnvironment === "production" ? import_storefront_sdk.Environment.Production : import_storefront_sdk.Environment.Staging);
261
+ const baseUrl = globalStorefrontConfig?.baseUrl || envBaseUrl;
262
+ const timeout = globalStorefrontConfig?.timeout || envTimeout;
263
+ const debug = globalStorefrontConfig?.debug !== void 0 ? globalStorefrontConfig.debug : envDebug;
264
+ const defaultHeaders = {
265
+ ...envDefaultHeaders,
266
+ ...globalStorefrontConfig?.defaultHeaders
267
+ };
268
+ if (!storeId || !apiKey) {
269
+ throw new Error(
270
+ `StorefrontSDK configuration missing! Please set the following environment variables:
271
+
272
+ NEXT_PUBLIC_STORE_ID=your-store-id
273
+ NEXT_PUBLIC_API_KEY=your-api-key
274
+ NEXT_PUBLIC_ENVIRONMENT=staging (or production)
275
+
276
+ These variables are required for both client and server contexts to work.`
277
+ );
278
+ }
279
+ const config = {
280
+ storeId,
281
+ apiKey,
282
+ environment
283
+ };
284
+ if (baseUrl) config.baseUrl = baseUrl;
285
+ if (timeout) config.timeout = timeout;
286
+ if (debug) config.debug = debug;
287
+ const logger = globalStorefrontConfig?.logger;
288
+ const accessToken = globalStorefrontConfig?.accessToken;
289
+ const refreshToken = globalStorefrontConfig?.refreshToken;
290
+ const onTokensUpdated = globalStorefrontConfig?.onTokensUpdated;
291
+ const onTokensCleared = globalStorefrontConfig?.onTokensCleared;
292
+ const tokenStorageOptions = globalStorefrontConfig?.tokenStorageOptions;
293
+ if (logger) config.logger = logger;
294
+ if (accessToken) config.accessToken = accessToken;
295
+ if (refreshToken) config.refreshToken = refreshToken;
296
+ if (onTokensUpdated) config.onTokensUpdated = onTokensUpdated;
297
+ if (onTokensCleared) config.onTokensCleared = onTokensCleared;
298
+ if (Object.keys(defaultHeaders).length > 0) config.defaultHeaders = defaultHeaders;
299
+ if (tokenStorageOptions) config.tokenStorageOptions = tokenStorageOptions;
300
+ return config;
301
+ }
302
+ var globalStorefrontConfig = null;
303
+ var clientSDK = null;
304
+ function createTokenStorage(cookieStore, options, config) {
305
+ if (typeof window !== "undefined") {
306
+ return new ClientTokenStorage(options);
307
+ }
308
+ if (cookieStore) {
309
+ return new ServerTokenStorage(cookieStore, options);
310
+ }
311
+ const shouldCache = process.env.NEXT_BUILD_CACHE_TOKENS === "true";
312
+ if (shouldCache && config) {
313
+ const cacheKey = `${config.storeId}:${config.environment || "production"}`;
314
+ return new BuildCachingMemoryTokenStorage(cacheKey);
315
+ }
316
+ return new import_storefront_sdk.MemoryTokenStorage();
317
+ }
318
+ var getServerSDKCached = (0, import_react.cache)((cookieStore) => {
319
+ const config = getConfig();
320
+ return new import_storefront_sdk.StorefrontSDK({
321
+ ...config,
322
+ tokenStorage: createTokenStorage(
323
+ cookieStore,
324
+ config.tokenStorageOptions,
325
+ config
326
+ )
327
+ });
328
+ });
329
+ var buildTimeSDK = null;
330
+ function getBuildTimeSDK() {
331
+ const config = getConfig();
332
+ if (!buildTimeSDK) {
333
+ buildTimeSDK = new import_storefront_sdk.StorefrontSDK({
334
+ ...config,
335
+ tokenStorage: createTokenStorage(
336
+ void 0,
337
+ config.tokenStorageOptions,
338
+ config
339
+ )
340
+ });
341
+ }
342
+ return buildTimeSDK;
343
+ }
260
344
  function getStorefrontSDK(cookieStore) {
261
- const manager = NextJSSDKManager.getInstance();
262
345
  if (typeof window !== "undefined") {
263
346
  if (cookieStore) {
264
347
  console.warn(
265
348
  "Cookie store passed in client environment - this will be ignored"
266
349
  );
267
350
  }
268
- return manager.getClientSDK();
351
+ const config = getConfig();
352
+ if (!clientSDK) {
353
+ clientSDK = new import_storefront_sdk.StorefrontSDK({
354
+ ...config,
355
+ tokenStorage: createTokenStorage(
356
+ void 0,
357
+ config.tokenStorageOptions,
358
+ config
359
+ )
360
+ });
361
+ }
362
+ return clientSDK;
269
363
  }
270
- if (!cookieStore) {
271
- let autoDetectMessage = "";
272
- try {
273
- require.resolve("next/headers");
274
- autoDetectMessage = `
275
-
276
- \u{1F50D} Auto-detection attempted but failed. You may be in:
277
- - Server Action (use: const sdk = getStorefrontSDK(await cookies()))
278
- - API Route (use: const sdk = getStorefrontSDK(cookies()))
279
- - Middleware (token access limited)
280
- `;
281
- } catch {
282
- autoDetectMessage = `
364
+ if (cookieStore) {
365
+ return getServerSDKCached(cookieStore);
366
+ }
367
+ return getBuildTimeSDK();
368
+ }
369
+ function setGlobalStorefrontConfig(config) {
370
+ globalStorefrontConfig = config;
371
+ clientSDK = null;
372
+ buildTimeSDK = null;
373
+ }
283
374
 
284
- \u{1F4A1} Make sure you have Next.js installed and are in a server context.
285
- `;
375
+ // src/create-storefront.ts
376
+ function createStorefront(config) {
377
+ if (config) {
378
+ setGlobalStorefrontConfig(config);
379
+ }
380
+ function storefront(cookieStoreOrOptions, options) {
381
+ if (typeof window !== "undefined") {
382
+ return getStorefrontSDK();
383
+ }
384
+ let cookieStore;
385
+ let isRootLayout = false;
386
+ if (cookieStoreOrOptions) {
387
+ if ("isRootLayout" in cookieStoreOrOptions) {
388
+ isRootLayout = cookieStoreOrOptions.isRootLayout;
389
+ } else {
390
+ cookieStore = cookieStoreOrOptions;
391
+ isRootLayout = options?.isRootLayout || false;
392
+ }
393
+ }
394
+ if (cookieStore) {
395
+ return getStorefrontSDK(cookieStore);
396
+ }
397
+ if (process.env.NEXT_IS_BUILD === "true" || process.env.NEXT_BUILD_CACHE_TOKENS === "true") {
398
+ return getStorefrontSDK();
399
+ }
400
+ if (isRootLayout) {
401
+ return getStorefrontSDK();
286
402
  }
287
403
  throw new Error(
288
- `
289
- \u{1F6A8} Server Environment Detected!
290
-
291
- You're calling getStorefrontSDK() on the server without cookies.
292
- Please pass the Next.js cookie store:
293
-
294
- \u2705 Correct usage:
295
- import { cookies } from 'next/headers';
296
-
297
- // Server Actions & Route Handlers
298
- const sdk = getStorefrontSDK(await cookies());
299
-
300
- // API Routes (Next.js 12)
301
- const sdk = getStorefrontSDK(cookies());
302
-
303
- \u274C Your current usage:
304
- const sdk = getStorefrontSDK(); // Missing cookies!
305
- ${autoDetectMessage}
306
- This is required for server-side token access.
307
- `.trim()
404
+ [
405
+ "\u{1F6A8} Server context requires cookies for user continuity!",
406
+ "",
407
+ "You're calling storefront() on the server without cookies.",
408
+ "This breaks user session continuity and analytics tracking.",
409
+ "",
410
+ "\u2705 Correct usage:",
411
+ " import { cookies } from 'next/headers'",
412
+ " const sdk = storefront(cookies())",
413
+ "",
414
+ "\u{1F4CD} Root Layout exception:",
415
+ " const sdk = storefront({ isRootLayout: true })",
416
+ "",
417
+ "This is required to maintain consistent user identity across requests."
418
+ ].join("\n")
308
419
  );
309
420
  }
310
- return manager.getServerSDK(cookieStore);
311
- }
312
- function initializeStorefrontSDK(config) {
313
- const manager = NextJSSDKManager.getInstance();
314
- manager.initialize(config);
315
- }
316
-
317
- // src/init-client.ts
318
- var import_react = require("react");
319
- function StorefrontSDKInitializer({
320
- config
321
- }) {
322
- (0, import_react.useEffect)(() => {
323
- initializeStorefrontSDK(config);
324
- }, [config]);
325
- return null;
421
+ return storefront;
326
422
  }
327
-
328
- // src/index.ts
329
- var import_storefront_sdk2 = require("@commercengine/storefront-sdk");
330
423
  // Annotate the CommonJS export names for ESM import in node:
331
424
  0 && (module.exports = {
332
- ClientTokenStorage,
333
- Environment,
334
- ServerTokenStorage,
335
- StorefrontSDKInitializer,
336
- getStorefrontSDK
425
+ createStorefront
337
426
  });
package/dist/index.d.cts CHANGED
@@ -1,116 +1,41 @@
1
- import { TokenStorage, StorefrontSDK, StorefrontSDKOptions } from '@commercengine/storefront-sdk';
2
- export { Environment, StorefrontSDK, StorefrontSDKOptions } from '@commercengine/storefront-sdk';
1
+ import { StorefrontSDK } from '@commercengine/storefront-sdk';
2
+ export { StorefrontSDK } from '@commercengine/storefront-sdk';
3
+ import { S as StorefrontRuntimeConfig } from './server-CwxgXezP.cjs';
3
4
 
4
- /**
5
- * Configuration options for NextJSTokenStorage
6
- */
7
- interface NextJSTokenStorageOptions {
8
- /**
9
- * Prefix for cookie names (default: "ce_")
10
- */
11
- prefix?: string;
12
- /**
13
- * Maximum age of cookies in seconds (default: 30 days)
14
- */
15
- maxAge?: number;
16
- /**
17
- * Cookie path (default: "/")
18
- */
19
- path?: string;
20
- /**
21
- * Cookie domain (default: current domain)
22
- */
23
- domain?: string;
24
- /**
25
- * Whether cookies should be secure (default: auto-detect based on environment)
26
- */
27
- secure?: boolean;
28
- /**
29
- * SameSite cookie attribute (default: "Lax")
30
- */
31
- sameSite?: "Strict" | "Lax" | "None";
32
- }
33
- /**
34
- * Client-side token storage that uses document.cookie
35
- */
36
- declare class ClientTokenStorage implements TokenStorage {
37
- private accessTokenKey;
38
- private refreshTokenKey;
39
- private options;
40
- constructor(options?: NextJSTokenStorageOptions);
41
- getAccessToken(): Promise<string | null>;
42
- setAccessToken(token: string): Promise<void>;
43
- getRefreshToken(): Promise<string | null>;
44
- setRefreshToken(token: string): Promise<void>;
45
- clearTokens(): Promise<void>;
46
- private getCookie;
47
- private setCookie;
48
- private deleteCookie;
49
- }
50
- type NextCookieStore$1 = {
51
- get: (name: string) => {
52
- value: string;
53
- } | undefined;
54
- set: (name: string, value: string, options?: any) => void;
55
- delete: (name: string) => void;
56
- };
57
- /**
58
- * Server-side token storage that uses Next.js cookies API
59
- */
60
- declare class ServerTokenStorage implements TokenStorage {
61
- private accessTokenKey;
62
- private refreshTokenKey;
63
- private options;
64
- private cookieStore;
65
- constructor(cookieStore: NextCookieStore$1, options?: NextJSTokenStorageOptions);
66
- getAccessToken(): Promise<string | null>;
67
- setAccessToken(token: string): Promise<void>;
68
- getRefreshToken(): Promise<string | null>;
69
- setRefreshToken(token: string): Promise<void>;
70
- clearTokens(): Promise<void>;
71
- }
72
-
73
- /**
74
- * Configuration for the NextJS SDK wrapper
75
- */
76
- interface NextJSSDKConfig extends Omit<StorefrontSDKOptions, "tokenStorage"> {
77
- /**
78
- * Token storage configuration options
79
- */
80
- tokenStorageOptions?: NextJSTokenStorageOptions;
81
- }
82
5
  type NextCookieStore = {
83
6
  get: (name: string) => {
7
+ name: string;
84
8
  value: string;
85
9
  } | undefined;
86
- set: (name: string, value: string, options?: any) => void;
10
+ set: (name: string, value: string, opts?: Record<string, unknown>) => void;
87
11
  delete: (name: string) => void;
88
12
  };
89
13
  /**
90
- * Smart SDK getter that automatically detects environment
14
+ * Creates a configured storefront function that works universally across all Next.js contexts
91
15
  *
92
16
  * Usage:
93
- * - Client-side: getStorefrontSDK()
94
- * - Server-side: getStorefrontSDK(await cookies())
95
- */
96
- declare function getStorefrontSDK(): StorefrontSDK;
97
- declare function getStorefrontSDK(cookieStore: NextCookieStore): StorefrontSDK;
98
-
99
- interface StorefrontSDKInitializerProps {
100
- config: NextJSSDKConfig;
101
- }
102
- /**
103
- * Client-side initialization component
104
- * Use this in your root layout to initialize the SDK once
17
+ * ```typescript
18
+ * // lib/storefront.ts
19
+ * import { createStorefront } from "@commercengine/storefront-sdk-nextjs";
105
20
  *
106
- * The core SDK middleware now automatically handles everything:
107
- * - Creates anonymous tokens automatically on first API request (if no tokens exist)
108
- * - Token state assessment and cleanup on first request per page load
109
- * - Expired token refresh with automatic anonymous fallback
110
- * - Graceful handling of partial token states
21
+ * export const storefront = createStorefront({
22
+ * debug: true,
23
+ * logger: (msg, ...args) => console.log('[DEBUG]', msg, ...args)
24
+ * });
25
+ * ```
111
26
  *
112
- * No manual token creation needed - just make API calls and everything works!
27
+ * @param config Optional configuration for advanced options (defaults to empty if not provided)
28
+ * @returns A storefront function that works in all Next.js contexts
113
29
  */
114
- declare function StorefrontSDKInitializer({ config, }: StorefrontSDKInitializerProps): null;
30
+ declare function createStorefront(config?: StorefrontRuntimeConfig): {
31
+ (): StorefrontSDK;
32
+ (cookieStore: NextCookieStore): StorefrontSDK;
33
+ (options: {
34
+ isRootLayout: true;
35
+ }): StorefrontSDK;
36
+ (cookieStore: NextCookieStore, options: {
37
+ isRootLayout?: boolean;
38
+ }): StorefrontSDK;
39
+ };
115
40
 
116
- export { ClientTokenStorage, type NextJSSDKConfig, type NextJSTokenStorageOptions, ServerTokenStorage, StorefrontSDKInitializer, getStorefrontSDK };
41
+ export { StorefrontRuntimeConfig, createStorefront };