@hanzo/commerce 7.6.1 → 7.6.4

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 (264) hide show
  1. package/LICENSE.md +21 -0
  2. package/client.ts +124 -64
  3. package/components/add-to-cart-widget.tsx +6 -0
  4. package/components/item/product-card.tsx +18 -1
  5. package/dist/billing.d.ts +2 -0
  6. package/dist/billing.js +3 -0
  7. package/dist/billing.js.map +1 -0
  8. package/dist/client.d.ts +432 -0
  9. package/dist/client.js +392 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/components/Icons.d.ts +18 -0
  12. package/dist/components/Icons.js +19 -0
  13. package/dist/components/Icons.js.map +1 -0
  14. package/dist/components/add-to-cart-widget.d.ts +11 -0
  15. package/dist/components/add-to-cart-widget.js +85 -0
  16. package/dist/components/add-to-cart-widget.js.map +1 -0
  17. package/dist/components/buy/buy-card.d.ts +30 -0
  18. package/dist/components/buy/buy-card.js +109 -0
  19. package/dist/components/buy/buy-card.js.map +1 -0
  20. package/dist/components/buy/carousel-buy-card.d.ts +12 -0
  21. package/dist/components/buy/carousel-buy-card.js +94 -0
  22. package/dist/components/buy/carousel-buy-card.js.map +1 -0
  23. package/dist/components/buy/multi-family/all-variants-carousel.d.ts +4 -0
  24. package/dist/components/buy/multi-family/all-variants-carousel.js +115 -0
  25. package/dist/components/buy/multi-family/all-variants-carousel.js.map +1 -0
  26. package/dist/components/buy/multi-family/family-carousel/index.d.ts +4 -0
  27. package/dist/components/buy/multi-family/family-carousel/index.js +27 -0
  28. package/dist/components/buy/multi-family/family-carousel/index.js.map +1 -0
  29. package/dist/components/buy/multi-family/family-carousel/slide.d.ts +11 -0
  30. package/dist/components/buy/multi-family/family-carousel/slide.js +35 -0
  31. package/dist/components/buy/multi-family/family-carousel/slide.js.map +1 -0
  32. package/dist/components/buy/multi-family/family-carousel/state.d.ts +20 -0
  33. package/dist/components/buy/multi-family/family-carousel/state.js +59 -0
  34. package/dist/components/buy/multi-family/family-carousel/state.js.map +1 -0
  35. package/dist/components/buy/multi-family/index.d.ts +2 -0
  36. package/dist/components/buy/multi-family/index.js +3 -0
  37. package/dist/components/buy/multi-family/index.js.map +1 -0
  38. package/dist/components/buy/single-family-selector.d.ts +15 -0
  39. package/dist/components/buy/single-family-selector.js +28 -0
  40. package/dist/components/buy/single-family-selector.js.map +1 -0
  41. package/dist/components/buy/title-and-byline.d.ts +8 -0
  42. package/dist/components/buy/title-and-byline.js +7 -0
  43. package/dist/components/buy/title-and-byline.js.map +1 -0
  44. package/dist/components/cart/cart-panel/cart-line-item.d.ts +11 -0
  45. package/dist/components/cart/cart-panel/cart-line-item.js +25 -0
  46. package/dist/components/cart/cart-panel/cart-line-item.js.map +1 -0
  47. package/dist/components/cart/cart-panel/index.d.ts +19 -0
  48. package/dist/components/cart/cart-panel/index.js +65 -0
  49. package/dist/components/cart/cart-panel/index.js.map +1 -0
  50. package/dist/components/cart/cart-panel/promo-code.d.ts +4 -0
  51. package/dist/components/cart/cart-panel/promo-code.js +62 -0
  52. package/dist/components/cart/cart-panel/promo-code.js.map +1 -0
  53. package/dist/components/cart/cart-panel/total-area.d.ts +7 -0
  54. package/dist/components/cart/cart-panel/total-area.js +14 -0
  55. package/dist/components/cart/cart-panel/total-area.js.map +1 -0
  56. package/dist/components/checkout/payment-step-form/card-icon-row.d.ts +2 -0
  57. package/dist/components/checkout/payment-step-form/card-icon-row.js +14 -0
  58. package/dist/components/checkout/payment-step-form/card-icon-row.js.map +1 -0
  59. package/dist/components/checkout/payment-step-form/card-icons/amex.d.ts +4 -0
  60. package/dist/components/checkout/payment-step-form/card-icons/amex.js +6 -0
  61. package/dist/components/checkout/payment-step-form/card-icons/amex.js.map +1 -0
  62. package/dist/components/checkout/payment-step-form/card-icons/diners-club.d.ts +4 -0
  63. package/dist/components/checkout/payment-step-form/card-icons/diners-club.js +6 -0
  64. package/dist/components/checkout/payment-step-form/card-icons/diners-club.js.map +1 -0
  65. package/dist/components/checkout/payment-step-form/card-icons/discover.d.ts +4 -0
  66. package/dist/components/checkout/payment-step-form/card-icons/discover.js +6 -0
  67. package/dist/components/checkout/payment-step-form/card-icons/discover.js.map +1 -0
  68. package/dist/components/checkout/payment-step-form/card-icons/jcb.d.ts +4 -0
  69. package/dist/components/checkout/payment-step-form/card-icons/jcb.js +6 -0
  70. package/dist/components/checkout/payment-step-form/card-icons/jcb.js.map +1 -0
  71. package/dist/components/checkout/payment-step-form/card-icons/mastercard.d.ts +4 -0
  72. package/dist/components/checkout/payment-step-form/card-icons/mastercard.js +6 -0
  73. package/dist/components/checkout/payment-step-form/card-icons/mastercard.js.map +1 -0
  74. package/dist/components/checkout/payment-step-form/card-icons/visa.d.ts +4 -0
  75. package/dist/components/checkout/payment-step-form/card-icons/visa.js +6 -0
  76. package/dist/components/checkout/payment-step-form/card-icons/visa.js.map +1 -0
  77. package/dist/components/checkout/payment-step-form/cc-button.d.ts +3 -0
  78. package/dist/components/checkout/payment-step-form/cc-button.js +6 -0
  79. package/dist/components/checkout/payment-step-form/cc-button.js.map +1 -0
  80. package/dist/components/checkout/payment-step-form/contact-form.d.ts +5 -0
  81. package/dist/components/checkout/payment-step-form/contact-form.js +6 -0
  82. package/dist/components/checkout/payment-step-form/contact-form.js.map +1 -0
  83. package/dist/components/checkout/payment-step-form/crypto-icons/btc.d.ts +4 -0
  84. package/dist/components/checkout/payment-step-form/crypto-icons/btc.js +6 -0
  85. package/dist/components/checkout/payment-step-form/crypto-icons/btc.js.map +1 -0
  86. package/dist/components/checkout/payment-step-form/crypto-icons/eth.d.ts +4 -0
  87. package/dist/components/checkout/payment-step-form/crypto-icons/eth.js +6 -0
  88. package/dist/components/checkout/payment-step-form/crypto-icons/eth.js.map +1 -0
  89. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.d.ts +4 -0
  90. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js +6 -0
  91. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js.map +1 -0
  92. package/dist/components/checkout/payment-step-form/index.d.ts +4 -0
  93. package/dist/components/checkout/payment-step-form/index.js +66 -0
  94. package/dist/components/checkout/payment-step-form/index.js.map +1 -0
  95. package/dist/components/checkout/payment-step-form/methods/bank-transfer.d.ts +4 -0
  96. package/dist/components/checkout/payment-step-form/methods/bank-transfer.js +24 -0
  97. package/dist/components/checkout/payment-step-form/methods/bank-transfer.js.map +1 -0
  98. package/dist/components/checkout/payment-step-form/methods/card.d.ts +4 -0
  99. package/dist/components/checkout/payment-step-form/methods/card.js +160 -0
  100. package/dist/components/checkout/payment-step-form/methods/card.js.map +1 -0
  101. package/dist/components/checkout/payment-step-form/methods/crypto.d.ts +9 -0
  102. package/dist/components/checkout/payment-step-form/methods/crypto.js +137 -0
  103. package/dist/components/checkout/payment-step-form/methods/crypto.js.map +1 -0
  104. package/dist/components/checkout/payment-step-form/methods/index.d.ts +6 -0
  105. package/dist/components/checkout/payment-step-form/methods/index.js +21 -0
  106. package/dist/components/checkout/payment-step-form/methods/index.js.map +1 -0
  107. package/dist/components/checkout/shipping-step-form.d.ts +3 -0
  108. package/dist/components/checkout/shipping-step-form.js +53 -0
  109. package/dist/components/checkout/shipping-step-form.js.map +1 -0
  110. package/dist/components/index.d.ts +8 -0
  111. package/dist/components/index.js +9 -0
  112. package/dist/components/index.js.map +1 -0
  113. package/dist/components/item/product-card.d.ts +7 -0
  114. package/dist/components/item/product-card.js +9 -0
  115. package/dist/components/item/product-card.js.map +1 -0
  116. package/dist/components/item-selector/button.d.ts +4 -0
  117. package/dist/components/item-selector/button.js +47 -0
  118. package/dist/components/item-selector/button.js.map +1 -0
  119. package/dist/components/item-selector/carousel/index.d.ts +12 -0
  120. package/dist/components/item-selector/carousel/index.js +74 -0
  121. package/dist/components/item-selector/carousel/index.js.map +1 -0
  122. package/dist/components/item-selector/carousel/slider.d.ts +8 -0
  123. package/dist/components/item-selector/carousel/slider.js +12 -0
  124. package/dist/components/item-selector/carousel/slider.js.map +1 -0
  125. package/dist/components/item-selector/index.d.ts +2 -0
  126. package/dist/components/item-selector/index.js +3 -0
  127. package/dist/components/item-selector/index.js.map +1 -0
  128. package/dist/components/item-selector/quantity-indicator.d.ts +9 -0
  129. package/dist/components/item-selector/quantity-indicator.js +16 -0
  130. package/dist/components/item-selector/quantity-indicator.js.map +1 -0
  131. package/dist/components/node-tabs/index.d.ts +14 -0
  132. package/dist/components/node-tabs/index.js +42 -0
  133. package/dist/components/node-tabs/index.js.map +1 -0
  134. package/dist/components/node-tabs/node-image.d.ts +6 -0
  135. package/dist/components/node-tabs/node-image.js +13 -0
  136. package/dist/components/node-tabs/node-image.js.map +1 -0
  137. package/dist/index.d.ts +9 -0
  138. package/dist/index.js +9 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/metering.d.ts +162 -0
  141. package/dist/metering.js +204 -0
  142. package/dist/metering.js.map +1 -0
  143. package/dist/metering.test.d.ts +13 -0
  144. package/dist/metering.test.js +181 -0
  145. package/dist/metering.test.js.map +1 -0
  146. package/dist/product-card.test.d.ts +14 -0
  147. package/dist/product-card.test.js +96 -0
  148. package/dist/product-card.test.js.map +1 -0
  149. package/dist/service/context.d.ts +8 -0
  150. package/dist/service/context.js +19 -0
  151. package/dist/service/context.js.map +1 -0
  152. package/dist/service/debug.d.ts +10 -0
  153. package/dist/service/debug.js +30 -0
  154. package/dist/service/debug.js.map +1 -0
  155. package/dist/service/impls/standalone/actual-line-item.d.ts +40 -0
  156. package/dist/service/impls/standalone/actual-line-item.js +84 -0
  157. package/dist/service/impls/standalone/actual-line-item.js.map +1 -0
  158. package/dist/service/impls/standalone/get-instance.d.ts +2 -0
  159. package/dist/service/impls/standalone/get-instance.js +39 -0
  160. package/dist/service/impls/standalone/get-instance.js.map +1 -0
  161. package/dist/service/impls/standalone/index.d.ts +67 -0
  162. package/dist/service/impls/standalone/index.js +416 -0
  163. package/dist/service/impls/standalone/index.js.map +1 -0
  164. package/dist/service/impls/standalone/order/firebase.d.ts +6 -0
  165. package/dist/service/impls/standalone/order/firebase.js +6 -0
  166. package/dist/service/impls/standalone/order/firebase.js.map +1 -0
  167. package/dist/service/impls/standalone/order/index.d.ts +30 -0
  168. package/dist/service/impls/standalone/order/index.js +21 -0
  169. package/dist/service/impls/standalone/order/index.js.map +1 -0
  170. package/dist/service/impls/standalone/persistence.d.ts +4 -0
  171. package/dist/service/impls/standalone/persistence.js +22 -0
  172. package/dist/service/impls/standalone/persistence.js.map +1 -0
  173. package/dist/service/path-utils.d.ts +7 -0
  174. package/dist/service/path-utils.js +16 -0
  175. package/dist/service/path-utils.js.map +1 -0
  176. package/dist/service/sep.d.ts +6 -0
  177. package/dist/service/sep.js +6 -0
  178. package/dist/service/sep.js.map +1 -0
  179. package/dist/types/category-node.d.ts +36 -0
  180. package/dist/types/category-node.js +2 -0
  181. package/dist/types/category-node.js.map +1 -0
  182. package/dist/types/checkout.d.ts +33 -0
  183. package/dist/types/checkout.js +2 -0
  184. package/dist/types/checkout.js.map +1 -0
  185. package/dist/types/commerce-config.d.ts +11 -0
  186. package/dist/types/commerce-config.js +2 -0
  187. package/dist/types/commerce-config.js.map +1 -0
  188. package/dist/types/commerce-service.d.ts +109 -0
  189. package/dist/types/commerce-service.js +2 -0
  190. package/dist/types/commerce-service.js.map +1 -0
  191. package/dist/types/family.d.ts +16 -0
  192. package/dist/types/family.js +2 -0
  193. package/dist/types/family.js.map +1 -0
  194. package/dist/types/index.d.ts +13 -0
  195. package/dist/types/index.js +8 -0
  196. package/dist/types/index.js.map +1 -0
  197. package/dist/types/item-selector.d.ts +72 -0
  198. package/dist/types/item-selector.js +2 -0
  199. package/dist/types/item-selector.js.map +1 -0
  200. package/dist/types/line-item.d.ts +14 -0
  201. package/dist/types/line-item.js +2 -0
  202. package/dist/types/line-item.js.map +1 -0
  203. package/dist/types/multi-family-selector-props.d.ts +16 -0
  204. package/dist/types/multi-family-selector-props.js +2 -0
  205. package/dist/types/multi-family-selector-props.js.map +1 -0
  206. package/dist/types/product.d.ts +15 -0
  207. package/dist/types/product.js +2 -0
  208. package/dist/types/product.js.map +1 -0
  209. package/dist/types/promo.d.ts +7 -0
  210. package/dist/types/promo.js +2 -0
  211. package/dist/types/promo.js.map +1 -0
  212. package/dist/types/selection-ui-specifier.d.ts +40 -0
  213. package/dist/types/selection-ui-specifier.js +2 -0
  214. package/dist/types/selection-ui-specifier.js.map +1 -0
  215. package/dist/types/string-mutator.d.ts +9 -0
  216. package/dist/types/string-mutator.js +2 -0
  217. package/dist/types/string-mutator.js.map +1 -0
  218. package/dist/types/token-separators.d.ts +6 -0
  219. package/dist/types/token-separators.js +2 -0
  220. package/dist/types/token-separators.js.map +1 -0
  221. package/dist/util/analytics.d.ts +9 -0
  222. package/dist/util/analytics.js +10 -0
  223. package/dist/util/analytics.js.map +1 -0
  224. package/dist/util/countries.d.ts +7 -0
  225. package/dist/util/countries.js +197 -0
  226. package/dist/util/countries.js.map +1 -0
  227. package/dist/util/error.d.ts +1 -0
  228. package/dist/util/error.js +22 -0
  229. package/dist/util/error.js.map +1 -0
  230. package/dist/util/index.d.ts +15 -0
  231. package/dist/util/index.js +54 -0
  232. package/dist/util/index.js.map +1 -0
  233. package/dist/util/item-selector-options-accessor.d.ts +3 -0
  234. package/dist/util/item-selector-options-accessor.js +27 -0
  235. package/dist/util/item-selector-options-accessor.js.map +1 -0
  236. package/dist/util/line-item-ref.d.ts +8 -0
  237. package/dist/util/line-item-ref.js +15 -0
  238. package/dist/util/line-item-ref.js.map +1 -0
  239. package/dist/util/multi-family-selector-options-accessor.d.ts +3 -0
  240. package/dist/util/multi-family-selector-options-accessor.js +11 -0
  241. package/dist/util/multi-family-selector-options-accessor.js.map +1 -0
  242. package/dist/util/obs-string-mutator.d.ts +8 -0
  243. package/dist/util/obs-string-mutator.js +15 -0
  244. package/dist/util/obs-string-mutator.js.map +1 -0
  245. package/dist/util/product-media-accessor.d.ts +29 -0
  246. package/dist/util/product-media-accessor.js +22 -0
  247. package/dist/util/product-media-accessor.js.map +1 -0
  248. package/dist/util/promo-codes.d.ts +3 -0
  249. package/dist/util/promo-codes.js +100 -0
  250. package/dist/util/promo-codes.js.map +1 -0
  251. package/dist/util/selection-ui-specifiers.d.ts +3 -0
  252. package/dist/util/selection-ui-specifiers.js +24 -0
  253. package/dist/util/selection-ui-specifiers.js.map +1 -0
  254. package/dist/util/square-payment.d.ts +7 -0
  255. package/dist/util/square-payment.js +37 -0
  256. package/dist/util/square-payment.js.map +1 -0
  257. package/dist/util/use-sync-sku-param-w-current-item.d.ts +2 -0
  258. package/dist/util/use-sync-sku-param-w-current-item.js +61 -0
  259. package/dist/util/use-sync-sku-param-w-current-item.js.map +1 -0
  260. package/index.ts +18 -3
  261. package/metering.test.ts +199 -0
  262. package/metering.ts +289 -0
  263. package/package.json +19 -17
  264. package/product-card.test.tsx +104 -0
