@juo/blocks 1.0.0 → 1.1.0-alpha.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 (59) hide show
  1. package/dist/{ExtensionRoot-CZyBNJZY.js → ExtensionRoot-unXhHjxE.js} +0 -5
  2. package/dist/core.js +945 -14
  3. package/dist/editor/components.d.ts.map +1 -1
  4. package/dist/editor.js +0 -2
  5. package/dist/services/customer/adapter.d.ts +13 -0
  6. package/dist/services/customer/adapter.d.ts.map +1 -0
  7. package/dist/services/customer/customerService.d.ts +7 -0
  8. package/dist/services/customer/customerService.d.ts.map +1 -0
  9. package/dist/services/customer/index.d.ts +5 -0
  10. package/dist/services/customer/index.d.ts.map +1 -0
  11. package/dist/services/customer/types.d.ts +17 -0
  12. package/dist/services/customer/types.d.ts.map +1 -0
  13. package/dist/services/index.d.ts +4 -0
  14. package/dist/services/index.d.ts.map +1 -1
  15. package/dist/services/login/index.d.ts +1 -0
  16. package/dist/services/login/index.d.ts.map +1 -1
  17. package/dist/services/login/loginService.d.ts +2 -0
  18. package/dist/services/login/loginService.d.ts.map +1 -1
  19. package/dist/services/order/adapter.d.ts +12 -0
  20. package/dist/services/order/adapter.d.ts.map +1 -0
  21. package/dist/services/order/index.d.ts +5 -0
  22. package/dist/services/order/index.d.ts.map +1 -0
  23. package/dist/services/order/orderService.d.ts +7 -0
  24. package/dist/services/order/orderService.d.ts.map +1 -0
  25. package/dist/services/order/types.d.ts +25 -0
  26. package/dist/services/order/types.d.ts.map +1 -0
  27. package/dist/services/product/adapter.d.ts.map +1 -1
  28. package/dist/services/product/types.d.ts +12 -0
  29. package/dist/services/product/types.d.ts.map +1 -1
  30. package/dist/services/router/index.d.ts +3 -0
  31. package/dist/services/router/index.d.ts.map +1 -0
  32. package/dist/services/router/routerService.d.ts +5 -0
  33. package/dist/services/router/routerService.d.ts.map +1 -0
  34. package/dist/services/router/types.d.ts +16 -0
  35. package/dist/services/router/types.d.ts.map +1 -0
  36. package/dist/services/schedules/adapter.d.ts +20 -0
  37. package/dist/services/schedules/adapter.d.ts.map +1 -0
  38. package/dist/services/schedules/index.d.ts +5 -0
  39. package/dist/services/schedules/index.d.ts.map +1 -0
  40. package/dist/services/schedules/schedulesService.d.ts +10 -0
  41. package/dist/services/schedules/schedulesService.d.ts.map +1 -0
  42. package/dist/services/schedules/types.d.ts +45 -0
  43. package/dist/services/schedules/types.d.ts.map +1 -0
  44. package/dist/services/subscription/adapter.d.ts +19 -2
  45. package/dist/services/subscription/adapter.d.ts.map +1 -1
  46. package/dist/services/subscription/index.d.ts +1 -1
  47. package/dist/services/subscription/index.d.ts.map +1 -1
  48. package/dist/services/subscription/subscriptionService.d.ts +1 -2
  49. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  50. package/dist/services/subscription/types.d.ts +29 -2
  51. package/dist/services/subscription/types.d.ts.map +1 -1
  52. package/dist/utils/index.d.ts +6 -0
  53. package/dist/utils/index.d.ts.map +1 -1
  54. package/dist/vue/block.d.ts.map +1 -1
  55. package/dist/vue.js +1 -5
  56. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  57. package/dist/web-components-editor.js +1 -1
  58. package/dist/web-components-runtime.js +1 -1
  59. package/package.json +1 -1
package/dist/core.js CHANGED
@@ -415,7 +415,18 @@ function createLoginService(init) {
415
415
  return { _tag: "Success", data: void 0 };
416
416
  },
417
417
  isAuthenticated: auth.isAuthenticated,
418
- getToken: () => auth.getToken()
418
+ getToken: () => auth.getToken(),
419
+ async getAuthHeaders() {
420
+ const delegated = auth.getDelegatedToken();
421
+ if (delegated) {
422
+ return { "X-Delegated-Token": delegated };
423
+ }
424
+ const token = await auth.getToken();
425
+ if (token) {
426
+ return { Authorization: `Bearer ${token}` };
427
+ }
428
+ return {};
429
+ }
419
430
  };
420
431
  return service;
421
432
  }
@@ -439,7 +450,19 @@ function createMockProductAdapter() {
439
450
  price: {
440
451
  amount: "12.49",
441
452
  currencyCode: "EUR"
442
- }
453
+ },
454
+ purchaseOptions: [
455
+ {
456
+ name: "Monthly",
457
+ price: { amount: "9.99", currencyCode: "EUR" },
458
+ interval: { intervalCount: 1, interval: "MONTH" }
459
+ },
460
+ {
461
+ name: "Every 2 months",
462
+ price: { amount: "10.99", currencyCode: "EUR" },
463
+ interval: { intervalCount: 2, interval: "MONTH" }
464
+ }
465
+ ]
443
466
  }
444
467
  ],
445
468
  collections: []
@@ -461,7 +484,14 @@ function createMockProductAdapter() {
461
484
  price: {
462
485
  amount: "12.49",
463
486
  currencyCode: "EUR"
464
- }
487
+ },
488
+ purchaseOptions: [
489
+ {
490
+ name: "Monthly",
491
+ price: { amount: "10.99", currencyCode: "EUR" },
492
+ interval: { intervalCount: 1, interval: "MONTH" }
493
+ }
494
+ ]
465
495
  }
