react-shopwave-connect 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,20 @@
3
3
  * Consistent return shape for every auto-fetching ("query") hook.
4
4
  */
5
5
  interface QueryState<T> {
6
+ /**
7
+ * The latest data for the current params. Kept while a `refetch()` is in
8
+ * flight (and after a failed refetch), so lists don't blank out and flash a
9
+ * skeleton after every save. Reset to `null` when the params change.
10
+ */
6
11
  data: T | null;
12
+ /** True while there's no data to show yet (first load, or params changed). */
7
13
  loading: boolean;
14
+ /** True whenever a request is in flight, including background refetches. */
15
+ fetching: boolean;
8
16
  error: string | null;
9
- /** Re-runs the underlying fetch. */
17
+ /** HTTP status of the last error (0 = no response), or `null`. */
18
+ errorStatus: number | null;
19
+ /** Re-runs the underlying fetch, keeping the current data visible meanwhile. */
10
20
  refetch: () => void;
11
21
  }
12
22
  /**
@@ -18,6 +28,8 @@ interface MutationState<TData, TArgs extends any[]> {
18
28
  data: TData | null;
19
29
  loading: boolean;
20
30
  error: string | null;
31
+ /** HTTP status of the last error (0 = no response), or `null`. */
32
+ errorStatus: number | null;
21
33
  }
22
34
  //#endregion
23
35
  //#region src/core/types.d.ts