@@ -0,0 +1,40 @@
1
+ import type { ImageDef, MediaTransform, VideoDef } from '@hanzo/ui/types';
2
+ import type { Product, LineItem, CommerceService } from '../../../types';
3
+ interface ActualLineItemSnapshot {
4
+ sku: string;
5
+ familyId: string;
6
+ title: string;
7
+ price: number;
8
+ quantity: number;
9
+ timeAdded: number;
10
+ timeModified: number;
11
+ }
12
+ declare class ActualLineItem implements LineItem {
13
+ qu: number;
14
+ id: string;
15
+ sku: string;
16
+ fullTitle?: string;
17
+ optionLabel: string;
18
+ optionLabelShort?: string;
19
+ familyTitle: string;
20
+ familyId: string;
21
+ byline?: string;
22
+ desc?: string;
23
+ price: number;
24
+ img?: ImageDef;
25
+ video?: VideoDef;
26
+ animation?: string;
27
+ mediaTransform?: MediaTransform;
28
+ optionImg?: ImageDef;
29
+ timeAdded: number;
30
+ timeModified: number;
31
+ constructor(prod: Product, snap?: ActualLineItemSnapshot);
32
+ get title(): string;
33
+ takeSnapshot: (cmmc: CommerceService) => ActualLineItemSnapshot;
34
+ get canDecrement(): boolean;
35
+ get quantity(): number;
36
+ get isInCart(): boolean;
37
+ increment(): void;
38
+ decrement(): void;
39
+ }
40
+ export { type ActualLineItemSnapshot, ActualLineItem as default };
@@ -0,0 +1,84 @@
1
+ import { action, computed, makeObservable, observable, } from 'mobx';
2
+ class ActualLineItem {
3
+ constructor(prod, snap) {
4
+ this.qu = 0;
5
+ this.timeAdded = 0; // Timestamp when added
6
+ this.timeModified = 0; // Timestamp quantity last modified (0 if not in cart)
7
+ this.takeSnapshot = (cmmc) => {
8
+ const title = this.fullTitle ?
9
+ this.fullTitle
10
+ :
11
+ ((cmmc.getFamilyById(this.familyId)?.title ?? this.familyTitle) + ', ' + this.optionLabel);
12
+ return {
13
+ sku: this.sku,
14
+ familyId: this.familyId,
15
+ title,
16
+ price: this.price,
17
+ quantity: this.qu,
18
+ timeAdded: this.timeAdded,
19
+ timeModified: this.timeModified
20
+ };
21
+ };
22
+ this.id = prod.id;
23
+ this.sku = prod.sku;
24
+ this.fullTitle = prod.fullTitle;
25
+ this.optionLabel = prod.optionLabel;
26
+ this.optionLabelShort = prod.optionLabelShort;
27
+ this.familyTitle = prod.familyTitle;
28
+ this.familyId = prod.familyId;
29
+ this.byline = prod.byline;
30
+ this.desc = prod.desc;
31
+ this.price = prod.price;
32
+ this.img = prod.img;
33
+ this.video = prod.video;
34
+ this.animation = prod.animation;
35
+ this.optionImg = prod.optionImg;
36
+ this.mediaTransform = prod.mediaTransform;
37
+ if (snap) {
38
+ this.qu = snap.quantity;
39
+ this.timeAdded = snap.timeAdded;
40
+ this.timeModified = snap.timeModified;
41
+ }
42
+ makeObservable(this, {
43
+ qu: observable,
44
+ timeAdded: observable,
45
+ timeModified: observable,
46
+ canDecrement: computed,
47
+ isInCart: computed,
48
+ title: computed,
49
+ increment: action,
50
+ decrement: action,
51
+ });
52
+ }
53
+ // TODO: create a way to pass template strings to the ui conf per sku path!
54
+ get title() {
55
+ return this.fullTitle ? this.fullTitle : (this.familyTitle + ', ' + this.optionLabel);
56
+ }
57
+ get canDecrement() { return this.qu > 0; }
58
+ get quantity() { return this.qu; }
59
+ get isInCart() { return this.qu > 0; }
60
+ increment() {
61
+ if (this.qu === 0) {
62
+ this.timeAdded = new Date().getTime();
63
+ this.timeModified = this.timeAdded;
64
+ }
65
+ else {
66
+ this.timeModified = new Date().getTime();
67
+ }
68
+ this.qu++;
69
+ }
70
+ decrement() {
71
+ if (this.canDecrement) {
72
+ this.qu--;
73
+ if (this.qu === 0) {
74
+ this.timeAdded = 0;
75
+ this.timeModified = 0;
76
+ }
77
+ else {
78
+ this.timeModified = new Date().getTime();
79
+ }
80
+ }
81
+ }
82
+ }
83
+ export { ActualLineItem as default };
84
+ //# sourceMappingURL=actual-line-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actual-line-item.js","sourceRoot":"","sources":["../../../../service/impls/standalone/actual-line-item.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CommerceService, CommerceConfig } from '../../../types';
2
+ export declare const getInstance: ({ families, rootNode, options, uiSpecifiers }: CommerceConfig) => CommerceService;
@@ -0,0 +1,39 @@
1
+ import { enableStaticRendering } from 'mobx-react-lite';
2
+ import { StandaloneService } from './index';
3
+ import { initSelectionUI } from '../../../util';
4
+ import { readSnapshot, writeSnapshotsOnChange } from './persistence';
5
+ enableStaticRendering(typeof window === "undefined");
6
+ const _LOG = false;
7
+ const _log = (s) => {
8
+ if (!_LOG)
9
+ return;
10
+ const d = new Date();
11
+ console.log(`TIMESTAMPED: ${d.getUTCMinutes()}:${d.getUTCSeconds()}:${d.getUTCMilliseconds()}`);
12
+ console.log(s);
13
+ };
14
+ // https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
15
+ let instance = undefined;
16
+ export const getInstance = ({ families, rootNode, options, uiSpecifiers }) => {
17
+ if (!options) {
18
+ throw new Error('cmmc getInstance(): Standalone Commerce Service requires config options!');
19
+ }
20
+ if (typeof window === "undefined") {
21
+ if (uiSpecifiers) {
22
+ initSelectionUI(uiSpecifiers);
23
+ }
24
+ _log("NEW INSTANCE: SERVER"); //////////
25
+ return new StandaloneService(families, rootNode, options);
26
+ }
27
+ // Client side, create the store only once in the client
28
+ if (!instance) {
29
+ if (uiSpecifiers) {
30
+ initSelectionUI(uiSpecifiers);
31
+ }
32
+ _log("NEW INSTANCE: CLIENT"); ///////////
33
+ const snapShot = readSnapshot(options.localStorageKey);
34
+ instance = new StandaloneService(families, rootNode, options, snapShot);
35
+ writeSnapshotsOnChange(instance, options.localStorageKey);
36
+ }
37
+ return instance;
38
+ };
39
+ //# sourceMappingURL=get-instance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-instance.js","sourceRoot":"","sources":["../../../../service/impls/standalone/get-instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAGvD,OAAO,EAAE,iBAAiB,EAAE,MAAO,SAAS,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAEpE,qBAAqB,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAA;AAEpD,MAAM,IAAI,GAAG,KAAK,CAAA;AAClB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;IACzB,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAA;IACpB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAA;IAC/F,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAChB,CAAC,CAAA;AAED,uEAAuE;AAEvE,IAAI,QAAQ,GAAmC,SAAS,CAAA;AAExD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAC1B,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,YAAY,EACG,EAAoB,EAAE;IAErC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IAEA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,IAAI,YAAY,EAAE,CAAC;YACjB,eAAe,CAAC,YAAY,CAAC,CAAA;QAC/B,CAAC;QACD,IAAI,CAAC,sBAAsB,CAAC,CAAA,CAAC,UAAU;QACvC,OAAO,IAAI,iBAAiB,CAC1B,QAAQ,EACR,QAAQ,EACR,OAAO,CACR,CAAA;IACH,CAAC;IAEC,wDAAwD;IAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,YAAY,EAAE,CAAC;YACjB,eAAe,CAAC,YAAY,CAAC,CAAA;QAC/B,CAAC;QACD,IAAI,CAAC,sBAAsB,CAAC,CAAA,CAAC,WAAW;QACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QACtD,QAAQ,GAAG,IAAI,iBAAiB,CAC9B,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,CACT,CAAA;QACD,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IAC3D,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA"}
@@ -0,0 +1,67 @@
1
+ import type { CommerceService, Family, LineItem, SelectedPaths, CategoryNode, CategoryNodeRole, Promo } from '../../../types';
2
+ import { type ActualLineItemSnapshot } from './actual-line-item';
3
+ import { getInstance } from './get-instance';
4
+ type StandaloneServiceOptions = {
5
+ dbName: string;
6
+ ordersTable: string;
7
+ localStorageKey: string;
8
+ };
9
+ interface StandaloneServiceSnapshot {
10
+ items: ActualLineItemSnapshot[];
11
+ }
12
+ declare class StandaloneService implements CommerceService {
13
+ private _familyMap;
14
+ private _rootNode;
15
+ private _selectedPaths;
16
+ private _promo;
17
+ private _options;
18
+ private _currentFamily;
19
+ private _currentItem;
20
+ constructor(families: Family[], rootNode: CategoryNode, options: StandaloneServiceOptions, serviceSnapshot?: StandaloneServiceSnapshot);
21
+ getFamilyById(id: string): Family | undefined;
22
+ getNodeAtPath(skuPath: string): CategoryNode | undefined;
23
+ peek(skuPath: string): {
24
+ role: CategoryNodeRole;
25
+ family: Family | undefined;
26
+ families: Family[] | undefined;
27
+ node: CategoryNode | undefined;
28
+ item: LineItem | undefined;
29
+ } | string;
30
+ getSelectedNodesAtLevel: (level: number) => CategoryNode[] | undefined;
31
+ get options(): StandaloneServiceOptions;
32
+ createOrder(email: string, name?: string): Promise<string | undefined>;
33
+ updateOrderShippingInfo(orderId: string, shippingInfo: any): Promise<void>;
34
+ updateOrderPaymentInfo(orderId: string, paymentInfo: any): Promise<void>;
35
+ takeSnapshot: () => StandaloneServiceSnapshot;
36
+ get recentItem(): {
37
+ item: LineItem;
38
+ modified: number;
39
+ } | undefined;
40
+ private get _cartItems();
41
+ get cartItems(): LineItem[];
42
+ get cartEmpty(): boolean;
43
+ get cartTotal(): number;
44
+ _promoValue_unsafe(value: number): number;
45
+ get promoAppliedCartTotal(): number;
46
+ itemPromoPrice(item: LineItem): number | undefined;
47
+ get cartQuantity(): number;
48
+ get appliedPromo(): Promo | null;
49
+ setAppliedPromo(promo: Promo | null): void;
50
+ getItemBySku: (skuToFind: string | undefined) => LineItem | undefined;
51
+ setCurrentItem: (skuToFind: string | undefined) => boolean;
52
+ get item(): LineItem | undefined;
53
+ get currentItem(): LineItem | undefined;
54
+ setCurrentFamily(id: string | undefined): boolean;
55
+ get currentFamily(): Family | undefined;
56
+ get family(): Family | undefined;
57
+ selectPaths(sel: SelectedPaths): Family[];
58
+ selectPath(skuPath: string): Family[];
59
+ get selectedPaths(): SelectedPaths;
60
+ get selectedFamilies(): Family[];
61
+ private _reduceNode;
62
+ private _processAndValidate;
63
+ get selectedItems(): LineItem[];
64
+ get hasSelection(): boolean;
65
+ getFamilySubtotal(familyId: string): number;
66
+ }
67
+ export { type StandaloneServiceOptions, type StandaloneServiceSnapshot, StandaloneService, getInstance };
@@ -0,0 +1,416 @@
1
+ import { computed, makeObservable, observable, runInAction, action, toJS } from 'mobx';
2
+ import { computedFn } from 'mobx-utils';
3
+ import { createOrder as createOrderHelper, updateOrderShippingInfo as updateOrderShippingInfoHelper, updateOrderPaymentInfo as updateOrderPaymentInfoHelper } from './order';
4
+ import ActualLineItem, {} from './actual-line-item';
5
+ import { getParentPath } from '../../path-utils';
6
+ import { getErrorMessage } from '../../../util';
7
+ import sep from '../../sep';
8
+ import { getInstance } from './get-instance';
9
+ class StandaloneService {
10
+ constructor(families, rootNode, options, serviceSnapshot) {
11
+ this._familyMap = new Map();
12
+ this._selectedPaths = {};
13
+ this._promo = null;
14
+ this._currentFamily = undefined;
15
+ this._currentItem = undefined;
16
+ this.getSelectedNodesAtLevel = computedFn((level) => {
17
+ let lvl = 1;
18
+ let nodesAtLevel = this._rootNode.subNodes;
19
+ do {
20
+ let selectedAtLevel = undefined;
21
+ // If not specified, assume all
22
+ if (lvl in this._selectedPaths) {
23
+ selectedAtLevel = nodesAtLevel.filter((n) => (this._selectedPaths[lvl].includes(n.skuToken)));
24
+ }
25
+ else {
26
+ selectedAtLevel = nodesAtLevel;
27
+ }
28
+ let allSubsOfSelected = [];
29
+ selectedAtLevel?.forEach((n) => {
30
+ if (n.subNodes) {
31
+ allSubsOfSelected = [...allSubsOfSelected, ...n.subNodes];
32
+ }
33
+ });
34
+ nodesAtLevel = allSubsOfSelected;
35
+ lvl++;
36
+ } while (nodesAtLevel.length > 0 && lvl <= level);
37
+ return (nodesAtLevel.length > 0 && ((lvl - 1) === level)) ? nodesAtLevel : undefined;
38
+ });
39
+ // Might as well use the ordered set.
40
+ this.takeSnapshot = () => ({
41
+ items: this.cartItems.map((it) => (it.takeSnapshot(this)))
42
+ });
43
+ this.getItemBySku = (skuToFind) => {
44
+ if (skuToFind === undefined || skuToFind.length === 0) {
45
+ return undefined;
46
+ }
47
+ // Self-calling
48
+ const found = (() => {
49
+ const familiesTried = [];
50
+ if (this.selectedFamilies && this.selectedFamilies.length > 0) {
51
+ for (let family of this.selectedFamilies) {
52
+ familiesTried.push(family.id);
53
+ const foundItem = family.products.find((p) => (p.sku === skuToFind));
54
+ if (foundItem) {
55
+ return foundItem;
56
+ }
57
+ }
58
+ }
59
+ for (const [familyId, family] of this._familyMap.entries()) {
60
+ if (familiesTried.includes(familyId))
61
+ continue;
62
+ const foundItem = family.products.find((p) => (p.sku === skuToFind));
63
+ if (foundItem) {
64
+ return foundItem;
65
+ }
66
+ }
67
+ return undefined;
68
+ })(); // Self-calling, necessary semi
69
+ return found;
70
+ };
71
+ this.setCurrentItem = (skuToFind) => {
72
+ if (skuToFind === undefined || skuToFind.length === 0) {
73
+ this._currentItem = undefined;
74
+ return true;
75
+ }
76
+ // self calling function
77
+ this._currentItem = this.getItemBySku(skuToFind);
78
+ this.setCurrentFamily(this._currentItem ? this._currentItem.familyId : undefined);
79
+ return !!this._currentItem;
80
+ };
81
+ this._rootNode = rootNode;
82
+ this._options = options;
83
+ families.forEach((fam) => {
84
+ fam.products = fam.products.map((p) => {
85
+ if (serviceSnapshot) {
86
+ const itemSnapshot = serviceSnapshot.items.find((is) => (is.sku === p.sku));
87
+ if (itemSnapshot) {
88
+ return new ActualLineItem(p, itemSnapshot);
89
+ }
90
+ }
91
+ return new ActualLineItem(p);
92
+ });
93
+ this._familyMap.set(fam.id, fam);
94
+ });
95
+ makeObservable(this, {
96
+ _selectedPaths: observable.deep,
97
+ _currentItem: observable.shallow,
98
+ _currentFamily: observable.shallow,
99
+ _promo: observable,
100
+ _cartItems: computed
101
+ });
102
+ makeObservable(this, {
103
+ setCurrentItem: action,
104
+ setCurrentFamily: action,
105
+ setAppliedPromo: action,
106
+ /* NOT selectPaths. It implements it's action mechanism */
107
+ cartItems: computed,
108
+ recentItem: computed,
109
+ cartQuantity: computed,
110
+ cartTotal: computed,
111
+ promoAppliedCartTotal: computed,
112
+ cartEmpty: computed,
113
+ selectedItems: computed,
114
+ selectedFamilies: computed,
115
+ hasSelection: computed,
116
+ currentItem: computed,
117
+ currentFamily: computed,
118
+ item: computed,
119
+ family: computed,
120
+ selectedPaths: computed,
121
+ appliedPromo: computed,
122
+ });
123
+ }
124
+ getFamilyById(id) {
125
+ return this._familyMap.get(id);
126
+ }
127
+ getNodeAtPath(skuPath) {
128
+ const toks = skuPath.split(sep.tok);
129
+ let level = 1;
130
+ let node = this._rootNode;
131
+ do {
132
+ node = node.subNodes?.find((sn) => (sn.skuToken === toks[level]));
133
+ level++;
134
+ } while (node && (level < toks.length));
135
+ return level === toks.length ? node : undefined;
136
+ }
137
+ peek(skuPath) {
138
+ const toks = skuPath.split(sep.tok);
139
+ let level;
140
+ let node = this._rootNode;
141
+ let parent = undefined;
142
+ for (level = 1; level < toks.length && node && node.subNodes; level++) {
143
+ // https://stackoverflow.com/questions/62367492/inference-problem-referenced-directly-or-indirectly-in-its-own-initializer
144
+ const _node = node.subNodes.find((sn) => (sn.skuToken === toks[level]));
145
+ if (!_node) {
146
+ return `service.peekAtNode: traversing '${skuPath}'... no CategoryNode at '${toks[level]}'!`;
147
+ }
148
+ parent = node;
149
+ node = _node;
150
+ }
151
+ const atEnd = level === toks.length;
152
+ const possibleSKU = level === toks.length - 1;
153
+ let role = 'non-outermost';
154
+ let families = undefined;
155
+ let family = undefined;
156
+ let item = undefined;
157
+ let error = undefined;
158
+ try {
159
+ if (node.subNodes && atEnd && node.outermost) {
160
+ role = 'multi-family';
161
+ families = node.subNodes.map((sub) => {
162
+ const familyId = skuPath + sep.tok + sub.skuToken;
163
+ const fam = this._familyMap.get(familyId);
164
+ if (!fam) {
165
+ throw new Error(`service.peekAtNode: No Family under for CategoryNode '${skuPath}' with id ${familyId}!`);
166
+ }
167
+ return fam;
168
+ });
169
+ }
170
+ else if (!node.subNodes && (atEnd || possibleSKU)) {
171
+ const _skuPath = (possibleSKU) ? getParentPath(skuPath) : skuPath;
172
+ if (parent?.outermost) {
173
+ role = 'family-in-multi-family';
174
+ const fam = this._familyMap.get(_skuPath);
175
+ if (!fam) {
176
+ throw new Error(`service.peekAtNode: '${_skuPath}' graphs as a Family under a multi-family node, but no such family exists!`);
177
+ }
178
+ family = fam;
179
+ const parentPath = getParentPath(_skuPath);
180
+ // get all siblings (subnodes of parent)
181
+ families = parent.subNodes.map((sn) => {
182
+ const familyId = parentPath + sep.tok + sn.skuToken;
183
+ const fam = this._familyMap.get(familyId);
184
+ if (!fam) {
185
+ throw new Error(`service.peekAtNode: No sibling Family for '${_skuPath}' with id '${familyId}'!`);
186
+ }
187
+ return fam;
188
+ });
189
+ node = parent;
190
+ }
191
+ else {
192
+ role = 'single-family';
193
+ const fam = this._familyMap.get(_skuPath);
194
+ if (!fam) {
195
+ throw new Error(`service.peekAtNode: '${_skuPath}' graphs as a single Family, but no such family exists!`);
196
+ }
197
+ family = fam;
198
+ }
199
+ if (possibleSKU) {
200
+ const skuToTry = family.id + sep.tok + toks[toks.length - 1];
201
+ const _item = family.products.find((p) => (p.sku === skuToTry));
202
+ if (_item) {
203
+ item = _item;
204
+ }
205
+ else {
206
+ throw new Error(`service.peekAtNode: '${skuPath}' graphs as LineItem in Family '${family.id}', but no such sku exists there!`);
207
+ }
208
+ }
209
+ }
210
+ }
211
+ catch (e) {
212
+ error = getErrorMessage(e);
213
+ }
214
+ return error ?? {
215
+ role,
216
+ family,
217
+ families,
218
+ node,
219
+ item
220
+ };
221
+ }
222
+ get options() { return this._options; }
223
+ //async createOrder(email: string, paymentMethod: string): Promise<string | undefined> {
224
+ async createOrder(email, name) {
225
+ const snapshot = this.takeSnapshot();
226
+ const order = await createOrderHelper(email, snapshot.items, this._options, name); // didn't want to have two levels of 'items'
227
+ return order.id;
228
+ }
229
+ // TODO: add shippingInfo type
230
+ async updateOrderShippingInfo(orderId, shippingInfo) {
231
+ updateOrderShippingInfoHelper(orderId, shippingInfo, this._options);
232
+ }
233
+ // TODO: add paymentInfo type
234
+ async updateOrderPaymentInfo(orderId, paymentInfo) {
235
+ updateOrderPaymentInfoHelper(orderId, paymentInfo, this._options);
236
+ }
237
+ // last cartItem whose quantity was modified (undefined if cartEmpty)
238
+ get recentItem() {
239
+ if (this.cartEmpty)
240
+ return undefined;
241
+ const mostRecent = this._cartItems.reduce((newest, item) => ((!newest) ? item : (item.timeModified > newest.timeModified) ? item : newest), undefined);
242
+ return { item: mostRecent, modified: mostRecent.timeModified };
243
+ }
244
+ get _cartItems() {
245
+ let result = [];
246
+ this._familyMap.forEach((fam) => {
247
+ result = [...result, ...fam.products.filter((item) => (item.isInCart))];
248
+ });
249
+ return result;
250
+ }
251
+ get cartItems() {
252
+ return this._cartItems.sort((it1, it2) => (it1.timeAdded - it2.timeAdded));
253
+ }
254
+ get cartEmpty() {
255
+ return this._cartItems.length === 0;
256
+ }
257
+ get cartTotal() {
258
+ return this._cartItems.reduce((total, item) => (total + item.price * item.quantity), 0);
259
+ }
260
+ _promoValue_unsafe(value) {
261
+ if (this._promo.type === 'percent') {
262
+ return value * (1 - this._promo.value / 100);
263
+ }
264
+ return value - this._promo.value;
265
+ }
266
+ get promoAppliedCartTotal() {
267
+ if (!this._promo) {
268
+ return this.cartTotal;
269
+ }
270
+ if (!this._promo.skus) {
271
+ return this._promoValue_unsafe(this.cartTotal);
272
+ }
273
+ let total = this._cartItems.reduce((total, item) => {
274
+ const itemPrice = this._promo.skus.includes(item.sku) ?
275
+ this._promoValue_unsafe(item.price)
276
+ :
277
+ item.price;
278
+ return total + itemPrice * item.quantity;
279
+ }, 0);
280
+ return total;
281
+ }
282
+ itemPromoPrice(item) {
283
+ if (this._promo && (!this._promo.skus || this._promo.skus.includes(item.sku))) {
284
+ return this._promoValue_unsafe(item.price);
285
+ }
286
+ return undefined;
287
+ }
288
+ get cartQuantity() {
289
+ return this.cartItems.reduce((total, item) => (total + item.quantity), 0);
290
+ }
291
+ get appliedPromo() {
292
+ return this._promo;
293
+ }
294
+ setAppliedPromo(promo) {
295
+ this._promo = promo;
296
+ }
297
+ /* for ObsLineItemRef */
298
+ get item() {
299
+ return this._currentItem;
300
+ }
301
+ get currentItem() {
302
+ return this._currentItem;
303
+ }
304
+ setCurrentFamily(id) {
305
+ if (id === undefined || id.length === 0) {
306
+ this._currentFamily = undefined;
307
+ return true;
308
+ }
309
+ const fam = this._familyMap.get(id);
310
+ this._currentFamily = fam; // undef ok
311
+ if (this._currentFamily &&
312
+ this._currentItem &&
313
+ this._currentItem.familyId !== this._currentFamily.id) {
314
+ this._currentItem = undefined;
315
+ }
316
+ return !!this._currentFamily;
317
+ }
318
+ get currentFamily() {
319
+ return this._currentFamily;
320
+ }
321
+ /* for ObsFamilyRef */
322
+ get family() {
323
+ return this._currentFamily;
324
+ }
325
+ selectPaths(sel) {
326
+ runInAction(() => {
327
+ this._selectedPaths = this._processAndValidate(sel);
328
+ });
329
+ return this.selectedFamilies;
330
+ }
331
+ selectPath(skuPath) {
332
+ const toks = skuPath.split(sep.tok);
333
+ const highestLevel = toks.length - 1;
334
+ const fsv = {};
335
+ for (let level = 1; level <= highestLevel; level++) {
336
+ fsv[level] = [toks[level]];
337
+ }
338
+ return this.selectPaths(fsv);
339
+ }
340
+ get selectedPaths() {
341
+ const result = {};
342
+ for (let level in this._selectedPaths) {
343
+ result[level] = [...this._selectedPaths[level]];
344
+ }
345
+ return result;
346
+ }
347
+ get selectedFamilies() {
348
+ if (Object.keys(toJS(this._selectedPaths)).length === 0) {
349
+ // FacetsDesc have never been set or unset, so cannot evaluate them
350
+ return [];
351
+ }
352
+ return this._rootNode.subNodes.reduce((acc, subFacet) => (
353
+ // Pass the root token as a one member array
354
+ this._reduceNode([this._rootNode.skuToken], acc, subFacet)), []);
355
+ }
356
+ _reduceNode(parentPath, acc, node) {
357
+ const path = [...parentPath, node.skuToken]; // Don't mutate original please :)
358
+ const level = path.length - 1;
359
+ // If there is no token array supplied for this level,
360
+ // assume all are specified. Otherwise, see if the
361
+ // current node is in the array
362
+ const specified = (!this._selectedPaths[level]
363
+ ||
364
+ this._selectedPaths[level].includes(node.skuToken));
365
+ if (specified) {
366
+ // Process subnodes
367
+ if (node.subNodes && node.subNodes.length > 0) {
368
+ return node.subNodes.reduce((acc, n) => (this._reduceNode(path, acc, n)), acc);
369
+ }
370
+ // Process leaf
371
+ const fam = this._familyMap.get(path.join(sep.tok));
372
+ if (!fam) {
373
+ throw new Error("selectedFamilies WTF?!" + path.join(sep.tok));
374
+ }
375
+ acc.push(fam);
376
+ }
377
+ return acc;
378
+ }
379
+ _processAndValidate(partial) {
380
+ const result = {};
381
+ let level = 1;
382
+ let currentSet = this._rootNode.subNodes;
383
+ while (true) {
384
+ let possibleCurrent = currentSet.map((el) => (el.skuToken));
385
+ const validTokens = !partial[level] ? undefined : partial[level].filter((tok) => possibleCurrent.includes(tok));
386
+ if (!validTokens) {
387
+ break;
388
+ }
389
+ result[level] = validTokens;
390
+ currentSet = validTokens.map((tok) => {
391
+ const fd = currentSet.find((node) => (node.skuToken === tok));
392
+ return (fd && fd.subNodes && fd.subNodes.length > 0) ? fd.subNodes : [];
393
+ }).flat();
394
+ level++;
395
+ }
396
+ return result;
397
+ }
398
+ get selectedItems() {
399
+ if (Object.keys(toJS(this._selectedPaths)).length === 0) {
400
+ // FacetsDesc have never been set or unset, so cannot evaluate them
401
+ return [];
402
+ }
403
+ return this.selectedFamilies.reduce((allProducts, fam) => ([...allProducts, ...fam.products]), []);
404
+ }
405
+ get hasSelection() {
406
+ return this.selectedFamilies.length > 0;
407
+ }
408
+ getFamilySubtotal(familyId) {
409
+ const c = this._familyMap.get(familyId);
410
+ return c.products.reduce(
411
+ // avoid floating point bs around zero
412
+ (total, item) => (item.quantity > 0 ? total + item.price * item.quantity : total), 0);
413
+ }
414
+ }
415
+ export { StandaloneService, getInstance };
416
+ //# sourceMappingURL=index.js.map