@malawistore/store-sdk 0.1.2 → 0.2.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/dist/index.js CHANGED
@@ -431,6 +431,11 @@ var AuthResource = class {
431
431
  }
432
432
  };
433
433
 
434
+ // src/headers.ts
435
+ function idempotencyHeaders(key) {
436
+ return key ? { "Idempotency-Key": key } : void 0;
437
+ }
438
+
434
439
  // src/path.ts
435
440
  function segment(value) {
436
441
  return encodeURIComponent(value);
@@ -442,9 +447,34 @@ var CartResource = class {
442
447
  this.http = http;
443
448
  }
444
449
  http;
445
- /** Active cart, created empty on first use. */
446
- get() {
447
- return this.http.request("GET", "/cart");
450
+ /** Active cart, created empty on first use (paging meta is dropped). */
451
+ get(params = {}) {
452
+ return this.http.request("GET", "/cart", {
453
+ query: {
454
+ q: params.q,
455
+ product_id: params.product_id,
456
+ variant_id: params.variant_id,
457
+ sort: params.sort,
458
+ page: params.page,
459
+ limit: params.limit,
460
+ offset: params.offset
461
+ }
462
+ });
463
+ }
464
+ /** Same as `get`, plus the `meta` paging counters. */
465
+ getPage(params = {}) {
466
+ return this.http.request("GET", "/cart", {
467
+ query: {
468
+ q: params.q,
469
+ product_id: params.product_id,
470
+ variant_id: params.variant_id,
471
+ sort: params.sort,
472
+ page: params.page,
473
+ limit: params.limit,
474
+ offset: params.offset
475
+ },
476
+ unwrap: false
477
+ });
448
478
  }
449
479
  /** Validates against the catalog and snapshots the current price. */
450
480
  addItem(input) {
@@ -453,6 +483,22 @@ var CartResource = class {
453
483
  retry: false
454
484
  });
455
485
  }
486
+ /**
487
+ * Adds up to MAX_BULK_ITEMS lines in one request. Per-line results carry
488
+ * the written line, plus the full updated cart.
489
+ */
490
+ addItems(input) {
491
+ const { idempotencyKey, ...body } = input;
492
+ return this.http.request(
493
+ "POST",
494
+ "/cart/items/bulk",
495
+ {
496
+ body,
497
+ headers: idempotencyHeaders(idempotencyKey),
498
+ retry: false
499
+ }
500
+ );
501
+ }
456
502
  /** `qty: 0` removes the line. */
457
503
  setQty(itemId, qty) {
458
504
  return this.http.request(
@@ -475,12 +521,11 @@ var CartResource = class {
475
521
  };
476
522
 
477
523
  // src/upload.ts
478
- function createUploadForm(file, field = "file") {
479
- const form = new FormData();
524
+ function appendFile(form, file, field) {
480
525
  if (typeof Blob !== "undefined" && file instanceof Blob) {
481
526
  const name = typeof File !== "undefined" && file instanceof File ? file.name : "upload";
482
527
  form.append(field, file, name);
483
- return form;
528
+ return;
484
529
  }
485
530
  if (typeof file !== "object" || file === null || !("data" in file) || typeof file.name !== "string") {
486
531
  throw new TypeError(
@@ -491,6 +536,19 @@ function createUploadForm(file, field = "file") {
491
536
  type: file.type ?? "application/octet-stream"
492
537
  });
493
538
  form.append(field, blob, file.name);
539
+ }
540
+ function createUploadForm(file, field = "file") {
541
+ const form = new FormData();
542
+ appendFile(form, file, field);
543
+ return form;
544
+ }
545
+ function createUploadFormMany(files, field = "files") {
546
+ const list = Array.isArray(files) ? files : [files];
547
+ if (list.length === 0) {
548
+ throw new TypeError("At least one UploadFile is required");
549
+ }
550
+ const form = new FormData();
551
+ for (const file of list) appendFile(form, file, field);
494
552
  return form;
495
553
  }
496
554
 
@@ -595,6 +653,21 @@ var InventoryResource = class {
595
653
  }
596
654
  });
597
655
  }
656
+ /**
657
+ * Reads availability for up to MAX_BULK_ITEMS variants in one request.
658
+ * Unknown ids are returned in `notFound` instead of failing.
659
+ */
660
+ getStockByVariants(variantIds) {
661
+ return this.http.request(
662
+ "GET",
663
+ "/admin/inventory/stock",
664
+ {
665
+ query: {
666
+ variantIds: Array.isArray(variantIds) ? variantIds : [variantIds]
667
+ }
668
+ }
669
+ );
670
+ }
598
671
  /** Upserts the on-hand quantity (restocking). */
599
672
  setStock(input) {
600
673
  return this.http.request("POST", "/admin/inventory/stock", {
@@ -602,6 +675,19 @@ var InventoryResource = class {
602
675
  retry: false
603
676
  });
604
677
  }
678
+ /** Sets on-hand stock for many SKUs; `atomic` commits all or none. */
679
+ setStockBulk(input) {
680
+ const { idempotencyKey, ...body } = input;
681
+ return this.http.request(
682
+ "POST",
683
+ "/admin/inventory/stock/bulk",
684
+ {
685
+ body,
686
+ headers: idempotencyHeaders(idempotencyKey),
687
+ retry: false
688
+ }
689
+ );
690
+ }
605
691
  /** Holds all lines atomically; one short line fails the whole order. */
606
692
  reserve(input) {
607
693
  return this.http.request(
@@ -643,9 +729,40 @@ var OrdersResource = class {
643
729
  retry: false
644
730
  });
645
731
  }
646
- /** Newest first. */
647
- list() {
648
- return this.http.request("GET", "/orders");
732
+ /** Newest first (paging meta is dropped). */
733
+ list(params = {}) {
734
+ return this.http.request("GET", "/orders", {
735
+ query: {
736
+ status: params.status,
737
+ currency: params.currency,
738
+ created_after: params.created_after,
739
+ created_before: params.created_before,
740
+ min_total_cents: params.min_total_cents,
741
+ max_total_cents: params.max_total_cents,
742
+ sort: params.sort,
743
+ page: params.page,
744
+ limit: params.limit,
745
+ offset: params.offset
746
+ }
747
+ });
748
+ }
749
+ /** Same filters as `list`, plus the `meta` paging counters. */
750
+ listPage(params = {}) {
751
+ return this.http.request("GET", "/orders", {
752
+ query: {
753
+ status: params.status,
754
+ currency: params.currency,
755
+ created_after: params.created_after,
756
+ created_before: params.created_before,
757
+ min_total_cents: params.min_total_cents,
758
+ max_total_cents: params.max_total_cents,
759
+ sort: params.sort,
760
+ page: params.page,
761
+ limit: params.limit,
762
+ offset: params.offset
763
+ },
764
+ unwrap: false
765
+ });
649
766
  }
650
767
  get(id) {
651
768
  return this.http.request("GET", `/orders/${segment(id)}`);
@@ -699,6 +816,7 @@ var ProductsResource = class {
699
816
  return this.http.request("GET", "/products", {
700
817
  query: {
701
818
  q: params.q,
819
+ ids: params.ids,
702
820
  category_id: params.category_id,
703
821
  category_slug: params.category_slug,
704
822
  min_price_cents: params.min_price_cents,
@@ -722,6 +840,7 @@ var ProductsResource = class {
722
840
  return this.http.request("GET", "/products", {
723
841
  query: {
724
842
  q: params.q,
843
+ ids: params.ids,
725
844
  category_id: params.category_id,
726
845
  category_slug: params.category_slug,
727
846
  min_price_cents: params.min_price_cents,
@@ -787,6 +906,86 @@ var ProductsResource = class {
787
906
  { form: createUploadForm(file), retry: false }
788
907
  );
789
908
  }
909
+ /**
910
+ * Admin only. Creates products in bulk. Per-item failures stay inside
911
+ * the 200 envelope; `atomic` rolls the whole batch back.
912
+ */
913
+ bulkCreate(input) {
914
+ const { idempotencyKey, ...body } = input;
915
+ return this.http.request(
916
+ "POST",
917
+ "/admin/products/bulk",
918
+ {
919
+ body,
920
+ headers: idempotencyHeaders(idempotencyKey),
921
+ retry: false
922
+ }
923
+ );
924
+ }
925
+ /** Admin only. Applies one partial patch per product id. */
926
+ bulkUpdate(input) {
927
+ const { idempotencyKey, ...body } = input;
928
+ return this.http.request(
929
+ "PATCH",
930
+ "/admin/products/bulk",
931
+ {
932
+ body,
933
+ headers: idempotencyHeaders(idempotencyKey),
934
+ retry: false
935
+ }
936
+ );
937
+ }
938
+ /**
939
+ * Admin only. POST rather than DELETE so the id list can travel in JSON.
940
+ * `dryRun` reports `wouldDelete` without writing.
941
+ */
942
+ bulkDelete(input) {
943
+ const { idempotencyKey, ...body } = input;
944
+ return this.http.request(
945
+ "POST",
946
+ "/admin/products/bulk-delete",
947
+ {
948
+ body,
949
+ headers: idempotencyHeaders(idempotencyKey),
950
+ retry: false
951
+ }
952
+ );
953
+ }
954
+ /** Admin only. Gallery rows, including uploads still queued (empty url). */
955
+ async listImages(id) {
956
+ const result = await this.http.request(
957
+ "GET",
958
+ `/admin/products/${segment(id)}/images`
959
+ );
960
+ return result.images;
961
+ }
962
+ /**
963
+ * Admin only. Multipart with repeated `files` parts (up to 20 per
964
+ * request). Each accepted file is queued asynchronously (HTTP 202).
965
+ */
966
+ async uploadImages(id, files) {
967
+ return this.http.request(
968
+ "POST",
969
+ `/admin/products/${segment(id)}/images`,
970
+ { form: createUploadFormMany(files), retry: false }
971
+ );
972
+ }
973
+ /** Admin only. Promotes the next ready image when the primary is deleted. */
974
+ deleteImage(id, imageId) {
975
+ return this.http.request(
976
+ "DELETE",
977
+ `/admin/products/${segment(id)}/images/${segment(imageId)}`,
978
+ { retry: false }
979
+ );
980
+ }
981
+ /** Admin only. Points the storefront primary image at one gallery row. */
982
+ setPrimaryImage(id, imageId) {
983
+ return this.http.request(
984
+ "PUT",
985
+ `/admin/products/${segment(id)}/images/${segment(imageId)}/primary`,
986
+ { retry: false }
987
+ );
988
+ }
790
989
  };
791
990
 
792
991
  // src/resources/reviews.ts
@@ -795,14 +994,47 @@ var ReviewsResource = class {
795
994
  this.http = http;
796
995
  }
797
996
  http;
798
- /** Public aggregate plus the newest reviews for a product. */
799
- summary(productId) {
997
+ /** Public aggregate plus one filtered review page (`summary.meta`). */
998
+ summary(productId, params = {}) {
800
999
  return this.http.request(
801
1000
  "GET",
802
1001
  `/products/${segment(productId)}/reviews`,
803
- { skipAuth: true }
1002
+ {
1003
+ query: {
1004
+ q: params.q,
1005
+ rating: params.rating,
1006
+ sort: params.sort,
1007
+ page: params.page,
1008
+ limit: params.limit,
1009
+ offset: params.offset
1010
+ },
1011
+ skipAuth: true
1012
+ }
804
1013
  );
805
1014
  }
1015
+ /** The caller's own reviews with product context (paging meta dropped). */
1016
+ listMine(params = {}) {
1017
+ return this.http.request("GET", "/reviews/me", {
1018
+ query: {
1019
+ sort: params.sort,
1020
+ page: params.page,
1021
+ limit: params.limit,
1022
+ offset: params.offset
1023
+ }
1024
+ });
1025
+ }
1026
+ /** Same as `listMine`, plus the `meta` paging counters. */
1027
+ listMinePage(params = {}) {
1028
+ return this.http.request("GET", "/reviews/me", {
1029
+ query: {
1030
+ sort: params.sort,
1031
+ page: params.page,
1032
+ limit: params.limit,
1033
+ offset: params.offset
1034
+ },
1035
+ unwrap: false
1036
+ });
1037
+ }
806
1038
  /** One review per user per product. */
807
1039
  create(productId, input) {
808
1040
  return this.http.request(
@@ -847,8 +1079,9 @@ var UsersResource = class {
847
1079
  me() {
848
1080
  return this.http.request("GET", "/users/me");
849
1081
  }
1082
+ /** Admin only. There is no public `GET /users/{id}` — owners use `me()`. */
850
1083
  get(id) {
851
- return this.http.request("GET", `/users/${segment(id)}`);
1084
+ return this.http.request("GET", `/admin/users/${segment(id)}`);
852
1085
  }
853
1086
  /** Admin only. User directory without envelope metadata. */
854
1087
  list(params = {}) {
@@ -928,6 +1161,32 @@ var VariantsResource = class {
928
1161
  { retry: false }
929
1162
  );
930
1163
  }
1164
+ /** Admin only. Creates up to MAX_BULK_ITEMS SKUs for one product. */
1165
+ createBulk(productId, input) {
1166
+ const { idempotencyKey, ...body } = input;
1167
+ return this.http.request(
1168
+ "POST",
1169
+ `/products/${segment(productId)}/variants/bulk`,
1170
+ {
1171
+ body,
1172
+ headers: idempotencyHeaders(idempotencyKey),
1173
+ retry: false
1174
+ }
1175
+ );
1176
+ }
1177
+ /** Admin only. Applies one partial patch per variant id. */
1178
+ updateBulk(input) {
1179
+ const { idempotencyKey, ...body } = input;
1180
+ return this.http.request(
1181
+ "PATCH",
1182
+ "/admin/variants/bulk",
1183
+ {
1184
+ body,
1185
+ headers: idempotencyHeaders(idempotencyKey),
1186
+ retry: false
1187
+ }
1188
+ );
1189
+ }
931
1190
  };
932
1191
 
933
1192
  // src/resources/wishlist.ts
@@ -936,9 +1195,32 @@ var WishlistResource = class {
936
1195
  this.http = http;
937
1196
  }
938
1197
  http;
939
- /** Newest first. */
940
- list() {
941
- return this.http.request("GET", "/wishlist");
1198
+ /** Newest first (paging meta is dropped). */
1199
+ list(params = {}) {
1200
+ return this.http.request("GET", "/wishlist", {
1201
+ query: {
1202
+ q: params.q,
1203
+ category_id: params.category_id,
1204
+ sort: params.sort,
1205
+ page: params.page,
1206
+ limit: params.limit,
1207
+ offset: params.offset
1208
+ }
1209
+ });
1210
+ }
1211
+ /** Same filters as `list`, plus the `meta` paging counters. */
1212
+ listPage(params = {}) {
1213
+ return this.http.request("GET", "/wishlist", {
1214
+ query: {
1215
+ q: params.q,
1216
+ category_id: params.category_id,
1217
+ sort: params.sort,
1218
+ page: params.page,
1219
+ limit: params.limit,
1220
+ offset: params.offset
1221
+ },
1222
+ unwrap: false
1223
+ });
942
1224
  }
943
1225
  /** Idempotent: re-hearting succeeds silently. */
944
1226
  add(productId) {
@@ -955,6 +1237,35 @@ var WishlistResource = class {
955
1237
  { retry: false }
956
1238
  );
957
1239
  }
1240
+ /** Hearts up to MAX_BULK_ITEMS products; already-hearted rows succeed. */
1241
+ addBulk(input) {
1242
+ const { idempotencyKey, ...body } = input;
1243
+ return this.http.request(
1244
+ "POST",
1245
+ "/wishlist/bulk",
1246
+ {
1247
+ body,
1248
+ headers: idempotencyHeaders(idempotencyKey),
1249
+ retry: false
1250
+ }
1251
+ );
1252
+ }
1253
+ /**
1254
+ * Unhearts by product id. `dryRun` reports `wouldDelete` without
1255
+ * writing; already-removed rows succeed.
1256
+ */
1257
+ removeBulk(input) {
1258
+ const { idempotencyKey, ...body } = input;
1259
+ return this.http.request(
1260
+ "POST",
1261
+ "/wishlist/bulk-delete",
1262
+ {
1263
+ body,
1264
+ headers: idempotencyHeaders(idempotencyKey),
1265
+ retry: false
1266
+ }
1267
+ );
1268
+ }
958
1269
  };
959
1270
 
960
1271
  // src/client.ts
@@ -1111,6 +1422,6 @@ async function constructStripeEvent(options) {
1111
1422
  return JSON.parse(text);
1112
1423
  }
1113
1424
 
1114
- export { MalawiStore, MalawiStoreError, buildQuery, constructStripeEvent, createUploadForm, isMalawiStoreError, verifyStripeSignature };
1425
+ export { MalawiStore, MalawiStoreError, buildQuery, constructStripeEvent, createUploadForm, createUploadFormMany, isMalawiStoreError, verifyStripeSignature };
1115
1426
  //# sourceMappingURL=index.js.map
1116
1427
  //# sourceMappingURL=index.js.map