@nymbalhq/sdk 1.3.0 → 1.5.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.
Files changed (44) hide show
  1. package/dist/chunk-333Z6VKZ.js +133 -0
  2. package/dist/chunk-333Z6VKZ.js.map +1 -0
  3. package/dist/chunk-4GP43MKT.js +19 -0
  4. package/dist/chunk-4GP43MKT.js.map +1 -0
  5. package/dist/chunk-BAWTE4QS.js +113 -0
  6. package/dist/chunk-BAWTE4QS.js.map +1 -0
  7. package/dist/chunk-EFRWJT3L.js +520 -0
  8. package/dist/chunk-EFRWJT3L.js.map +1 -0
  9. package/dist/chunk-FWEQBOEX.js +92 -0
  10. package/dist/chunk-FWEQBOEX.js.map +1 -0
  11. package/dist/chunk-KRVUYBKB.js +118 -0
  12. package/dist/chunk-KRVUYBKB.js.map +1 -0
  13. package/dist/chunk-L7EZURSK.js +130 -0
  14. package/dist/chunk-L7EZURSK.js.map +1 -0
  15. package/dist/chunk-QUSTGYBM.js +52 -0
  16. package/dist/chunk-QUSTGYBM.js.map +1 -0
  17. package/dist/chunk-U6QF2DRY.js +30 -0
  18. package/dist/chunk-U6QF2DRY.js.map +1 -0
  19. package/dist/core-DCBjP2Ev.d.ts +523 -0
  20. package/dist/core.d.ts +2 -0
  21. package/dist/core.js +17 -0
  22. package/dist/core.js.map +1 -0
  23. package/dist/index.d.ts +4 -429
  24. package/dist/index.js +32 -974
  25. package/dist/index.js.map +1 -1
  26. package/dist/ns/auth.d.ts +2 -0
  27. package/dist/ns/auth.js +4 -0
  28. package/dist/ns/auth.js.map +1 -0
  29. package/dist/ns/cart.d.ts +2 -0
  30. package/dist/ns/cart.js +4 -0
  31. package/dist/ns/cart.js.map +1 -0
  32. package/dist/ns/checkout.d.ts +2 -0
  33. package/dist/ns/checkout.js +5 -0
  34. package/dist/ns/checkout.js.map +1 -0
  35. package/dist/ns/product-list.d.ts +2 -0
  36. package/dist/ns/product-list.js +4 -0
  37. package/dist/ns/product-list.js.map +1 -0
  38. package/dist/ns/product.d.ts +2 -0
  39. package/dist/ns/product.js +4 -0
  40. package/dist/ns/product.js.map +1 -0
  41. package/dist/ns/search.d.ts +2 -0
  42. package/dist/ns/search.js +4 -0
  43. package/dist/ns/search.js.map +1 -0
  44. package/package.json +17 -2
