@commercengine/js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,367 @@
1
+ # @commercengine/js
2
+
3
+ Embed Commerce Engine checkout in any website.
4
+
5
+ ## Installation
6
+
7
+ ### CDN (Recommended)
8
+
9
+ ```html
10
+ <script src="https://js.commercengine.com/v1.js" async></script>
11
+ ```
12
+
13
+ ### npm
14
+
15
+ ```bash
16
+ npm install @commercengine/js
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```html
22
+ <script src="https://js.commercengine.com/v1.js" async></script>
23
+ <script>
24
+ window.Commercengine.onLoad = async () => {
25
+ const checkout = await Commercengine.init({
26
+ storeId: "store_xxx",
27
+ apiKey: "ak_xxx",
28
+ });
29
+
30
+ document.getElementById("cart-btn").onclick = () => checkout.openCart();
31
+ };
32
+ </script>
33
+ ```
34
+
35
+ ## Configuration
36
+
37
+ ### CheckoutConfig
38
+
39
+ ```typescript
40
+ interface CheckoutConfig {
41
+ // === Credentials (required) ===
42
+ storeId: string; // Your Commerce Engine Store ID
43
+ apiKey: string; // Your Commerce Engine API Key
44
+
45
+ // === Development ===
46
+ url?: string; // Direct checkout URL (local dev only)
47
+ // If provided, storeId/apiKey are optional
48
+
49
+ // === Theme ===
50
+ theme?: "light" | "dark" | "system"; // Default: "system"
51
+
52
+ // === Appearance ===
53
+ appearance?: {
54
+ zIndex?: number; // Overlay z-index. Default: 99999
55
+ };
56
+
57
+ // === Authentication ===
58
+ authMode?: "managed" | "provided"; // Default: "managed"
59
+ accessToken?: string; // Initial access token (if user logged in)
60
+ refreshToken?: string; // Initial refresh token
61
+
62
+ // === Quick Buy (add item on init) ===
63
+ quickBuy?: {
64
+ productId: string; // Product ID (required)
65
+ variantId: string | null; // Variant ID (required, null for non-variant)
66
+ quantity?: number; // Default: 1
67
+ };
68
+ sessionMode?: "continue-existing" | "force-new"; // Default: "continue-existing"
69
+ autoDetectQuickBuy?: boolean; // Auto-detect from parent URL. Default: false
70
+
71
+ // === Callbacks ===
72
+ onReady?: () => void;
73
+ onOpen?: () => void;
74
+ onClose?: () => void;
75
+ onComplete?: (order: OrderData) => void;
76
+ onCartUpdate?: (cart: CartData) => void;
77
+ onAuthChange?: (auth: AuthChangeData) => void;
78
+ }
79
+ ```
80
+
81
+ ### Example: Full Configuration
82
+
83
+ ```typescript
84
+ const checkout = await Commercengine.init({
85
+ storeId: "store_xxx",
86
+ apiKey: "ak_xxx",
87
+ theme: "dark",
88
+ appearance: {
89
+ zIndex: 100000,
90
+ },
91
+ accessToken: userSession?.accessToken,
92
+ refreshToken: userSession?.refreshToken,
93
+ onReady: () => {
94
+ console.log("Checkout loaded");
95
+ },
96
+ onComplete: (order) => {
97
+ window.location.href = `/thank-you?order=${order.orderNumber}`;
98
+ },
99
+ onCartUpdate: (cart) => {
100
+ updateCartBadge(cart.count);
101
+ },
102
+ onAuthChange: ({ type, accessToken }) => {
103
+ if (type === "login") {
104
+ // User logged in via checkout - sync to your auth system
105
+ saveUserSession(accessToken);
106
+ } else if (type === "logout") {
107
+ clearUserSession();
108
+ }
109
+ },
110
+ });
111
+ ```
112
+
113
+ ## Methods
114
+
115
+ ### `openCart()`
116
+
117
+ Open the cart drawer.
118
+
119
+ ```typescript
120
+ checkout.openCart();
121
+ ```
122
+
123
+ ### `openCheckout()`
124
+
125
+ Open checkout directly, bypassing cart. Use for "Buy Now" flows.
126
+
127
+ ```typescript
128
+ checkout.openCheckout();
129
+ ```
130
+
131
+ ### `close()`
132
+
133
+ Close the checkout overlay.
134
+
135
+ ```typescript
136
+ checkout.close();
137
+ ```
138
+
139
+ ### `updateTokens(accessToken, refreshToken?)`
140
+
141
+ Sync authentication state from parent site. Call when user logs in/out on your site.
142
+
143
+ ```typescript
144
+ // When user logs in on your site
145
+ checkout.updateTokens(session.accessToken, session.refreshToken);
146
+
147
+ // When user logs out
148
+ checkout.updateTokens("", "");
149
+ ```
150
+
151
+ ### `addToCart(productId, variantId, quantity?)`
152
+
153
+ Add an item to cart and open the cart drawer. This is the canonical implementation of "quick buy" functionality.
154
+
155
+ ```typescript
156
+ // Add a product (non-variant)
157
+ checkout.addToCart("prod_123", null, 1);
158
+
159
+ // Add a product variant
160
+ checkout.addToCart("prod_123", "var_456", 2);
161
+
162
+ // Quantity defaults to 1
163
+ checkout.addToCart("prod_123", "var_456");
164
+ ```
165
+
166
+ **Parameters:**
167
+ - `productId` (string, required) - Product ID
168
+ - `variantId` (string | null, required) - Variant ID, or `null` for non-variant products
169
+ - `quantity` (number, optional) - Quantity to add, defaults to 1
170
+
171
+ **Behavior:**
172
+ - Adds item to cart and automatically opens the cart drawer
173
+ - If item already in cart: adds to existing quantity
174
+ - If item not in cart: adds new item
175
+ - If no cart exists: creates cart with the item
176
+
177
+ ### `getCart()`
178
+
179
+ Get current cart state.
180
+
181
+ ```typescript
182
+ const cart = checkout.getCart();
183
+ console.log(cart.count, cart.total, cart.currency);
184
+ ```
185
+
186
+ ### `destroy()`
187
+
188
+ Remove checkout iframe and cleanup event listeners.
189
+
190
+ ```typescript
191
+ checkout.destroy();
192
+ ```
193
+
194
+ ## Properties
195
+
196
+ | Property | Type | Description |
197
+ |----------|------|-------------|
198
+ | `ready` | `boolean` | Whether checkout is initialized and ready |
199
+ | `open` | `boolean` | Whether checkout overlay is currently visible |
200
+
201
+ ## Events
202
+
203
+ Subscribe via callbacks (in config) or the event emitter.
204
+
205
+ ### Event Types
206
+
207
+ | Event | Callback | Data | Description |
208
+ |-------|----------|------|-------------|
209
+ | `ready` | `onReady` | - | Checkout iframe loaded |
210
+ | `open` | `onOpen` | - | Drawer opened |
211
+ | `close` | `onClose` | - | All drawers closed |
212
+ | `complete` | `onComplete` | `OrderData` | Order placed successfully |
213
+ | `cart:updated` | `onCartUpdate` | `CartData` | Cart state changed |
214
+ | `auth:change` | `onAuthChange` | `AuthChangeData` | Auth state changed |
215
+
216
+ ### Event Data Types
217
+
218
+ ```typescript
219
+ interface OrderData {
220
+ id: string; // Order ID
221
+ orderNumber: string; // Human-readable order number
222
+ }
223
+
224
+ interface CartData {
225
+ count: number; // Number of items
226
+ total: number; // Subtotal amount
227
+ currency: string; // Currency code (e.g., "USD", "INR")
228
+ }
229
+
230
+ interface AuthChangeData {
231
+ type: "login" | "logout" | "refresh";
232
+ accessToken?: string; // New token (on login/refresh)
233
+ refreshToken?: string; // New refresh token
234
+ }
235
+ ```
236
+
237
+ ### Event Emitter API
238
+
239
+ ```typescript
240
+ // Subscribe
241
+ checkout.on("cart:updated", (cart) => {
242
+ console.log("Cart:", cart.count, cart.total);
243
+ });
244
+
245
+ // Subscribe once
246
+ checkout.once("complete", (order) => {
247
+ console.log("Order:", order.orderNumber);
248
+ });
249
+
250
+ // Unsubscribe
251
+ const handler = (cart) => console.log(cart);
252
+ checkout.on("cart:updated", handler);
253
+ checkout.off("cart:updated", handler);
254
+ ```
255
+
256
+ ## Authentication Flow
257
+
258
+ ### Scenario 1: User Not Logged In
259
+
260
+ User will be prompted to login within checkout (WhatsApp, Phone, or Email OTP).
261
+
262
+ ```typescript
263
+ const checkout = await Commercengine.init({
264
+ storeId: "store_xxx",
265
+ apiKey: "ak_xxx",
266
+ onAuthChange: ({ type, accessToken, refreshToken }) => {
267
+ if (type === "login") {
268
+ // Save tokens to your auth system
269
+ saveSession({ accessToken, refreshToken });
270
+ }
271
+ },
272
+ });
273
+ ```
274
+
275
+ ### Scenario 2: User Already Logged In
276
+
277
+ Pass tokens to skip login screen.
278
+
279
+ ```typescript
280
+ const checkout = await Commercengine.init({
281
+ storeId: "store_xxx",
282
+ apiKey: "ak_xxx",
283
+ accessToken: currentSession.accessToken,
284
+ refreshToken: currentSession.refreshToken,
285
+ });
286
+ ```
287
+
288
+ ### Scenario 3: Sync Auth Changes
289
+
290
+ When user logs in/out on your site, sync to checkout.
291
+
292
+ ```typescript
293
+ // User logs in on your site
294
+ myAuth.onLogin((session) => {
295
+ checkout.updateTokens(session.accessToken, session.refreshToken);
296
+ });
297
+
298
+ // User logs out on your site
299
+ myAuth.onLogout(() => {
300
+ checkout.updateTokens("", "");
301
+ });
302
+ ```
303
+
304
+ ## TypeScript
305
+
306
+ All types are exported:
307
+
308
+ ```typescript
309
+ import {
310
+ Commercengine,
311
+ Checkout,
312
+ type CheckoutConfig,
313
+ type CheckoutEventType,
314
+ type CartData,
315
+ type OrderData,
316
+ type AuthChangeData,
317
+ } from "@commercengine/js";
318
+ ```
319
+
320
+ ## URL Parameters (Advanced)
321
+
322
+ For direct iframe integration without the SDK, checkout accepts these URL parameters:
323
+
324
+ | Parameter | Description | Example |
325
+ |-----------|-------------|---------|
326
+ | `store_id` | Store ID | `store_xxx` |
327
+ | `api_key` | API Key | `ak_xxx` |
328
+ | `mode` | Deployment mode | `iframe` |
329
+ | `parent_origin` | Parent origin for postMessage | `https://brand.com` |
330
+ | `theme` | Theme preference | `light`, `dark` |
331
+ | `token` | Access token | JWT string |
332
+ | `refresh_token` | Refresh token | JWT string |
333
+ | `auth_mode` | Auth management | `provided`, `managed` |
334
+ | `product_id` | Quick buy product | Product ID |
335
+ | `variant_id` | Quick buy variant | Variant ID |
336
+ | `qty` | Quick buy quantity | `1` |
337
+ | `session_mode` | Session behavior | `continue-existing`, `force-new` |
338
+
339
+ ### Auth Modes
340
+
341
+ - **`managed`** (default): Checkout manages token lifecycle with auto-refresh
342
+ - **`provided`**: Parent manages tokens. Checkout uses in-memory only, syncs changes via events
343
+
344
+ ### Session Modes
345
+
346
+ - **`continue-existing`** (default): Add quick-buy item to existing cart
347
+ - **`force-new`**: Delete existing cart and start fresh with only the quick-buy item
348
+
349
+ **Note:** When quick buy params are provided (via config or auto-detected), the cart drawer automatically opens once checkout is ready.
350
+
351
+ ### Auto-Detect Quick Buy
352
+
353
+ For ad-driven traffic, enable `autoDetectQuickBuy` to automatically parse quick buy params from the parent page URL:
354
+
355
+ ```typescript
356
+ // Ad link: https://brand.com?product_id=prod_123&variant_id=var_456&qty=2
357
+
358
+ const checkout = await Commercengine.init({
359
+ storeId: "store_xxx",
360
+ apiKey: "ak_xxx",
361
+ autoDetectQuickBuy: true, // Reads product_id, variant_id, qty from parent URL
362
+ });
363
+ ```
364
+
365
+ This allows embedded checkout to handle ad clicks natively without custom URL parsing.
366
+
367
+ **URL Cleanup:** When quick buy params are detected, they are automatically removed from the browser URL (using `replaceState`) to prevent duplicate adds on page refresh.