@commercengine/pos 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import "openapi-fetch";
1
2
  import { ApiResult, BaseAPIClient, BaseSDKOptions, DebugLoggerFn, ResponseUtils } from "@commercengine/sdk-core";
2
3
 
3
4
  //#region src/types/pos.d.ts
package/dist/index.js CHANGED
@@ -1,6 +1,418 @@
1
- import { BaseAPIClient, ResponseUtils, getPathnameFromUrl } from "@commercengine/sdk-core";
1
+ import createClient from "openapi-fetch";
2
2
  import { decodeJwt } from "jose";
3
3
 
4
+ //#region ../sdk-core/dist/index.js
5
+ /**
6
+ * Response utilities for debugging and working with Response objects
7
+ */
8
+ var ResponseUtils = class {
9
+ /**
10
+ * Get response headers as a plain object
11
+ */
12
+ static getHeaders(response) {
13
+ return Object.fromEntries(response.headers.entries());
14
+ }
15
+ /**
16
+ * Get specific header value
17
+ */
18
+ static getHeader(response, name) {
19
+ return response.headers.get(name);
20
+ }
21
+ /**
22
+ * Check if response was successful
23
+ */
24
+ static isSuccess(response) {
25
+ return response.ok;
26
+ }
27
+ /**
28
+ * Get response metadata
29
+ */
30
+ static getMetadata(response) {
31
+ return {
32
+ status: response.status,
33
+ statusText: response.statusText,
34
+ ok: response.ok,
35
+ url: response.url,
36
+ redirected: response.redirected,
37
+ type: response.type,
38
+ headers: Object.fromEntries(response.headers.entries())
39
+ };
40
+ }
41
+ /**
42
+ * Clone and read response as text (useful for debugging)
43
+ * Note: This can only be called once per response
44
+ */
45
+ static async getText(response) {
46
+ const cloned = response.clone();
47
+ return await cloned.text();
48
+ }
49
+ /**
50
+ * Clone and read response as JSON (useful for debugging)
51
+ * Note: This can only be called once per response
52
+ */
53
+ static async getJSON(response) {
54
+ const cloned = response.clone();
55
+ return await cloned.json();
56
+ }
57
+ /**
58
+ * Format response information for debugging
59
+ */
60
+ static format(response) {
61
+ const metadata = this.getMetadata(response);
62
+ return `${metadata.status} ${metadata.statusText} - ${metadata.url}`;
63
+ }
64
+ /**
65
+ * Format response for logging purposes (enhanced version)
66
+ */
67
+ static formatResponse(response) {
68
+ return {
69
+ status: response.status,
70
+ statusText: response.statusText,
71
+ url: response.url,
72
+ ok: response.ok
73
+ };
74
+ }
75
+ };
76
+ /**
77
+ * Debug logging utilities
78
+ */
79
+ var DebugLogger = class {
80
+ logger;
81
+ responseTextCache = /* @__PURE__ */ new Map();
82
+ constructor(logger) {
83
+ this.logger = logger || ((level, message, data) => {
84
+ console.log(`[${level.toUpperCase()}]`, message);
85
+ if (data) console.log(data);
86
+ });
87
+ }
88
+ /**
89
+ * Log debug information about API request
90
+ */
91
+ logRequest(request, requestBody) {
92
+ this.logger("info", "API Request Debug Info", {
93
+ method: request.method,
94
+ url: request.url,
95
+ headers: Object.fromEntries(request.headers.entries()),
96
+ body: requestBody,
97
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
98
+ });
99
+ }
100
+ /**
101
+ * Log debug information about API response
102
+ */
103
+ async logResponse(response, responseBody) {
104
+ if (responseBody && typeof responseBody === "string") this.responseTextCache.set(response.url, responseBody);
105
+ this.logger("info", "API Response Debug Info", {
106
+ url: response.url,
107
+ status: response.status,
108
+ statusText: response.statusText,
109
+ ok: response.ok,
110
+ headers: Object.fromEntries(response.headers.entries()),
111
+ redirected: response.redirected,
112
+ type: response.type,
113
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
114
+ });
115
+ if (responseBody) this.logger("info", "API Response Data", {
116
+ data: responseBody,
117
+ contentType: response.headers.get("content-type"),
118
+ contentLength: response.headers.get("content-length")
119
+ });
120
+ }
121
+ /**
122
+ * Log error information
123
+ */
124
+ logError(message, error) {
125
+ this.logger("error", message, error);
126
+ }
127
+ /**
128
+ * Get cached response text for a URL (if available)
129
+ */
130
+ getCachedResponseText(url) {
131
+ return this.responseTextCache.get(url) || null;
132
+ }
133
+ /**
134
+ * Clear cached response texts
135
+ */
136
+ clearCache() {
137
+ this.responseTextCache.clear();
138
+ }
139
+ info(message, data) {
140
+ this.logger("info", message, data);
141
+ }
142
+ warn(message, data) {
143
+ this.logger("warn", message, data);
144
+ }
145
+ error(message, data) {
146
+ this.logger("error", message, data);
147
+ }
148
+ };
149
+ /**
150
+ * Extract request body for logging
151
+ */
152
+ async function extractRequestBody(request) {
153
+ if (request.method === "GET" || request.method === "HEAD") return null;
154
+ try {
155
+ const clonedRequest = request.clone();
156
+ const contentType = request.headers.get("content-type")?.toLowerCase();
157
+ if (contentType?.startsWith("application/json")) return await clonedRequest.json();
158
+ else if (contentType?.startsWith("multipart/form-data")) return "[FormData - cannot display]";
159
+ else if (contentType?.startsWith("text/")) return await clonedRequest.text();
160
+ return "[Request body - unknown format]";
161
+ } catch (error) {
162
+ return "[Request body unavailable]";
163
+ }
164
+ }
165
+ /**
166
+ * Create debug middleware for openapi-fetch (internal use)
167
+ * Enhanced version that combines original functionality with duration tracking
168
+ */
169
+ function createDebugMiddleware(logger) {
170
+ const debugLogger = new DebugLogger(logger);
171
+ return {
172
+ async onRequest({ request }) {
173
+ request.__debugStartTime = Date.now();
174
+ const requestBody = await extractRequestBody(request);
175
+ debugLogger.logRequest(request, requestBody);
176
+ return request;
177
+ },
178
+ async onResponse({ request, response }) {
179
+ const startTime = request.__debugStartTime;
180
+ const duration = startTime ? Date.now() - startTime : 0;
181
+ const cloned = response.clone();
182
+ let responseBody = null;
183
+ try {
184
+ const contentType = response.headers.get("content-type")?.toLowerCase();
185
+ if (contentType?.startsWith("application/json")) responseBody = await cloned.json();
186
+ else if (contentType?.startsWith("text/")) responseBody = await cloned.text();
187
+ } catch (error) {}
188
+ await debugLogger.logResponse(response, responseBody);
189
+ if (duration > 0) debugLogger.info(`Request completed in ${duration}ms`, {
190
+ url: request.url,
191
+ method: request.method
192
+ });
193
+ return response;
194
+ },
195
+ async onError({ error, request }) {
196
+ debugLogger.logError("API Request Failed", {
197
+ error: {
198
+ name: error instanceof Error ? error.name : "Unknown",
199
+ message: error instanceof Error ? error.message : String(error),
200
+ stack: error instanceof Error ? error.stack : void 0
201
+ },
202
+ request: {
203
+ method: request.method,
204
+ url: request.url,
205
+ headers: Object.fromEntries(request.headers.entries())
206
+ },
207
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
208
+ });
209
+ throw error;
210
+ }
211
+ };
212
+ }
213
+ /**
214
+ * Timeout middleware for Commerce Engine SDKs
215
+ */
216
+ /**
217
+ * Create timeout middleware for openapi-fetch
218
+ * Adds configurable request timeout functionality
219
+ *
220
+ * @param timeoutMs - Timeout duration in milliseconds
221
+ * @returns Middleware object with onRequest handler
222
+ */
223
+ function createTimeoutMiddleware(timeoutMs) {
224
+ return { onRequest: async ({ request }) => {
225
+ const controller = new AbortController();
226
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
227
+ if (request.signal) request.signal.addEventListener("abort", () => controller.abort());
228
+ const newRequest = new Request(request, { signal: controller.signal });
229
+ controller.signal.addEventListener("abort", () => clearTimeout(timeoutId));
230
+ return newRequest;
231
+ } };
232
+ }
233
+ /**
234
+ * Transform headers using a transformation mapping
235
+ * Headers not in the transformation map are passed through unchanged
236
+ *
237
+ * @param headers - Headers object with original names
238
+ * @param transformations - Mapping of original names to transformed names
239
+ * @returns Headers object with transformed names
240
+ */
241
+ function transformHeaders(headers, transformations) {
242
+ const transformed = {};
243
+ for (const [key, value] of Object.entries(headers)) if (value !== void 0) {
244
+ const headerName = transformations[key] || key;
245
+ transformed[headerName] = value;
246
+ }
247
+ return transformed;
248
+ }
249
+ /**
250
+ * Merge headers with transformation support
251
+ * Transforms default headers, then merges with method headers
252
+ *
253
+ * @param defaultHeaders - Default headers from SDK configuration
254
+ * @param methodHeaders - Headers passed to the specific method call
255
+ * @param transformations - Mapping for header name transformations
256
+ * @returns Merged headers object with transformations applied
257
+ */
258
+ function mergeAndTransformHeaders(defaultHeaders, methodHeaders, transformations) {
259
+ const merged = {};
260
+ if (defaultHeaders && transformations) {
261
+ const transformedDefaults = transformHeaders(defaultHeaders, transformations);
262
+ Object.assign(merged, transformedDefaults);
263
+ } else if (defaultHeaders) Object.assign(merged, defaultHeaders);
264
+ if (methodHeaders) Object.assign(merged, methodHeaders);
265
+ Object.keys(merged).forEach((key) => {
266
+ if (merged[key] === void 0) delete merged[key];
267
+ });
268
+ return merged;
269
+ }
270
+ /**
271
+ * Execute a request and handle the response consistently
272
+ * This provides unified error handling and response processing across all SDKs
273
+ *
274
+ * @param apiCall - Function that executes the API request
275
+ * @returns Promise with the API response in standardized format
276
+ */
277
+ async function executeRequest(apiCall) {
278
+ try {
279
+ const { data, error, response } = await apiCall();
280
+ if (error) return {
281
+ data: null,
282
+ error,
283
+ response
284
+ };
285
+ if (data && data.content !== void 0) return {
286
+ data: data.content,
287
+ error: null,
288
+ response
289
+ };
290
+ return {
291
+ data,
292
+ error: null,
293
+ response
294
+ };
295
+ } catch (err) {
296
+ const mockResponse = new Response(null, {
297
+ status: 0,
298
+ statusText: "Network Error"
299
+ });
300
+ const errorResult = {
301
+ data: null,
302
+ error: {
303
+ success: false,
304
+ code: "NETWORK_ERROR",
305
+ message: "Network error occurred",
306
+ error: err
307
+ },
308
+ response: mockResponse
309
+ };
310
+ return errorResult;
311
+ }
312
+ }
313
+ /**
314
+ * Generic base API client that all Commerce Engine SDKs can extend
315
+ * Handles common functionality like middleware setup, request execution, and header management
316
+ * Does NOT include token management - that's SDK-specific
317
+ *
318
+ * @template TPaths - OpenAPI paths type
319
+ * @template THeaders - Supported default headers type
320
+ */
321
+ var BaseAPIClient = class {
322
+ client;
323
+ config;
324
+ baseUrl;
325
+ headerTransformations;
326
+ /**
327
+ * Create a new BaseAPIClient
328
+ *
329
+ * @param config - Configuration for the API client
330
+ * @param baseUrl - The base URL for the API (must be provided by subclass)
331
+ * @param headerTransformations - Header name transformations for this SDK
332
+ */
333
+ constructor(config, baseUrl, headerTransformations = {}) {
334
+ this.config = { ...config };
335
+ this.headerTransformations = headerTransformations;
336
+ this.baseUrl = baseUrl;
337
+ this.client = createClient({ baseUrl: this.baseUrl });
338
+ this.setupMiddleware();
339
+ }
340
+ /**
341
+ * Set up all middleware for the client
342
+ */
343
+ setupMiddleware() {
344
+ if (this.config.timeout) {
345
+ const timeoutMiddleware = createTimeoutMiddleware(this.config.timeout);
346
+ this.client.use(timeoutMiddleware);
347
+ }
348
+ if (this.config.debug) {
349
+ const debugMiddleware = createDebugMiddleware(this.config.logger);
350
+ this.client.use(debugMiddleware);
351
+ }
352
+ }
353
+ /**
354
+ * Get the base URL of the API
355
+ *
356
+ * @returns The base URL of the API
357
+ */
358
+ getBaseUrl() {
359
+ return this.baseUrl;
360
+ }
361
+ /**
362
+ * Execute a request and handle the response consistently
363
+ * This provides unified error handling and response processing
364
+ *
365
+ * @param apiCall - Function that executes the API request
366
+ * @returns Promise with the API response in standardized format
367
+ */
368
+ async executeRequest(apiCall) {
369
+ return executeRequest(apiCall);
370
+ }
371
+ /**
372
+ * Merge default headers with method-level headers
373
+ * Method-level headers take precedence over default headers
374
+ * Automatically applies SDK-specific header transformations
375
+ *
376
+ * @param methodHeaders - Headers passed to the specific method call
377
+ * @returns Merged headers object with proper HTTP header names
378
+ */
379
+ mergeHeaders(methodHeaders) {
380
+ return mergeAndTransformHeaders(this.config.defaultHeaders, methodHeaders, this.headerTransformations);
381
+ }
382
+ /**
383
+ * Set default headers for the client
384
+ *
385
+ * @param headers - Default headers to set
386
+ */
387
+ setDefaultHeaders(headers) {
388
+ this.config.defaultHeaders = headers;
389
+ }
390
+ /**
391
+ * Get current default headers
392
+ *
393
+ * @returns Current default headers
394
+ */
395
+ getDefaultHeaders() {
396
+ return this.config.defaultHeaders;
397
+ }
398
+ };
399
+ /**
400
+ * Generic URL utility functions for any SDK
401
+ */
402
+ /**
403
+ * Extract pathname from URL
404
+ * Useful for middleware that needs to inspect request paths
405
+ */
406
+ function getPathnameFromUrl(url) {
407
+ try {
408
+ const urlObj = new URL(url);
409
+ return urlObj.pathname;
410
+ } catch {
411
+ return url.split("?")[0] || url;
412
+ }
413
+ }
414
+
415
+ //#endregion
4
416
  //#region src/lib/utils/jwt.ts