package/dist/index.js CHANGED
@@ -1,977 +1,35 @@
1
- // src/adapter/fetch-client.ts
2
- var NymbalApiError = class extends Error {
3
- constructor(code, message, status, context) {
4
- super(message);
5
- this.code = code;
6
- this.status = status;
7
- this.context = context;
8
- this.name = "NymbalApiError";
9
- }
10
- code;
11
- status;
12
- context;
13
- };
14
- var CSRF_HEADER = "x-csrf-token";
15
- var UNSAFE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
16
- var FetchClient = class {
17
- baseUrl;
18
- credentials;
19
- getAccessToken;
20
- getCartToken;
21
- onUnauthorized;
22
- handlingUnauthorized = false;
23
- /** The token `GET /api/csrf` answered: the API's `nymbal.csrf` cookie, which this origin may not be able to read. */
24
- csrfToken = null;
25
- constructor(options) {
26
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
27
- this.credentials = options.credentials ?? "include";
28
- this.getAccessToken = options.getAccessToken ?? (() => null);
29
- this.getCartToken = options.getCartToken;
30
- this.onUnauthorized = options.onUnauthorized;
31
- }
32
- async request(method, path, body) {
33
- return (await this.requestWithMeta(method, path, body)).data;
34
- }
35
- /** Like `request`, keeping the envelope's `meta` (pagination cursors live there). */
36
- async requestWithMeta(method, path, body) {
37
- let response = await this.doFetch(method, path, body);
38
- if (await this.isCsrfRejection(response)) {
39
- this.csrfToken = null;
40
- response = await this.doFetch(method, path, body);
41
- }
42
- if (response.status === 401 && this.onUnauthorized && !this.handlingUnauthorized) {
43
- this.handlingUnauthorized = true;
44
- try {
45
- await this.onUnauthorized();
46
- } finally {
47
- this.handlingUnauthorized = false;
48
- }
49
- const retry = await this.doFetch(method, path, body);
50
- return this.parseResponse(retry);
51
- }
52
- return this.parseResponse(response);
53
- }
54
- csrf() {
55
- this.csrfToken ??= this.fetchCsrfToken().catch((err) => {
56
- this.csrfToken = null;
57
- throw err;
58
- });
59
- return this.csrfToken;
60
- }
61
- async fetchCsrfToken() {
62
- const response = await globalThis.fetch(`${this.baseUrl}/api/csrf`, {
63
- method: "GET",
64
- credentials: this.credentials
65
- });
66
- const { data } = await this.parseResponse(response);
67
- return data.token;
68
- }
69
- async isCsrfRejection(response) {
70
- if (response.status !== 403) return false;
71
- const text = await response.clone().text();
72
- try {
73
- return JSON.parse(text).error?.code === "csrf.invalid";
74
- } catch {
75
- return false;
76
- }
77
- }
78
- async doFetch(method, path, body) {
79
- const headers = {};
80
- const cookies = [];
81
- if (UNSAFE_METHODS.has(method.toUpperCase())) {
82
- const csrf = await this.csrf();
83
- headers[CSRF_HEADER] = csrf;
84
- cookies.push(`nymbal.csrf=${csrf}`);
85
- }
86
- if (body !== void 0) {
87
- headers["Content-Type"] = "application/json";
88
- }
89
- const token = this.getAccessToken();
90
- if (token) {
91
- headers["Authorization"] = `Bearer ${token}`;
92
- }
93
- const cartToken = this.getCartToken?.();
94
- if (cartToken) {
95
- cookies.unshift(`nymbal.cart=${cartToken}`);
96
- }
97
- if (cookies.length > 0) {
98
- headers["Cookie"] = cookies.join("; ");
99
- }
100
- return globalThis.fetch(`${this.baseUrl}${path}`, {
101
- method,
102
- headers,
103
- credentials: this.credentials,
104
- ...body !== void 0 && { body: JSON.stringify(body) }
105
- });
106
- }
107
- async parseResponse(response) {
108
- const text = await response.text();
109
- if (!text) {
110
- return { data: void 0, meta: {} };
111
- }
112
- const envelope = JSON.parse(text);
113
- if (envelope.error) {
114
- throw new NymbalApiError(
115
- envelope.error.code,
116
- envelope.error.message,
117
- response.status,
118
- envelope.error.context
119
- );
120
- }
121
- return { data: envelope.data, meta: envelope.meta ?? {} };
122
- }
123
- };
124
-
125
- // src/adapter/nymbal-api-adapter.ts
126
- function createNymbalApiAdapter(fetchClient) {
127
- return {
128
- capabilities: {
129
- get() {
130
- return fetchClient.request("GET", "/api/capabilities");
131
- }
132
- },
133
- cart: {
134
- get() {
135
- return fetchClient.request("GET", "/api/cart");
136
- },
137
- addItem(variantId, qty) {
138
- return fetchClient.request("POST", "/api/cart/items", { variantId, qty });
139
- },
140
- removeItem(variantId) {
141
- return fetchClient.request(
142
- "DELETE",
143
- `/api/cart/items/${encodeURIComponent(variantId)}`
144
- );
145
- },
146
- updateQuantity(variantId, qty) {
147
- return fetchClient.request(
148
- "PATCH",
149
- `/api/cart/items/${encodeURIComponent(variantId)}`,
150
- { qty }
151
- );
152
- },
153
- clear() {
154
- return fetchClient.request("DELETE", "/api/cart");
155
- }
156
- },
157
- products: {
158
- getBySlug(slug) {
159
- return fetchClient.request(
160
- "GET",
161
- `/api/products/${encodeURIComponent(slug)}`
162
- );
163
- },
164
- list(params) {
165
- const search = new URLSearchParams();
166
- if (params?.limit !== void 0) search.set("limit", String(params.limit));
167
- if (params?.cursor !== void 0) search.set("cursor", params.cursor);
168
- if (params?.category !== void 0) search.set("category", params.category);
169
- if (params?.sort !== void 0) search.set("sort", params.sort);
170
- const qs = search.toString();
171
- return fetchClient.request("GET", `/api/products${qs ? `?${qs}` : ""}`);
172
- },
173
- search(query, params) {
174
- const search = new URLSearchParams();
175
- search.set("q", query);
176
- if (params?.limit !== void 0) search.set("limit", String(params.limit));
177
- if (params?.cursor !== void 0) search.set("cursor", params.cursor);
178
- if (params?.category !== void 0) search.set("category", params.category);
179
- return fetchClient.request(
180
- "GET",
181
- `/api/products/search?${search.toString()}`
182
- );
183
- }
184
- },
185
- checkout: {
186
- create(details) {
187
- return fetchClient.request("POST", "/api/checkout", details);
188
- }
189
- },
190
- customers: {
191
- register(params) {
192
- return fetchClient.request("POST", "/api/auth/register", params);
193
- },
194
- login(email, password) {
195
- return fetchClient.request("POST", "/api/auth/login", { email, password });
196
- },
197
- async logout() {
198
- await fetchClient.request("POST", "/api/auth/logout");
199
- },
200
- refresh() {
201
- return fetchClient.request(
202
- "POST",
203
- "/api/auth/refresh"
204
- );
205
- },
206
- getProfile() {
207
- return fetchClient.request("GET", "/api/customers/me");
208
- },
209
- updateProfile(updates) {
210
- return fetchClient.request("PATCH", "/api/customers/me", updates);
211
- },
212
- listAddresses() {
213
- return fetchClient.request("GET", "/api/customers/me/addresses");
214
- },
215
- addAddress(address) {
216
- return fetchClient.request("POST", "/api/customers/me/addresses", address);
217
- },
218
- async removeAddress(id) {
219
- await fetchClient.request(
220
- "DELETE",
221
- `/api/customers/me/addresses/${encodeURIComponent(id)}`
222
- );
223
- },
224
- async listOrders(params) {
225
- const qs = params?.cursor !== void 0 ? `?cursor=${encodeURIComponent(params.cursor)}` : "";
226
- const { data, meta } = await fetchClient.requestWithMeta("GET", `/api/orders${qs}`);
227
- const nextCursor = typeof meta.nextCursor === "string" ? meta.nextCursor : null;
228
- return { items: data ?? [], nextCursor };
229
- },
230
- getOrder(orderNumber) {
231
- return fetchClient.request("GET", `/api/orders/${encodeURIComponent(orderNumber)}`);
232
- }
233
- },
234
- reviews: {
235
- getForProduct(productId, params) {
236
- const search = new URLSearchParams();
237
- if (params?.limit !== void 0) search.set("limit", String(params.limit));
238
- if (params?.cursor !== void 0) search.set("cursor", params.cursor);
239
- const qs = search.toString();
240
- return fetchClient.request(
241
- "GET",
242
- `/api/products/${encodeURIComponent(productId)}/reviews${qs ? `?${qs}` : ""}`
243
- );
244
- },
245
- submit(review) {
246
- return fetchClient.request("POST", "/api/reviews", review);
247
- }
248
- }
249
- };
250
- }
251
-
252
- // src/auth/token-manager.ts
253
- var DEFAULT_STORAGE_KEY = "nymbal.auth.accessToken";
254
- function createTokenManager(options) {
255
- const storageMode = options?.storage ?? "memory";
256
- const storageKey = options?.storageKey ?? DEFAULT_STORAGE_KEY;
257
- let memoryToken = null;
258
- let refreshTimer = null;
259
- let refreshFn = null;
260
- function getAccessToken() {
261
- if (storageMode === "localStorage" && typeof globalThis.localStorage !== "undefined") {
262
- return globalThis.localStorage.getItem(storageKey);
263
- }
264
- return memoryToken;
265
- }
266
- function setAccessToken(token) {
267
- memoryToken = token;
268
- if (storageMode === "localStorage" && typeof globalThis.localStorage !== "undefined") {
269
- if (token) {
270
- globalThis.localStorage.setItem(storageKey, token);
271
- } else {
272
- globalThis.localStorage.removeItem(storageKey);
273
- }
274
- }
275
- }
276
- function setTokens(accessToken, expiresIn) {
277
- setAccessToken(accessToken);
278
- scheduleAutoRefresh(expiresIn);
279
- }
280
- function clear() {
281
- setAccessToken(null);
282
- if (refreshTimer !== null) {
283
- clearTimeout(refreshTimer);
284
- refreshTimer = null;
285
- }
286
- }
287
- function scheduleAutoRefresh(expiresIn) {
288
- if (refreshTimer !== null) {
289
- clearTimeout(refreshTimer);
290
- }
291
- const delayMs = Math.max(1e3, expiresIn * 0.8 * 1e3);
292
- refreshTimer = setTimeout(async () => {
293
- if (!refreshFn) return;
294
- try {
295
- const result = await refreshFn();
296
- setTokens(result.accessToken, result.expiresIn);
297
- } catch (err) {
298
- console.error("[TokenManager] auto-refresh failed, clearing session", err);
299
- clear();
300
- }
301
- }, delayMs);
302
- }
303
- function scheduleRefresh(fn) {
304
- refreshFn = fn;
305
- }
306
- function destroy() {
307
- clear();
308
- refreshFn = null;
309
- }
310
- return { getAccessToken, setTokens, clear, scheduleRefresh, destroy };
311
- }
312
-
313
- // src/store/create-store.ts
314
- function createStore(initialState) {
315
- let state = initialState;
316
- const listeners = /* @__PURE__ */ new Set();
317
- function getState() {
318
- return state;
319
- }
320
- function setState(partial) {
321
- const next = typeof partial === "function" ? partial(state) : partial;
322
- state = { ...state, ...next };
323
- for (const listener of listeners) {
324
- listener();
325
- }
326
- }
327
- function subscribe(listener) {
328
- listeners.add(listener);
329
- return () => {
330
- listeners.delete(listener);
331
- };
332
- }
333
- function destroy() {
334
- listeners.clear();
335
- }
336
- return { getState, setState, subscribe, destroy };
337
- }
338
-
339
- // src/store/cart-store.ts
340
- function deriveItemCount(items) {
341
- let count = 0;
342
- for (const item of items) {
343
- count += item.qty;
344
- }
345
- return count;
346
- }
347
- var INITIAL_STATE = {
348
- items: [],
349
- subtotalMinor: 0,
350
- currency: "USD",
351
- itemCount: 0,
352
- loading: false,
353
- error: null
354
- };
355
- function createCartStore(adapter) {
356
- const store = createStore(INITIAL_STATE);
357
- async function load() {
358
- store.setState({ loading: true, error: null });
359
- try {
360
- const cart = await adapter.cart.get();
361
- store.setState({
362
- items: cart.items,
363
- subtotalMinor: cart.subtotalMinor,
364
- currency: cart.currency,
365
- itemCount: deriveItemCount(cart.items),
366
- loading: false
367
- });
368
- } catch (err) {
369
- store.setState({
370
- loading: false,
371
- error: err instanceof Error ? err.message : String(err)
372
- });
373
- }
374
- }
375
- async function addItem(variantId, qty = 1) {
376
- store.setState({ loading: true, error: null });
377
- try {
378
- const cart = await adapter.cart.addItem(variantId, qty);
379
- store.setState({
380
- items: cart.items,
381
- subtotalMinor: cart.subtotalMinor,
382
- currency: cart.currency,
383
- itemCount: deriveItemCount(cart.items),
384
- loading: false
385
- });
386
- } catch (err) {
387
- store.setState({
388
- loading: false,
389
- error: err instanceof Error ? err.message : String(err)
390
- });
391
- }
392
- }
393
- async function removeItem(variantId) {
394
- store.setState({ loading: true, error: null });
395
- try {
396
- const cart = await adapter.cart.removeItem(variantId);
397
- store.setState({
398
- items: cart.items,
399
- subtotalMinor: cart.subtotalMinor,
400
- currency: cart.currency,
401
- itemCount: deriveItemCount(cart.items),
402
- loading: false
403
- });
404
- } catch (err) {
405
- store.setState({
406
- loading: false,
407
- error: err instanceof Error ? err.message : String(err)
408
- });
409
- }
410
- }
411
- async function updateQuantity(variantId, qty) {
412
- store.setState({ loading: true, error: null });
413
- try {
414
- const cart = await adapter.cart.updateQuantity(variantId, qty);
415
- store.setState({
416
- items: cart.items,
417
- subtotalMinor: cart.subtotalMinor,
418
- currency: cart.currency,
419
- itemCount: deriveItemCount(cart.items),
420
- loading: false
421
- });
422
- } catch (err) {
423
- store.setState({
424
- loading: false,
425
- error: err instanceof Error ? err.message : String(err)
426
- });
427
- }
428
- }
429
- async function clear() {
430
- store.setState({ loading: true, error: null });
431
- try {
432
- await adapter.cart.clear();
433
- store.setState({
434
- items: [],
435
- subtotalMinor: 0,
436
- itemCount: 0,
437
- loading: false
438
- });
439
- } catch (err) {
440
- store.setState({
441
- loading: false,
442
- error: err instanceof Error ? err.message : String(err)
443
- });
444
- }
445
- }
446
- return {
447
- getState: store.getState,
448
- subscribe: store.subscribe,
449
- addItem,
450
- removeItem,
451
- updateQuantity,
452
- clear,
453
- load,
454
- destroy: store.destroy
455
- };
456
- }
457
-
458
- // src/store/product-store.ts
459
- var INITIAL_STATE2 = {
460
- product: null,
461
- selectedVariant: null,
462
- loading: false,
463
- error: null
464
- };
465
- function createProductStore(adapter) {
466
- const store = createStore(INITIAL_STATE2);
467
- async function loadBySlug(slug) {
468
- store.setState({ loading: true, error: null });
469
- try {
470
- const product = await adapter.products.getBySlug(slug);
471
- const firstVariant = product.variants[0] ?? null;
472
- store.setState({
473
- product,
474
- selectedVariant: firstVariant,
475
- loading: false
476
- });
477
- } catch (err) {
478
- store.setState({
479
- loading: false,
480
- error: err instanceof Error ? err.message : String(err)
481
- });
482
- }
483
- }
484
- function selectVariant(variant) {
485
- store.setState({ selectedVariant: variant });
486
- }
487
- return {
488
- getState: store.getState,
489
- subscribe: store.subscribe,
490
- loadBySlug,
491
- selectVariant,
492
- destroy: store.destroy
493
- };
494
- }
495
-
496
- // src/store/product-list-store.ts
497
- import { DEFAULT_PRODUCT_SORT } from "@nymbalhq/types";
498
- var INITIAL_STATE3 = {
499
- products: [],
500
- facets: [],
501
- filters: {},
502
- sort: DEFAULT_PRODUCT_SORT,
503
- pagination: { cursor: null, hasMore: false },
504
- loading: false,
505
- error: null
506
- };
507
- function createProductListStore(adapter) {
508
- const store = createStore(INITIAL_STATE3);
509
- let lastLimit;
510
- let generation = 0;
511
- function buildParams() {
512
- const state = store.getState();
513
- const params = { sort: state.sort };
514
- if (lastLimit !== void 0) params.limit = lastLimit;
515
- const category = state.filters["category"];
516
- if (typeof category === "string") {
517
- params.category = category;
518
- }
519
- return params;
520
- }
521
- async function load(params) {
522
- if (params !== void 0) {
523
- if (params.limit !== void 0) lastLimit = params.limit;
524
- const filters = { ...store.getState().filters };
525
- if (params.category !== void 0) filters["category"] = params.category;
526
- else delete filters["category"];
527
- store.setState({ filters, sort: params.sort ?? DEFAULT_PRODUCT_SORT, loading: true });
528
- }
529
- const request = buildParams();
530
- if (params?.cursor !== void 0) request.cursor = params.cursor;
531
- const current = ++generation;
532
- store.setState({ loading: true });
533
- try {
534
- const result = await adapter.products.list(request);
535
- if (current !== generation) return;
536
- store.setState({
537
- products: result.items,
538
- facets: result.facets ?? store.getState().facets,
539
- pagination: { cursor: result.nextCursor, hasMore: result.nextCursor !== null },
540
- loading: false,
541
- error: null
542
- });
543
- } catch (err) {
544
- if (current !== generation) return;
545
- console.error("[ProductListStore] load failed", err);
546
- store.setState({ loading: false, error: err instanceof Error ? err.message : String(err) });
547
- }
548
- }
549
- async function loadMore() {
550
- const state = store.getState();
551
- if (!state.pagination.hasMore || state.loading) return;
552
- const current = ++generation;
553
- store.setState({ loading: true });
554
- try {
555
- const params = buildParams();
556
- if (state.pagination.cursor !== null) {
557
- params.cursor = state.pagination.cursor;
558
- }
559
- const result = await adapter.products.list(params);
560
- if (current !== generation) return;
561
- store.setState({
562
- products: [...state.products, ...result.items],
563
- pagination: { cursor: result.nextCursor, hasMore: result.nextCursor !== null },
564
- loading: false,
565
- error: null
566
- });
567
- } catch (err) {
568
- if (current !== generation) return;
569
- console.error("[ProductListStore] loadMore failed", err);
570
- store.setState({ loading: false, error: err instanceof Error ? err.message : String(err) });
571
- }
572
- }
573
- async function applyFilter(name, value) {
574
- const filters = { ...store.getState().filters, [name]: value };
575
- store.setState({ filters });
576
- await load();
577
- }
578
- async function removeFilter(name) {
579
- const filters = { ...store.getState().filters };
580
- delete filters[name];
581
- store.setState({ filters });
582
- await load();
583
- }
584
- async function setSort(sort) {
585
- store.setState({ sort });
586
- await load();
587
- }
588
- return {
589
- getState: store.getState,
590
- subscribe: store.subscribe,
591
- load,
592
- loadMore,
593
- applyFilter,
594
- removeFilter,
595
- setSort,
596
- destroy: store.destroy
597
- };
598
- }
599
-
600
- // src/store/search-store.ts
601
- var INITIAL_STATE4 = {
602
- query: "",
603
- category: null,
604
- results: [],
605
- total: 0,
606
- nextCursor: null,
607
- facets: [],
608
- loading: false
609
- };
610
- function createSearchStore(adapter) {
611
- const store = createStore(INITIAL_STATE4);
612
- let generation = 0;
613
- async function search(query, options) {
614
- const run = ++generation;
615
- if (!query.trim()) {
616
- store.setState({ ...INITIAL_STATE4 });
617
- return;
618
- }
619
- const category = options?.category ?? null;
620
- store.setState({ query, category, loading: true });
621
- try {
622
- const result = await (category === null ? adapter.products.search(query) : adapter.products.search(query, { category }));
623
- if (run !== generation) return;
624
- store.setState({
625
- results: result.items,
626
- total: result.total,
627
- nextCursor: result.nextCursor,
628
- facets: result.facets ?? [],
629
- loading: false
630
- });
631
- } catch (err) {
632
- if (run !== generation) return;
633
- console.error("[SearchStore] search failed", err);
634
- store.setState({ loading: false });
635
- }
636
- }
637
- async function loadMore() {
638
- const { query, category, nextCursor, loading } = store.getState();
639
- if (nextCursor === null || loading) return;
640
- const run = generation;
641
- store.setState({ loading: true });
642
- try {
643
- const result = await adapter.products.search(query, {
644
- cursor: nextCursor,
645
- ...category !== null && { category }
646
- });
647
- if (run !== generation) return;
648
- store.setState({
649
- results: [...store.getState().results, ...result.items],
650
- total: result.total,
651
- nextCursor: result.nextCursor,
652
- loading: false
653
- });
654
- } catch (err) {
655
- if (run !== generation) return;
656
- console.error("[SearchStore] load more failed", err);
657
- store.setState({ loading: false });
658
- }
659
- }
660
- function setCategory(category) {
661
- return search(store.getState().query, { category });
662
- }
663
- function clearSearch() {
664
- generation++;
665
- store.setState({ ...INITIAL_STATE4 });
666
- }
667
- return {
668
- getState: store.getState,
669
- subscribe: store.subscribe,
670
- search,
671
- loadMore,
672
- setCategory,
673
- clearSearch,
674
- destroy: store.destroy
675
- };
676
- }
677
-
678
- // src/store/checkout-store.ts
679
- var INITIAL_STATE5 = {
680
- step: "contact",
681
- email: "",
682
- shippingAddress: null,
683
- billingAddress: null,
684
- shippingMethod: null,
685
- paymentStatus: "idle",
686
- error: null,
687
- order: null,
688
- placedOrderNumber: null
689
- };
690
- function namedOrder(err) {
691
- if (!(err instanceof NymbalApiError)) return null;
692
- const orderNumber = err.context?.["orderNumber"];
693
- return typeof orderNumber === "string" ? orderNumber : null;
694
- }
695
- function createCheckoutStore(adapter, cart) {
696
- const store = createStore(INITIAL_STATE5);
697
- function setEmail(email) {
698
- store.setState({ email, step: "shipping" });
699
- }
700
- function setShippingAddress(address) {
701
- store.setState({ shippingAddress: address });
702
- }
703
- function setBillingAddress(address) {
704
- store.setState({ billingAddress: address });
705
- }
706
- function setShippingMethod(method) {
707
- store.setState({ shippingMethod: method, step: "payment" });
708
- }
709
- async function submitPayment() {
710
- const state = store.getState();
711
- if (!state.shippingAddress || !state.billingAddress) {
712
- store.setState({ error: "Shipping and billing addresses are required" });
713
- return null;
714
- }
715
- store.setState({ paymentStatus: "processing", error: null, placedOrderNumber: null });
716
- try {
717
- const result = await adapter.checkout.create({
718
- email: state.email,
719
- billingAddress: state.billingAddress,
720
- shippingAddress: state.shippingAddress
721
- });
722
- const { status, reason } = result.payment;
723
- store.setState({
724
- paymentStatus: status,
725
- order: {
726
- orderId: result.orderId,
727
- orderNumber: result.orderNumber,
728
- paymentIntent: result.paymentIntent
729
- },
730
- error: status === "failed" ? `Your payment did not go through${reason ? ` (${reason})` : ""}. Please try again.` : null,
731
- ...status === "succeeded" && { step: "confirmation" }
732
- });
733
- await cart?.load();
734
- return result;
735
- } catch (err) {
736
- const placedOrderNumber = namedOrder(err);
737
- store.setState({
738
- paymentStatus: "failed",
739
- error: err instanceof Error ? err.message : String(err),
740
- placedOrderNumber
741
- });
742
- if (placedOrderNumber !== null) await cart?.load();
743
- return null;
744
- }
745
- }
746
- function markConfirmed() {
747
- store.setState({ paymentStatus: "succeeded", step: "confirmation" });
748
- }
749
- function reset() {
750
- store.setState(INITIAL_STATE5);
751
- }
752
- return {
753
- getState: store.getState,
754
- subscribe: store.subscribe,
755
- setEmail,
756
- setShippingAddress,
757
- setBillingAddress,
758
- setShippingMethod,
759
- submitPayment,
760
- markConfirmed,
761
- reset,
762
- destroy: store.destroy
763
- };
764
- }
765
-
766
- // src/store/auth-store.ts
767
- var INITIAL_STATE6 = {
768
- customer: null,
769
- isAuthenticated: false,
770
- loading: false,
771
- error: null
772
- };
773
- function createAuthStore(adapter, tokenManager) {
774
- const store = createStore(INITIAL_STATE6);
775
- async function login(email, password) {
776
- store.setState({ loading: true, error: null });
777
- try {
778
- const result = await adapter.customers.login(email, password);
779
- tokenManager.setTokens(result.accessToken, result.expiresIn);
780
- store.setState({
781
- customer: result.customer,
782
- isAuthenticated: true,
783
- loading: false
784
- });
785
- } catch (err) {
786
- const message = err instanceof Error ? err.message : String(err);
787
- store.setState({ loading: false, error: message });
788
- throw err;
789
- }
790
- }
791
- async function register(params) {
792
- store.setState({ loading: true, error: null });
793
- try {
794
- const result = await adapter.customers.register(params);
795
- tokenManager.setTokens(result.accessToken, result.expiresIn);
796
- store.setState({
797
- customer: result.customer,
798
- isAuthenticated: true,
799
- loading: false
800
- });
801
- } catch (err) {
802
- const message = err instanceof Error ? err.message : String(err);
803
- store.setState({ loading: false, error: message });
804
- throw err;
805
- }
806
- }
807
- async function logout() {
808
- store.setState({ loading: true, error: null });
809
- try {
810
- await adapter.customers.logout();
811
- tokenManager.clear();
812
- store.setState({
813
- customer: null,
814
- isAuthenticated: false,
815
- loading: false
816
- });
817
- } catch (err) {
818
- tokenManager.clear();
819
- store.setState({
820
- customer: null,
821
- isAuthenticated: false,
822
- loading: false,
823
- error: err instanceof Error ? err.message : String(err)
824
- });
825
- }
826
- }
827
- async function refreshToken() {
828
- try {
829
- const result = await adapter.customers.refresh();
830
- tokenManager.setTokens(result.accessToken, result.expiresIn);
831
- } catch (err) {
832
- console.error("[AuthStore] token refresh failed, logging out", err);
833
- tokenManager.clear();
834
- store.setState({
835
- customer: null,
836
- isAuthenticated: false
837
- });
838
- }
839
- }
840
- async function updateProfile(updates) {
841
- store.setState({ loading: true, error: null });
842
- try {
843
- const customer = await adapter.customers.updateProfile(updates);
844
- store.setState({ customer, loading: false });
845
- } catch (err) {
846
- store.setState({
847
- loading: false,
848
- error: err instanceof Error ? err.message : String(err)
849
- });
850
- }
851
- }
852
- async function loadProfile() {
853
- if (!tokenManager.getAccessToken()) return;
854
- store.setState({ loading: true, error: null });
855
- try {
856
- const customer = await adapter.customers.getProfile();
857
- store.setState({
858
- customer,
859
- isAuthenticated: true,
860
- loading: false
861
- });
862
- } catch (err) {
863
- store.setState({
864
- loading: false,
865
- error: err instanceof Error ? err.message : String(err)
866
- });
867
- }
868
- }
869
- return {
870
- getState: store.getState,
871
- subscribe: store.subscribe,
872
- login,
873
- register,
874
- logout,
875
- refreshToken,
876
- updateProfile,
877
- loadProfile,
878
- destroy: store.destroy
879
- };
880
- }
881
-
882
- // src/client.ts
883
- function createNymbalClient(options) {
884
- const tokenManager = createTokenManager({
885
- ...options.tokenStorage !== void 0 && { storage: options.tokenStorage }
886
- });
887
- let adapter;
888
- if (options.adapter) {
889
- adapter = options.adapter;
890
- } else {
891
- const fetchClient = new FetchClient({
892
- baseUrl: options.baseUrl,
893
- ...options.credentials !== void 0 && { credentials: options.credentials },
894
- getAccessToken: () => tokenManager.getAccessToken(),
895
- ...options.getCartToken !== void 0 && { getCartToken: options.getCartToken },
896
- onUnauthorized: async () => {
897
- try {
898
- const result = await adapter.customers.refresh();
899
- tokenManager.setTokens(result.accessToken, result.expiresIn);
900
- } catch (err) {
901
- console.warn("[NymbalClient] token refresh on unauthorized failed", err);
902
- tokenManager.clear();
903
- }
904
- }
905
- });
906
- adapter = createNymbalApiAdapter(fetchClient);
907
- }
908
- const cart = createCartStore(adapter);
909
- const product = createProductStore(adapter);
910
- const productList = createProductListStore(adapter);
911
- const search = createSearchStore(adapter);
912
- const checkout = createCheckoutStore(adapter, cart);
913
- const auth = createAuthStore(adapter, tokenManager);
914
- const customer = {
915
- addresses: {
916
- list: () => adapter.customers.listAddresses(),
917
- create: (address) => adapter.customers.addAddress(address),
918
- remove: (id) => adapter.customers.removeAddress(id)
919
- },
920
- orders: {
921
- list: (opts) => adapter.customers.listOrders(opts),
922
- get: (orderNumber) => adapter.customers.getOrder(orderNumber)
923
- }
924
- };
925
- let report = null;
926
- const capabilities = {
927
- get() {
928
- if (report === null) {
929
- const reader = adapter.capabilities;
930
- report = reader === void 0 ? Promise.reject(new Error("This client\u2019s adapter cannot read the store capabilities.")) : reader.get();
931
- report.catch(() => {
932
- report = null;
933
- });
934
- }
935
- return report;
936
- }
937
- };
938
- tokenManager.scheduleRefresh(() => adapter.customers.refresh());
939
- function destroy() {
940
- cart.destroy();
941
- product.destroy();
942
- productList.destroy();
943
- search.destroy();
944
- checkout.destroy();
945
- auth.destroy();
946
- tokenManager.destroy();
947
- }
948
- return {
949
- capabilities,
950
- cart,
951
- product,
952
- productList,
953
- search,
954
- checkout,
955
- auth,
956
- customer,
957
- adapter,
958
- destroy
959
- };
960
- }
961
-
962
- // src/payment-drivers.ts
963
- var DRIVERS_KEY = /* @__PURE__ */ Symbol.for("nymbal.paymentDrivers");
964
- function drivers() {
965
- const holder = globalThis;
966
- holder[DRIVERS_KEY] ??= /* @__PURE__ */ new Map();
967
- return holder[DRIVERS_KEY];
968
- }
969
- function registerPaymentDriver(name, driver) {
970
- drivers().set(name, driver);
971
- }
972
- function getPaymentDriver(name) {
973
- return drivers().get(name);
974
- }
1
+ import {
2
+ getPaymentDriver,
3
+ registerPaymentDriver
4
+ } from "./chunk-4GP43MKT.js";
5
+ import {
6
+ createProductStore
7
+ } from "./chunk-QUSTGYBM.js";
8
+ import {
9
+ createProductListStore
10
+ } from "./chunk-KRVUYBKB.js";
11
+ import {
12
+ createSearchStore
13
+ } from "./chunk-FWEQBOEX.js";
14
+ import {
15
+ createCheckoutStore
16
+ } from "./chunk-BAWTE4QS.js";
17
+ import {
18
+ createCartStore
19
+ } from "./chunk-333Z6VKZ.js";
20
+ import {
21
+ createAuthStore
22
+ } from "./chunk-L7EZURSK.js";
23
+ import {
24
+ createStore
25
+ } from "./chunk-U6QF2DRY.js";
26
+ import {
27
+ FetchClient,
28
+ NymbalApiError,
29
+ createNymbalApiAdapter,
30
+ createNymbalClient,
31
+ createTokenManager
32
+ } from "./chunk-EFRWJT3L.js";
975
33
  export {
976
34
  FetchClient,
977
35
  NymbalApiError,