466
496
  ],
467
497
  collections: []
@@ -472,18 +502,43 @@ function createMockProductAdapter() {
472
502
  featuredImage: {
473
503
  url: "https://via.placeholder.com/400x400?text=Product+3"
474
504
  },
475
- hasOnlyDefaultVariant: true,
505
+ hasOnlyDefaultVariant: false,
476
506
  variants: [
477
507
  {
478
508
  id: "sample-3-1",
479
509
  title: "Green tea and jasmine",
480
510
  image: {
481
- url: "https://via.placeholder.com/400x400?text=Product+3"
511
+ url: "https://via.placeholder.com/400x400?text=Product+3a"
482
512
  },
483
513
  price: {
484
514
  amount: "6.7",
485
515
  currencyCode: "EUR"
486
- }
516
+ },
517
+ purchaseOptions: [
518
+ {
519
+ name: "Monthly",
520
+ price: { amount: "5.36", currencyCode: "EUR" },
521
+ interval: { intervalCount: 1, interval: "MONTH" }
522
+ }
523
+ ]
524
+ },
525
+ {
526
+ id: "sample-3-2",
527
+ title: "Lavender and mint",
528
+ image: {
529
+ url: "https://via.placeholder.com/400x400?text=Product+3b"
530
+ },
531
+ price: {
532
+ amount: "7.5",
533
+ currencyCode: "EUR"
534
+ },
535
+ purchaseOptions: [
536
+ {
537
+ name: "Monthly",
538
+ price: { amount: "6.00", currencyCode: "EUR" },
539
+ interval: { intervalCount: 1, interval: "MONTH" }
540
+ }
541
+ ]
487
542
  }
488
543
  ],
489
544
  collections: []
@@ -621,6 +676,32 @@ function createMockSubscriptionAdapter() {
621
676
  updatedAt: "2024-10-10T00:00:00Z"
622
677
  }
623
678
  ];
679
+ const mockUpsellProducts = [
680
+ {
681
+ id: "upsell-1",
682
+ variantId: "upsell-v-1",
683
+ title: "Retinol Night Cream",
684
+ imageUrl: "https://images.unsplash.com/photo-1617897903246-719242758050?w=200",
685
+ price: { amount: "38.00", currencyCode: "USD" },
686
+ description: "Anti-aging night treatment"
687
+ },
688
+ {
689
+ id: "upsell-2",
690
+ variantId: "upsell-v-2",
691
+ title: "SPF 50 Day Shield",
692
+ imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
693
+ price: { amount: "24.00", currencyCode: "USD" },
694
+ description: "Lightweight daily sun protection"
695
+ },
696
+ {
697
+ id: "upsell-3",
698
+ variantId: "upsell-v-3",
699
+ title: "Collagen Eye Patches",
700
+ imageUrl: "https://images.unsplash.com/photo-1512290923902-8a9f81dc236c?w=200",
701
+ price: { amount: "18.00", currencyCode: "USD" },
702
+ description: "Depuffing under-eye treatment"
703
+ }
704
+ ];
624
705
  return {
625
706
  async getById(id) {
626
707
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -697,7 +778,9 @@ function createMockSubscriptionAdapter() {
697
778
  data: {
698
779
  ...subscription,
699
780
  items: subscription.items.map((item) => ({ ...item })),
700
- discounts: subscription.discounts.map((discount) => ({ ...discount }))
781
+ discounts: subscription.discounts.map((discount) => ({
782
+ ...discount
783
+ }))
701
784
  }
702
785
  };
703
786
  },
@@ -719,7 +802,9 @@ function createMockSubscriptionAdapter() {
719
802
  data: {
720
803
  ...subscription,
721
804
  items: subscription.items.map((item) => ({ ...item })),
722
- discounts: subscription.discounts.map((discount) => ({ ...discount }))
805
+ discounts: subscription.discounts.map((discount) => ({
806
+ ...discount
807
+ }))
723
808
  }
724
809
  };
725
810
  },
@@ -741,7 +826,9 @@ function createMockSubscriptionAdapter() {
741
826
  data: {
742
827
  ...subscription,
743
828
  items: subscription.items.map((item) => ({ ...item })),
744
- discounts: subscription.discounts.map((discount) => ({ ...discount }))
829
+ discounts: subscription.discounts.map((discount) => ({
830
+ ...discount
831
+ }))
745
832
  }
746
833
  };
747
834
  },
@@ -763,7 +850,9 @@ function createMockSubscriptionAdapter() {
763
850
  data: {
764
851
  ...subscription,
765
852
  items: subscription.items.map((item) => ({ ...item })),
766
- discounts: subscription.discounts.map((discount) => ({ ...discount }))
853
+ discounts: subscription.discounts.map((discount) => ({
854
+ ...discount
855
+ }))
767
856
  }
768
857
  };
769
858
  },
@@ -785,7 +874,9 @@ function createMockSubscriptionAdapter() {
785
874
  data: {
786
875
  ...subscription,
787
876
  items: subscription.items.map((item) => ({ ...item })),
788
- discounts: subscription.discounts.map((discount) => ({ ...discount }))
877
+ discounts: subscription.discounts.map((discount) => ({
878
+ ...discount
879
+ }))
789
880
  }
790
881
  };
791
882
  },