@@ -56,19 +68,24 @@ interface apiResponse {
56
68
  /**
57
69
  * Per-call configuration shared by every core API function.
58
70
  *
59
- * Nothing here is React-specific. By accepting these options per call, the
60
- * core layer works in the browser/Next (relative `/api/...` URLs, the default)
61
- * AND in Node / CLI / Vue / Angular by passing an absolute `baseUrl`, an auth
62
- * `token`, and/or a custom `fetch` implementation.
71
+ * Nothing here is React-specific. In the browser/Next leave `baseUrl` empty to
72
+ * call the app's own `/api/...` routes (which hold the session). From Node, a
73
+ * CLI or tests, pass an absolute `baseUrl` pointing at such an app plus a
74
+ * `token`.
63
75
  */
64
76
  interface RequestOptions {
65
77
  /**
66
78
  * Prefixed in front of every request path. Leave undefined in the browser to
67
- * use relative URLs (e.g. `/api/products`). In Node/CLI pass something like
68
- * `https://api.shopwave.com`.
79
+ * use relative URLs (e.g. `/api/products`). From Node pass the app origin,
80
+ * e.g. `http://localhost:3000`.
69
81
  */
70
82
  baseUrl?: string;
71
- /** OAuth/session token forwarded in the `extras.token` header. */
83
+ /**
84
+ * Shopwave OAuth access token. Sent as `Authorization: OAuth <token>` on every
85
+ * request (GET, POST, PUT and DELETE alike). A value that already starts with
86
+ * a scheme (`OAuth …` / `Bearer …`) is sent as-is. Leave unset in the browser:
87
+ * the app's routes use the session cookie.
88
+ */
72
89
  token?: string;
73
90
  /**
74
91
  * Custom fetch implementation. Defaults to the global `fetch`. Useful for
@@ -92,7 +109,7 @@ interface FetchCategoriesParams {
92
109
  categoryIds?: Array<number>;
93
110
  /** Whether to include soft-deleted records. Defaults to `false`. */
94
111
  deleted?: boolean;
95
- /** Token override (also accepted via `options.token`). */
112
+ /** @deprecated Pass `options.token` instead. Sent the same way (Authorization header). */
96
113
  token?: string;
97
114
  }
98
115
  //#endregion
@@ -126,6 +143,8 @@ interface FetchEmployeesParams {
126
143
  employeeIds?: Array<number>;
127
144
  /** Whether to include soft-deleted records. Defaults to `false`. */
128
145
  deleted?: boolean;
146
+ /** @deprecated Pass `options.token` instead. Sent the same way (Authorization header). */
147
+ token?: string;
129
148
  }
130
149
  //#endregion
131
150
  //#region src/core/product.d.ts
@@ -160,7 +179,7 @@ interface FetchProductsParams {
160
179
  storeId?: number;
161
180
  /** Whether to include soft-deleted records. Defaults to `false`. */
162
181
  deleted?: boolean;
163
- /** Token override (also accepted via `options.token`). */
182
+ /** @deprecated Pass `options.token` instead. Sent the same way (Authorization header). */
164
183
  token?: string;
165
184
  }
166
185
  //#endregion
@@ -203,7 +222,7 @@ interface FetchPromotionsParams {
203
222
  active?: boolean;
204
223
  /** Filter for expired promotions. */
205
224
  expired?: boolean;
206
- /** Token override (also accepted via `options.token`). */
225
+ /** @deprecated Pass `options.token` instead. Sent the same way (Authorization header). */
207
226
  token?: string;
208
227
  }
209
228
  //#endregion
@@ -225,8 +244,12 @@ interface Store {
225
244
  sandbox: boolean | null;
226
245
  }
227
246
  interface FetchStoresParams {
247
+ /** Optional id filter. */
248
+ storeIds?: Array<number>;
228
249
  /** Whether to include soft-deleted records. Defaults to `false`. */
229
250
  deleted?: boolean;
251
+ /** @deprecated Pass `options.token` instead. Sent the same way (Authorization header). */
252
+ token?: string;
230
253
  }
231
254
  //#endregion
232
255
  //#region src/core/report.d.ts
@@ -322,6 +345,181 @@ interface BasketPagination {
322
345
  total: number;
323
346
  }
324
347
  //#endregion
348
+ //#region src/core/resources.d.ts
349
+ /**
350
+ * What an upload is for. Sent to Shopwave as the `contentType` header of
351
+ * `PUT /uploader`. `merchant` is for the receipt and square logos (stored
352
+ * under `…/merchant/<id>/logo/`), `merchantFeature` for the featured image.
353
+ * The API spells two of its values `applicaionLogo` / `applicaionImages`; use
354
+ * the correctly spelt names here and the server maps them.
355
+ */
356
+ type UploadKind = "merchant" | "merchantFeature" | "product" | "user" | "applicationLogo" | "applicationImages";
357
+ //#endregion
358
+ //#region src/core/imageFit.d.ts
359
+ interface FitImageOptions {
360
+ /** Output type. Default `"image/png"`. */
361
+ type?: "image/png" | "image/jpeg" | "image/webp";
362
+ /** 0–1, for JPEG/WebP. */
363
+ quality?: number;
364
+ /** Return the file untouched when it's already the right size and type. Default true. */
365
+ keepIfExact?: boolean;
366
+ }
367
+ //#endregion
368
+ //#region src/core/upload.d.ts
369
+ interface UploadImageParams {
370
+ /** What the image is for (sent to Shopwave as the uploader's `contentType`). */
371
+ kind: UploadKind;
372
+ /** File name to send when `file` is a Blob without one. Defaults to `File.name`, else `"upload"`. */
373
+ fileName?: string;
374
+ }
375
+ interface UploadedImage {
376
+ /** The generated file name (products store it in `images`). */
377
+ id: string;
378
+ /** Public HTTPS URL of the file (see {@link getImageUrl}). */
379
+ url: string;
380
+ /** The URL exactly as the API returned it (`http://static.merchantstack.com/images/…`). */
381
+ path: string;
382
+ }
383
+ //#endregion
384
+ //#region src/core/merchantImages.d.ts
385
+ /**
386
+ * Merchant images, as adminV1 saves them and adminV2 reads them:
387
+ *
388
+ * ```
389
+ * { logo: { receipt: "<file>", square: "<file>" }, feature: ["<file>"] }
390
+ * ```
391
+ *
392
+ * - **Writes** take the uploader's `fileName` (`<hash>.png`), not a URL.
393
+ * - **Reads** return full URLs (`http://static.merchantstack.com/images/…`),
394
+ * so a value read back must be turned into a file name before it's saved
395
+ * again ({@link toStoredImageIds}; `updateMerchant` does this for you).
396
+ * - Sending `imageIds` replaces the whole stored object (`{}` clears it);
397
+ * leaving it out keeps it.
398
+ * - The API builds each URL from the key, not from where the file is:
399
+ * `logo.*` → `…/merchant/<id>/logo/<file>`, `feature` → `…/feature/<file>`.
400
+ * So a featured image must be uploaded with kind `merchantFeature` (which
401
+ * stores it under `feature/`); a `merchant` upload lands under `logo/`.
402
+ *
403
+ * Confirmed on the live API, merchant 5644, 30 Sep 2026.
404
+ */
405
+ interface MerchantImageIds {
406
+ logo?: {
407
+ receipt?: string | null;
408
+ square?: string | null;
409
+ [key: string]: string | null | undefined;
410
+ } | null;
411
+ feature?: string[] | null;
412
+ [key: string]: unknown;
413
+ }
414
+ /** The three image slots on the merchant settings page. */
415
+ declare const MERCHANT_IMAGE_SLOT_KEYS: readonly ["receipt", "square", "featured"];
416
+ type MerchantImageSlot = (typeof MERCHANT_IMAGE_SLOT_KEYS)[number];
417
+ interface UploadMerchantImageOptions extends RequestOptions {
418
+ /**
419
+ * Scale and centre-crop the image to the slot's exact size before upload
420
+ * (browser only). Default true. With `false` the file is sent as-is.
421
+ */
422
+ fit?: boolean;
423
+ /** Output type and quality when fitting. Default PNG. */
424
+ fitOptions?: FitImageOptions;
425
+ }
426
+ //#endregion
427
+ //#region src/core/merchant.d.ts
428
+ /** A colour set: hex strings (`"#1a2b3c"`). */
429
+ interface MerchantColourSet {
430
+ main?: string | null;
431
+ highlight?: string | null;
432
+ contrast?: string | null;
433
+ [key: string]: string | null | undefined;
434
+ }
435
+ /**
436
+ * Brand colours, as adminV1 saves them and adminV2 reads them
437
+ * (`colours.primary.main` is the logo background): `{ primary: { main,
438
+ * highlight, contrast } }`. `{}` when unset. Confirmed live, 30 Sep 2026.
439
+ */
440
+ interface MerchantColours {
441
+ primary?: MerchantColourSet | null;
442
+ [key: string]: MerchantColourSet | null | undefined;
443
+ }
444
+ /**
445
+ * Web and social links, as adminV1 saves them:
446
+ * `{ website: { home }, social: { twitter, facebook, instagram } }`.
447
+ * `{}` when empty (confirmed live, 30 Sep 2026). Use {@link normalizeMerchantLinks} to read older shapes and
448
+ * {@link merchantLinksToForm} / {@link merchantLinksFromForm} for flat forms.
449
+ */
450
+ interface MerchantLinks {
451
+ website?: {
452
+ home?: string | null;
453
+ [key: string]: string | null | undefined;
454
+ } | null;
455
+ social?: {
456
+ twitter?: string | null;
457
+ facebook?: string | null;
458
+ instagram?: string | null;
459
+ [key: string]: string | null | undefined;
460
+ } | null;
461
+ [key: string]: unknown;
462
+ }
463
+ interface Merchant {
464
+ id: number;
465
+ name: string;
466
+ description?: string | null;
467
+ /** Company registration number. */
468
+ companyNumber?: string | null;
469
+ vatNumber?: string | null;
470
+ categoryId?: number | null;
471
+ estAnnualRevenue?: number | string | null;
472
+ note?: string | null;
473
+ links?: MerchantLinks | null;
474
+ colours?: MerchantColours | null;
475
+ imageIds?: MerchantImageIds | null;
476
+ createdDate?: string;
477
+ modifiedDate?: string;
478
+ /** Other fields the API returns are kept as-is. */
479
+ [field: string]: unknown;
480
+ }
481
+ /** What `updateMerchant` accepts: any subset of the merchant's fields. */
482
+ type MerchantPatch = Partial<Merchant> & {
483
+ [field: string]: unknown;
484
+ };
485
+ interface UpdateMerchantOptions extends RequestOptions {
486
+ /**
487
+ * Read the merchant first and send the patch merged over it (the default).
488
+ * Scalar fields are merged over the stored ones. Object fields
489
+ * (`colours`, `links`, `imageIds`) are sent only when the patch has them,
490
+ * and then replace the stored one as a whole.
491
+ *
492
+ * Set to `false` to send only the patch (it must then include `id`). Only
493
+ * do that if you know the API keeps the fields you leave out.
494
+ */
495
+ merge?: boolean;
496
+ }
497
+ //#endregion
498
+ //#region src/core/user.d.ts
499
+ /** The logged-in user's employee record (`GET /user` → `user.employee`). */
500
+ interface UserEmployee {
501
+ merchantId?: number;
502
+ /** See `rolesById`. */
503
+ roleId?: number;
504
+ /** Store roles, keyed by store id. */
505
+ stores?: Record<string, unknown>;
506
+ [field: string]: unknown;
507
+ }
508
+ /** The logged-in user (`GET /user`). */
509
+ interface User {
510
+ id: number;
511
+ firstName: string;
512
+ lastName: string;
513
+ email: string;
514
+ employee?: UserEmployee | null;
515
+ /** Documented in the API reference but not returned by the live API (Sep 2026). */
516
+ createdDate?: string;
517
+ /** Not returned by the live API (Sep 2026); use `fetchMerchant()`. */
518
+ merchant?: Merchant | null;
519
+ /** Other fields the API returns are kept as-is. */
520
+ [field: string]: unknown;
521
+ }
522
+ //#endregion
325
523
  //#region src/hooks/useCategory.d.ts
326
524
  /**
327
525
  * Auto-fetches categories on mount and whenever the params change.
@@ -428,6 +626,59 @@ declare function useLogout(options?: RequestOptions): MutationState<void, []>;
428
626
  */
429
627
  declare function useSession(options?: RequestOptions): QueryState<SessionStatus>;
430
628
  //#endregion
629
+ //#region src/hooks/useMerchant.d.ts
630
+ /**
631
+ * The logged-in user's merchant, fetched on mount. `data` is `null` while
632
+ * loading or when the API has no merchant.
633
+ *
634
+ * @example
635
+ * const { data: merchant, loading, refetch } = useMerchant();
636
+ */
637
+ declare function useMerchant(options?: RequestOptions): QueryState<Merchant | null>;
638
+ /**
639
+ * Manually-triggered merchant update (see `updateMerchant`: the patch is merged
640
+ * over the current merchant by default). Resolves to the saved merchant, or
641
+ * `null` on error (then `error` / `errorStatus` are set).
642
+ *
643
+ * @example
644
+ * const { mutate: saveMerchant, loading: saving } = useUpdateMerchant();
645
+ * const saved = await saveMerchant({ vatNumber: "GB123" });
646
+ */
647
+ declare function useUpdateMerchant(options?: UpdateMerchantOptions): MutationState<Merchant, [MerchantPatch]>;
648
+ //#endregion
649
+ //#region src/hooks/useUser.d.ts
650
+ /**
651
+ * The logged-in user, fetched on mount. `errorStatus` is 401 when logged out.
652
+ *
653
+ * @example
654
+ * const { data: user } = useUser();
655
+ */
656
+ declare function useUser(options?: RequestOptions & {
657
+ enabled?: boolean;
658
+ }): QueryState<User | null>;
659
+ //#endregion
660
+ //#region src/hooks/useUploadImage.d.ts
661
+ /**
662
+ * Manually-triggered image upload. Resolves to `{ id, url }`, or `null` on
663
+ * error (then `error` / `errorStatus` are set).
664
+ *
665
+ * @example
666
+ * const { mutate: upload, loading: uploading } = useUploadImage();
667
+ * const image = await upload(file, { kind: "merchant" });
668
+ */
669
+ declare function useUploadImage(options?: RequestOptions): MutationState<UploadedImage, [Blob, UploadImageParams]>;
670
+ /**
671
+ * Manually-triggered upload for a merchant image slot (`receipt`, `square`,
672
+ * `featured`): fits the image to the slot's exact size, uploads it with the
673
+ * slot's kind, and resolves to `{ id, url }`. Put `id` into `imageIds` with
674
+ * `setMerchantImage`.
675
+ *
676
+ * @example
677
+ * const { mutate: upload } = useUploadMerchantImage();
678
+ * const image = await upload(file, "square");
679
+ */
680
+ declare function useUploadMerchantImage(options?: UploadMerchantImageOptions): MutationState<UploadedImage, [Blob, MerchantImageSlot]>;
681
+ //#endregion
431
682
  //#region src/hooks/useBasketReport.d.ts
432
683
  interface UseBasketReportReturn {
433
684
  rows: BasketReportRow[];
@@ -448,5 +699,5 @@ interface UseBasketReportReturn {
448
699
  */
449
700
  declare function useBasketReport(options?: RequestOptions): UseBasketReportReturn;
450
701
  //#endregion
451
- export { type MutationState, type QueryState, type UseBasketReportReturn, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useProduct, usePromotion, useReport, useSession, useStore, useSubmit };
702
+ export { type MutationState, type QueryState, type UseBasketReportReturn, useBasketReport, useCategory, useConsumer, useDelete, useEmployee, useLogout, useMerchant, useProduct, usePromotion, useReport, useSession, useStore, useSubmit, useUpdateMerchant, useUploadImage, useUploadMerchantImage, useUser };
452
703
  //# sourceMappingURL=index.d.cts.map