5
417
  /**
6
418
  * Decode and extract user information from a JWT token
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["refreshPromise: Promise<void> | null","newTokens: { access_token: string; refresh_token: string }","errors: string[]","config: PosSDKOptions"],"sources":["../src/lib/utils/jwt.ts","../src/lib/utils/auth.ts","../src/lib/middleware/auth.ts","../src/lib/utils/url.ts","../src/lib/client.ts","../src/lib/pos.ts","../src/index.ts"],"sourcesContent":["import { decodeJwt } from \"jose\";\n\n/**\n * JWT payload structure for POS tokens\n */\nexport interface JwtPayload {\n token_type: string;\n exp: number;\n iat: number;\n jti: string;\n ulid: string;\n username: string;\n email: string;\n phone: string;\n first_name: string;\n last_name: string;\n store_id: string;\n is_logged_in: boolean;\n customer_id: string | null;\n customer_group_id: string | null;\n device: {\n device_id: string;\n device_name: string;\n };\n location: {\n id: string;\n name: string;\n };\n role: {\n id: string;\n name: string;\n };\n tenant_id: string;\n channel: {\n id: string;\n name: string;\n type: string;\n };\n sid: string;\n}\n\n/**\n * User information extracted from POS JWT token\n */\nexport interface UserInfo {\n id: string;\n username: string;\n email: string;\n phone: string;\n firstName: string;\n lastName: string;\n storeId: string;\n isLoggedIn: boolean;\n customerId: string | null;\n customerGroupId: string | null;\n device: {\n deviceId: string;\n deviceName: string;\n };\n location: {\n id: string;\n name: string;\n };\n role: {\n id: string;\n name: string;\n };\n tenantId: string;\n channel: {\n id: string;\n name: string;\n type: string;\n };\n sessionId: string;\n tokenExpiry: Date;\n tokenIssuedAt: Date;\n}\n\n/**\n * Decode and extract user information from a JWT token\n *\n * @param token - The JWT token to decode\n * @returns User information or null if token is invalid\n */\nexport function extractUserInfoFromToken(token: string): UserInfo | null {\n try {\n const payload = decodeJwt(token) as JwtPayload;\n\n return {\n id: payload.ulid,\n username: payload.username,\n email: payload.email,\n phone: payload.phone,\n firstName: payload.first_name,\n lastName: payload.last_name,\n storeId: payload.store_id,\n isLoggedIn: payload.is_logged_in,\n customerId: payload.customer_id,\n customerGroupId: payload.customer_group_id,\n device: {\n deviceId: payload.device.device_id,\n deviceName: payload.device.device_name,\n },\n location: {\n id: payload.location.id,\n name: payload.location.name,\n },\n role: {\n id: payload.role.id,\n name: payload.role.name,\n },\n tenantId: payload.tenant_id,\n channel: {\n id: payload.channel.id,\n name: payload.channel.name,\n type: payload.channel.type,\n },\n sessionId: payload.sid,\n tokenExpiry: new Date(payload.exp * 1000),\n tokenIssuedAt: new Date(payload.iat * 1000),\n };\n } catch (error) {\n console.warn(\"Failed to decode JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Check if a JWT token is expired\n *\n * @param token - The JWT token to check\n * @param bufferSeconds - Buffer time in seconds (default: 30)\n * @returns True if token is expired or will expire within buffer time\n */\nexport function isTokenExpired(\n token: string,\n bufferSeconds: number = 30\n): boolean {\n try {\n const payload = decodeJwt(token);\n if (!payload.exp) return true;\n\n const currentTime = Math.floor(Date.now() / 1000);\n const expiryTime = payload.exp;\n\n // Consider token expired if it expires within the buffer time\n return currentTime >= expiryTime - bufferSeconds;\n } catch (error) {\n console.warn(\"Failed to decode JWT token:\", error);\n return true; // Treat invalid tokens as expired\n }\n}\n\n/**\n * Get the user ID from a JWT token\n *\n * @param token - The JWT token\n * @returns User ID (ulid) or null if token is invalid\n */\nexport function getUserIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.id || null;\n}\n\n/**\n * Check if user is logged in based on JWT token\n *\n * @param token - The JWT token\n * @returns True if user is logged in, false otherwise\n */\nexport function isUserLoggedIn(token: string): boolean {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.isLoggedIn || false;\n}\n\n/**\n * Check if user is authenticated (has valid POS token)\n * Checks the token for isLoggedIn status\n *\n * @param token - The JWT token\n * @returns True if user is authenticated with valid POS access\n */\nexport function isUserAuthenticated(token: string): boolean {\n const userInfo = extractUserInfoFromToken(token);\n return !!userInfo?.isLoggedIn;\n}\n\n/**\n * Get the device ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Device ID or null if token is invalid\n */\nexport function getDeviceIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.device?.deviceId || null;\n}\n\n/**\n * Get the location ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Location ID or null if token is invalid\n */\nexport function getLocationIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.location?.id || null;\n}\n\n/**\n * Get the role information from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Role object with id and name, or null if token is invalid\n */\nexport function getRoleFromToken(\n token: string\n): { id: string; name: string } | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.role || null;\n}\n\n/**\n * Get the tenant ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Tenant ID or null if token is invalid\n */\nexport function getTenantIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.tenantId || null;\n}\n\n/**\n * Get the channel information from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Channel object with id and name, or null if token is invalid\n */\nexport function getChannelFromToken(\n token: string\n): { id: string; name: string } | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.channel || null;\n}\n\n/**\n * Get the session ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Session ID or null if token is invalid\n */\nexport function getSessionIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.sessionId || null;\n}\n","/**\n * Check if a URL path is a POS login endpoint that should use API key\n * Based on POS spec, only these 5 endpoints use X-Api-Key:\n * - /pos/auth/login/email\n * - /pos/auth/login/phone\n * - /pos/auth/login/whatsapp\n * - /pos/auth/pair-device\n * - /pos/auth/verify-otp\n */\nexport function isApiKeyEndpoint(pathname: string): boolean {\n const apiKeyEndpoints = [\n \"/pos/auth/login/email\",\n \"/pos/auth/login/phone\",\n \"/pos/auth/login/whatsapp\",\n \"/pos/auth/pair-device\",\n \"/pos/auth/verify-otp\",\n ];\n return apiKeyEndpoints.some((endpoint) => pathname.includes(endpoint));\n}\n\n/**\n * Check if a URL path is a POS endpoint that returns tokens\n * Based on POS spec, only these endpoints return tokens:\n * - /pos/auth/verify-otp (after OTP verification)\n * - /pos/auth/refresh-token\n */\nexport function isTokenReturningEndpoint(pathname: string): boolean {\n const tokenEndpoints = [\"/pos/auth/verify-otp\", \"/pos/auth/refresh-token\"];\n return tokenEndpoints.some((endpoint) => pathname.includes(endpoint));\n}\n\n/**\n * Check if a URL path is a POS logout endpoint\n */\nexport function isLogoutEndpoint(pathname: string): boolean {\n return (\n pathname.includes(\"/pos/auth/logout\") || pathname.includes(\"/pos/logout\")\n );\n}\n\n// Re-export JWT utilities from jwt.ts\nexport {\n isTokenExpired,\n extractUserInfoFromToken,\n getUserIdFromToken,\n isUserLoggedIn,\n isUserAuthenticated,\n getDeviceIdFromToken,\n getLocationIdFromToken,\n getRoleFromToken,\n getTenantIdFromToken,\n} from \"./jwt\";\nexport type { UserInfo, JwtPayload } from \"./jwt\";\n","import type { Middleware } from \"openapi-fetch\";\nimport { getPathnameFromUrl } from \"@commercengine/sdk-core\";\nimport {\n isApiKeyEndpoint,\n isTokenReturningEndpoint,\n isLogoutEndpoint,\n isTokenExpired,\n} from \"../utils/auth\";\n\n/**\n * Token storage interface for the POS auth middleware\n */\nexport interface TokenStorage {\n getAccessToken(): Promise<string | null>;\n setAccessToken(token: string): Promise<void>;\n getRefreshToken(): Promise<string | null>;\n setRefreshToken(token: string): Promise<void>;\n clearTokens(): Promise<void>;\n}\n\n/**\n * Simple in-memory token storage implementation\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private accessToken: string | null = null;\n private refreshToken: string | null = null;\n\n async getAccessToken(): Promise<string | null> {\n return this.accessToken;\n }\n\n async setAccessToken(token: string): Promise<void> {\n this.accessToken = token;\n }\n\n async getRefreshToken(): Promise<string | null> {\n return this.refreshToken;\n }\n\n async setRefreshToken(token: string): Promise<void> {\n this.refreshToken = token;\n }\n\n async clearTokens(): Promise<void> {\n this.accessToken = null;\n this.refreshToken = null;\n }\n}\n\n/**\n * Browser localStorage token storage implementation for POS\n */\nexport class BrowserTokenStorage implements TokenStorage {\n private accessTokenKey: string;\n private refreshTokenKey: string;\n\n constructor(prefix: string = \"pos_\") {\n this.accessTokenKey = `${prefix}access_token`;\n this.refreshTokenKey = `${prefix}refresh_token`;\n }\n\n async getAccessToken(): Promise<string | null> {\n if (typeof localStorage === \"undefined\") return null;\n return localStorage.getItem(this.accessTokenKey);\n }\n\n async setAccessToken(token: string): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(this.accessTokenKey, token);\n }\n }\n\n async getRefreshToken(): Promise<string | null> {\n if (typeof localStorage === \"undefined\") return null;\n return localStorage.getItem(this.refreshTokenKey);\n }\n\n async setRefreshToken(token: string): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(this.refreshTokenKey, token);\n }\n }\n\n async clearTokens(): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.removeItem(this.accessTokenKey);\n localStorage.removeItem(this.refreshTokenKey);\n }\n }\n}\n\n/**\n * Configuration for the POS auth middleware\n */\nexport interface PosAuthMiddlewareConfig {\n /**\n * Token storage implementation\n */\n tokenStorage: TokenStorage;\n\n /**\n * API key for X-Api-Key endpoints (login, pair-device, verify-otp)\n * Required for POS authentication flows and fallback scenarios\n */\n apiKey: string;\n\n /**\n * Base URL for the API (used for refresh token endpoint)\n */\n baseUrl: string;\n\n /**\n * Function to refresh tokens\n * Should make a call to the POS refresh token endpoint\n */\n refreshTokenFn?: (refreshToken: string) => Promise<{\n access_token: string;\n refresh_token: string;\n }>;\n\n /**\n * Callback when tokens are updated (login/refresh)\n */\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n\n /**\n * Callback when tokens are cleared (logout/error)\n */\n onTokensCleared?: () => void;\n}\n\n/**\n * Create POS authentication middleware for openapi-fetch\n *\n * POS Authentication Rules:\n * 1. API Key endpoints (X-Api-Key): login/email, login/phone, login/whatsapp, pair-device, verify-otp\n * 2. Bearer token endpoints: All other endpoints\n * 3. Token returning endpoints: verify-otp, refresh-token\n */\nexport function createPosAuthMiddleware(\n config: PosAuthMiddlewareConfig\n): Middleware {\n let isRefreshing = false;\n let refreshPromise: Promise<void> | null = null;\n let hasAssessedTokens = false;\n\n const assessTokenStateOnce = async (): Promise<void> => {\n // Skip if already assessed (tokenStorage is guaranteed to exist when middleware is created)\n if (hasAssessedTokens) return;\n \n hasAssessedTokens = true;\n \n try {\n const accessToken = await config.tokenStorage.getAccessToken();\n const refreshToken = await config.tokenStorage.getRefreshToken();\n \n // Case 1: Valid access token - do nothing\n if (accessToken && !isTokenExpired(accessToken)) {\n return;\n }\n \n // Case 2: Orphaned refresh token (no access token but refresh token exists)\n if (!accessToken && refreshToken) {\n // Clean up orphaned refresh token to prevent confusion\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('Cleaned up orphaned refresh token in POS');\n return;\n }\n \n // Case 3: Expired access token with valid refresh token\n if (accessToken && refreshToken && !isTokenExpired(refreshToken)) {\n try {\n await refreshTokens();\n console.info('POS tokens refreshed proactively on startup');\n } catch (error) {\n // Refresh failed - both tokens are likely invalid, clear them\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('POS tokens cleared after failed refresh on startup');\n }\n return;\n }\n \n // Case 4: Both tokens expired or invalid - clear stale tokens\n if ((accessToken && isTokenExpired(accessToken)) || \n (refreshToken && isTokenExpired(refreshToken))) {\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('POS stale tokens cleared on startup - user needs to re-authenticate');\n return;\n }\n \n // Case 5: No tokens at all - valid unauthenticated state\n if (!accessToken && !refreshToken) {\n // This is normal - user hasn't logged in or has logged out\n // No action needed, POS will work with API key endpoints\n return;\n }\n \n // Note: Unlike storefront, POS doesn't have anonymous fallback\n // Users must explicitly authenticate through login endpoints\n } catch (error) {\n // Silent fail - don't break the request flow\n console.warn('POS token state assessment failed:', error);\n }\n };\n\n const refreshTokens = async (): Promise<void> => {\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = (async () => {\n try {\n const refreshToken = await config.tokenStorage.getRefreshToken();\n\n if (!refreshToken || isTokenExpired(refreshToken)) {\n throw new Error(\"No valid refresh token available\");\n }\n\n let newTokens: { access_token: string; refresh_token: string };\n\n if (config.refreshTokenFn) {\n // Use provided refresh function\n newTokens = await config.refreshTokenFn(refreshToken);\n } else {\n // Default refresh implementation for POS\n const response = await fetch(\n `${config.baseUrl}/pos/auth/refresh-token`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${await config.tokenStorage.getAccessToken()}`,\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n }\n );\n\n if (!response.ok) {\n throw new Error(`POS token refresh failed: ${response.status}`);\n }\n\n const data = await response.json();\n newTokens = data.content || data;\n }\n\n // Store new tokens\n await config.tokenStorage.setAccessToken(newTokens.access_token);\n await config.tokenStorage.setRefreshToken(newTokens.refresh_token);\n\n // Notify callback\n config.onTokensUpdated?.(\n newTokens.access_token,\n newTokens.refresh_token\n );\n } catch (error) {\n console.error(\"POS token refresh failed:\", error);\n // Clear tokens on refresh failure\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n throw error;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n })();\n\n return refreshPromise;\n };\n\n return {\n async onRequest({ request }) {\n const pathname = getPathnameFromUrl(request.url);\n \n // Assess token state once per middleware instance (POS session start)\n await assessTokenStateOnce();\n\n // Handle API Key endpoints (5 specific endpoints only)\n if (isApiKeyEndpoint(pathname)) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n return request;\n }\n\n // For all other endpoints, use Bearer token\n let accessToken = await config.tokenStorage.getAccessToken();\n\n // Check if token needs refresh\n if (accessToken && isTokenExpired(accessToken)) {\n try {\n await refreshTokens();\n accessToken = await config.tokenStorage.getAccessToken();\n } catch (error) {\n // If refresh fails, continue without token (will get 401)\n console.warn(\"Token refresh failed:\", error);\n accessToken = null;\n }\n }\n\n // Add Authorization header if we have a token\n if (accessToken) {\n request.headers.set(\"Authorization\", `Bearer ${accessToken}`);\n }\n\n return request;\n },\n\n async onResponse({ request, response }) {\n const pathname = getPathnameFromUrl(request.url);\n\n // Handle successful responses that return tokens (verify-otp, refresh-token)\n if (response.ok && isTokenReturningEndpoint(pathname)) {\n try {\n const data = await response.clone().json();\n const content = data.content || data;\n\n if (content?.access_token && content?.refresh_token) {\n await config.tokenStorage.setAccessToken(content.access_token);\n await config.tokenStorage.setRefreshToken(content.refresh_token);\n config.onTokensUpdated?.(\n content.access_token,\n content.refresh_token\n );\n }\n } catch (error) {\n console.warn(\"Failed to extract tokens from POS response:\", error);\n }\n } else if (response.ok && isLogoutEndpoint(pathname)) {\n // Clear tokens on successful logout\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n }\n\n // Handle 401 responses - retry once if token was expired\n if (response.status === 401 && !isApiKeyEndpoint(pathname)) {\n const currentToken = await config.tokenStorage.getAccessToken();\n\n // Only attempt refresh if we have a token and it's expired\n if (currentToken && isTokenExpired(currentToken, 0)) {\n try {\n await refreshTokens();\n\n // Retry the original request with new token\n const newToken = await config.tokenStorage.getAccessToken();\n if (newToken) {\n const retryRequest = request.clone();\n retryRequest.headers.set(\"Authorization\", `Bearer ${newToken}`);\n return fetch(retryRequest);\n }\n } catch (error) {\n // If refresh fails, let the original 401 response through\n console.warn(\"POS token refresh failed on 401 response:\", error);\n }\n }\n }\n\n return response;\n },\n };\n}\n\n/**\n * Helper function to create POS auth middleware with sensible defaults\n */\nexport function createDefaultPosAuthMiddleware(options: {\n apiKey: string;\n baseUrl: string;\n tokenStorage?: TokenStorage;\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n onTokensCleared?: () => void;\n}): Middleware {\n const tokenStorage =\n options.tokenStorage ||\n (typeof localStorage !== \"undefined\"\n ? new BrowserTokenStorage()\n : new MemoryTokenStorage());\n\n return createPosAuthMiddleware({\n tokenStorage,\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n onTokensUpdated: options.onTokensUpdated,\n onTokensCleared: options.onTokensCleared,\n });\n}\n","/**\n * Environment configuration for POS API\n */\nexport enum Environment {\n Development = \"dev\",\n Staging = \"staging\",\n Production = \"production\",\n}\n\n/**\n * Configuration for building POS API URLs\n */\nexport interface PosURLConfig {\n storeId: string;\n environment?: Environment;\n baseUrl?: string;\n}\n\n/**\n * Build the base URL for POS API requests\n *\n * @param config - URL configuration\n * @returns The base URL for POS API requests\n */\nexport function buildPosURL(config: PosURLConfig): string {\n // If custom baseUrl is provided, use it directly\n if (config.baseUrl) {\n return config.baseUrl.replace(/\\/$/, \"\"); // Remove trailing slash\n }\n\n // Build URL based on environment and store ID\n const env = config.environment || Environment.Production;\n\n switch (env) {\n case Environment.Staging:\n return `https://staging.api.commercengine.io/api/v1/${config.storeId}/storefront`;\n case Environment.Production:\n default:\n return `https://prod.api.commercengine.io/api/v1/${config.storeId}/storefront`;\n }\n}\n","import type { paths } from \"../types/pos\";\nimport { BaseAPIClient, getPathnameFromUrl } from \"@commercengine/sdk-core\";\nimport { createDefaultPosAuthMiddleware } from \"./middleware/auth\";\nimport { isApiKeyEndpoint } from \"./utils/auth\";\nimport { buildPosURL } from \"./utils/url\";\nimport type { PosSDKOptions, SupportedDefaultHeaders } from \"../index\";\n\n/**\n * POS API client that extends the generic BaseAPIClient\n * Adds Commerce Engine POS specific authentication and token management\n */\nexport class PosAPIClient extends BaseAPIClient<\n paths,\n SupportedDefaultHeaders\n> {\n protected config: PosSDKOptions;\n private initializationPromise: Promise<void> | null = null;\n\n /**\n * Validate required configuration parameters\n * @param config - Configuration to validate\n * @throws Error with descriptive message if validation fails\n */\n private static validateConfig(config: PosSDKOptions): void {\n const errors: string[] = [];\n\n // Required fields validation\n if (!config.storeId?.trim()) {\n errors.push(\"storeId is required and cannot be empty\");\n }\n\n if (!config.apiKey?.trim()) {\n errors.push(\"apiKey is required for POS authentication (needed for login, device pairing, and token refresh fallbacks)\");\n }\n\n // Token configuration validation\n if (config.accessToken && !config.tokenStorage && !config.refreshToken) {\n errors.push(\"When providing accessToken without tokenStorage, consider providing refreshToken for token refresh capability\");\n }\n\n if (config.refreshToken && !config.accessToken) {\n errors.push(\"refreshToken cannot be provided without accessToken (orphaned refresh token)\");\n }\n\n if (config.refreshToken && !config.tokenStorage) {\n errors.push(\"refreshToken requires tokenStorage for automatic token management\");\n }\n\n // Callback validation\n if ((config.onTokensUpdated || config.onTokensCleared) && !config.tokenStorage) {\n errors.push(\"Token callbacks (onTokensUpdated/onTokensCleared) require tokenStorage for automatic token management\");\n }\n\n // URL validation\n if (config.baseUrl && !PosAPIClient.isValidUrl(config.baseUrl)) {\n errors.push(\"baseUrl must be a valid HTTP/HTTPS URL\");\n }\n\n if (errors.length > 0) {\n throw new Error(`POS SDK configuration validation failed:\\n- ${errors.join('\\n- ')}`);\n }\n }\n\n /**\n * Check if a string is a valid URL\n * @param url - URL string to validate\n * @returns True if valid URL\n */\n private static isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n /**\n * Create a new PosAPIClient\n *\n * @param config - Configuration for the API client\n */\n constructor(config: PosSDKOptions) {\n // Validate required configuration first (before calling super)\n PosAPIClient.validateConfig(config);\n\n // Build base URL from Commerce Engine config\n const baseUrl = buildPosURL({\n storeId: config.storeId,\n environment: config.environment,\n baseUrl: config.baseUrl,\n });\n\n // Header transformations for POS API\n const headerTransformations = {\n customer_group_id: \"x-customer-group-id\",\n // Add any other header transformations here\n } as Record<keyof SupportedDefaultHeaders, string>;\n\n // Call parent constructor with generic config\n super(\n {\n baseUrl: baseUrl,\n timeout: config.timeout,\n defaultHeaders: config.defaultHeaders,\n debug: config.debug,\n logger: config.logger,\n },\n baseUrl,\n headerTransformations\n );\n\n // Store full config for POS-specific features\n this.config = { ...config };\n\n // Set up POS-specific auth middleware\n this.setupPosAuth();\n }\n\n /**\n * Set up POS-specific authentication middleware\n */\n private setupPosAuth(): void {\n const config = this.config as PosSDKOptions;\n\n // Set up auth middleware if token storage is provided\n if (config.tokenStorage) {\n const authMiddleware = createDefaultPosAuthMiddleware({\n apiKey: config.apiKey,\n baseUrl: this.getBaseUrl(),\n tokenStorage: config.tokenStorage,\n onTokensUpdated: config.onTokensUpdated,\n onTokensCleared: config.onTokensCleared,\n });\n this.client.use(authMiddleware);\n\n // If initial tokens were provided, store them in tokenStorage\n if (config.accessToken) {\n this.initializationPromise = this.initializeTokens(\n config.accessToken,\n config.refreshToken\n );\n // Clear the manual tokens since we're using storage\n config.accessToken = undefined;\n config.refreshToken = undefined;\n }\n } else {\n // For manual token management, add simple header injection middleware\n this.client.use({\n onRequest: async ({ request }) => {\n const pathname = getPathnameFromUrl(request.url);\n\n // For login endpoints, use API key\n if (isApiKeyEndpoint(pathname)) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n return request;\n }\n\n // For all other endpoints, prefer access token, fallback to API key\n if (config.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${config.accessToken}`\n );\n } else if (config.apiKey) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n }\n\n return request;\n },\n });\n }\n }\n\n /**\n * Get the authorization header value\n * If using token storage, gets the current token from storage\n * Otherwise returns the manual token\n *\n * @returns The Authorization header value or empty string if no token is set\n */\n public async getAuthorizationHeader(): Promise<string> {\n // Wait for initialization to complete if using token storage\n if (this.config.tokenStorage && this.initializationPromise) {\n await this.initializationPromise;\n }\n\n if (this.config.tokenStorage) {\n const token = await this.config.tokenStorage.getAccessToken();\n return token ? `Bearer ${token}` : \"\";\n }\n return this.config.accessToken ? `Bearer ${this.config.accessToken}` : \"\";\n }\n\n /**\n * Set authentication tokens\n *\n * @param accessToken - The access token (required)\n * @param refreshToken - The refresh token (optional)\n *\n * Behavior:\n * - If tokenStorage is provided: Stores tokens for automatic management\n * - If tokenStorage is not provided: Only stores access token for manual management\n */\n public async setTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n if (this.config.tokenStorage) {\n // Automatic token management\n await this.config.tokenStorage.setAccessToken(accessToken);\n if (refreshToken) {\n await this.config.tokenStorage.setRefreshToken(refreshToken);\n }\n } else {\n // Manual token management - only access token\n this.config.accessToken = accessToken;\n if (refreshToken) {\n console.warn(\n \"Refresh token provided but ignored in manual token management mode. Use tokenStorage for automatic management.\"\n );\n }\n }\n }\n\n /**\n * Clear all authentication tokens\n *\n * Behavior:\n * - If tokenStorage is provided: Clears both access and refresh tokens from storage\n * - If tokenStorage is not provided: Clears the manual access token\n */\n public async clearTokens(): Promise<void> {\n if (this.config.tokenStorage) {\n await this.config.tokenStorage.clearTokens();\n } else {\n this.config.accessToken = undefined;\n }\n }\n\n /**\n * Set the X-Api-Key header\n *\n * @param apiKey - The API key to set\n */\n public setApiKey(apiKey: string): void {\n this.config.apiKey = apiKey;\n }\n\n\n /**\n * Initialize tokens in storage (private helper method)\n */\n private async initializeTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n try {\n if (this.config.tokenStorage) {\n await this.config.tokenStorage.setAccessToken(accessToken);\n if (refreshToken) {\n await this.config.tokenStorage.setRefreshToken(refreshToken);\n }\n }\n } catch (error) {\n console.warn(\"Failed to initialize tokens in storage:\", error);\n }\n }\n}\n","import { PosAPIClient } from \"./client\";\nimport type { ApiResult } from \"@commercengine/sdk-core\";\nimport type {\n // Auth types\n LoginPosDeviceWithEmailBody,\n LoginPosDeviceWithEmailContent,\n LoginPosDeviceWithPhoneBody,\n LoginPosDeviceWithPhoneContent,\n LoginPosDeviceWithWhatsappBody,\n LoginPosDeviceWithWhatsappContent,\n PairPosDeviceBody,\n PairPosDeviceContent,\n RefreshPosAccessTokenBody,\n RefreshPosAccessTokenContent,\n VerifyPosLoginOtpBody,\n VerifyPosLoginOtpContent,\n LogoutFromPosDeviceResponse,\n\n // Cart types\n PosCreateCartBody,\n PosCreateCartContent,\n PosGetCartPathParams,\n PosGetCartContent,\n PosDeleteCartPathParams,\n PosDeleteCartResponse,\n PosUpdateCartPathParams,\n PosUpdateCartBody,\n PosUpdateCartContent,\n\n // Cart address\n PosCreateCartAddressPathParams,\n PosCreateCartAddressBody,\n PosCreateCartAddressContent,\n\n // Coupons\n PosListCouponsContent,\n PosListCouponsHeaderParams,\n PosApplyCouponPathParams,\n PosApplyCouponBody,\n PosApplyCouponContent,\n PosRemoveCouponPathParams,\n PosRemoveCouponContent,\n PosEvaluateCouponsPathParams,\n PosEvaluateCouponsContent,\n\n // Promotions\n PosListPromotionsContent,\n PosListPromotionsHeaderParams,\n PosEvaluatePromotionsPathParams,\n PosEvaluatePromotionsContent,\n\n // Credit balance\n PosRedeemCreditBalancePathParams,\n PosRedeemCreditBalanceBody,\n PosRedeemCreditBalanceContent,\n PosRemoveCreditBalancePathParams,\n PosRemoveCreditBalanceContent,\n\n // Gift cards\n PosRedeemGiftCardPathParams,\n PosRedeemGiftCardBody,\n PosRedeemGiftCardContent,\n PosRemoveGiftCardPathParams,\n PosRemoveGiftCardContent,\n\n // Loyalty points\n PosRedeemLoyaltyPointsPathParams,\n PosRedeemLoyaltyPointsBody,\n PosRedeemLoyaltyPointsContent,\n PosRemoveLoyaltyPointsPathParams,\n PosRemoveLoyaltyPointsContent,\n\n // Fulfillment\n PosUpdateFulfillmentPreferencePathParams,\n PosUpdateFulfillmentPreferenceBody,\n PosUpdateFulfillmentPreferenceResponse,\n GetPosFulfillmentOptionsBody,\n GetPosFulfillmentOptionsContent,\n\n // Customer\n UpdatePosCartCustomerPathParams,\n UpdatePosCartCustomerBody,\n UpdatePosCartCustomerContent,\n\n // Orders\n CreatePosOrderBody,\n CreatePosOrderContent,\n\n // Catalog types\n PosListCategoriesContent,\n PosListCategoriesQuery,\n PosListProductsContent,\n PosListProductsQuery,\n PosListProductsHeaderParams,\n PosListCrosssellProductsContent,\n PosListCrosssellProductsQuery,\n PosListCrosssellProductsHeaderParams,\n PosSearchProductsBody,\n PosSearchProductsContent,\n PosSearchProductsHeaderParams,\n PosListSimilarProductsContent,\n PosListSimilarProductsQuery,\n PosListSimilarProductsHeaderParams,\n PosListUpsellProductsContent,\n PosListUpsellProductsQuery,\n PosListUpsellProductsHeaderParams,\n PosGetProductDetailPathParams,\n PosGetProductDetailContent,\n PosGetProductDetailHeaderParams,\n PosListProductReviewsPathParams,\n PosListProductReviewsContent,\n PosListProductReviewsQuery,\n PosListProductVariantsPathParams,\n PosListProductVariantsContent,\n PosListProductVariantsHeaderParams,\n PosGetVariantDetailPathParams,\n PosGetVariantDetailContent,\n PosGetVariantDetailHeaderParams,\n PosListSkusContent,\n PosListSkusQuery,\n PosListSkusHeaderParams,\n} from \"../types/pos-api-types\";\n\n/**\n * Client for interacting with POS endpoints\n * Single client that handles all POS operations including auth, cart, orders, etc.\n */\nexport class PosClient extends PosAPIClient {\n // ===============================\n // AUTHENTICATION ENDPOINTS\n // ===============================\n\n /**\n * Login with email address for POS device\n * @param body - Login credentials containing device ID and email\n * @returns Promise with OTP token and action\n */\n public async loginWithEmail(\n body: LoginPosDeviceWithEmailBody\n ): Promise<ApiResult<LoginPosDeviceWithEmailContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/email\", {\n body: body,\n })\n );\n }\n\n /**\n * Login with phone number for POS device\n * @param body - Login credentials containing device ID and phone\n * @returns Promise with OTP token and action\n */\n public async loginWithPhone(\n body: LoginPosDeviceWithPhoneBody\n ): Promise<ApiResult<LoginPosDeviceWithPhoneContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/phone\", { body })\n );\n }\n\n /**\n * Login with WhatsApp for POS device\n * @param body - Login credentials containing device ID and phone\n * @returns Promise with OTP token and action\n */\n public async loginWithWhatsapp(\n body: LoginPosDeviceWithWhatsappBody\n ): Promise<ApiResult<LoginPosDeviceWithWhatsappContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/whatsapp\", { body })\n );\n }\n\n /**\n * Pair POS device with pairing code\n * @param body - Pairing code received via phone/email\n * @returns Promise with device information\n */\n public async pairDevice(\n body: PairPosDeviceBody\n ): Promise<ApiResult<PairPosDeviceContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/pair-device\", { body })\n );\n }\n\n /**\n * Verify OTP for POS login\n * @param body - OTP verification data\n * @returns Promise with user info and tokens\n */\n public async verifyOtp(\n body: VerifyPosLoginOtpBody\n ): Promise<ApiResult<VerifyPosLoginOtpContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/verify-otp\", { body })\n );\n }\n\n /**\n * Refresh POS access token\n * @param body - Refresh token data\n * @returns Promise with new tokens\n */\n public async refreshAccessToken(\n body: RefreshPosAccessTokenBody\n ): Promise<ApiResult<RefreshPosAccessTokenContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/refresh-token\", { body })\n );\n }\n\n /**\n * Logout from POS device\n * @returns Promise with logout confirmation\n */\n public async logout(): Promise<ApiResult<LogoutFromPosDeviceResponse>> {\n return this.executeRequest(() => this.client.POST(\"/pos/auth/logout\"));\n }\n\n // ===============================\n // CART ENDPOINTS\n // ===============================\n\n /**\n * Create a new cart\n * @param body - Cart creation data with items\n * @returns Promise with created cart\n */\n public async createCart(\n body: PosCreateCartBody\n ): Promise<ApiResult<PosCreateCartContent>> {\n return this.executeRequest(() => this.client.POST(\"/pos/carts\", { body }));\n }\n\n /**\n * Get cart details\n * @param pathParams - Cart ID\n * @returns Promise with cart details\n */\n public async getCart(\n pathParams: PosGetCartPathParams\n ): Promise<ApiResult<PosGetCartContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Delete cart (remove all items)\n * @param pathParams - Cart ID\n * @returns Promise with deletion confirmation\n */\n public async deleteCart(\n pathParams: PosDeleteCartPathParams\n ): Promise<ApiResult<PosDeleteCartResponse>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Add/update cart item (set quantity to 0 to remove)\n * @param pathParams - Cart ID\n * @param body - Item update data\n * @returns Promise with updated cart\n */\n public async updateCart(\n pathParams: PosUpdateCartPathParams,\n body: PosUpdateCartBody\n ): Promise<ApiResult<PosUpdateCartContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/items\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Update cart address (billing/shipping)\n * @param pathParams - Cart ID\n * @param body - Address data (registered user IDs or guest addresses)\n * @returns Promise with updated cart\n */\n public async createCartAddress(\n pathParams: PosCreateCartAddressPathParams,\n body: PosCreateCartAddressBody\n ): Promise<ApiResult<PosCreateCartAddressContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/address\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n // ===============================\n // COUPON & PROMOTION ENDPOINTS\n // ===============================\n\n /**\n * List all available coupons\n * @param headers - Optional header parameters (customer_group_id, etc.)\n * @returns Promise with available coupons\n */\n public async listCoupons(\n headers?: PosListCouponsHeaderParams\n ): Promise<ApiResult<PosListCouponsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/available-coupons\", {\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List all available promotions\n * @param headers - Optional header parameters (customer_group_id, etc.)\n * @returns Promise with available promotions\n */\n public async listPromotions(\n headers?: PosListPromotionsHeaderParams\n ): Promise<ApiResult<PosListPromotionsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/available-promotions\", {\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Apply coupon to cart\n * @param pathParams - Cart ID\n * @param body - Coupon code\n * @returns Promise with updated cart\n */\n public async applyCoupon(\n pathParams: PosApplyCouponPathParams,\n body: PosApplyCouponBody\n ): Promise<ApiResult<PosApplyCouponContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/coupon\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove coupon from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeCoupon(\n pathParams: PosRemoveCouponPathParams\n ): Promise<ApiResult<PosRemoveCouponContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/coupon\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Evaluate applicable/inapplicable coupons for cart\n * @param pathParams - Cart ID\n * @returns Promise with coupon evaluation results\n */\n public async evaluateCoupons(\n pathParams: PosEvaluateCouponsPathParams\n ): Promise<ApiResult<PosEvaluateCouponsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}/evaluate-coupons\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Evaluate applicable/inapplicable promotions for cart\n * @param pathParams - Cart ID\n * @returns Promise with promotion evaluation results\n */\n public async evaluatePromotions(\n pathParams: PosEvaluatePromotionsPathParams\n ): Promise<ApiResult<PosEvaluatePromotionsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}/evaluate-promotions\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // CREDIT BALANCE ENDPOINTS\n // ===============================\n\n /**\n * Apply credit balance to cart\n * @param pathParams - Cart ID\n * @param body - Credit balance amount to use\n * @returns Promise with updated cart\n */\n public async redeemCreditBalance(\n pathParams: PosRedeemCreditBalancePathParams,\n body: PosRedeemCreditBalanceBody\n ): Promise<ApiResult<PosRedeemCreditBalanceContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/credit-balance\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove credit balance from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeCreditBalance(\n pathParams: PosRemoveCreditBalancePathParams\n ): Promise<ApiResult<PosRemoveCreditBalanceContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/credit-balance\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // GIFT CARD ENDPOINTS\n // ===============================\n\n /**\n * Redeem gift card for cart\n * @param pathParams - Cart ID\n * @param body - Gift card code\n * @returns Promise with updated cart\n */\n public async redeemGiftCard(\n pathParams: PosRedeemGiftCardPathParams,\n body: PosRedeemGiftCardBody\n ): Promise<ApiResult<PosRedeemGiftCardContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/gift-card\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove gift card from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeGiftCard(\n pathParams: PosRemoveGiftCardPathParams\n ): Promise<ApiResult<PosRemoveGiftCardContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/gift-card\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // LOYALTY POINTS ENDPOINTS\n // ===============================\n\n /**\n * Redeem loyalty points for cart\n * @param pathParams - Cart ID\n * @param body - Loyalty points to redeem\n * @returns Promise with updated cart\n */\n public async redeemLoyaltyPoints(\n pathParams: PosRedeemLoyaltyPointsPathParams,\n body: PosRedeemLoyaltyPointsBody\n ): Promise<ApiResult<PosRedeemLoyaltyPointsContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/loyalty-points\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove loyalty points from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeLoyaltyPoints(\n pathParams: PosRemoveLoyaltyPointsPathParams\n ): Promise<ApiResult<PosRemoveLoyaltyPointsContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/loyalty-points\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // FULFILLMENT ENDPOINTS\n // ===============================\n\n /**\n * Update cart fulfillment preference (delivery/pickup)\n * @param pathParams - Cart ID\n * @param body - Fulfillment preference data\n * @returns Promise with confirmation\n */\n public async updateFulfillmentPreference(\n pathParams: PosUpdateFulfillmentPreferencePathParams,\n body: PosUpdateFulfillmentPreferenceBody\n ): Promise<ApiResult<PosUpdateFulfillmentPreferenceResponse>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/fulfillment-preference\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Get fulfillment options for cart\n * @param body - Cart data for fulfillment calculation\n * @returns Promise with fulfillment options\n */\n public async getFulfillmentOptions(\n body: GetPosFulfillmentOptionsBody\n ): Promise<ApiResult<GetPosFulfillmentOptionsContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/fulfillment-options\", { body })\n );\n }\n\n // ===============================\n // CUSTOMER ENDPOINTS\n // ===============================\n\n /**\n * Update cart customer information\n * @param pathParams - Cart ID\n * @param body - Customer update data\n * @returns Promise with updated cart\n */\n public async updateCartCustomer(\n pathParams: UpdatePosCartCustomerPathParams,\n body: UpdatePosCartCustomerBody\n ): Promise<ApiResult<UpdatePosCartCustomerContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/update-customer\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n // ===============================\n // ORDER ENDPOINTS\n // ===============================\n\n /**\n * Create order from cart\n * @param body - Order creation data\n * @returns Promise with created order\n */\n public async createOrder(\n body: CreatePosOrderBody\n ): Promise<ApiResult<CreatePosOrderContent>> {\n return this.executeRequest(() => this.client.POST(\"/pos/orders\", { body }));\n }\n\n // ===============================\n // CATALOG ENDPOINTS\n // ===============================\n\n /**\n * List all categories\n * @param query - Optional query parameters for filtering categories\n * @returns Promise with list of categories\n */\n public async listCategories(\n query?: PosListCategoriesQuery\n ): Promise<ApiResult<PosListCategoriesContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/categories\", {\n params: { query },\n })\n );\n }\n\n /**\n * List all products\n * @param query - Optional query parameters for filtering products\n * @param headers - Optional header parameters\n * @returns Promise with list of products\n */\n public async listProducts(\n query?: PosListProductsQuery,\n headers?: PosListProductsHeaderParams\n ): Promise<ApiResult<PosListProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List cross-sell products\n * @param query - Query parameters with product IDs for cross-sell recommendations\n * @param headers - Optional header parameters\n * @returns Promise with cross-sell products\n */\n public async listCrosssellProducts(\n query: PosListCrosssellProductsQuery,\n headers?: PosListCrosssellProductsHeaderParams\n ): Promise<ApiResult<PosListCrosssellProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/cross-sell\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Search products\n * @param body - Search criteria and parameters\n * @param headers - Optional header parameters\n * @returns Promise with search results\n */\n public async searchProducts(\n body: PosSearchProductsBody,\n headers?: PosSearchProductsHeaderParams\n ): Promise<ApiResult<PosSearchProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.POST(\"/pos/catalog/products/search\", {\n body,\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List similar products\n * @param query - Query parameters with product ID for similarity recommendations\n * @param headers - Optional header parameters\n * @returns Promise with similar products\n */\n public async listSimilarProducts(\n query: PosListSimilarProductsQuery,\n headers?: PosListSimilarProductsHeaderParams\n ): Promise<ApiResult<PosListSimilarProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/similar\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List up-sell products\n * @param query - Query parameters with product IDs for up-sell recommendations\n * @param headers - Optional header parameters\n * @returns Promise with up-sell products\n */\n public async listUpsellProducts(\n query: PosListUpsellProductsQuery,\n headers?: PosListUpsellProductsHeaderParams\n ): Promise<ApiResult<PosListUpsellProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/up-sell\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Get product details\n * @param pathParams - Product ID or slug\n * @param headers - Optional header parameters\n * @returns Promise with product details\n */\n public async getProductDetail(\n pathParams: PosGetProductDetailPathParams,\n headers?: PosGetProductDetailHeaderParams\n ): Promise<ApiResult<PosGetProductDetailContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id_or_slug}\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List product reviews\n * @param pathParams - Product ID\n * @param query - Optional query parameters for filtering reviews\n * @returns Promise with product reviews\n */\n public async listProductReviews(\n pathParams: PosListProductReviewsPathParams,\n query?: PosListProductReviewsQuery\n ): Promise<ApiResult<PosListProductReviewsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/reviews\", {\n params: {\n path: pathParams,\n query,\n },\n })\n );\n }\n\n /**\n * List product variants\n * @param pathParams - Product ID\n * @param headers - Optional header parameters\n * @returns Promise with product variants\n */\n public async listProductVariants(\n pathParams: PosListProductVariantsPathParams,\n headers?: PosListProductVariantsHeaderParams\n ): Promise<ApiResult<PosListProductVariantsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/variants\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Get variant details\n * @param pathParams - Product ID and variant ID\n * @param headers - Optional header parameters\n * @returns Promise with variant details\n */\n public async getVariantDetail(\n pathParams: PosGetVariantDetailPathParams,\n headers?: PosGetVariantDetailHeaderParams\n ): Promise<ApiResult<PosGetVariantDetailContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/variants/{variant_id}\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List all SKUs\n * @param query - Optional query parameters for filtering SKUs\n * @param headers - Optional header parameters\n * @returns Promise with list of SKUs\n */\n public async listSkus(\n query?: PosListSkusQuery,\n headers?: PosListSkusHeaderParams\n ): Promise<ApiResult<PosListSkusContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/skus\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n}\n","import { PosAPIClient } from \"./lib/client\";\nimport { type BaseSDKOptions } from \"@commercengine/sdk-core\";\nimport { Environment } from \"./lib/utils/url\";\nimport { PosClient } from \"./lib/pos\";\nimport {\n type TokenStorage,\n MemoryTokenStorage,\n BrowserTokenStorage,\n} from \"./lib/middleware/auth\";\nimport {\n extractUserInfoFromToken,\n getUserIdFromToken,\n isUserLoggedIn,\n isUserAuthenticated,\n getDeviceIdFromToken,\n getLocationIdFromToken,\n getRoleFromToken,\n getTenantIdFromToken,\n type UserInfo,\n} from \"./lib/utils/jwt\";\nimport { ResponseUtils } from \"@commercengine/sdk-core\";\n\n/**\n * Supported default headers for POS API\n */\nexport interface SupportedDefaultHeaders {\n /**\n * Customer group ID used for pricing and promotions\n */\n customer_group_id?: string;\n}\n\n/**\n * SDK initialization options for the POS API\n */\nexport interface PosSDKOptions extends BaseSDKOptions<SupportedDefaultHeaders> {\n /**\n * Store ID for the API requests\n */\n storeId: string;\n\n /**\n * Environment to use (defaults to Production)\n * Overrides baseUrl if provided\n */\n environment?: Environment;\n\n /**\n * Custom base URL (overrides environment if provided)\n * If not provided, will be built from storeId and environment\n */\n baseUrl?: string;\n\n /**\n * X-Api-Key for authentication endpoints that require API key\n * Required for login, pair-device, and verify-otp endpoints\n * Always required even when initializing with tokens (for refresh fallbacks)\n */\n apiKey: string;\n\n /**\n * Optional initial access token\n * - If tokenStorage is provided: Used as initial token value, then managed automatically\n * - If tokenStorage is not provided: Used for manual token management\n */\n accessToken?: string;\n\n /**\n * Optional initial refresh token\n * - Only used when tokenStorage is provided\n * - Allows initialization with both access and refresh tokens\n */\n refreshToken?: string;\n\n /**\n * Optional token storage for automatic token management\n * If provided, enables automatic token refresh and management\n */\n tokenStorage?: TokenStorage;\n\n /**\n * Callback when tokens are updated (login/refresh)\n */\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n\n /**\n * Callback when tokens are cleared (logout/error)\n */\n onTokensCleared?: () => void;\n}\n\n/**\n * Main SDK class for the POS API\n * Provides access to all POS endpoints through a single client\n */\nexport class PosSDK {\n /**\n * Client for all POS operations (auth, cart, orders, etc.)\n */\n public readonly pos: PosClient;\n\n /**\n * Create a new PosSDK instance\n *\n * @param options - Configuration options for the SDK\n */\n constructor(options: PosSDKOptions) {\n // Convert options to internal config format\n const config: PosSDKOptions = {\n storeId: options.storeId,\n environment: options.environment,\n baseUrl: options.baseUrl,\n accessToken: options.accessToken,\n refreshToken: options.refreshToken,\n apiKey: options.apiKey,\n timeout: options.timeout,\n tokenStorage: options.tokenStorage,\n onTokensUpdated: options.onTokensUpdated,\n onTokensCleared: options.onTokensCleared,\n defaultHeaders: options.defaultHeaders,\n debug: options.debug,\n logger: options.logger,\n };\n\n this.pos = new PosClient(config);\n }\n\n /**\n * Set authentication tokens for the client\n *\n * @param accessToken - The access token (required)\n * @param refreshToken - The refresh token (optional)\n *\n * Behavior:\n * - If tokenStorage is provided: Stores tokens for automatic management\n * - If tokenStorage is not provided: Only stores access token for manual management\n */\n public async setTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n await this.pos.setTokens(accessToken, refreshToken);\n }\n\n /**\n * Clear all authentication tokens from the client\n *\n * Behavior:\n * - If tokenStorage is provided: Clears both access and refresh tokens from storage\n * - If tokenStorage is not provided: Clears the manual access token\n */\n public async clearTokens(): Promise<void> {\n await this.pos.clearTokens();\n }\n\n /**\n * Set the API key for the client\n *\n * @param apiKey - The API key to set\n */\n public setApiKey(apiKey: string): void {\n this.pos.setApiKey(apiKey);\n }\n\n\n /**\n * Get the current access token if available\n */\n public async getAccessToken(): Promise<string | null> {\n const header = await this.pos.getAuthorizationHeader();\n return header.startsWith(\"Bearer \") ? header.substring(7) : null;\n }\n\n /**\n * Set default headers for the client\n *\n * @param headers - Default headers to set\n */\n public setDefaultHeaders(headers: SupportedDefaultHeaders): void {\n this.pos.setDefaultHeaders(headers);\n }\n\n /**\n * Get current default headers\n */\n public getDefaultHeaders(): SupportedDefaultHeaders | undefined {\n return this.pos.getDefaultHeaders();\n }\n\n /**\n * Get user information from the current access token\n *\n * @returns User information extracted from JWT token, or null if no token or invalid token\n */\n public async getUserInfo(): Promise<UserInfo | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return extractUserInfoFromToken(token);\n }\n\n /**\n * Get the current user ID from the access token\n *\n * @returns User ID (ulid) or null if no token or invalid token\n */\n public async getUserId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getUserIdFromToken(token);\n }\n\n /**\n * Check if the current user is logged in\n *\n * @returns True if user is logged in, false otherwise\n */\n public async isLoggedIn(): Promise<boolean> {\n const token = await this.getAccessToken();\n if (!token) return false;\n return isUserLoggedIn(token);\n }\n\n /**\n * Check if the current user is authenticated with POS access\n * This verifies the user has valid device and role information\n *\n * @returns True if user is authenticated for POS operations\n */\n public async isAuthenticated(): Promise<boolean> {\n const token = await this.getAccessToken();\n if (!token) return false;\n return isUserAuthenticated(token);\n }\n\n /**\n * Get the device ID from the current access token\n * This is commonly needed for POS API requests\n *\n * @returns Device ID or null if no token or invalid token\n */\n public async getDeviceId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getDeviceIdFromToken(token);\n }\n\n /**\n * Get the location ID from the current access token\n * This is commonly needed for POS API requests\n *\n * @returns Location ID or null if no token or invalid token\n */\n public async getLocationId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getLocationIdFromToken(token);\n }\n\n /**\n * Get the role information from the current access token\n *\n * @returns Role object with id and name, or null if no token or invalid token\n */\n public async getRole(): Promise<{ id: string; name: string } | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getRoleFromToken(token);\n }\n\n /**\n * Get the tenant ID from the current access token\n *\n * @returns Tenant ID or null if no token or invalid token\n */\n public async getTenantId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getTenantIdFromToken(token);\n }\n}\n\n// Export the main SDK class as default\nexport default PosSDK;\n\n// Export individual clients for advanced usage\nexport {\n PosAPIClient,\n PosClient,\n ResponseUtils,\n};\n\n// Export environment enum\nexport { Environment } from \"./lib/utils/url\";\n\n// Export token storage types\nexport type { TokenStorage };\nexport { MemoryTokenStorage, BrowserTokenStorage };\n\n// Export logger types\nexport type { DebugLoggerFn } from \"@commercengine/sdk-core\";\n\n// Export POS-specific JWT types\nexport type { UserInfo } from \"./lib/utils/jwt\";\n\n// Export API types for consumer usage\nexport type { components, operations, paths } from \"./types/pos\";\nexport type * from \"./types/pos-api-types\";"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["refreshPromise: Promise<void> | null","newTokens: { access_token: string; refresh_token: string }","errors: string[]","config: PosSDKOptions"],"sources":["../../sdk-core/dist/index.js","../src/lib/utils/jwt.ts","../src/lib/utils/auth.ts","../src/lib/middleware/auth.ts","../src/lib/utils/url.ts","../src/lib/client.ts","../src/lib/pos.ts","../src/index.ts"],"sourcesContent":["import createClient from \"openapi-fetch\";\n\n//#region src/middleware/debug.ts\n/**\n* Response utilities for debugging and working with Response objects\n*/\nvar ResponseUtils = class {\n\t/**\n\t* Get response headers as a plain object\n\t*/\n\tstatic getHeaders(response) {\n\t\treturn Object.fromEntries(response.headers.entries());\n\t}\n\t/**\n\t* Get specific header value\n\t*/\n\tstatic getHeader(response, name) {\n\t\treturn response.headers.get(name);\n\t}\n\t/**\n\t* Check if response was successful\n\t*/\n\tstatic isSuccess(response) {\n\t\treturn response.ok;\n\t}\n\t/**\n\t* Get response metadata\n\t*/\n\tstatic getMetadata(response) {\n\t\treturn {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\tok: response.ok,\n\t\t\turl: response.url,\n\t\t\tredirected: response.redirected,\n\t\t\ttype: response.type,\n\t\t\theaders: Object.fromEntries(response.headers.entries())\n\t\t};\n\t}\n\t/**\n\t* Clone and read response as text (useful for debugging)\n\t* Note: This can only be called once per response\n\t*/\n\tstatic async getText(response) {\n\t\tconst cloned = response.clone();\n\t\treturn await cloned.text();\n\t}\n\t/**\n\t* Clone and read response as JSON (useful for debugging)\n\t* Note: This can only be called once per response\n\t*/\n\tstatic async getJSON(response) {\n\t\tconst cloned = response.clone();\n\t\treturn await cloned.json();\n\t}\n\t/**\n\t* Format response information for debugging\n\t*/\n\tstatic format(response) {\n\t\tconst metadata = this.getMetadata(response);\n\t\treturn `${metadata.status} ${metadata.statusText} - ${metadata.url}`;\n\t}\n\t/**\n\t* Format response for logging purposes (enhanced version)\n\t*/\n\tstatic formatResponse(response) {\n\t\treturn {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\turl: response.url,\n\t\t\tok: response.ok\n\t\t};\n\t}\n};\n/**\n* Debug logging utilities\n*/\nvar DebugLogger = class {\n\tlogger;\n\tresponseTextCache = /* @__PURE__ */ new Map();\n\tconstructor(logger) {\n\t\tthis.logger = logger || ((level, message, data) => {\n\t\t\tconsole.log(`[${level.toUpperCase()}]`, message);\n\t\t\tif (data) console.log(data);\n\t\t});\n\t}\n\t/**\n\t* Log debug information about API request\n\t*/\n\tlogRequest(request, requestBody) {\n\t\tthis.logger(\"info\", \"API Request Debug Info\", {\n\t\t\tmethod: request.method,\n\t\t\turl: request.url,\n\t\t\theaders: Object.fromEntries(request.headers.entries()),\n\t\t\tbody: requestBody,\n\t\t\ttimestamp: (/* @__PURE__ */ new Date()).toISOString()\n\t\t});\n\t}\n\t/**\n\t* Log debug information about API response\n\t*/\n\tasync logResponse(response, responseBody) {\n\t\tif (responseBody && typeof responseBody === \"string\") this.responseTextCache.set(response.url, responseBody);\n\t\tthis.logger(\"info\", \"API Response Debug Info\", {\n\t\t\turl: response.url,\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\tok: response.ok,\n\t\t\theaders: Object.fromEntries(response.headers.entries()),\n\t\t\tredirected: response.redirected,\n\t\t\ttype: response.type,\n\t\t\ttimestamp: (/* @__PURE__ */ new Date()).toISOString()\n\t\t});\n\t\tif (responseBody) this.logger(\"info\", \"API Response Data\", {\n\t\t\tdata: responseBody,\n\t\t\tcontentType: response.headers.get(\"content-type\"),\n\t\t\tcontentLength: response.headers.get(\"content-length\")\n\t\t});\n\t}\n\t/**\n\t* Log error information\n\t*/\n\tlogError(message, error) {\n\t\tthis.logger(\"error\", message, error);\n\t}\n\t/**\n\t* Get cached response text for a URL (if available)\n\t*/\n\tgetCachedResponseText(url) {\n\t\treturn this.responseTextCache.get(url) || null;\n\t}\n\t/**\n\t* Clear cached response texts\n\t*/\n\tclearCache() {\n\t\tthis.responseTextCache.clear();\n\t}\n\tinfo(message, data) {\n\t\tthis.logger(\"info\", message, data);\n\t}\n\twarn(message, data) {\n\t\tthis.logger(\"warn\", message, data);\n\t}\n\terror(message, data) {\n\t\tthis.logger(\"error\", message, data);\n\t}\n};\n/**\n* Extract request body for logging\n*/\nasync function extractRequestBody(request) {\n\tif (request.method === \"GET\" || request.method === \"HEAD\") return null;\n\ttry {\n\t\tconst clonedRequest = request.clone();\n\t\tconst contentType = request.headers.get(\"content-type\")?.toLowerCase();\n\t\tif (contentType?.startsWith(\"application/json\")) return await clonedRequest.json();\n\t\telse if (contentType?.startsWith(\"multipart/form-data\")) return \"[FormData - cannot display]\";\n\t\telse if (contentType?.startsWith(\"text/\")) return await clonedRequest.text();\n\t\treturn \"[Request body - unknown format]\";\n\t} catch (error) {\n\t\treturn \"[Request body unavailable]\";\n\t}\n}\n/**\n* Create debug middleware for openapi-fetch (internal use)\n* Enhanced version that combines original functionality with duration tracking\n*/\nfunction createDebugMiddleware(logger) {\n\tconst debugLogger = new DebugLogger(logger);\n\treturn {\n\t\tasync onRequest({ request }) {\n\t\t\trequest.__debugStartTime = Date.now();\n\t\t\tconst requestBody = await extractRequestBody(request);\n\t\t\tdebugLogger.logRequest(request, requestBody);\n\t\t\treturn request;\n\t\t},\n\t\tasync onResponse({ request, response }) {\n\t\t\tconst startTime = request.__debugStartTime;\n\t\t\tconst duration = startTime ? Date.now() - startTime : 0;\n\t\t\tconst cloned = response.clone();\n\t\t\tlet responseBody = null;\n\t\t\ttry {\n\t\t\t\tconst contentType = response.headers.get(\"content-type\")?.toLowerCase();\n\t\t\t\tif (contentType?.startsWith(\"application/json\")) responseBody = await cloned.json();\n\t\t\t\telse if (contentType?.startsWith(\"text/\")) responseBody = await cloned.text();\n\t\t\t} catch (error) {}\n\t\t\tawait debugLogger.logResponse(response, responseBody);\n\t\t\tif (duration > 0) debugLogger.info(`Request completed in ${duration}ms`, {\n\t\t\t\turl: request.url,\n\t\t\t\tmethod: request.method\n\t\t\t});\n\t\t\treturn response;\n\t\t},\n\t\tasync onError({ error, request }) {\n\t\t\tdebugLogger.logError(\"API Request Failed\", {\n\t\t\t\terror: {\n\t\t\t\t\tname: error instanceof Error ? error.name : \"Unknown\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tstack: error instanceof Error ? error.stack : void 0\n\t\t\t\t},\n\t\t\t\trequest: {\n\t\t\t\t\tmethod: request.method,\n\t\t\t\t\turl: request.url,\n\t\t\t\t\theaders: Object.fromEntries(request.headers.entries())\n\t\t\t\t},\n\t\t\t\ttimestamp: (/* @__PURE__ */ new Date()).toISOString()\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n//#endregion\n//#region src/middleware/timeout.ts\n/**\n* Timeout middleware for Commerce Engine SDKs\n*/\n/**\n* Create timeout middleware for openapi-fetch\n* Adds configurable request timeout functionality\n* \n* @param timeoutMs - Timeout duration in milliseconds\n* @returns Middleware object with onRequest handler\n*/\nfunction createTimeoutMiddleware(timeoutMs) {\n\treturn { onRequest: async ({ request }) => {\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\t\tif (request.signal) request.signal.addEventListener(\"abort\", () => controller.abort());\n\t\tconst newRequest = new Request(request, { signal: controller.signal });\n\t\tcontroller.signal.addEventListener(\"abort\", () => clearTimeout(timeoutId));\n\t\treturn newRequest;\n\t} };\n}\n\n//#endregion\n//#region src/middleware/headers.ts\n/**\n* Header transformation and merging utilities for Commerce Engine SDKs\n*/\n/**\n* Merge two header objects\n* Method-level headers take precedence over default headers\n*\n* @param defaultHeaders - Default headers from SDK configuration\n* @param methodHeaders - Headers passed to the specific method call\n* @returns Merged headers object\n*/\nfunction mergeHeaders(defaultHeaders, methodHeaders) {\n\tconst merged = {};\n\tif (defaultHeaders) Object.assign(merged, defaultHeaders);\n\tif (methodHeaders) Object.assign(merged, methodHeaders);\n\tObject.keys(merged).forEach((key) => {\n\t\tif (merged[key] === void 0) delete merged[key];\n\t});\n\treturn merged;\n}\n/**\n* Transform headers using a transformation mapping\n* Headers not in the transformation map are passed through unchanged\n*\n* @param headers - Headers object with original names\n* @param transformations - Mapping of original names to transformed names\n* @returns Headers object with transformed names\n*/\nfunction transformHeaders(headers, transformations) {\n\tconst transformed = {};\n\tfor (const [key, value] of Object.entries(headers)) if (value !== void 0) {\n\t\tconst headerName = transformations[key] || key;\n\t\ttransformed[headerName] = value;\n\t}\n\treturn transformed;\n}\n/**\n* Merge headers with transformation support\n* Transforms default headers, then merges with method headers\n*\n* @param defaultHeaders - Default headers from SDK configuration\n* @param methodHeaders - Headers passed to the specific method call\n* @param transformations - Mapping for header name transformations\n* @returns Merged headers object with transformations applied\n*/\nfunction mergeAndTransformHeaders(defaultHeaders, methodHeaders, transformations) {\n\tconst merged = {};\n\tif (defaultHeaders && transformations) {\n\t\tconst transformedDefaults = transformHeaders(defaultHeaders, transformations);\n\t\tObject.assign(merged, transformedDefaults);\n\t} else if (defaultHeaders) Object.assign(merged, defaultHeaders);\n\tif (methodHeaders) Object.assign(merged, methodHeaders);\n\tObject.keys(merged).forEach((key) => {\n\t\tif (merged[key] === void 0) delete merged[key];\n\t});\n\treturn merged;\n}\n\n//#endregion\n//#region src/utils/response.ts\n/**\n* Execute a request and handle the response consistently\n* This provides unified error handling and response processing across all SDKs\n*\n* @param apiCall - Function that executes the API request\n* @returns Promise with the API response in standardized format\n*/\nasync function executeRequest(apiCall) {\n\ttry {\n\t\tconst { data, error, response } = await apiCall();\n\t\tif (error) return {\n\t\t\tdata: null,\n\t\t\terror,\n\t\t\tresponse\n\t\t};\n\t\tif (data && data.content !== void 0) return {\n\t\t\tdata: data.content,\n\t\t\terror: null,\n\t\t\tresponse\n\t\t};\n\t\treturn {\n\t\t\tdata,\n\t\t\terror: null,\n\t\t\tresponse\n\t\t};\n\t} catch (err) {\n\t\tconst mockResponse = new Response(null, {\n\t\t\tstatus: 0,\n\t\t\tstatusText: \"Network Error\"\n\t\t});\n\t\tconst errorResult = {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\tsuccess: false,\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage: \"Network error occurred\",\n\t\t\t\terror: err\n\t\t\t},\n\t\t\tresponse: mockResponse\n\t\t};\n\t\treturn errorResult;\n\t}\n}\n\n//#endregion\n//#region src/base-client.ts\n/**\n* Generic base API client that all Commerce Engine SDKs can extend\n* Handles common functionality like middleware setup, request execution, and header management\n* Does NOT include token management - that's SDK-specific\n* \n* @template TPaths - OpenAPI paths type\n* @template THeaders - Supported default headers type\n*/\nvar BaseAPIClient = class {\n\tclient;\n\tconfig;\n\tbaseUrl;\n\theaderTransformations;\n\t/**\n\t* Create a new BaseAPIClient\n\t*\n\t* @param config - Configuration for the API client\n\t* @param baseUrl - The base URL for the API (must be provided by subclass)\n\t* @param headerTransformations - Header name transformations for this SDK\n\t*/\n\tconstructor(config, baseUrl, headerTransformations = {}) {\n\t\tthis.config = { ...config };\n\t\tthis.headerTransformations = headerTransformations;\n\t\tthis.baseUrl = baseUrl;\n\t\tthis.client = createClient({ baseUrl: this.baseUrl });\n\t\tthis.setupMiddleware();\n\t}\n\t/**\n\t* Set up all middleware for the client\n\t*/\n\tsetupMiddleware() {\n\t\tif (this.config.timeout) {\n\t\t\tconst timeoutMiddleware = createTimeoutMiddleware(this.config.timeout);\n\t\t\tthis.client.use(timeoutMiddleware);\n\t\t}\n\t\tif (this.config.debug) {\n\t\t\tconst debugMiddleware = createDebugMiddleware(this.config.logger);\n\t\t\tthis.client.use(debugMiddleware);\n\t\t}\n\t}\n\t/**\n\t* Get the base URL of the API\n\t*\n\t* @returns The base URL of the API\n\t*/\n\tgetBaseUrl() {\n\t\treturn this.baseUrl;\n\t}\n\t/**\n\t* Execute a request and handle the response consistently\n\t* This provides unified error handling and response processing\n\t*\n\t* @param apiCall - Function that executes the API request\n\t* @returns Promise with the API response in standardized format\n\t*/\n\tasync executeRequest(apiCall) {\n\t\treturn executeRequest(apiCall);\n\t}\n\t/**\n\t* Merge default headers with method-level headers\n\t* Method-level headers take precedence over default headers\n\t* Automatically applies SDK-specific header transformations\n\t*\n\t* @param methodHeaders - Headers passed to the specific method call\n\t* @returns Merged headers object with proper HTTP header names\n\t*/\n\tmergeHeaders(methodHeaders) {\n\t\treturn mergeAndTransformHeaders(this.config.defaultHeaders, methodHeaders, this.headerTransformations);\n\t}\n\t/**\n\t* Set default headers for the client\n\t*\n\t* @param headers - Default headers to set\n\t*/\n\tsetDefaultHeaders(headers) {\n\t\tthis.config.defaultHeaders = headers;\n\t}\n\t/**\n\t* Get current default headers\n\t*\n\t* @returns Current default headers\n\t*/\n\tgetDefaultHeaders() {\n\t\treturn this.config.defaultHeaders;\n\t}\n};\n\n//#endregion\n//#region src/utils/url.ts\n/**\n* Generic URL utility functions for any SDK\n*/\n/**\n* Extract pathname from URL\n* Useful for middleware that needs to inspect request paths\n*/\nfunction getPathnameFromUrl(url) {\n\ttry {\n\t\tconst urlObj = new URL(url);\n\t\treturn urlObj.pathname;\n\t} catch {\n\t\treturn url.split(\"?\")[0] || url;\n\t}\n}\n\n//#endregion\nexport { BaseAPIClient, DebugLogger, ResponseUtils, createDebugMiddleware, createTimeoutMiddleware, executeRequest, extractRequestBody, getPathnameFromUrl, mergeAndTransformHeaders, mergeHeaders, transformHeaders };","import { decodeJwt } from \"jose\";\n\n/**\n * JWT payload structure for POS tokens\n */\nexport interface JwtPayload {\n token_type: string;\n exp: number;\n iat: number;\n jti: string;\n ulid: string;\n username: string;\n email: string;\n phone: string;\n first_name: string;\n last_name: string;\n store_id: string;\n is_logged_in: boolean;\n customer_id: string | null;\n customer_group_id: string | null;\n device: {\n device_id: string;\n device_name: string;\n };\n location: {\n id: string;\n name: string;\n };\n role: {\n id: string;\n name: string;\n };\n tenant_id: string;\n channel: {\n id: string;\n name: string;\n type: string;\n };\n sid: string;\n}\n\n/**\n * User information extracted from POS JWT token\n */\nexport interface UserInfo {\n id: string;\n username: string;\n email: string;\n phone: string;\n firstName: string;\n lastName: string;\n storeId: string;\n isLoggedIn: boolean;\n customerId: string | null;\n customerGroupId: string | null;\n device: {\n deviceId: string;\n deviceName: string;\n };\n location: {\n id: string;\n name: string;\n };\n role: {\n id: string;\n name: string;\n };\n tenantId: string;\n channel: {\n id: string;\n name: string;\n type: string;\n };\n sessionId: string;\n tokenExpiry: Date;\n tokenIssuedAt: Date;\n}\n\n/**\n * Decode and extract user information from a JWT token\n *\n * @param token - The JWT token to decode\n * @returns User information or null if token is invalid\n */\nexport function extractUserInfoFromToken(token: string): UserInfo | null {\n try {\n const payload = decodeJwt(token) as JwtPayload;\n\n return {\n id: payload.ulid,\n username: payload.username,\n email: payload.email,\n phone: payload.phone,\n firstName: payload.first_name,\n lastName: payload.last_name,\n storeId: payload.store_id,\n isLoggedIn: payload.is_logged_in,\n customerId: payload.customer_id,\n customerGroupId: payload.customer_group_id,\n device: {\n deviceId: payload.device.device_id,\n deviceName: payload.device.device_name,\n },\n location: {\n id: payload.location.id,\n name: payload.location.name,\n },\n role: {\n id: payload.role.id,\n name: payload.role.name,\n },\n tenantId: payload.tenant_id,\n channel: {\n id: payload.channel.id,\n name: payload.channel.name,\n type: payload.channel.type,\n },\n sessionId: payload.sid,\n tokenExpiry: new Date(payload.exp * 1000),\n tokenIssuedAt: new Date(payload.iat * 1000),\n };\n } catch (error) {\n console.warn(\"Failed to decode JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Check if a JWT token is expired\n *\n * @param token - The JWT token to check\n * @param bufferSeconds - Buffer time in seconds (default: 30)\n * @returns True if token is expired or will expire within buffer time\n */\nexport function isTokenExpired(\n token: string,\n bufferSeconds: number = 30\n): boolean {\n try {\n const payload = decodeJwt(token);\n if (!payload.exp) return true;\n\n const currentTime = Math.floor(Date.now() / 1000);\n const expiryTime = payload.exp;\n\n // Consider token expired if it expires within the buffer time\n return currentTime >= expiryTime - bufferSeconds;\n } catch (error) {\n console.warn(\"Failed to decode JWT token:\", error);\n return true; // Treat invalid tokens as expired\n }\n}\n\n/**\n * Get the user ID from a JWT token\n *\n * @param token - The JWT token\n * @returns User ID (ulid) or null if token is invalid\n */\nexport function getUserIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.id || null;\n}\n\n/**\n * Check if user is logged in based on JWT token\n *\n * @param token - The JWT token\n * @returns True if user is logged in, false otherwise\n */\nexport function isUserLoggedIn(token: string): boolean {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.isLoggedIn || false;\n}\n\n/**\n * Check if user is authenticated (has valid POS token)\n * Checks the token for isLoggedIn status\n *\n * @param token - The JWT token\n * @returns True if user is authenticated with valid POS access\n */\nexport function isUserAuthenticated(token: string): boolean {\n const userInfo = extractUserInfoFromToken(token);\n return !!userInfo?.isLoggedIn;\n}\n\n/**\n * Get the device ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Device ID or null if token is invalid\n */\nexport function getDeviceIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.device?.deviceId || null;\n}\n\n/**\n * Get the location ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Location ID or null if token is invalid\n */\nexport function getLocationIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.location?.id || null;\n}\n\n/**\n * Get the role information from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Role object with id and name, or null if token is invalid\n */\nexport function getRoleFromToken(\n token: string\n): { id: string; name: string } | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.role || null;\n}\n\n/**\n * Get the tenant ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Tenant ID or null if token is invalid\n */\nexport function getTenantIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.tenantId || null;\n}\n\n/**\n * Get the channel information from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Channel object with id and name, or null if token is invalid\n */\nexport function getChannelFromToken(\n token: string\n): { id: string; name: string } | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.channel || null;\n}\n\n/**\n * Get the session ID from a POS JWT token\n *\n * @param token - The JWT token\n * @returns Session ID or null if token is invalid\n */\nexport function getSessionIdFromToken(token: string): string | null {\n const userInfo = extractUserInfoFromToken(token);\n return userInfo?.sessionId || null;\n}\n","/**\n * Check if a URL path is a POS login endpoint that should use API key\n * Based on POS spec, only these 5 endpoints use X-Api-Key:\n * - /pos/auth/login/email\n * - /pos/auth/login/phone\n * - /pos/auth/login/whatsapp\n * - /pos/auth/pair-device\n * - /pos/auth/verify-otp\n */\nexport function isApiKeyEndpoint(pathname: string): boolean {\n const apiKeyEndpoints = [\n \"/pos/auth/login/email\",\n \"/pos/auth/login/phone\",\n \"/pos/auth/login/whatsapp\",\n \"/pos/auth/pair-device\",\n \"/pos/auth/verify-otp\",\n ];\n return apiKeyEndpoints.some((endpoint) => pathname.includes(endpoint));\n}\n\n/**\n * Check if a URL path is a POS endpoint that returns tokens\n * Based on POS spec, only these endpoints return tokens:\n * - /pos/auth/verify-otp (after OTP verification)\n * - /pos/auth/refresh-token\n */\nexport function isTokenReturningEndpoint(pathname: string): boolean {\n const tokenEndpoints = [\"/pos/auth/verify-otp\", \"/pos/auth/refresh-token\"];\n return tokenEndpoints.some((endpoint) => pathname.includes(endpoint));\n}\n\n/**\n * Check if a URL path is a POS logout endpoint\n */\nexport function isLogoutEndpoint(pathname: string): boolean {\n return (\n pathname.includes(\"/pos/auth/logout\") || pathname.includes(\"/pos/logout\")\n );\n}\n\n// Re-export JWT utilities from jwt.ts\nexport {\n isTokenExpired,\n extractUserInfoFromToken,\n getUserIdFromToken,\n isUserLoggedIn,\n isUserAuthenticated,\n getDeviceIdFromToken,\n getLocationIdFromToken,\n getRoleFromToken,\n getTenantIdFromToken,\n} from \"./jwt\";\nexport type { UserInfo, JwtPayload } from \"./jwt\";\n","import type { Middleware } from \"openapi-fetch\";\nimport { getPathnameFromUrl } from \"@commercengine/sdk-core\";\nimport {\n isApiKeyEndpoint,\n isTokenReturningEndpoint,\n isLogoutEndpoint,\n isTokenExpired,\n} from \"../utils/auth\";\n\n/**\n * Token storage interface for the POS auth middleware\n */\nexport interface TokenStorage {\n getAccessToken(): Promise<string | null>;\n setAccessToken(token: string): Promise<void>;\n getRefreshToken(): Promise<string | null>;\n setRefreshToken(token: string): Promise<void>;\n clearTokens(): Promise<void>;\n}\n\n/**\n * Simple in-memory token storage implementation\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private accessToken: string | null = null;\n private refreshToken: string | null = null;\n\n async getAccessToken(): Promise<string | null> {\n return this.accessToken;\n }\n\n async setAccessToken(token: string): Promise<void> {\n this.accessToken = token;\n }\n\n async getRefreshToken(): Promise<string | null> {\n return this.refreshToken;\n }\n\n async setRefreshToken(token: string): Promise<void> {\n this.refreshToken = token;\n }\n\n async clearTokens(): Promise<void> {\n this.accessToken = null;\n this.refreshToken = null;\n }\n}\n\n/**\n * Browser localStorage token storage implementation for POS\n */\nexport class BrowserTokenStorage implements TokenStorage {\n private accessTokenKey: string;\n private refreshTokenKey: string;\n\n constructor(prefix: string = \"pos_\") {\n this.accessTokenKey = `${prefix}access_token`;\n this.refreshTokenKey = `${prefix}refresh_token`;\n }\n\n async getAccessToken(): Promise<string | null> {\n if (typeof localStorage === \"undefined\") return null;\n return localStorage.getItem(this.accessTokenKey);\n }\n\n async setAccessToken(token: string): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(this.accessTokenKey, token);\n }\n }\n\n async getRefreshToken(): Promise<string | null> {\n if (typeof localStorage === \"undefined\") return null;\n return localStorage.getItem(this.refreshTokenKey);\n }\n\n async setRefreshToken(token: string): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(this.refreshTokenKey, token);\n }\n }\n\n async clearTokens(): Promise<void> {\n if (typeof localStorage !== \"undefined\") {\n localStorage.removeItem(this.accessTokenKey);\n localStorage.removeItem(this.refreshTokenKey);\n }\n }\n}\n\n/**\n * Configuration for the POS auth middleware\n */\nexport interface PosAuthMiddlewareConfig {\n /**\n * Token storage implementation\n */\n tokenStorage: TokenStorage;\n\n /**\n * API key for X-Api-Key endpoints (login, pair-device, verify-otp)\n * Required for POS authentication flows and fallback scenarios\n */\n apiKey: string;\n\n /**\n * Base URL for the API (used for refresh token endpoint)\n */\n baseUrl: string;\n\n /**\n * Function to refresh tokens\n * Should make a call to the POS refresh token endpoint\n */\n refreshTokenFn?: (refreshToken: string) => Promise<{\n access_token: string;\n refresh_token: string;\n }>;\n\n /**\n * Callback when tokens are updated (login/refresh)\n */\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n\n /**\n * Callback when tokens are cleared (logout/error)\n */\n onTokensCleared?: () => void;\n}\n\n/**\n * Create POS authentication middleware for openapi-fetch\n *\n * POS Authentication Rules:\n * 1. API Key endpoints (X-Api-Key): login/email, login/phone, login/whatsapp, pair-device, verify-otp\n * 2. Bearer token endpoints: All other endpoints\n * 3. Token returning endpoints: verify-otp, refresh-token\n */\nexport function createPosAuthMiddleware(\n config: PosAuthMiddlewareConfig\n): Middleware {\n let isRefreshing = false;\n let refreshPromise: Promise<void> | null = null;\n let hasAssessedTokens = false;\n\n const assessTokenStateOnce = async (): Promise<void> => {\n // Skip if already assessed (tokenStorage is guaranteed to exist when middleware is created)\n if (hasAssessedTokens) return;\n \n hasAssessedTokens = true;\n \n try {\n const accessToken = await config.tokenStorage.getAccessToken();\n const refreshToken = await config.tokenStorage.getRefreshToken();\n \n // Case 1: Valid access token - do nothing\n if (accessToken && !isTokenExpired(accessToken)) {\n return;\n }\n \n // Case 2: Orphaned refresh token (no access token but refresh token exists)\n if (!accessToken && refreshToken) {\n // Clean up orphaned refresh token to prevent confusion\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('Cleaned up orphaned refresh token in POS');\n return;\n }\n \n // Case 3: Expired access token with valid refresh token\n if (accessToken && refreshToken && !isTokenExpired(refreshToken)) {\n try {\n await refreshTokens();\n console.info('POS tokens refreshed proactively on startup');\n } catch (error) {\n // Refresh failed - both tokens are likely invalid, clear them\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('POS tokens cleared after failed refresh on startup');\n }\n return;\n }\n \n // Case 4: Both tokens expired or invalid - clear stale tokens\n if ((accessToken && isTokenExpired(accessToken)) || \n (refreshToken && isTokenExpired(refreshToken))) {\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n console.info('POS stale tokens cleared on startup - user needs to re-authenticate');\n return;\n }\n \n // Case 5: No tokens at all - valid unauthenticated state\n if (!accessToken && !refreshToken) {\n // This is normal - user hasn't logged in or has logged out\n // No action needed, POS will work with API key endpoints\n return;\n }\n \n // Note: Unlike storefront, POS doesn't have anonymous fallback\n // Users must explicitly authenticate through login endpoints\n } catch (error) {\n // Silent fail - don't break the request flow\n console.warn('POS token state assessment failed:', error);\n }\n };\n\n const refreshTokens = async (): Promise<void> => {\n if (isRefreshing && refreshPromise) {\n return refreshPromise;\n }\n\n isRefreshing = true;\n refreshPromise = (async () => {\n try {\n const refreshToken = await config.tokenStorage.getRefreshToken();\n\n if (!refreshToken || isTokenExpired(refreshToken)) {\n throw new Error(\"No valid refresh token available\");\n }\n\n let newTokens: { access_token: string; refresh_token: string };\n\n if (config.refreshTokenFn) {\n // Use provided refresh function\n newTokens = await config.refreshTokenFn(refreshToken);\n } else {\n // Default refresh implementation for POS\n const response = await fetch(\n `${config.baseUrl}/pos/auth/refresh-token`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${await config.tokenStorage.getAccessToken()}`,\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n }\n );\n\n if (!response.ok) {\n throw new Error(`POS token refresh failed: ${response.status}`);\n }\n\n const data = await response.json();\n newTokens = data.content || data;\n }\n\n // Store new tokens\n await config.tokenStorage.setAccessToken(newTokens.access_token);\n await config.tokenStorage.setRefreshToken(newTokens.refresh_token);\n\n // Notify callback\n config.onTokensUpdated?.(\n newTokens.access_token,\n newTokens.refresh_token\n );\n } catch (error) {\n console.error(\"POS token refresh failed:\", error);\n // Clear tokens on refresh failure\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n throw error;\n } finally {\n isRefreshing = false;\n refreshPromise = null;\n }\n })();\n\n return refreshPromise;\n };\n\n return {\n async onRequest({ request }) {\n const pathname = getPathnameFromUrl(request.url);\n \n // Assess token state once per middleware instance (POS session start)\n await assessTokenStateOnce();\n\n // Handle API Key endpoints (5 specific endpoints only)\n if (isApiKeyEndpoint(pathname)) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n return request;\n }\n\n // For all other endpoints, use Bearer token\n let accessToken = await config.tokenStorage.getAccessToken();\n\n // Check if token needs refresh\n if (accessToken && isTokenExpired(accessToken)) {\n try {\n await refreshTokens();\n accessToken = await config.tokenStorage.getAccessToken();\n } catch (error) {\n // If refresh fails, continue without token (will get 401)\n console.warn(\"Token refresh failed:\", error);\n accessToken = null;\n }\n }\n\n // Add Authorization header if we have a token\n if (accessToken) {\n request.headers.set(\"Authorization\", `Bearer ${accessToken}`);\n }\n\n return request;\n },\n\n async onResponse({ request, response }) {\n const pathname = getPathnameFromUrl(request.url);\n\n // Handle successful responses that return tokens (verify-otp, refresh-token)\n if (response.ok && isTokenReturningEndpoint(pathname)) {\n try {\n const data = await response.clone().json();\n const content = data.content || data;\n\n if (content?.access_token && content?.refresh_token) {\n await config.tokenStorage.setAccessToken(content.access_token);\n await config.tokenStorage.setRefreshToken(content.refresh_token);\n config.onTokensUpdated?.(\n content.access_token,\n content.refresh_token\n );\n }\n } catch (error) {\n console.warn(\"Failed to extract tokens from POS response:\", error);\n }\n } else if (response.ok && isLogoutEndpoint(pathname)) {\n // Clear tokens on successful logout\n await config.tokenStorage.clearTokens();\n config.onTokensCleared?.();\n }\n\n // Handle 401 responses - retry once if token was expired\n if (response.status === 401 && !isApiKeyEndpoint(pathname)) {\n const currentToken = await config.tokenStorage.getAccessToken();\n\n // Only attempt refresh if we have a token and it's expired\n if (currentToken && isTokenExpired(currentToken, 0)) {\n try {\n await refreshTokens();\n\n // Retry the original request with new token\n const newToken = await config.tokenStorage.getAccessToken();\n if (newToken) {\n const retryRequest = request.clone();\n retryRequest.headers.set(\"Authorization\", `Bearer ${newToken}`);\n return fetch(retryRequest);\n }\n } catch (error) {\n // If refresh fails, let the original 401 response through\n console.warn(\"POS token refresh failed on 401 response:\", error);\n }\n }\n }\n\n return response;\n },\n };\n}\n\n/**\n * Helper function to create POS auth middleware with sensible defaults\n */\nexport function createDefaultPosAuthMiddleware(options: {\n apiKey: string;\n baseUrl: string;\n tokenStorage?: TokenStorage;\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n onTokensCleared?: () => void;\n}): Middleware {\n const tokenStorage =\n options.tokenStorage ||\n (typeof localStorage !== \"undefined\"\n ? new BrowserTokenStorage()\n : new MemoryTokenStorage());\n\n return createPosAuthMiddleware({\n tokenStorage,\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n onTokensUpdated: options.onTokensUpdated,\n onTokensCleared: options.onTokensCleared,\n });\n}\n","/**\n * Environment configuration for POS API\n */\nexport enum Environment {\n Development = \"dev\",\n Staging = \"staging\",\n Production = \"production\",\n}\n\n/**\n * Configuration for building POS API URLs\n */\nexport interface PosURLConfig {\n storeId: string;\n environment?: Environment;\n baseUrl?: string;\n}\n\n/**\n * Build the base URL for POS API requests\n *\n * @param config - URL configuration\n * @returns The base URL for POS API requests\n */\nexport function buildPosURL(config: PosURLConfig): string {\n // If custom baseUrl is provided, use it directly\n if (config.baseUrl) {\n return config.baseUrl.replace(/\\/$/, \"\"); // Remove trailing slash\n }\n\n // Build URL based on environment and store ID\n const env = config.environment || Environment.Production;\n\n switch (env) {\n case Environment.Staging:\n return `https://staging.api.commercengine.io/api/v1/${config.storeId}/storefront`;\n case Environment.Production:\n default:\n return `https://prod.api.commercengine.io/api/v1/${config.storeId}/storefront`;\n }\n}\n","import type { paths } from \"../types/pos\";\nimport { BaseAPIClient, getPathnameFromUrl } from \"@commercengine/sdk-core\";\nimport { createDefaultPosAuthMiddleware } from \"./middleware/auth\";\nimport { isApiKeyEndpoint } from \"./utils/auth\";\nimport { buildPosURL } from \"./utils/url\";\nimport type { PosSDKOptions, SupportedDefaultHeaders } from \"../index\";\n\n/**\n * POS API client that extends the generic BaseAPIClient\n * Adds Commerce Engine POS specific authentication and token management\n */\nexport class PosAPIClient extends BaseAPIClient<\n paths,\n SupportedDefaultHeaders\n> {\n protected config: PosSDKOptions;\n private initializationPromise: Promise<void> | null = null;\n\n /**\n * Validate required configuration parameters\n * @param config - Configuration to validate\n * @throws Error with descriptive message if validation fails\n */\n private static validateConfig(config: PosSDKOptions): void {\n const errors: string[] = [];\n\n // Required fields validation\n if (!config.storeId?.trim()) {\n errors.push(\"storeId is required and cannot be empty\");\n }\n\n if (!config.apiKey?.trim()) {\n errors.push(\"apiKey is required for POS authentication (needed for login, device pairing, and token refresh fallbacks)\");\n }\n\n // Token configuration validation\n if (config.accessToken && !config.tokenStorage && !config.refreshToken) {\n errors.push(\"When providing accessToken without tokenStorage, consider providing refreshToken for token refresh capability\");\n }\n\n if (config.refreshToken && !config.accessToken) {\n errors.push(\"refreshToken cannot be provided without accessToken (orphaned refresh token)\");\n }\n\n if (config.refreshToken && !config.tokenStorage) {\n errors.push(\"refreshToken requires tokenStorage for automatic token management\");\n }\n\n // Callback validation\n if ((config.onTokensUpdated || config.onTokensCleared) && !config.tokenStorage) {\n errors.push(\"Token callbacks (onTokensUpdated/onTokensCleared) require tokenStorage for automatic token management\");\n }\n\n // URL validation\n if (config.baseUrl && !PosAPIClient.isValidUrl(config.baseUrl)) {\n errors.push(\"baseUrl must be a valid HTTP/HTTPS URL\");\n }\n\n if (errors.length > 0) {\n throw new Error(`POS SDK configuration validation failed:\\n- ${errors.join('\\n- ')}`);\n }\n }\n\n /**\n * Check if a string is a valid URL\n * @param url - URL string to validate\n * @returns True if valid URL\n */\n private static isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n }\n\n /**\n * Create a new PosAPIClient\n *\n * @param config - Configuration for the API client\n */\n constructor(config: PosSDKOptions) {\n // Validate required configuration first (before calling super)\n PosAPIClient.validateConfig(config);\n\n // Build base URL from Commerce Engine config\n const baseUrl = buildPosURL({\n storeId: config.storeId,\n environment: config.environment,\n baseUrl: config.baseUrl,\n });\n\n // Header transformations for POS API\n const headerTransformations = {\n customer_group_id: \"x-customer-group-id\",\n // Add any other header transformations here\n } as Record<keyof SupportedDefaultHeaders, string>;\n\n // Call parent constructor with generic config\n super(\n {\n baseUrl: baseUrl,\n timeout: config.timeout,\n defaultHeaders: config.defaultHeaders,\n debug: config.debug,\n logger: config.logger,\n },\n baseUrl,\n headerTransformations\n );\n\n // Store full config for POS-specific features\n this.config = { ...config };\n\n // Set up POS-specific auth middleware\n this.setupPosAuth();\n }\n\n /**\n * Set up POS-specific authentication middleware\n */\n private setupPosAuth(): void {\n const config = this.config as PosSDKOptions;\n\n // Set up auth middleware if token storage is provided\n if (config.tokenStorage) {\n const authMiddleware = createDefaultPosAuthMiddleware({\n apiKey: config.apiKey,\n baseUrl: this.getBaseUrl(),\n tokenStorage: config.tokenStorage,\n onTokensUpdated: config.onTokensUpdated,\n onTokensCleared: config.onTokensCleared,\n });\n this.client.use(authMiddleware);\n\n // If initial tokens were provided, store them in tokenStorage\n if (config.accessToken) {\n this.initializationPromise = this.initializeTokens(\n config.accessToken,\n config.refreshToken\n );\n // Clear the manual tokens since we're using storage\n config.accessToken = undefined;\n config.refreshToken = undefined;\n }\n } else {\n // For manual token management, add simple header injection middleware\n this.client.use({\n onRequest: async ({ request }) => {\n const pathname = getPathnameFromUrl(request.url);\n\n // For login endpoints, use API key\n if (isApiKeyEndpoint(pathname)) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n return request;\n }\n\n // For all other endpoints, prefer access token, fallback to API key\n if (config.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${config.accessToken}`\n );\n } else if (config.apiKey) {\n request.headers.set(\"X-Api-Key\", config.apiKey);\n }\n\n return request;\n },\n });\n }\n }\n\n /**\n * Get the authorization header value\n * If using token storage, gets the current token from storage\n * Otherwise returns the manual token\n *\n * @returns The Authorization header value or empty string if no token is set\n */\n public async getAuthorizationHeader(): Promise<string> {\n // Wait for initialization to complete if using token storage\n if (this.config.tokenStorage && this.initializationPromise) {\n await this.initializationPromise;\n }\n\n if (this.config.tokenStorage) {\n const token = await this.config.tokenStorage.getAccessToken();\n return token ? `Bearer ${token}` : \"\";\n }\n return this.config.accessToken ? `Bearer ${this.config.accessToken}` : \"\";\n }\n\n /**\n * Set authentication tokens\n *\n * @param accessToken - The access token (required)\n * @param refreshToken - The refresh token (optional)\n *\n * Behavior:\n * - If tokenStorage is provided: Stores tokens for automatic management\n * - If tokenStorage is not provided: Only stores access token for manual management\n */\n public async setTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n if (this.config.tokenStorage) {\n // Automatic token management\n await this.config.tokenStorage.setAccessToken(accessToken);\n if (refreshToken) {\n await this.config.tokenStorage.setRefreshToken(refreshToken);\n }\n } else {\n // Manual token management - only access token\n this.config.accessToken = accessToken;\n if (refreshToken) {\n console.warn(\n \"Refresh token provided but ignored in manual token management mode. Use tokenStorage for automatic management.\"\n );\n }\n }\n }\n\n /**\n * Clear all authentication tokens\n *\n * Behavior:\n * - If tokenStorage is provided: Clears both access and refresh tokens from storage\n * - If tokenStorage is not provided: Clears the manual access token\n */\n public async clearTokens(): Promise<void> {\n if (this.config.tokenStorage) {\n await this.config.tokenStorage.clearTokens();\n } else {\n this.config.accessToken = undefined;\n }\n }\n\n /**\n * Set the X-Api-Key header\n *\n * @param apiKey - The API key to set\n */\n public setApiKey(apiKey: string): void {\n this.config.apiKey = apiKey;\n }\n\n\n /**\n * Initialize tokens in storage (private helper method)\n */\n private async initializeTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n try {\n if (this.config.tokenStorage) {\n await this.config.tokenStorage.setAccessToken(accessToken);\n if (refreshToken) {\n await this.config.tokenStorage.setRefreshToken(refreshToken);\n }\n }\n } catch (error) {\n console.warn(\"Failed to initialize tokens in storage:\", error);\n }\n }\n}\n","import { PosAPIClient } from \"./client\";\nimport type { ApiResult } from \"@commercengine/sdk-core\";\nimport type {\n // Auth types\n LoginPosDeviceWithEmailBody,\n LoginPosDeviceWithEmailContent,\n LoginPosDeviceWithPhoneBody,\n LoginPosDeviceWithPhoneContent,\n LoginPosDeviceWithWhatsappBody,\n LoginPosDeviceWithWhatsappContent,\n PairPosDeviceBody,\n PairPosDeviceContent,\n RefreshPosAccessTokenBody,\n RefreshPosAccessTokenContent,\n VerifyPosLoginOtpBody,\n VerifyPosLoginOtpContent,\n LogoutFromPosDeviceResponse,\n\n // Cart types\n PosCreateCartBody,\n PosCreateCartContent,\n PosGetCartPathParams,\n PosGetCartContent,\n PosDeleteCartPathParams,\n PosDeleteCartResponse,\n PosUpdateCartPathParams,\n PosUpdateCartBody,\n PosUpdateCartContent,\n\n // Cart address\n PosCreateCartAddressPathParams,\n PosCreateCartAddressBody,\n PosCreateCartAddressContent,\n\n // Coupons\n PosListCouponsContent,\n PosListCouponsHeaderParams,\n PosApplyCouponPathParams,\n PosApplyCouponBody,\n PosApplyCouponContent,\n PosRemoveCouponPathParams,\n PosRemoveCouponContent,\n PosEvaluateCouponsPathParams,\n PosEvaluateCouponsContent,\n\n // Promotions\n PosListPromotionsContent,\n PosListPromotionsHeaderParams,\n PosEvaluatePromotionsPathParams,\n PosEvaluatePromotionsContent,\n\n // Credit balance\n PosRedeemCreditBalancePathParams,\n PosRedeemCreditBalanceBody,\n PosRedeemCreditBalanceContent,\n PosRemoveCreditBalancePathParams,\n PosRemoveCreditBalanceContent,\n\n // Gift cards\n PosRedeemGiftCardPathParams,\n PosRedeemGiftCardBody,\n PosRedeemGiftCardContent,\n PosRemoveGiftCardPathParams,\n PosRemoveGiftCardContent,\n\n // Loyalty points\n PosRedeemLoyaltyPointsPathParams,\n PosRedeemLoyaltyPointsBody,\n PosRedeemLoyaltyPointsContent,\n PosRemoveLoyaltyPointsPathParams,\n PosRemoveLoyaltyPointsContent,\n\n // Fulfillment\n PosUpdateFulfillmentPreferencePathParams,\n PosUpdateFulfillmentPreferenceBody,\n PosUpdateFulfillmentPreferenceResponse,\n GetPosFulfillmentOptionsBody,\n GetPosFulfillmentOptionsContent,\n\n // Customer\n UpdatePosCartCustomerPathParams,\n UpdatePosCartCustomerBody,\n UpdatePosCartCustomerContent,\n\n // Orders\n CreatePosOrderBody,\n CreatePosOrderContent,\n\n // Catalog types\n PosListCategoriesContent,\n PosListCategoriesQuery,\n PosListProductsContent,\n PosListProductsQuery,\n PosListProductsHeaderParams,\n PosListCrosssellProductsContent,\n PosListCrosssellProductsQuery,\n PosListCrosssellProductsHeaderParams,\n PosSearchProductsBody,\n PosSearchProductsContent,\n PosSearchProductsHeaderParams,\n PosListSimilarProductsContent,\n PosListSimilarProductsQuery,\n PosListSimilarProductsHeaderParams,\n PosListUpsellProductsContent,\n PosListUpsellProductsQuery,\n PosListUpsellProductsHeaderParams,\n PosGetProductDetailPathParams,\n PosGetProductDetailContent,\n PosGetProductDetailHeaderParams,\n PosListProductReviewsPathParams,\n PosListProductReviewsContent,\n PosListProductReviewsQuery,\n PosListProductVariantsPathParams,\n PosListProductVariantsContent,\n PosListProductVariantsHeaderParams,\n PosGetVariantDetailPathParams,\n PosGetVariantDetailContent,\n PosGetVariantDetailHeaderParams,\n PosListSkusContent,\n PosListSkusQuery,\n PosListSkusHeaderParams,\n} from \"../types/pos-api-types\";\n\n/**\n * Client for interacting with POS endpoints\n * Single client that handles all POS operations including auth, cart, orders, etc.\n */\nexport class PosClient extends PosAPIClient {\n // ===============================\n // AUTHENTICATION ENDPOINTS\n // ===============================\n\n /**\n * Login with email address for POS device\n * @param body - Login credentials containing device ID and email\n * @returns Promise with OTP token and action\n */\n public async loginWithEmail(\n body: LoginPosDeviceWithEmailBody\n ): Promise<ApiResult<LoginPosDeviceWithEmailContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/email\", {\n body: body,\n })\n );\n }\n\n /**\n * Login with phone number for POS device\n * @param body - Login credentials containing device ID and phone\n * @returns Promise with OTP token and action\n */\n public async loginWithPhone(\n body: LoginPosDeviceWithPhoneBody\n ): Promise<ApiResult<LoginPosDeviceWithPhoneContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/phone\", { body })\n );\n }\n\n /**\n * Login with WhatsApp for POS device\n * @param body - Login credentials containing device ID and phone\n * @returns Promise with OTP token and action\n */\n public async loginWithWhatsapp(\n body: LoginPosDeviceWithWhatsappBody\n ): Promise<ApiResult<LoginPosDeviceWithWhatsappContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/login/whatsapp\", { body })\n );\n }\n\n /**\n * Pair POS device with pairing code\n * @param body - Pairing code received via phone/email\n * @returns Promise with device information\n */\n public async pairDevice(\n body: PairPosDeviceBody\n ): Promise<ApiResult<PairPosDeviceContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/pair-device\", { body })\n );\n }\n\n /**\n * Verify OTP for POS login\n * @param body - OTP verification data\n * @returns Promise with user info and tokens\n */\n public async verifyOtp(\n body: VerifyPosLoginOtpBody\n ): Promise<ApiResult<VerifyPosLoginOtpContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/verify-otp\", { body })\n );\n }\n\n /**\n * Refresh POS access token\n * @param body - Refresh token data\n * @returns Promise with new tokens\n */\n public async refreshAccessToken(\n body: RefreshPosAccessTokenBody\n ): Promise<ApiResult<RefreshPosAccessTokenContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/auth/refresh-token\", { body })\n );\n }\n\n /**\n * Logout from POS device\n * @returns Promise with logout confirmation\n */\n public async logout(): Promise<ApiResult<LogoutFromPosDeviceResponse>> {\n return this.executeRequest(() => this.client.POST(\"/pos/auth/logout\"));\n }\n\n // ===============================\n // CART ENDPOINTS\n // ===============================\n\n /**\n * Create a new cart\n * @param body - Cart creation data with items\n * @returns Promise with created cart\n */\n public async createCart(\n body: PosCreateCartBody\n ): Promise<ApiResult<PosCreateCartContent>> {\n return this.executeRequest(() => this.client.POST(\"/pos/carts\", { body }));\n }\n\n /**\n * Get cart details\n * @param pathParams - Cart ID\n * @returns Promise with cart details\n */\n public async getCart(\n pathParams: PosGetCartPathParams\n ): Promise<ApiResult<PosGetCartContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Delete cart (remove all items)\n * @param pathParams - Cart ID\n * @returns Promise with deletion confirmation\n */\n public async deleteCart(\n pathParams: PosDeleteCartPathParams\n ): Promise<ApiResult<PosDeleteCartResponse>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Add/update cart item (set quantity to 0 to remove)\n * @param pathParams - Cart ID\n * @param body - Item update data\n * @returns Promise with updated cart\n */\n public async updateCart(\n pathParams: PosUpdateCartPathParams,\n body: PosUpdateCartBody\n ): Promise<ApiResult<PosUpdateCartContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/items\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Update cart address (billing/shipping)\n * @param pathParams - Cart ID\n * @param body - Address data (registered user IDs or guest addresses)\n * @returns Promise with updated cart\n */\n public async createCartAddress(\n pathParams: PosCreateCartAddressPathParams,\n body: PosCreateCartAddressBody\n ): Promise<ApiResult<PosCreateCartAddressContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/address\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n // ===============================\n // COUPON & PROMOTION ENDPOINTS\n // ===============================\n\n /**\n * List all available coupons\n * @param headers - Optional header parameters (customer_group_id, etc.)\n * @returns Promise with available coupons\n */\n public async listCoupons(\n headers?: PosListCouponsHeaderParams\n ): Promise<ApiResult<PosListCouponsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/available-coupons\", {\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List all available promotions\n * @param headers - Optional header parameters (customer_group_id, etc.)\n * @returns Promise with available promotions\n */\n public async listPromotions(\n headers?: PosListPromotionsHeaderParams\n ): Promise<ApiResult<PosListPromotionsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/available-promotions\", {\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Apply coupon to cart\n * @param pathParams - Cart ID\n * @param body - Coupon code\n * @returns Promise with updated cart\n */\n public async applyCoupon(\n pathParams: PosApplyCouponPathParams,\n body: PosApplyCouponBody\n ): Promise<ApiResult<PosApplyCouponContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/coupon\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove coupon from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeCoupon(\n pathParams: PosRemoveCouponPathParams\n ): Promise<ApiResult<PosRemoveCouponContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/coupon\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Evaluate applicable/inapplicable coupons for cart\n * @param pathParams - Cart ID\n * @returns Promise with coupon evaluation results\n */\n public async evaluateCoupons(\n pathParams: PosEvaluateCouponsPathParams\n ): Promise<ApiResult<PosEvaluateCouponsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}/evaluate-coupons\", {\n params: { path: pathParams },\n })\n );\n }\n\n /**\n * Evaluate applicable/inapplicable promotions for cart\n * @param pathParams - Cart ID\n * @returns Promise with promotion evaluation results\n */\n public async evaluatePromotions(\n pathParams: PosEvaluatePromotionsPathParams\n ): Promise<ApiResult<PosEvaluatePromotionsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/carts/{id}/evaluate-promotions\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // CREDIT BALANCE ENDPOINTS\n // ===============================\n\n /**\n * Apply credit balance to cart\n * @param pathParams - Cart ID\n * @param body - Credit balance amount to use\n * @returns Promise with updated cart\n */\n public async redeemCreditBalance(\n pathParams: PosRedeemCreditBalancePathParams,\n body: PosRedeemCreditBalanceBody\n ): Promise<ApiResult<PosRedeemCreditBalanceContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/credit-balance\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove credit balance from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeCreditBalance(\n pathParams: PosRemoveCreditBalancePathParams\n ): Promise<ApiResult<PosRemoveCreditBalanceContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/credit-balance\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // GIFT CARD ENDPOINTS\n // ===============================\n\n /**\n * Redeem gift card for cart\n * @param pathParams - Cart ID\n * @param body - Gift card code\n * @returns Promise with updated cart\n */\n public async redeemGiftCard(\n pathParams: PosRedeemGiftCardPathParams,\n body: PosRedeemGiftCardBody\n ): Promise<ApiResult<PosRedeemGiftCardContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/gift-card\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove gift card from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeGiftCard(\n pathParams: PosRemoveGiftCardPathParams\n ): Promise<ApiResult<PosRemoveGiftCardContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/gift-card\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // LOYALTY POINTS ENDPOINTS\n // ===============================\n\n /**\n * Redeem loyalty points for cart\n * @param pathParams - Cart ID\n * @param body - Loyalty points to redeem\n * @returns Promise with updated cart\n */\n public async redeemLoyaltyPoints(\n pathParams: PosRedeemLoyaltyPointsPathParams,\n body: PosRedeemLoyaltyPointsBody\n ): Promise<ApiResult<PosRedeemLoyaltyPointsContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/loyalty-points\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Remove loyalty points from cart\n * @param pathParams - Cart ID\n * @returns Promise with updated cart\n */\n public async removeLoyaltyPoints(\n pathParams: PosRemoveLoyaltyPointsPathParams\n ): Promise<ApiResult<PosRemoveLoyaltyPointsContent>> {\n return this.executeRequest(() =>\n this.client.DELETE(\"/pos/carts/{id}/loyalty-points\", {\n params: { path: pathParams },\n })\n );\n }\n\n // ===============================\n // FULFILLMENT ENDPOINTS\n // ===============================\n\n /**\n * Update cart fulfillment preference (delivery/pickup)\n * @param pathParams - Cart ID\n * @param body - Fulfillment preference data\n * @returns Promise with confirmation\n */\n public async updateFulfillmentPreference(\n pathParams: PosUpdateFulfillmentPreferencePathParams,\n body: PosUpdateFulfillmentPreferenceBody\n ): Promise<ApiResult<PosUpdateFulfillmentPreferenceResponse>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/fulfillment-preference\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n /**\n * Get fulfillment options for cart\n * @param body - Cart data for fulfillment calculation\n * @returns Promise with fulfillment options\n */\n public async getFulfillmentOptions(\n body: GetPosFulfillmentOptionsBody\n ): Promise<ApiResult<GetPosFulfillmentOptionsContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/fulfillment-options\", { body })\n );\n }\n\n // ===============================\n // CUSTOMER ENDPOINTS\n // ===============================\n\n /**\n * Update cart customer information\n * @param pathParams - Cart ID\n * @param body - Customer update data\n * @returns Promise with updated cart\n */\n public async updateCartCustomer(\n pathParams: UpdatePosCartCustomerPathParams,\n body: UpdatePosCartCustomerBody\n ): Promise<ApiResult<UpdatePosCartCustomerContent>> {\n return this.executeRequest(() =>\n this.client.POST(\"/pos/carts/{id}/update-customer\", {\n params: { path: pathParams },\n body,\n })\n );\n }\n\n // ===============================\n // ORDER ENDPOINTS\n // ===============================\n\n /**\n * Create order from cart\n * @param body - Order creation data\n * @returns Promise with created order\n */\n public async createOrder(\n body: CreatePosOrderBody\n ): Promise<ApiResult<CreatePosOrderContent>> {\n return this.executeRequest(() => this.client.POST(\"/pos/orders\", { body }));\n }\n\n // ===============================\n // CATALOG ENDPOINTS\n // ===============================\n\n /**\n * List all categories\n * @param query - Optional query parameters for filtering categories\n * @returns Promise with list of categories\n */\n public async listCategories(\n query?: PosListCategoriesQuery\n ): Promise<ApiResult<PosListCategoriesContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/categories\", {\n params: { query },\n })\n );\n }\n\n /**\n * List all products\n * @param query - Optional query parameters for filtering products\n * @param headers - Optional header parameters\n * @returns Promise with list of products\n */\n public async listProducts(\n query?: PosListProductsQuery,\n headers?: PosListProductsHeaderParams\n ): Promise<ApiResult<PosListProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List cross-sell products\n * @param query - Query parameters with product IDs for cross-sell recommendations\n * @param headers - Optional header parameters\n * @returns Promise with cross-sell products\n */\n public async listCrosssellProducts(\n query: PosListCrosssellProductsQuery,\n headers?: PosListCrosssellProductsHeaderParams\n ): Promise<ApiResult<PosListCrosssellProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/cross-sell\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Search products\n * @param body - Search criteria and parameters\n * @param headers - Optional header parameters\n * @returns Promise with search results\n */\n public async searchProducts(\n body: PosSearchProductsBody,\n headers?: PosSearchProductsHeaderParams\n ): Promise<ApiResult<PosSearchProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.POST(\"/pos/catalog/products/search\", {\n body,\n params: {\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List similar products\n * @param query - Query parameters with product ID for similarity recommendations\n * @param headers - Optional header parameters\n * @returns Promise with similar products\n */\n public async listSimilarProducts(\n query: PosListSimilarProductsQuery,\n headers?: PosListSimilarProductsHeaderParams\n ): Promise<ApiResult<PosListSimilarProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/similar\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List up-sell products\n * @param query - Query parameters with product IDs for up-sell recommendations\n * @param headers - Optional header parameters\n * @returns Promise with up-sell products\n */\n public async listUpsellProducts(\n query: PosListUpsellProductsQuery,\n headers?: PosListUpsellProductsHeaderParams\n ): Promise<ApiResult<PosListUpsellProductsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/up-sell\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Get product details\n * @param pathParams - Product ID or slug\n * @param headers - Optional header parameters\n * @returns Promise with product details\n */\n public async getProductDetail(\n pathParams: PosGetProductDetailPathParams,\n headers?: PosGetProductDetailHeaderParams\n ): Promise<ApiResult<PosGetProductDetailContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id_or_slug}\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List product reviews\n * @param pathParams - Product ID\n * @param query - Optional query parameters for filtering reviews\n * @returns Promise with product reviews\n */\n public async listProductReviews(\n pathParams: PosListProductReviewsPathParams,\n query?: PosListProductReviewsQuery\n ): Promise<ApiResult<PosListProductReviewsContent>> {\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/reviews\", {\n params: {\n path: pathParams,\n query,\n },\n })\n );\n }\n\n /**\n * List product variants\n * @param pathParams - Product ID\n * @param headers - Optional header parameters\n * @returns Promise with product variants\n */\n public async listProductVariants(\n pathParams: PosListProductVariantsPathParams,\n headers?: PosListProductVariantsHeaderParams\n ): Promise<ApiResult<PosListProductVariantsContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/variants\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * Get variant details\n * @param pathParams - Product ID and variant ID\n * @param headers - Optional header parameters\n * @returns Promise with variant details\n */\n public async getVariantDetail(\n pathParams: PosGetVariantDetailPathParams,\n headers?: PosGetVariantDetailHeaderParams\n ): Promise<ApiResult<PosGetVariantDetailContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/products/{product_id}/variants/{variant_id}\", {\n params: {\n path: pathParams,\n header: mergedHeaders,\n },\n })\n );\n }\n\n /**\n * List all SKUs\n * @param query - Optional query parameters for filtering SKUs\n * @param headers - Optional header parameters\n * @returns Promise with list of SKUs\n */\n public async listSkus(\n query?: PosListSkusQuery,\n headers?: PosListSkusHeaderParams\n ): Promise<ApiResult<PosListSkusContent>> {\n const mergedHeaders = this.mergeHeaders(headers);\n return this.executeRequest(() =>\n this.client.GET(\"/pos/catalog/skus\", {\n params: {\n query,\n header: mergedHeaders,\n },\n })\n );\n }\n}\n","import { PosAPIClient } from \"./lib/client\";\nimport { type BaseSDKOptions } from \"@commercengine/sdk-core\";\nimport { Environment } from \"./lib/utils/url\";\nimport { PosClient } from \"./lib/pos\";\nimport {\n type TokenStorage,\n MemoryTokenStorage,\n BrowserTokenStorage,\n} from \"./lib/middleware/auth\";\nimport {\n extractUserInfoFromToken,\n getUserIdFromToken,\n isUserLoggedIn,\n isUserAuthenticated,\n getDeviceIdFromToken,\n getLocationIdFromToken,\n getRoleFromToken,\n getTenantIdFromToken,\n type UserInfo,\n} from \"./lib/utils/jwt\";\nimport { ResponseUtils } from \"@commercengine/sdk-core\";\n\n/**\n * Supported default headers for POS API\n */\nexport interface SupportedDefaultHeaders {\n /**\n * Customer group ID used for pricing and promotions\n */\n customer_group_id?: string;\n}\n\n/**\n * SDK initialization options for the POS API\n */\nexport interface PosSDKOptions extends BaseSDKOptions<SupportedDefaultHeaders> {\n /**\n * Store ID for the API requests\n */\n storeId: string;\n\n /**\n * Environment to use (defaults to Production)\n * Overrides baseUrl if provided\n */\n environment?: Environment;\n\n /**\n * Custom base URL (overrides environment if provided)\n * If not provided, will be built from storeId and environment\n */\n baseUrl?: string;\n\n /**\n * X-Api-Key for authentication endpoints that require API key\n * Required for login, pair-device, and verify-otp endpoints\n * Always required even when initializing with tokens (for refresh fallbacks)\n */\n apiKey: string;\n\n /**\n * Optional initial access token\n * - If tokenStorage is provided: Used as initial token value, then managed automatically\n * - If tokenStorage is not provided: Used for manual token management\n */\n accessToken?: string;\n\n /**\n * Optional initial refresh token\n * - Only used when tokenStorage is provided\n * - Allows initialization with both access and refresh tokens\n */\n refreshToken?: string;\n\n /**\n * Optional token storage for automatic token management\n * If provided, enables automatic token refresh and management\n */\n tokenStorage?: TokenStorage;\n\n /**\n * Callback when tokens are updated (login/refresh)\n */\n onTokensUpdated?: (accessToken: string, refreshToken: string) => void;\n\n /**\n * Callback when tokens are cleared (logout/error)\n */\n onTokensCleared?: () => void;\n}\n\n/**\n * Main SDK class for the POS API\n * Provides access to all POS endpoints through a single client\n */\nexport class PosSDK {\n /**\n * Client for all POS operations (auth, cart, orders, etc.)\n */\n public readonly pos: PosClient;\n\n /**\n * Create a new PosSDK instance\n *\n * @param options - Configuration options for the SDK\n */\n constructor(options: PosSDKOptions) {\n // Convert options to internal config format\n const config: PosSDKOptions = {\n storeId: options.storeId,\n environment: options.environment,\n baseUrl: options.baseUrl,\n accessToken: options.accessToken,\n refreshToken: options.refreshToken,\n apiKey: options.apiKey,\n timeout: options.timeout,\n tokenStorage: options.tokenStorage,\n onTokensUpdated: options.onTokensUpdated,\n onTokensCleared: options.onTokensCleared,\n defaultHeaders: options.defaultHeaders,\n debug: options.debug,\n logger: options.logger,\n };\n\n this.pos = new PosClient(config);\n }\n\n /**\n * Set authentication tokens for the client\n *\n * @param accessToken - The access token (required)\n * @param refreshToken - The refresh token (optional)\n *\n * Behavior:\n * - If tokenStorage is provided: Stores tokens for automatic management\n * - If tokenStorage is not provided: Only stores access token for manual management\n */\n public async setTokens(\n accessToken: string,\n refreshToken?: string\n ): Promise<void> {\n await this.pos.setTokens(accessToken, refreshToken);\n }\n\n /**\n * Clear all authentication tokens from the client\n *\n * Behavior:\n * - If tokenStorage is provided: Clears both access and refresh tokens from storage\n * - If tokenStorage is not provided: Clears the manual access token\n */\n public async clearTokens(): Promise<void> {\n await this.pos.clearTokens();\n }\n\n /**\n * Set the API key for the client\n *\n * @param apiKey - The API key to set\n */\n public setApiKey(apiKey: string): void {\n this.pos.setApiKey(apiKey);\n }\n\n\n /**\n * Get the current access token if available\n */\n public async getAccessToken(): Promise<string | null> {\n const header = await this.pos.getAuthorizationHeader();\n return header.startsWith(\"Bearer \") ? header.substring(7) : null;\n }\n\n /**\n * Set default headers for the client\n *\n * @param headers - Default headers to set\n */\n public setDefaultHeaders(headers: SupportedDefaultHeaders): void {\n this.pos.setDefaultHeaders(headers);\n }\n\n /**\n * Get current default headers\n */\n public getDefaultHeaders(): SupportedDefaultHeaders | undefined {\n return this.pos.getDefaultHeaders();\n }\n\n /**\n * Get user information from the current access token\n *\n * @returns User information extracted from JWT token, or null if no token or invalid token\n */\n public async getUserInfo(): Promise<UserInfo | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return extractUserInfoFromToken(token);\n }\n\n /**\n * Get the current user ID from the access token\n *\n * @returns User ID (ulid) or null if no token or invalid token\n */\n public async getUserId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getUserIdFromToken(token);\n }\n\n /**\n * Check if the current user is logged in\n *\n * @returns True if user is logged in, false otherwise\n */\n public async isLoggedIn(): Promise<boolean> {\n const token = await this.getAccessToken();\n if (!token) return false;\n return isUserLoggedIn(token);\n }\n\n /**\n * Check if the current user is authenticated with POS access\n * This verifies the user has valid device and role information\n *\n * @returns True if user is authenticated for POS operations\n */\n public async isAuthenticated(): Promise<boolean> {\n const token = await this.getAccessToken();\n if (!token) return false;\n return isUserAuthenticated(token);\n }\n\n /**\n * Get the device ID from the current access token\n * This is commonly needed for POS API requests\n *\n * @returns Device ID or null if no token or invalid token\n */\n public async getDeviceId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getDeviceIdFromToken(token);\n }\n\n /**\n * Get the location ID from the current access token\n * This is commonly needed for POS API requests\n *\n * @returns Location ID or null if no token or invalid token\n */\n public async getLocationId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getLocationIdFromToken(token);\n }\n\n /**\n * Get the role information from the current access token\n *\n * @returns Role object with id and name, or null if no token or invalid token\n */\n public async getRole(): Promise<{ id: string; name: string } | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getRoleFromToken(token);\n }\n\n /**\n * Get the tenant ID from the current access token\n *\n * @returns Tenant ID or null if no token or invalid token\n */\n public async getTenantId(): Promise<string | null> {\n const token = await this.getAccessToken();\n if (!token) return null;\n return getTenantIdFromToken(token);\n }\n}\n\n// Export the main SDK class as default\nexport default PosSDK;\n\n// Export individual clients for advanced usage\nexport {\n PosAPIClient,\n PosClient,\n ResponseUtils,\n};\n\n// Export environment enum\nexport { Environment } from \"./lib/utils/url\";\n\n// Export token storage types\nexport type { TokenStorage };\nexport { MemoryTokenStorage, BrowserTokenStorage };\n\n// Export logger types\nexport type { DebugLoggerFn } from \"@commercengine/sdk-core\";\n\n// Export POS-specific JWT types\nexport type { UserInfo } from \"./lib/utils/jwt\";\n\n// Export API types for consumer usage\nexport type { components, operations, paths } from \"./types/pos\";\nexport type * from \"./types/pos-api-types\";"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercengine/pos",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "TypeScript SDK for the POS API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",