@@ -819,6 +910,316 @@ function createMockSubscriptionAdapter() {
819
910
  var _a;
820
911
  await new Promise((resolve) => setTimeout(resolve, 300));
821
912
  return { _tag: "Success", data: ((_a = mockSubscriptions[0]) == null ? void 0 : _a.id) ?? null };
913
+ },
914
+ async getDeliveryFrequencies() {
915
+ await new Promise((resolve) => setTimeout(resolve, 200));
916
+ return {
917
+ _tag: "Success",
918
+ data: [
919
+ {
920
+ id: "plan_1",
921
+ name: "Monthly",
922
+ billingPolicy: { intervalCount: 1, interval: "MONTH" },
923
+ deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
924
+ },
925
+ {
926
+ id: "plan_2",
927
+ name: "Every 2 months",
928
+ billingPolicy: { intervalCount: 2, interval: "MONTH" },
929
+ deliveryPolicy: { intervalCount: 2, interval: "MONTH" }
930
+ }
931
+ ]
932
+ };
933
+ },
934
+ async getUpsellProducts() {
935
+ await new Promise((resolve) => setTimeout(resolve, 300));
936
+ return { _tag: "Success", data: [...mockUpsellProducts] };
937
+ },
938
+ async addUpsellProduct() {
939
+ await new Promise((resolve) => setTimeout(resolve, 400));
940
+ return { _tag: "Success", data: void 0 };
941
+ },
942
+ async changeFrequency(params) {
943
+ await new Promise((resolve) => setTimeout(resolve, 300));
944
+ const subscription = mockSubscriptions.find(
945
+ (sub) => sub.id === params.subscriptionId
946
+ );
947
+ if (!subscription) {
948
+ return { _tag: "Failure", error: "Subscription not found" };
949
+ }
950
+ subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
951
+ return {
952
+ _tag: "Success",
953
+ data: { ...subscription }
954
+ };
955
+ }
956
+ };
957
+ }
958
+ function createApiSubscriptionAdapter(fetcher) {
959
+ return {
960
+ async search(options) {
961
+ try {
962
+ const params = new URLSearchParams();
963
+ if (options == null ? void 0 : options.filters) {
964
+ params.set("filters", JSON.stringify(options.filters));
965
+ }
966
+ if (options == null ? void 0 : options.pagination) {
967
+ if ("after" in options.pagination) {
968
+ params.set("after", options.pagination.after);
969
+ } else if ("before" in options.pagination) {
970
+ params.set("before", options.pagination.before);
971
+ }
972
+ }
973
+ const query = params.toString() ? `?${params.toString()}` : "";
974
+ const res = await fetcher(`/customer/v1/subscriptions${query}`);
975
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
976
+ const body = await res.json();
977
+ body.data.forEach((sub) => {
978
+ if (sub.nextDeliveryDate) {
979
+ sub.nextDeliveryDate = new Date(sub.nextDeliveryDate);
980
+ }
981
+ sub.items.forEach((item) => {
982
+ if (item.nextDeliveryDate) {
983
+ item.nextDeliveryDate = new Date(item.nextDeliveryDate);
984
+ }
985
+ });
986
+ });
987
+ const data = {
988
+ items: body.data,
989
+ pageInfo: {
990
+ hasNextPage: body.hasNextPage,
991
+ hasPrevPage: body.hasPrevPage,
992
+ startCursor: body.startCursor,
993
+ endCursor: body.endCursor
994
+ }
995
+ };
996
+ return { _tag: "Success", data };
997
+ } catch (e2) {
998
+ return { _tag: "Failure", error: e2 };
999
+ }
1000
+ },
1001
+ async getById(id) {
1002
+ try {
1003
+ const res = await fetcher(`/customer/v1/subscriptions/${id}`);
1004
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1005
+ const data = await res.json();
1006
+ if (data.nextDeliveryDate)
1007
+ data.nextDeliveryDate = new Date(data.nextDeliveryDate);
1008
+ return { _tag: "Success", data };
1009
+ } catch (e2) {
1010
+ return { _tag: "Failure", error: e2 };
1011
+ }
1012
+ },
1013
+ async addItem({ subscriptionId, item }) {
1014
+ try {
1015
+ const res = await fetcher(
1016
+ `/customer/v1/subscriptions/${subscriptionId}/items`,
1017
+ {
1018
+ method: "POST",
1019
+ headers: { "Content-Type": "application/json" },
1020
+ body: JSON.stringify(item)
1021
+ }
1022
+ );
1023
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1024
+ return { _tag: "Success", data: void 0 };
1025
+ } catch (e2) {
1026
+ return { _tag: "Failure", error: e2 };
1027
+ }
1028
+ },
1029
+ async removeItem({ subscriptionId, itemId }) {
1030
+ try {
1031
+ const res = await fetcher(
1032
+ `/customer/v1/subscriptions/${subscriptionId}/items/${itemId}`,
1033
+ { method: "DELETE" }
1034
+ );
1035
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1036
+ return { _tag: "Success", data: void 0 };
1037
+ } catch (e2) {
1038
+ return { _tag: "Failure", error: e2 };
1039
+ }
1040
+ },
1041
+ async addDiscount({ subscriptionId, code }) {
1042
+ try {
1043
+ const res = await fetcher(
1044
+ `/customer/v1/subscriptions/${subscriptionId}/discounts`,
1045
+ {
1046
+ method: "POST",
1047
+ headers: { "Content-Type": "application/json" },
1048
+ body: JSON.stringify({ code })
1049
+ }
1050
+ );
1051
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1052
+ return { _tag: "Success", data: void 0 };
1053
+ } catch (e2) {
1054
+ return { _tag: "Failure", error: e2 };
1055
+ }
1056
+ },
1057
+ async removeDiscount({ subscriptionId, discountId }) {
1058
+ try {
1059
+ const res = await fetcher(
1060
+ `/customer/v1/subscriptions/${subscriptionId}/discounts/${discountId}`,
1061
+ { method: "DELETE" }
1062
+ );
1063
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1064
+ return { _tag: "Success", data: void 0 };
1065
+ } catch (e2) {
1066
+ return { _tag: "Failure", error: e2 };
1067
+ }
1068
+ },
1069
+ async reschedule({ subscriptionId, newDate }) {
1070
+ try {
1071
+ const res = await fetcher(
1072
+ `/customer/v1/subscriptions/${subscriptionId}/reschedule`,
1073
+ {
1074
+ method: "POST",
1075
+ headers: { "Content-Type": "application/json" },
1076
+ body: JSON.stringify({ newDate })
1077
+ }
1078
+ );
1079
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1080
+ const data = await res.json();
1081
+ if (data.nextDeliveryDate)
1082
+ data.nextDeliveryDate = new Date(data.nextDeliveryDate);
1083
+ return { _tag: "Success", data };
1084
+ } catch (e2) {
1085
+ return { _tag: "Failure", error: e2 };
1086
+ }
1087
+ },
1088
+ async resume({ subscriptionId }) {
1089
+ try {
1090
+ const res = await fetcher(
1091
+ `/customer/v1/subscriptions/${subscriptionId}/resume`,
1092
+ { method: "POST" }
1093
+ );
1094
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1095
+ const data = await res.json();
1096
+ return { _tag: "Success", data };
1097
+ } catch (e2) {
1098
+ return { _tag: "Failure", error: e2 };
1099
+ }
1100
+ },
1101
+ async pause({ subscriptionId }) {
1102
+ try {
1103
+ const res = await fetcher(
1104
+ `/customer/v1/subscriptions/${subscriptionId}/pause`,
1105
+ { method: "POST" }
1106
+ );
1107
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1108
+ const data = await res.json();
1109
+ return { _tag: "Success", data };
1110
+ } catch (e2) {
1111
+ return { _tag: "Failure", error: e2 };
1112
+ }
1113
+ },
1114
+ async reactivate({ subscriptionId }) {
1115
+ try {
1116
+ const res = await fetcher(
1117
+ `/customer/v1/subscriptions/${subscriptionId}/reactivate`,
1118
+ { method: "POST" }
1119
+ );
1120
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1121
+ const data = await res.json();
1122
+ return { _tag: "Success", data };
1123
+ } catch (e2) {
1124
+ return { _tag: "Failure", error: e2 };
1125
+ }
1126
+ },
1127
+ async cancel({ subscriptionId, reason }) {
1128
+ try {
1129
+ const res = await fetcher(
1130
+ `/customer/v1/subscriptions/${subscriptionId}/cancel`,
1131
+ {
1132
+ method: "POST",
1133
+ headers: { "Content-Type": "application/json" },
1134
+ body: JSON.stringify({ reason })
1135
+ }
1136
+ );
1137
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1138
+ const data = await res.json();
1139
+ return { _tag: "Success", data };
1140
+ } catch (e2) {
1141
+ return { _tag: "Failure", error: e2 };
1142
+ }
1143
+ },
1144
+ async getAvailablePlans({ subscriptionId }) {
1145
+ try {
1146
+ const res = await fetcher(
1147
+ `/customer/v1/subscriptions/${subscriptionId}/plans`
1148
+ );
1149
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1150
+ const data = await res.json();
1151
+ return { _tag: "Success", data: data.items };
1152
+ } catch (e2) {
1153
+ return { _tag: "Failure", error: e2 };
1154
+ }
1155
+ },
1156
+ async getDefaultSubscriptionId() {
1157
+ var _a;
1158
+ try {
1159
+ const res = await fetcher(`/customer/v1/subscriptions?limit=1`);
1160
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1161
+ const body = await res.json();
1162
+ return { _tag: "Success", data: ((_a = body.data[0]) == null ? void 0 : _a.id) ?? null };
1163
+ } catch (e2) {
1164
+ return { _tag: "Failure", error: e2 };
1165
+ }
1166
+ },
1167
+ async getDeliveryFrequencies({ subscriptionId }) {
1168
+ try {
1169
+ const res = await fetcher(
1170
+ `/customer/v1/subscriptions/${subscriptionId}/frequencies`
1171
+ );
1172
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1173
+ const data = await res.json();
1174
+ return { _tag: "Success", data: data.items };
1175
+ } catch (e2) {
1176
+ return { _tag: "Failure", error: e2 };
1177
+ }
1178
+ },
1179
+ async getUpsellProducts({ subscriptionId }) {
1180
+ try {
1181
+ const res = await fetcher(
1182
+ `/customer/v1/subscriptions/${subscriptionId}/upsells`
1183
+ );
1184
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1185
+ const data = await res.json();
1186
+ return { _tag: "Success", data: data.items };
1187
+ } catch (e2) {
1188
+ return { _tag: "Failure", error: e2 };
1189
+ }
1190
+ },
1191
+ async addUpsellProduct({ subscriptionId, variantId, quantity, oneTime }) {
1192
+ try {
1193
+ const res = await fetcher(
1194
+ `/customer/v1/subscriptions/${subscriptionId}/upsells`,
1195
+ {
1196
+ method: "POST",
1197
+ headers: { "Content-Type": "application/json" },
1198
+ body: JSON.stringify({ variantId, quantity, oneTime })
1199
+ }
1200
+ );
1201
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1202
+ return { _tag: "Success", data: void 0 };
1203
+ } catch (e2) {
1204
+ return { _tag: "Failure", error: e2 };
1205
+ }
1206
+ },
1207
+ async changeFrequency({ subscriptionId, sellingPlanId }) {
1208
+ try {
1209
+ const res = await fetcher(
1210
+ `/customer/v1/subscriptions/${subscriptionId}/frequency`,
1211
+ {
1212
+ method: "POST",
1213
+ headers: { "Content-Type": "application/json" },
1214
+ body: JSON.stringify({ sellingPlanId })
1215
+ }
1216
+ );
1217
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1218
+ const data = await res.json();
1219
+ return { _tag: "Success", data };
1220
+ } catch (e2) {
1221
+ return { _tag: "Failure", error: e2 };
1222
+ }
822
1223
  }
823
1224
  };
824
1225
  }
@@ -843,9 +1244,25 @@ function getCurrentSubscriptionId() {
843
1244
  return null;
844
1245
  }
845
1246
  function createSubscriptionService(adapter) {
1247
+ const current = d(null);
1248
+ const hasPendingBilling = d(false);
846
1249
  return {
847
- search: adapter.search,
848
- getById: adapter.getById,
1250
+ current,
1251
+ hasPendingBilling,
1252
+ async search(options) {
1253
+ const result = await adapter.search(options);
1254
+ if (result._tag === "Success") {
1255
+ current.value = result.data.items[0] ?? null;
1256
+ }
1257
+ return result;
1258
+ },
1259
+ async getById(id) {
1260
+ const result = await adapter.getById(id);
1261
+ if (result._tag === "Success" && result.data) {
1262
+ current.value = result.data;
1263
+ }
1264
+ return result;
1265
+ },
849
1266
  getCurrentSubscriptionId,
850
1267
  addItem: (subscriptionId, item) => adapter.addItem({ subscriptionId, item }),
851
1268
  removeItem: (subscriptionId, itemId) => adapter.removeItem({ subscriptionId, itemId }),
@@ -857,9 +1274,509 @@ function createSubscriptionService(adapter) {
857
1274
  reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
858
1275
  cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
859
1276
  getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
860
- getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId()
1277
+ getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
1278
+ getDeliveryFrequencies: (params) => adapter.getDeliveryFrequencies ? adapter.getDeliveryFrequencies(params) : Promise.resolve({ _tag: "Success", data: [] }),
1279
+ getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
1280
+ addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 }),
1281
+ changeFrequency: (params) => adapter.changeFrequency ? adapter.changeFrequency(params) : Promise.resolve({ _tag: "Failure", error: "Not implemented" })
1282
+ };
1283
+ }
1284
+ function createMockCustomerAdapter() {
1285
+ let customers = [
1286
+ {
1287
+ id: "customer-1",
1288
+ name: "Customer 1",
1289
+ metadata: { mealCount: 3 }
1290
+ },
1291
+ {
1292
+ id: "customer-2",
1293
+ name: "Customer 2",
1294
+ metadata: { mealCount: 4 }
1295
+ }
1296
+ ];
1297
+ return {
1298
+ async getCurrent() {
1299
+ return { _tag: "Success", data: customers[0] ?? null };
1300
+ },
1301
+ async getAll() {
1302
+ return { _tag: "Success", data: [...customers] };
1303
+ },
1304
+ async getById(id) {
1305
+ return {
1306
+ _tag: "Success",
1307
+ data: customers.find((c2) => c2.id === id) ?? null
1308
+ };
1309
+ },
1310
+ async create(data) {
1311
+ const customer = { id: `customer-${Date.now()}`, ...data };
1312
+ customers = [...customers, customer];
1313
+ return { _tag: "Success", data: customer };
1314
+ },
1315
+ async update(id, data) {
1316
+ const existing = customers.find((c2) => c2.id === id);
1317
+ if (!existing) return { _tag: "Failure", error: "Customer not found" };
1318
+ const updated = { ...existing, ...data };
1319
+ customers = customers.map((c2) => c2.id === id ? updated : c2);
1320
+ return { _tag: "Success", data: updated };
1321
+ },
1322
+ async remove(id) {
1323
+ customers = customers.filter((c2) => c2.id !== id);
1324
+ return { _tag: "Success", data: void 0 };
1325
+ }
1326
+ };
1327
+ }
1328
+ function createApiCustomerAdapter(fetcher) {
1329
+ return {
1330
+ async getCurrent() {
1331
+ try {
1332
+ const res = await fetcher("/customer/v1/customer");
1333
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1334
+ const data = await res.json();
1335
+ return { _tag: "Success", data };
1336
+ } catch (e2) {
1337
+ return { _tag: "Failure", error: e2 };
1338
+ }
1339
+ },
1340
+ async getAll() {
1341
+ try {
1342
+ const res = await fetcher("/customer/v1/customers");
1343
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1344
+ const data = await res.json();
1345
+ return { _tag: "Success", data };
1346
+ } catch (e2) {
1347
+ return { _tag: "Failure", error: e2 };
1348
+ }
1349
+ },
1350
+ async getById(id) {
1351
+ try {
1352
+ const res = await fetcher(`/customer/v1/customers/${id}`);
1353
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1354
+ const data = await res.json();
1355
+ return { _tag: "Success", data };
1356
+ } catch (e2) {
1357
+ return { _tag: "Failure", error: e2 };
1358
+ }
1359
+ },
1360
+ async create(data) {
1361
+ try {
1362
+ const res = await fetcher("/customer/v1/customers", {
1363
+ method: "POST",
1364
+ headers: { "Content-Type": "application/json" },
1365
+ body: JSON.stringify(data)
1366
+ });
1367
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1368
+ const created = await res.json();
1369
+ return { _tag: "Success", data: created };
1370
+ } catch (e2) {
1371
+ return { _tag: "Failure", error: e2 };
1372
+ }
1373
+ },
1374
+ async update(id, data) {
1375
+ try {
1376
+ const res = await fetcher(`/customer/v1/customers/${id}`, {
1377
+ method: "PATCH",
1378
+ headers: { "Content-Type": "application/json" },
1379
+ body: JSON.stringify(data)
1380
+ });
1381
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1382
+ const updated = await res.json();
1383
+ return { _tag: "Success", data: updated };
1384
+ } catch (e2) {
1385
+ return { _tag: "Failure", error: e2 };
1386
+ }
1387
+ },
1388
+ async remove(id) {
1389
+ try {
1390
+ const res = await fetcher(`/customer/v1/customers/${id}`, {
1391
+ method: "DELETE"
1392
+ });
1393
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1394
+ return { _tag: "Success", data: void 0 };
1395
+ } catch (e2) {
1396
+ return { _tag: "Failure", error: e2 };
1397
+ }
1398
+ }
1399
+ };
1400
+ }
1401
+ const CustomerServiceContext = createContext("services/customer");
1402
+ function createCustomerService(adapter) {
1403
+ return {
1404
+ getCurrent: () => adapter.getCurrent(),
1405
+ getAll: () => adapter.getAll(),
1406
+ getById: (id) => adapter.getById(id),
1407
+ create: (data) => adapter.create(data),
1408
+ update: (id, data) => adapter.update(id, data),
1409
+ remove: (id) => adapter.remove(id)
1410
+ };
1411
+ }
1412
+ function createMockOrderAdapter() {
1413
+ let orders = [
1414
+ {
1415
+ id: "order-1",
1416
+ customerId: "customer-1",
1417
+ items: [],
1418
+ deliveryDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0] ?? null,
1419
+ status: "pending"
1420
+ },
1421
+ {
1422
+ id: "order-2",
1423
+ customerId: "customer-1",
1424
+ items: [
1425
+ { id: "item-1", productId: "p1", variantId: "v1", quantity: 1 },
1426
+ { id: "item-2", productId: "p2", variantId: "v2", quantity: 2 }
1427
+ ],
1428
+ deliveryDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0] ?? null,
1429
+ status: "delivered"
1430
+ },
1431
+ {
1432
+ id: "order-3",
1433
+ customerId: "customer-1",
1434
+ items: [
1435
+ { id: "item-3", productId: "p1", variantId: "v1", quantity: 1 }
1436
+ ],
1437
+ deliveryDate: new Date(Date.now() - 60 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0] ?? null,
1438
+ status: "delivered"
1439
+ },
1440
+ {
1441
+ id: "order-4",
1442
+ customerId: "customer-1",
1443
+ items: [],
1444
+ deliveryDate: new Date(Date.now() - 90 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0] ?? null,
1445
+ status: "skipped"
1446
+ }
1447
+ ];
1448
+ return {
1449
+ async getUpcoming() {
1450
+ return {
1451
+ _tag: "Success",
1452
+ data: orders.filter((o2) => o2.status === "pending")
1453
+ };
1454
+ },
1455
+ async getHistory() {
1456
+ return {
1457
+ _tag: "Success",
1458
+ data: orders.filter((o2) => o2.status === "delivered" || o2.status === "skipped").sort((a3, b3) => (b3.deliveryDate ?? "").localeCompare(a3.deliveryDate ?? ""))
1459
+ };
1460
+ },
1461
+ async getById(id) {
1462
+ return {
1463
+ _tag: "Success",
1464
+ data: orders.find((o2) => o2.id === id) ?? null
1465
+ };
1466
+ },
1467
+ async updateItems(orderId, items) {
1468
+ const order = orders.find((o2) => o2.id === orderId);
1469
+ if (!order) return { _tag: "Failure", error: "Order not found" };
1470
+ const updated = {
1471
+ ...order,
1472
+ items: items.map((item, i2) => ({
1473
+ id: `item-${Date.now()}-${i2}`,
1474
+ ...item
1475
+ }))
1476
+ };
1477
+ orders = orders.map((o2) => o2.id === orderId ? updated : o2);
1478
+ return { _tag: "Success", data: updated };
1479
+ },
1480
+ async skip(orderId) {
1481
+ const order = orders.find((o2) => o2.id === orderId);
1482
+ if (!order) return { _tag: "Failure", error: "Order not found" };
1483
+ const updated = { ...order, status: "skipped" };
1484
+ orders = orders.map((o2) => o2.id === orderId ? updated : o2);
1485
+ return { _tag: "Success", data: updated };
1486
+ }
1487
+ };
1488
+ }
1489
+ function createApiOrderAdapter(fetcher) {
1490
+ return {
1491
+ async getUpcoming() {
1492
+ try {
1493
+ const res = await fetcher("/customer/v1/orders?status=pending");
1494
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1495
+ const body = await res.json();
1496
+ return { _tag: "Success", data: body.orders };
1497
+ } catch (e2) {
1498
+ return { _tag: "Failure", error: e2 };
1499
+ }
1500
+ },
1501
+ async getHistory() {
1502
+ try {
1503
+ const res = await fetcher("/customer/v1/orders?status=delivered,skipped");
1504
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1505
+ const body = await res.json();
1506
+ return { _tag: "Success", data: body.orders };
1507
+ } catch (e2) {
1508
+ return { _tag: "Failure", error: e2 };
1509
+ }
1510
+ },
1511
+ async getById(id) {
1512
+ try {
1513
+ const res = await fetcher(`/customer/v1/orders/${id}`);
1514
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1515
+ const data = await res.json();
1516
+ return { _tag: "Success", data };
1517
+ } catch (e2) {
1518
+ return { _tag: "Failure", error: e2 };
1519
+ }
1520
+ },
1521
+ async updateItems(orderId, items) {
1522
+ try {
1523
+ const res = await fetcher(`/customer/v1/orders/${orderId}/items`, {
1524
+ method: "PUT",
1525
+ headers: { "Content-Type": "application/json" },
1526
+ body: JSON.stringify({ items })
1527
+ });
1528
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1529
+ const data = await res.json();
1530
+ return { _tag: "Success", data };
1531
+ } catch (e2) {
1532
+ return { _tag: "Failure", error: e2 };
1533
+ }
1534
+ },
1535
+ async skip(orderId) {
1536
+ try {
1537
+ const res = await fetcher(`/customer/v1/orders/${orderId}/skip`, {
1538
+ method: "POST"
1539
+ });
1540
+ if (!res.ok) return { _tag: "Failure", error: await res.text() };
1541
+ const data = await res.json();
1542
+ return { _tag: "Success", data };
1543
+ } catch (e2) {
1544
+ return { _tag: "Failure", error: e2 };
1545
+ }
1546
+ }
1547
+ };
1548
+ }
1549
+ const OrderServiceContext = createContext("services/order");
1550
+ function createOrderService(adapter) {
1551
+ return {
1552
+ getUpcoming: () => adapter.getUpcoming(),
1553
+ getHistory: () => adapter.getHistory(),
1554
+ getById: (id) => adapter.getById(id),
1555
+ updateItems: (orderId, items) => adapter.updateItems(orderId, items),
1556
+ skip: (orderId) => adapter.skip(orderId)
1557
+ };
1558
+ }
1559
+ function futureDateStr(daysFromNow) {
1560
+ const d2 = /* @__PURE__ */ new Date();
1561
+ d2.setDate(d2.getDate() + daysFromNow);
1562
+ return d2.toISOString().split("T")[0] ?? "";
1563
+ }
1564
+ function createMockSchedulesAdapter() {
1565
+ let orders = [
1566
+ {
1567
+ id: "schedule-order-1",
1568
+ subscriptionId: "sub_1",
1569
+ deliveryDate: futureDateStr(7),
1570
+ items: [
1571
+ {
1572
+ id: "si-1",
1573
+ productId: "p-beauty-1",
1574
+ variantId: "v-beauty-1",
1575
+ quantity: 1,
1576
+ title: "Rose Face Serum",
1577
+ imageUrl: "https://images.unsplash.com/photo-1570194065650-d99fb4b38b68?w=200"
1578
+ },
1579
+ {
1580
+ id: "si-2",
1581
+ productId: "p-beauty-2",
1582
+ variantId: "v-beauty-2",
1583
+ quantity: 1,
1584
+ title: "Vitamin C Moisturizer",
1585
+ imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200"
1586
+ }
1587
+ ],
1588
+ status: "scheduled"
1589
+ },
1590
+ {
1591
+ id: "schedule-order-2",
1592
+ subscriptionId: "sub_1",
1593
+ deliveryDate: futureDateStr(35),
1594
+ items: [
1595
+ {
1596
+ id: "si-3",
1597
+ productId: "p-beauty-1",
1598
+ variantId: "v-beauty-1",
1599
+ quantity: 1,
1600
+ title: "Rose Face Serum",
1601
+ imageUrl: "https://images.unsplash.com/photo-1570194065650-d99fb4b38b68?w=200"
1602
+ },
1603
+ {
1604
+ id: "si-4",
1605
+ productId: "p-beauty-3",
1606
+ variantId: "v-beauty-3",
1607
+ quantity: 1,
1608
+ title: "Hyaluronic Acid Serum",
1609
+ imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200"
1610
+ }
1611
+ ],
1612
+ status: "scheduled"
1613
+ }
1614
+ ];
1615
+ let adjustments = [];
1616
+ return {
1617
+ async getUpcomingOrders(count) {
1618
+ await new Promise((r2) => setTimeout(r2, 200));
1619
+ return { _tag: "Success", data: orders.slice(0, count) };
1620
+ },
1621
+ async getAdjustments() {
1622
+ await new Promise((r2) => setTimeout(r2, 200));
1623
+ return { _tag: "Success", data: [...adjustments] };
1624
+ },
1625
+ async skipOrder({ subscriptionId }) {
1626
+ await new Promise((r2) => setTimeout(r2, 300));
1627
+ const order = orders.find(
1628
+ (o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
1629
+ );
1630
+ if (!order) return { _tag: "Failure", error: "No scheduled order found" };
1631
+ orders = orders.map(
1632
+ (o2) => o2.id === order.id ? { ...o2, status: "skipped" } : o2
1633
+ );
1634
+ const adj = {
1635
+ id: `adj-${Date.now()}`,
1636
+ subscriptionId,
1637
+ type: "skip"
1638
+ };
1639
+ adjustments = [...adjustments, adj];
1640
+ return { _tag: "Success", data: void 0 };
1641
+ },
1642
+ async changeDateAdjustment({ subscriptionId, newDate }) {
1643
+ await new Promise((r2) => setTimeout(r2, 300));
1644
+ const order = orders.find(
1645
+ (o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
1646
+ );
1647
+ if (!order) return { _tag: "Failure", error: "No scheduled order found" };
1648
+ orders = orders.map(
1649
+ (o2) => o2.id === order.id ? { ...o2, deliveryDate: newDate } : o2
1650
+ );
1651
+ const adj = {
1652
+ id: `adj-${Date.now()}`,
1653
+ subscriptionId,
1654
+ type: "date_change",
1655
+ newDate
1656
+ };
1657
+ adjustments = [...adjustments, adj];
1658
+ return { _tag: "Success", data: void 0 };
1659
+ },
1660
+ async removeAdjustment({ adjustmentId }) {
1661
+ await new Promise((r2) => setTimeout(r2, 200));
1662
+ adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
1663
+ return { _tag: "Success", data: void 0 };
1664
+ }
1665
+ };
1666
+ }
1667
+ function createApiSchedulesAdapter(fetcher) {
1668
+ return {
1669
+ async getUpcomingOrders(count) {
1670
+ try {
1671
+ const res = await fetcher(
1672
+ `/customer/v1/schedules?count=${count}`
1673
+ );
1674
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1675
+ const data = await res.json();
1676
+ return { _tag: "Success", data: data.orders };
1677
+ } catch (e2) {
1678
+ return { _tag: "Failure", error: e2 };
1679
+ }
1680
+ },
1681
+ async getAdjustments() {
1682
+ try {
1683
+ const res = await fetcher(`/customer/v1/schedules/adjustments`);
1684
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1685
+ const data = await res.json();
1686
+ return { _tag: "Success", data: data.items };
1687
+ } catch (e2) {
1688
+ return { _tag: "Failure", error: e2 };
1689
+ }
1690
+ },
1691
+ async skipOrder(params) {
1692
+ try {
1693
+ const res = await fetcher(`/customer/v1/schedules/adjustments`, {
1694
+ method: "POST",
1695
+ headers: { "Content-Type": "application/json" },
1696
+ body: JSON.stringify({ action: "skip", ...params })
1697
+ });
1698
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1699
+ return { _tag: "Success", data: void 0 };
1700
+ } catch (e2) {
1701
+ return { _tag: "Failure", error: e2 };
1702
+ }
1703
+ },
1704
+ async changeDateAdjustment(params) {
1705
+ try {
1706
+ const res = await fetcher(`/customer/v1/schedules/adjustments`, {
1707
+ method: "POST",
1708
+ headers: { "Content-Type": "application/json" },
1709
+ body: JSON.stringify({ action: "date_change", ...params })
1710
+ });
1711
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1712
+ return { _tag: "Success", data: void 0 };
1713
+ } catch (e2) {
1714
+ return { _tag: "Failure", error: e2 };
1715
+ }
1716
+ },
1717
+ async removeAdjustment({ adjustmentId }) {
1718
+ try {
1719
+ const res = await fetcher(
1720
+ `/customer/v1/schedules/adjustments/${adjustmentId}`,
1721
+ { method: "DELETE" }
1722
+ );
1723
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1724
+ return { _tag: "Success", data: void 0 };
1725
+ } catch (e2) {
1726
+ return { _tag: "Failure", error: e2 };
1727
+ }
1728
+ }
1729
+ };
1730
+ }
1731
+ const SchedulesServiceContext = createContext("services/schedules");
1732
+ function createSchedulesService(adapter, opts) {
1733
+ const upcoming = d([]);
1734
+ async function refreshUpcoming() {
1735
+ const count = Math.max(upcoming.value.length, 3);
1736
+ const result = await adapter.getUpcomingOrders(count);
1737
+ if (result._tag === "Success") {
1738
+ upcoming.value = result.data;
1739
+ }
1740
+ }
1741
+ return {
1742
+ upcoming,
1743
+ hasPendingBilling: opts.hasPendingBilling,
1744
+ async getUpcomingOrder() {
1745
+ const result = await adapter.getUpcomingOrders(1);
1746
+ if (result._tag === "Failure") return result;
1747
+ upcoming.value = result.data;
1748
+ return { _tag: "Success", data: result.data[0] ?? null };
1749
+ },
1750
+ async getUpcomingOrders(count) {
1751
+ const result = await adapter.getUpcomingOrders(count);
1752
+ if (result._tag === "Success") {
1753
+ upcoming.value = result.data;
1754
+ }
1755
+ return result;
1756
+ },
1757
+ async getAdjustments() {
1758
+ return adapter.getAdjustments();
1759
+ },
1760
+ async skipOrder(params) {
1761
+ const result = await adapter.skipOrder(params);
1762
+ if (result._tag === "Success") {
1763
+ await refreshUpcoming();
1764
+ }
1765
+ return result;
1766
+ },
1767
+ async changeDateAdjustment(params) {
1768
+ const result = await adapter.changeDateAdjustment(params);
1769
+ if (result._tag === "Success") {
1770
+ await refreshUpcoming();
1771
+ }
1772
+ return result;
1773
+ },
1774
+ async removeAdjustment(params) {
1775
+ return adapter.removeAdjustment(params);
1776
+ }
861
1777
  };
862
1778
  }
1779
+ const RouterServiceContext = createContext("services/router");
863
1780
  const MOCK_FLOWS = {
864
1781
  cancellation: [
865
1782
  {
@@ -1116,9 +2033,13 @@ export {
1116
2033
  B as BlockWrapperEvent,
1117
2034
  n as ContextProvideEvent,
1118
2035
  C as ContextRequestEvent,
2036
+ CustomerServiceContext,
1119
2037
  D as DEFAULT_GLOBAL_STYLES,
1120
2038
  LoginServiceContext,
2039
+ OrderServiceContext,
1121
2040
  ProductServiceContext,
2041
+ RouterServiceContext,
2042
+ SchedulesServiceContext,
1122
2043
  S as SelectedBlockContext,
1123
2044
  u as Signal,
1124
2045
  StateContext,
@@ -1127,15 +2048,25 @@ export {
1127
2048
  T2 as TranslationContext,
1128
2049
  W as WorkflowServiceContext,
1129
2050
  w as computed,
2051
+ createApiCustomerAdapter,
2052
+ createApiOrderAdapter,
2053
+ createApiSchedulesAdapter,
2054
+ createApiSubscriptionAdapter,
1130
2055
  a as createBlockInstance,
1131
2056
  b as createBlockInstanceFromJSON,
1132
2057
  e as createBlockInstanceFromObject,
1133
2058
  f as createCeRenderer,
1134
2059
  createContext,
2060
+ createCustomerService,
2061
+ createMockCustomerAdapter,
2062
+ createMockOrderAdapter,
1135
2063
  createMockProductAdapter,
2064
+ createMockSchedulesAdapter,
1136
2065
  createMockSubscriptionAdapter,
1137
2066
  createMockWorkflowApiAdapter,
2067
+ createOrderService,
1138
2068
  createProductService,
2069
+ createSchedulesService,
1139
2070
  k as createSelectedBlock,
1140
2071
  createState,
1141
2072
  createSubscriptionService,