@aglyn/plugins-commerce 1.0.0-beta.231 → 1.0.0-beta.233

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 (266) hide show
  1. package/package.json +13 -13
  2. package/src/lib/components/cart-extras.d.ts +6 -0
  3. package/src/lib/components/cart-extras.js +4 -1
  4. package/src/lib/components/cart-extras.js.map +1 -1
  5. package/src/lib/components/cart-fulfillment.d.ts +117 -0
  6. package/src/lib/components/cart-fulfillment.js +367 -0
  7. package/src/lib/components/cart-fulfillment.js.map +1 -0
  8. package/src/lib/components/cart.js +52 -10
  9. package/src/lib/components/cart.js.map +1 -1
  10. package/src/lib/components/commerce-console-page.js +42 -1
  11. package/src/lib/components/commerce-console-page.js.map +1 -1
  12. package/src/lib/components/console/catalog-organization-card.component.js +1 -0
  13. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
  14. package/src/lib/components/console/host-orders-card.component.js +42 -11
  15. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  16. package/src/lib/components/console/local-delivery-settings-card.component.d.ts +37 -0
  17. package/src/lib/components/console/local-delivery-settings-card.component.js +542 -0
  18. package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -0
  19. package/src/lib/components/console/locations-card.component.js +177 -3
  20. package/src/lib/components/console/locations-card.component.js.map +1 -1
  21. package/src/lib/components/console/order-detail-dialog.component.js +10 -0
  22. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  23. package/src/lib/components/console/order-local-fulfillment-panel.component.d.ts +44 -0
  24. package/src/lib/components/console/order-local-fulfillment-panel.component.js +265 -0
  25. package/src/lib/components/console/order-local-fulfillment-panel.component.js.map +1 -0
  26. package/src/lib/components/console/order-offline-notice.component.d.ts +12 -0
  27. package/src/lib/components/console/order-offline-notice.component.js +53 -0
  28. package/src/lib/components/console/order-offline-notice.component.js.map +1 -0
  29. package/src/lib/components/console/pickup-delivery-queue-card.component.d.ts +35 -0
  30. package/src/lib/components/console/pickup-delivery-queue-card.component.js +222 -0
  31. package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -0
  32. package/src/lib/components/console/pos/pos-api.d.ts +24 -1
  33. package/src/lib/components/console/pos/pos-api.js +13 -0
  34. package/src/lib/components/console/pos/pos-api.js.map +1 -1
  35. package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +12 -0
  36. package/src/lib/components/console/pos/pos-item-dialog.component.js +10 -8
  37. package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
  38. package/src/lib/components/console/pos/pos-kiosk-queue.component.d.ts +22 -0
  39. package/src/lib/components/console/pos/pos-kiosk-queue.component.js +168 -0
  40. package/src/lib/components/console/pos/pos-kiosk-queue.component.js.map +1 -0
  41. package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +18 -0
  42. package/src/lib/components/console/pos/pos-tender-dialogs.component.js +116 -1
  43. package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -1
  44. package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +8 -0
  45. package/src/lib/components/console/pos/pos-tender-panel.component.js +77 -18
  46. package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
  47. package/src/lib/components/console/pos/use-pos-display.d.ts +5 -2
  48. package/src/lib/components/console/pos/use-pos-display.js +3 -2
  49. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  50. package/src/lib/components/console/pos-devices-card.component.js +2 -2
  51. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  52. package/src/lib/components/console/pos-display/pairing-screen.d.ts +5 -2
  53. package/src/lib/components/console/pos-display/pairing-screen.js +7 -5
  54. package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -1
  55. package/src/lib/components/console/pos-display/pos-display-api.d.ts +7 -1
  56. package/src/lib/components/console/pos-display/pos-display-api.js +7 -2
  57. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  58. package/src/lib/components/console/pos-kiosk/kiosk-checkout.d.ts +41 -0
  59. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js +275 -0
  60. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js.map +1 -0
  61. package/src/lib/components/console/pos-kiosk/kiosk-menu.d.ts +32 -0
  62. package/src/lib/components/console/pos-kiosk/kiosk-menu.js +344 -0
  63. package/src/lib/components/console/pos-kiosk/kiosk-menu.js.map +1 -0
  64. package/src/lib/components/console/pos-kiosk/kiosk-staff.d.ts +12 -0
  65. package/src/lib/components/console/pos-kiosk/kiosk-staff.js +257 -0
  66. package/src/lib/components/console/pos-kiosk/kiosk-staff.js.map +1 -0
  67. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.d.ts +114 -0
  68. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js +189 -0
  69. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js.map +1 -0
  70. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.d.ts +16 -0
  71. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js +80 -0
  72. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js.map +1 -0
  73. package/src/lib/components/console/pos-kiosk-page.component.d.ts +28 -0
  74. package/src/lib/components/console/pos-kiosk-page.component.js +791 -0
  75. package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -0
  76. package/src/lib/components/console/pos-offline/pos-offline-api.d.ts +44 -0
  77. package/src/lib/components/console/pos-offline/pos-offline-api.js +69 -0
  78. package/src/lib/components/console/pos-offline/pos-offline-api.js.map +1 -0
  79. package/src/lib/components/console/pos-offline/pos-offline-banner.component.d.ts +7 -0
  80. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js +135 -0
  81. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js.map +1 -0
  82. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.d.ts +32 -0
  83. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js +287 -0
  84. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js.map +1 -0
  85. package/src/lib/components/console/pos-offline/pos-offline-store.d.ts +63 -0
  86. package/src/lib/components/console/pos-offline/pos-offline-store.js +145 -0
  87. package/src/lib/components/console/pos-offline/pos-offline-store.js.map +1 -0
  88. package/src/lib/components/console/pos-offline/register-offline.d.ts +24 -0
  89. package/src/lib/components/console/pos-offline/register-offline.js +24 -0
  90. package/src/lib/components/console/pos-offline/register-offline.js.map +1 -0
  91. package/src/lib/components/console/pos-offline/use-pos-offline.d.ts +85 -0
  92. package/src/lib/components/console/pos-offline/use-pos-offline.js +542 -0
  93. package/src/lib/components/console/pos-offline/use-pos-offline.js.map +1 -0
  94. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +72 -17
  95. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -1
  96. package/src/lib/components/console/pos-page.component.js +228 -51
  97. package/src/lib/components/console/pos-page.component.js.map +1 -1
  98. package/src/lib/components/console/pos-zones.d.ts +23 -0
  99. package/src/lib/components/console/pos-zones.js +31 -0
  100. package/src/lib/components/console/pos-zones.js.map +1 -0
  101. package/src/lib/components/console/product-editor-dialog.component.js +10 -64
  102. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  103. package/src/lib/components/console/products-hub-card.component.js +46 -30
  104. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  105. package/src/lib/components/console/shipping-settings-card.component.js +1 -1
  106. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
  107. package/src/lib/components/console/stock-movements-card.component.js +48 -16
  108. package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
  109. package/src/lib/components/console/store-zones.d.ts +8 -1
  110. package/src/lib/components/console/store-zones.js +11 -1
  111. package/src/lib/components/console/store-zones.js.map +1 -1
  112. package/src/lib/components/console/storefront-tax-summary-card.component.js +1 -0
  113. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -1
  114. package/src/lib/components/order-status.js +66 -0
  115. package/src/lib/components/order-status.js.map +1 -1
  116. package/src/lib/components/product-detail.js +42 -15
  117. package/src/lib/components/product-detail.js.map +1 -1
  118. package/src/lib/constants/local-fulfillment-list-query.d.ts +48 -0
  119. package/src/lib/constants/local-fulfillment-list-query.js +84 -0
  120. package/src/lib/constants/local-fulfillment-list-query.js.map +1 -0
  121. package/src/lib/constants/orders-list-query.d.ts +7 -2
  122. package/src/lib/constants/orders-list-query.js +89 -8
  123. package/src/lib/constants/orders-list-query.js.map +1 -1
  124. package/src/lib/constants/pos-shift-list-query.d.ts +22 -0
  125. package/src/lib/constants/pos-shift-list-query.js +115 -0
  126. package/src/lib/constants/pos-shift-list-query.js.map +1 -0
  127. package/src/lib/constants/product-list-query.d.ts +6 -1
  128. package/src/lib/constants/product-list-query.js +77 -8
  129. package/src/lib/constants/product-list-query.js.map +1 -1
  130. package/src/lib/constants/stock-movement-query.d.ts +3 -2
  131. package/src/lib/constants/stock-movement-query.js +52 -8
  132. package/src/lib/constants/stock-movement-query.js.map +1 -1
  133. package/src/lib/declarations.server.js +21 -0
  134. package/src/lib/declarations.server.js.map +1 -1
  135. package/src/lib/model/buyer-notifications.d.ts +5 -3
  136. package/src/lib/model/buyer-notifications.js +25 -4
  137. package/src/lib/model/buyer-notifications.js.map +1 -1
  138. package/src/lib/model/commerce-orders.d.ts +103 -1
  139. package/src/lib/model/commerce-orders.js +2 -1
  140. package/src/lib/model/commerce-orders.js.map +1 -1
  141. package/src/lib/model/commerce-pos-kiosk.d.ts +175 -0
  142. package/src/lib/model/commerce-pos-kiosk.js +147 -0
  143. package/src/lib/model/commerce-pos-kiosk.js.map +1 -0
  144. package/src/lib/model/commerce-pos-offline.d.ts +234 -0
  145. package/src/lib/model/commerce-pos-offline.js +301 -0
  146. package/src/lib/model/commerce-pos-offline.js.map +1 -0
  147. package/src/lib/model/commerce-pos-ops.d.ts +16 -6
  148. package/src/lib/model/commerce-pos-ops.js +12 -4
  149. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  150. package/src/lib/model/commerce-pos.d.ts +13 -1
  151. package/src/lib/model/commerce-pos.js +5 -4
  152. package/src/lib/model/commerce-pos.js.map +1 -1
  153. package/src/lib/model/commerce-stock-holds.d.ts +24 -3
  154. package/src/lib/model/commerce-stock-holds.js +26 -8
  155. package/src/lib/model/commerce-stock-holds.js.map +1 -1
  156. package/src/lib/model/commerce.d.ts +7 -1
  157. package/src/lib/model/commerce.js.map +1 -1
  158. package/src/lib/model/index.d.ts +5 -0
  159. package/src/lib/model/index.js +5 -0
  160. package/src/lib/model/index.js.map +1 -1
  161. package/src/lib/model/local-fulfillment-settings.d.ts +178 -0
  162. package/src/lib/model/local-fulfillment-settings.js +361 -0
  163. package/src/lib/model/local-fulfillment-settings.js.map +1 -0
  164. package/src/lib/model/order-list-fields.d.ts +10 -1
  165. package/src/lib/model/order-list-fields.js +1 -0
  166. package/src/lib/model/order-list-fields.js.map +1 -1
  167. package/src/lib/model/order-local-fulfillment.d.ts +131 -0
  168. package/src/lib/model/order-local-fulfillment.js +125 -0
  169. package/src/lib/model/order-local-fulfillment.js.map +1 -0
  170. package/src/lib/model/order-shipping-export.js +4 -0
  171. package/src/lib/model/order-shipping-export.js.map +1 -1
  172. package/src/lib/model/order-status-view.d.ts +20 -1
  173. package/src/lib/model/order-status-view.js +60 -6
  174. package/src/lib/model/order-status-view.js.map +1 -1
  175. package/src/lib/model/product-write.d.ts +186 -0
  176. package/src/lib/model/product-write.js +116 -0
  177. package/src/lib/model/product-write.js.map +1 -0
  178. package/src/lib/plugin-config.js +6 -2
  179. package/src/lib/plugin-config.js.map +1 -1
  180. package/src/lib/plugin.js +11 -0
  181. package/src/lib/plugin.js.map +1 -1
  182. package/src/lib/pos-kiosk-config.d.ts +26 -0
  183. package/src/lib/pos-kiosk-config.js +59 -0
  184. package/src/lib/pos-kiosk-config.js.map +1 -0
  185. package/src/lib/server/api-v1/openapi.js +8 -0
  186. package/src/lib/server/api-v1/openapi.js.map +1 -1
  187. package/src/lib/server/api-v1/order-view.d.ts +19 -0
  188. package/src/lib/server/api-v1/order-view.js +35 -0
  189. package/src/lib/server/api-v1/order-view.js.map +1 -1
  190. package/src/lib/server/billing-webhook.js +238 -87
  191. package/src/lib/server/billing-webhook.js.map +1 -1
  192. package/src/lib/server/cart-checkout.d.ts +2 -0
  193. package/src/lib/server/cart-checkout.js +173 -13
  194. package/src/lib/server/cart-checkout.js.map +1 -1
  195. package/src/lib/server/channel-order-updates.d.ts +50 -0
  196. package/src/lib/server/channel-order-updates.js +290 -0
  197. package/src/lib/server/channel-order-updates.js.map +1 -0
  198. package/src/lib/server/channel-orders.d.ts +85 -0
  199. package/src/lib/server/channel-orders.js +543 -0
  200. package/src/lib/server/channel-orders.js.map +1 -0
  201. package/src/lib/server/checkout-extras.js +18 -4
  202. package/src/lib/server/checkout-extras.js.map +1 -1
  203. package/src/lib/server/checkout.js +71 -14
  204. package/src/lib/server/checkout.js.map +1 -1
  205. package/src/lib/server/local-fulfillment-status.d.ts +86 -0
  206. package/src/lib/server/local-fulfillment-status.js +379 -0
  207. package/src/lib/server/local-fulfillment-status.js.map +1 -0
  208. package/src/lib/server/local-fulfillment.d.ts +190 -0
  209. package/src/lib/server/local-fulfillment.js +580 -0
  210. package/src/lib/server/local-fulfillment.js.map +1 -0
  211. package/src/lib/server/membership-register.js +3 -1
  212. package/src/lib/server/membership-register.js.map +1 -1
  213. package/src/lib/server/order-notifications.js +61 -0
  214. package/src/lib/server/order-notifications.js.map +1 -1
  215. package/src/lib/server/pos-display.d.ts +27 -1
  216. package/src/lib/server/pos-display.js +50 -9
  217. package/src/lib/server/pos-display.js.map +1 -1
  218. package/src/lib/server/pos-kiosk-principal.d.ts +29 -0
  219. package/src/lib/server/pos-kiosk-principal.js +42 -0
  220. package/src/lib/server/pos-kiosk-principal.js.map +1 -0
  221. package/src/lib/server/pos-kiosk.d.ts +54 -0
  222. package/src/lib/server/pos-kiosk.js +972 -0
  223. package/src/lib/server/pos-kiosk.js.map +1 -0
  224. package/src/lib/server/pos-offline-sync.d.ts +85 -0
  225. package/src/lib/server/pos-offline-sync.js +765 -0
  226. package/src/lib/server/pos-offline-sync.js.map +1 -0
  227. package/src/lib/server/pos-order.js +22 -4
  228. package/src/lib/server/pos-order.js.map +1 -1
  229. package/src/lib/server/pos-payment.d.ts +6 -0
  230. package/src/lib/server/pos-payment.js +225 -6
  231. package/src/lib/server/pos-payment.js.map +1 -1
  232. package/src/lib/server/pos-print.js +5 -0
  233. package/src/lib/server/pos-print.js.map +1 -1
  234. package/src/lib/server/pos-return.js +27 -0
  235. package/src/lib/server/pos-return.js.map +1 -1
  236. package/src/lib/server/pos-sale.d.ts +6 -0
  237. package/src/lib/server/pos-sale.js +2 -0
  238. package/src/lib/server/pos-sale.js.map +1 -1
  239. package/src/lib/server/pos-shift.js +8 -1
  240. package/src/lib/server/pos-shift.js.map +1 -1
  241. package/src/lib/server/product-catalog.js +5 -1
  242. package/src/lib/server/product-catalog.js.map +1 -1
  243. package/src/lib/server/product-drafts.d.ts +5 -1
  244. package/src/lib/server/product-drafts.js +3 -3
  245. package/src/lib/server/product-drafts.js.map +1 -1
  246. package/src/lib/server/product-writer.d.ts +19 -0
  247. package/src/lib/server/product-writer.js +261 -0
  248. package/src/lib/server/product-writer.js.map +1 -0
  249. package/src/lib/server/products-write.d.ts +61 -0
  250. package/src/lib/server/products-write.js +375 -0
  251. package/src/lib/server/products-write.js.map +1 -0
  252. package/src/lib/server/refund.js +3 -0
  253. package/src/lib/server/refund.js.map +1 -1
  254. package/src/lib/server/stock-hold.d.ts +9 -1
  255. package/src/lib/server/stock-hold.js +15 -7
  256. package/src/lib/server/stock-hold.js.map +1 -1
  257. package/src/lib/server.js +21 -0
  258. package/src/lib/server.js.map +1 -1
  259. package/src/lib/tenant-emails.js +161 -0
  260. package/src/lib/tenant-emails.js.map +1 -1
  261. package/src/lib/testing/memory-firestore.d.ts +16 -3
  262. package/src/lib/testing/memory-firestore.js +11 -3
  263. package/src/lib/testing/memory-firestore.js.map +1 -1
  264. package/src/lib/transfer/products.server.d.ts +5 -0
  265. package/src/lib/transfer/products.server.js +2 -2
  266. package/src/lib/transfer/products.server.js.map +1 -1
@@ -31,6 +31,8 @@ export * from './commerce-gift-cards';
31
31
  export * from './commerce-orders';
32
32
  export * from './commerce-printers';
33
33
  export * from './commerce-pos';
34
+ export * from './commerce-pos-offline';
35
+ export * from './commerce-pos-kiosk';
34
36
  export * from './product-modifiers';
35
37
  export * from './commerce-promotions';
36
38
  export * from './commerce-receipt';
@@ -46,6 +48,8 @@ export * from './purchase-analytics';
46
48
  export * from './tracking-url';
47
49
  export * from './buyer-notifications';
48
50
  export * from './order-fulfillment';
51
+ export * from './order-local-fulfillment';
52
+ export * from './local-fulfillment-settings';
49
53
  export * from './order-events';
50
54
  export * from './commerce-returns';
51
55
  export * from './order-shipping-export';
@@ -54,3 +58,4 @@ export * from './order-webhooks';
54
58
  export * from './shipstation';
55
59
  export * from './commerce-payment-methods';
56
60
  export * from './product-channel';
61
+ export * from './product-write';
@@ -29,6 +29,8 @@ export * from "./commerce-gift-cards.js";
29
29
  export * from "./commerce-orders.js";
30
30
  export * from "./commerce-printers.js";
31
31
  export * from "./commerce-pos.js";
32
+ export * from "./commerce-pos-offline.js";
33
+ export * from "./commerce-pos-kiosk.js";
32
34
  export * from "./product-modifiers.js";
33
35
  export * from "./commerce-promotions.js";
34
36
  export * from "./commerce-receipt.js";
@@ -44,6 +46,8 @@ export * from "./purchase-analytics.js";
44
46
  export * from "./tracking-url.js";
45
47
  export * from "./buyer-notifications.js";
46
48
  export * from "./order-fulfillment.js";
49
+ export * from "./order-local-fulfillment.js";
50
+ export * from "./local-fulfillment-settings.js";
47
51
  export * from "./order-events.js";
48
52
  export * from "./commerce-returns.js";
49
53
  export * from "./order-shipping-export.js";
@@ -52,5 +56,6 @@ export * from "./order-webhooks.js";
52
56
  export * from "./shipstation.js";
53
57
  export * from "./commerce-payment-methods.js";
54
58
  export * from "./product-channel.js";
59
+ export * from "./product-write.js";
55
60
 
56
61
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Commerce domain model (AGL-411): pure types + logic relocated from the\n * core `@aglyn/aglyn` app-utils — the commerce plugin owns its domain.\n * Context-free and framework-free, so both the plugin's client components\n * and its `/server` handlers (and other plugins/apps via\n * `@aglyn/plugins-commerce/model`) can import it.\n */\nexport * from './commerce'\nexport * from './commerce-cart'\nexport * from './commerce-connect-transfer'\nexport * from './commerce-discounts'\nexport * from './commerce-dispute'\nexport * from './commerce-topics'\nexport * from './commerce-gift-cards'\nexport * from './commerce-orders'\nexport * from './commerce-printers'\nexport * from './commerce-pos'\nexport * from './product-modifiers'\nexport * from './commerce-promotions'\nexport * from './commerce-receipt'\nexport * from './commerce-reservations'\nexport * from './commerce-shipping'\nexport * from './commerce-stock-holds'\nexport * from './commerce-subscription-status'\nexport * from './commerce-tax'\nexport * from './commerce-tax-decision'\nexport * from './order-figures'\nexport * from './order-list-fields'\nexport * from './purchase-analytics'\nexport * from './tracking-url'\nexport * from './buyer-notifications'\nexport * from './order-fulfillment'\nexport * from './order-events'\nexport * from './commerce-returns'\nexport * from './order-shipping-export'\nexport * from './order-status-view'\nexport * from './order-webhooks'\nexport * from './shipstation'\nexport * from './commerce-payment-methods'\nexport * from './product-channel'\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;CAMC,GACD,cAAc,gBAAY;AAC1B,cAAc,qBAAiB;AAC/B,cAAc,iCAA6B;AAC3C,cAAc,0BAAsB;AACpC,cAAc,wBAAoB;AAClC,cAAc,uBAAmB;AACjC,cAAc,2BAAuB;AACrC,cAAc,uBAAmB;AACjC,cAAc,yBAAqB;AACnC,cAAc,oBAAgB;AAC9B,cAAc,yBAAqB;AACnC,cAAc,2BAAuB;AACrC,cAAc,wBAAoB;AAClC,cAAc,6BAAyB;AACvC,cAAc,yBAAqB;AACnC,cAAc,4BAAwB;AACtC,cAAc,oCAAgC;AAC9C,cAAc,oBAAgB;AAC9B,cAAc,6BAAyB;AACvC,cAAc,qBAAiB;AAC/B,cAAc,yBAAqB;AACnC,cAAc,0BAAsB;AACpC,cAAc,oBAAgB;AAC9B,cAAc,2BAAuB;AACrC,cAAc,yBAAqB;AACnC,cAAc,oBAAgB;AAC9B,cAAc,wBAAoB;AAClC,cAAc,6BAAyB;AACvC,cAAc,yBAAqB;AACnC,cAAc,sBAAkB;AAChC,cAAc,mBAAe;AAC7B,cAAc,gCAA4B;AAC1C,cAAc,uBAAmB"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Commerce domain model (AGL-411): pure types + logic relocated from the\n * core `@aglyn/aglyn` app-utils — the commerce plugin owns its domain.\n * Context-free and framework-free, so both the plugin's client components\n * and its `/server` handlers (and other plugins/apps via\n * `@aglyn/plugins-commerce/model`) can import it.\n */\nexport * from './commerce'\nexport * from './commerce-cart'\nexport * from './commerce-connect-transfer'\nexport * from './commerce-discounts'\nexport * from './commerce-dispute'\nexport * from './commerce-topics'\nexport * from './commerce-gift-cards'\nexport * from './commerce-orders'\nexport * from './commerce-printers'\nexport * from './commerce-pos'\nexport * from './commerce-pos-offline'\nexport * from './commerce-pos-kiosk'\nexport * from './product-modifiers'\nexport * from './commerce-promotions'\nexport * from './commerce-receipt'\nexport * from './commerce-reservations'\nexport * from './commerce-shipping'\nexport * from './commerce-stock-holds'\nexport * from './commerce-subscription-status'\nexport * from './commerce-tax'\nexport * from './commerce-tax-decision'\nexport * from './order-figures'\nexport * from './order-list-fields'\nexport * from './purchase-analytics'\nexport * from './tracking-url'\nexport * from './buyer-notifications'\nexport * from './order-fulfillment'\nexport * from './order-local-fulfillment'\nexport * from './local-fulfillment-settings'\nexport * from './order-events'\nexport * from './commerce-returns'\nexport * from './order-shipping-export'\nexport * from './order-status-view'\nexport * from './order-webhooks'\nexport * from './shipstation'\nexport * from './commerce-payment-methods'\nexport * from './product-channel'\nexport * from './product-write'\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;CAMC,GACD,cAAc,gBAAY;AAC1B,cAAc,qBAAiB;AAC/B,cAAc,iCAA6B;AAC3C,cAAc,0BAAsB;AACpC,cAAc,wBAAoB;AAClC,cAAc,uBAAmB;AACjC,cAAc,2BAAuB;AACrC,cAAc,uBAAmB;AACjC,cAAc,yBAAqB;AACnC,cAAc,oBAAgB;AAC9B,cAAc,4BAAwB;AACtC,cAAc,0BAAsB;AACpC,cAAc,yBAAqB;AACnC,cAAc,2BAAuB;AACrC,cAAc,wBAAoB;AAClC,cAAc,6BAAyB;AACvC,cAAc,yBAAqB;AACnC,cAAc,4BAAwB;AACtC,cAAc,oCAAgC;AAC9C,cAAc,oBAAgB;AAC9B,cAAc,6BAAyB;AACvC,cAAc,qBAAiB;AAC/B,cAAc,yBAAqB;AACnC,cAAc,0BAAsB;AACpC,cAAc,oBAAgB;AAC9B,cAAc,2BAAuB;AACrC,cAAc,yBAAqB;AACnC,cAAc,+BAA2B;AACzC,cAAc,kCAA8B;AAC5C,cAAc,oBAAgB;AAC9B,cAAc,wBAAoB;AAClC,cAAc,6BAAyB;AACvC,cAAc,yBAAqB;AACnC,cAAc,sBAAkB;AAChC,cAAc,mBAAe;AAC7B,cAAc,gCAA4B;AAC1C,cAAc,uBAAmB;AACjC,cAAc,qBAAiB"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type OpeningHoursRow } from '@aglyn/aglyn/app-utils/local-business';
18
+ import type { InventoryLocation, PostalAddress } from './commerce';
19
+ import type { PickupLocationSettings } from './order-local-fulfillment';
20
+ /**
21
+ * Buy online, pick up in store, and the store's own local delivery (AGL-3624):
22
+ * what a merchant configures, and the pure decisions checkout takes from it.
23
+ *
24
+ * PICKUP is per location. A location of `hosts/{hostId}/locations` (AGL-286,
25
+ * the same stock buckets the register sells from) offers pickup when its
26
+ * `pickup.enabled` is on, with its own hours and arrival instructions. The
27
+ * buyer picks one at the cart; the order is routed there and its stock comes
28
+ * off that location's bucket.
29
+ *
30
+ * LOCAL DELIVERY is per store, on `settings/store.localDelivery`: zones
31
+ * matched by postal code (no outside service needed) or by distance from the
32
+ * store (only where the store's address check returns map coordinates — see
33
+ * `server/local-fulfillment.ts`), each with a fee, an order minimum and a
34
+ * free-over threshold, and delivery windows written in the same
35
+ * `Mo-Fr 09:00-12:00` syntax as a business's opening hours.
36
+ */
37
+ /** A pickup location as the cart and the order show it. Public facts only. */
38
+ export interface PickupLocationOption {
39
+ id: string;
40
+ name: string;
41
+ address?: string;
42
+ hours?: string;
43
+ instructions?: string;
44
+ readyWithinMinutes?: number;
45
+ }
46
+ export declare const PICKUP_INSTRUCTIONS_MAX = 400;
47
+ export declare const PICKUP_HOURS_MAX = 600;
48
+ export declare const PICKUP_LOCATIONS_MAX = 25;
49
+ /** A stored pickup block made safe; never throws. */
50
+ export declare function normalizePickupSettings(value: unknown): PickupLocationSettings;
51
+ /** A postal address on one line, or the location's free-text address. */
52
+ export declare function formatPostalAddressLine(address?: PostalAddress | null, fallback?: string | null): string;
53
+ /**
54
+ * The locations a buyer may pick up from, default location first, then by
55
+ * name. A location without pickup switched on is never offered, however
56
+ * complete the rest of it is.
57
+ */
58
+ export declare function pickupLocationOptions(locations: ReadonlyArray<(InventoryLocation & {
59
+ id: string;
60
+ }) | null | undefined>): PickupLocationOption[];
61
+ /** "Usually ready in 2 hours" from a preparation time, or `''`. */
62
+ export declare function pickupReadyWithinLabel(minutes: number | undefined): string;
63
+ export interface LocalDeliveryCoordinates {
64
+ lat: number;
65
+ lng: number;
66
+ }
67
+ export interface LocalDeliveryZone {
68
+ id: string;
69
+ name: string;
70
+ /**
71
+ * `postcode` matches the buyer's postal code against `postcodes`;
72
+ * `radius` measures the distance from the store's `origin`.
73
+ */
74
+ kind: 'postcode' | 'radius';
75
+ /**
76
+ * Codes this zone delivers to: `10001` exactly, `100*` by prefix, or
77
+ * `10001-10099` as a numeric range.
78
+ */
79
+ postcodes?: string[];
80
+ /** Kilometers from the store's origin, for a `radius` zone. */
81
+ radiusKm?: number;
82
+ /** The delivery fee, in cents. */
83
+ feeCents: number;
84
+ /** The smallest order (items, in cents) this zone delivers. */
85
+ minimumCents?: number;
86
+ /** Items total (cents) at or above which delivery is free. */
87
+ freeOverCents?: number;
88
+ }
89
+ /** `settings/store.localDelivery`. */
90
+ export interface LocalDeliverySettings {
91
+ enabled?: boolean;
92
+ /** The one country delivered within, ISO-3166 alpha-2. */
93
+ country?: string;
94
+ /** The location orders leave from, and whose stock they take. */
95
+ locationId?: string;
96
+ /** Where radius zones measure from, as the store's address check placed it. */
97
+ origin?: LocalDeliveryCoordinates;
98
+ zones?: LocalDeliveryZone[];
99
+ /** Delivery windows, one line per set of days: `Mo-Fr 09:00-12:00`. */
100
+ windows?: string;
101
+ /** How long before a window opens an order must be placed, in minutes. */
102
+ leadTimeMinutes?: number;
103
+ /** How many days ahead a window can be booked. */
104
+ daysAhead?: number;
105
+ /** What the buyer is told about delivery: "We call when we're 10 minutes away". */
106
+ instructions?: string;
107
+ }
108
+ export declare const LOCAL_DELIVERY_ZONES_MAX = 20;
109
+ export declare const LOCAL_DELIVERY_POSTCODES_MAX = 200;
110
+ export declare const LOCAL_DELIVERY_DEFAULT_LEAD_MINUTES = 120;
111
+ export declare const LOCAL_DELIVERY_DEFAULT_DAYS_AHEAD = 7;
112
+ export declare const LOCAL_DELIVERY_MAX_DAYS_AHEAD = 30;
113
+ /** A cart offers at most this many windows; the earliest are kept. */
114
+ export declare const LOCAL_DELIVERY_WINDOWS_OFFERED_MAX = 40;
115
+ export declare const LOCAL_DELIVERY_RADIUS_MAX_KM = 200;
116
+ /**
117
+ * One postal code as zones compare it: upper-cased with spaces removed, and a
118
+ * US ZIP+4 cut to its five digits so `10001-1234` is in the `10001` zone.
119
+ */
120
+ export declare function normalizePostcode(value: unknown, country?: string): string;
121
+ /** Whether a postal code is one a zone entry names. */
122
+ export declare function postcodePatternMatches(pattern: string, postcode: string): boolean;
123
+ /** The stored settings made safe; never throws. */
124
+ export declare function normalizeLocalDeliverySettings(value: unknown): LocalDeliverySettings;
125
+ /** Great-circle distance in kilometers (haversine). */
126
+ export declare function distanceKm(a: LocalDeliveryCoordinates, b: LocalDeliveryCoordinates): number;
127
+ /** Whether any zone measures distance, so checkout needs the full address placed on a map. */
128
+ export declare function localDeliveryHasRadiusZones(settings: LocalDeliverySettings | undefined): boolean;
129
+ /**
130
+ * The zone a destination falls in, or `null`. Postal-code zones are asked
131
+ * first, in the order the store listed them, so a store can carve a cheaper
132
+ * neighbourhood out of a wider one by listing it above. Radius zones answer
133
+ * only with both ends on a map — the store's origin and the destination's
134
+ * coordinates — and the tightest radius that reaches wins.
135
+ */
136
+ export declare function matchLocalDeliveryZone(settings: LocalDeliverySettings | undefined, destination: {
137
+ country?: string;
138
+ postalCode?: string;
139
+ coordinates?: LocalDeliveryCoordinates | null;
140
+ }): LocalDeliveryZone | null;
141
+ /** What a zone charges for an order of `itemsCents`. */
142
+ export declare function localDeliveryFeeCents(zone: LocalDeliveryZone, itemsCents: number): number;
143
+ /** How far an order of `itemsCents` is below the zone's minimum; 0 when it meets it. */
144
+ export declare function localDeliveryMinimumShortfall(zone: LocalDeliveryZone, itemsCents: number): number;
145
+ /** One bookable delivery window. `id` is its start instant, which is what the buyer sends back. */
146
+ export interface LocalDeliveryWindow {
147
+ id: string;
148
+ startMs: number;
149
+ endMs: number;
150
+ }
151
+ /** The windows rows a store's settings parse to. Lines that do not read are dropped. */
152
+ export declare function localDeliveryWindowRows(settings: LocalDeliverySettings | undefined): OpeningHoursRow[];
153
+ /**
154
+ * The windows a buyer may book now, soonest first: every row on every day
155
+ * from today to `daysAhead`, in the store's time zone, that opens at least
156
+ * the lead time from now. Pure in `nowMs`, so a spec can stand at any hour.
157
+ */
158
+ export declare function upcomingLocalDeliveryWindows(settings: LocalDeliverySettings | undefined, context: {
159
+ nowMs: number;
160
+ timeZone: string;
161
+ }): LocalDeliveryWindow[];
162
+ /** The bookable window starting at `startMs`, or `null` when no such window is open now. */
163
+ export declare function findLocalDeliveryWindow(settings: LocalDeliverySettings | undefined, startMs: unknown, context: {
164
+ nowMs: number;
165
+ timeZone: string;
166
+ }): LocalDeliveryWindow | null;
167
+ /** Whether checkout can offer local delivery at all. */
168
+ export declare function localDeliveryOffered(settings: LocalDeliverySettings | undefined): boolean;
169
+ /**
170
+ * What stops saved settings from offering delivery, in the console's words.
171
+ * Empty when checkout will offer it (or when it is switched off).
172
+ */
173
+ export declare function localDeliveryProblems(settings: LocalDeliverySettings | undefined): string[];
174
+ /** "Tue, Oct 14, 9:00 AM – 12:00 PM" in the store's zone. */
175
+ export declare function formatLocalDeliveryWindow(window: {
176
+ startMs: number;
177
+ endMs: number;
178
+ }, timeZone: string): string;
@@ -0,0 +1,361 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { parseOpeningHours } from "@aglyn/aglyn/app-utils/local-business";
18
+ import { zonedDateTime, zonedWallTimeToInstant } from "@aglyn/shared-util-timestamp/zoned-time";
19
+ export const PICKUP_INSTRUCTIONS_MAX = 400;
20
+ export const PICKUP_HOURS_MAX = 600;
21
+ export const PICKUP_LOCATIONS_MAX = 25;
22
+ const text = (value, max)=>typeof value === 'string' ? value.trim().slice(0, max) : '';
23
+ const wholeMinutes = (value, max)=>{
24
+ const minutes = Math.round(Number(value));
25
+ return Number.isFinite(minutes) && minutes > 0 ? Math.min(minutes, max) : undefined;
26
+ };
27
+ /** A stored pickup block made safe; never throws. */ export function normalizePickupSettings(value) {
28
+ if (!value || typeof value !== 'object') return {};
29
+ const raw = value;
30
+ const settings = {};
31
+ if (raw['enabled'] === true) settings.enabled = true;
32
+ const hours = text(raw['hours'], PICKUP_HOURS_MAX);
33
+ if (hours) settings.hours = hours;
34
+ const instructions = text(raw['instructions'], PICKUP_INSTRUCTIONS_MAX);
35
+ if (instructions) settings.instructions = instructions;
36
+ const ready = wholeMinutes(raw['readyWithinMinutes'], 14 * 24 * 60);
37
+ if (ready) settings.readyWithinMinutes = ready;
38
+ return settings;
39
+ }
40
+ /** A postal address on one line, or the location's free-text address. */ export function formatPostalAddressLine(address, fallback) {
41
+ const parts = [
42
+ address == null ? void 0 : address.line1,
43
+ address == null ? void 0 : address.line2,
44
+ [
45
+ address == null ? void 0 : address.city,
46
+ address == null ? void 0 : address.state
47
+ ].filter(Boolean).join(', '),
48
+ address == null ? void 0 : address.postalCode
49
+ ].map((part)=>String(part != null ? part : '').trim()).filter(Boolean);
50
+ return parts.length ? parts.join(', ') : String(fallback != null ? fallback : '').trim();
51
+ }
52
+ /**
53
+ * The locations a buyer may pick up from, default location first, then by
54
+ * name. A location without pickup switched on is never offered, however
55
+ * complete the rest of it is.
56
+ */ export function pickupLocationOptions(locations) {
57
+ return locations.filter((location)=>Boolean((location == null ? void 0 : location.id) && normalizePickupSettings(location.pickup).enabled)).sort((a, b)=>{
58
+ var _a_name, _b_name;
59
+ return Number(Boolean(b.isDefault)) - Number(Boolean(a.isDefault)) || String((_a_name = a.name) != null ? _a_name : '').localeCompare(String((_b_name = b.name) != null ? _b_name : ''));
60
+ }).slice(0, PICKUP_LOCATIONS_MAX).map((location)=>{
61
+ const pickup = normalizePickupSettings(location.pickup);
62
+ const address = formatPostalAddressLine(location.postalAddress, location.address);
63
+ return _extends({
64
+ id: location.id,
65
+ name: String(location.name || 'Store').slice(0, 80)
66
+ }, address ? {
67
+ address
68
+ } : {}, pickup.hours ? {
69
+ hours: pickup.hours
70
+ } : {}, pickup.instructions ? {
71
+ instructions: pickup.instructions
72
+ } : {}, pickup.readyWithinMinutes ? {
73
+ readyWithinMinutes: pickup.readyWithinMinutes
74
+ } : {});
75
+ });
76
+ }
77
+ /** "Usually ready in 2 hours" from a preparation time, or `''`. */ export function pickupReadyWithinLabel(minutes) {
78
+ if (!minutes || minutes <= 0) return '';
79
+ if (minutes < 60) return `Usually ready in ${minutes} minutes`;
80
+ const hours = Math.round(minutes / 60);
81
+ if (hours < 48) return `Usually ready in ${hours} hour${hours === 1 ? '' : 's'}`;
82
+ const days = Math.round(hours / 24);
83
+ return `Usually ready in ${days} days`;
84
+ }
85
+ export const LOCAL_DELIVERY_ZONES_MAX = 20;
86
+ export const LOCAL_DELIVERY_POSTCODES_MAX = 200;
87
+ export const LOCAL_DELIVERY_DEFAULT_LEAD_MINUTES = 120;
88
+ export const LOCAL_DELIVERY_DEFAULT_DAYS_AHEAD = 7;
89
+ export const LOCAL_DELIVERY_MAX_DAYS_AHEAD = 30;
90
+ /** A cart offers at most this many windows; the earliest are kept. */ export const LOCAL_DELIVERY_WINDOWS_OFFERED_MAX = 40;
91
+ export const LOCAL_DELIVERY_RADIUS_MAX_KM = 200;
92
+ const wholeCents = (value)=>{
93
+ const cents = Math.round(Number(value != null ? value : 0));
94
+ return Number.isFinite(cents) && cents > 0 ? cents : 0;
95
+ };
96
+ const coordinates = (value)=>{
97
+ if (!value || typeof value !== 'object') return undefined;
98
+ const lat = Number(value['lat']);
99
+ const lng = Number(value['lng']);
100
+ if (!Number.isFinite(lat) || !Number.isFinite(lng)) return undefined;
101
+ if (Math.abs(lat) > 90 || Math.abs(lng) > 180) return undefined;
102
+ return {
103
+ lat,
104
+ lng
105
+ };
106
+ };
107
+ /**
108
+ * One postal code as zones compare it: upper-cased with spaces removed, and a
109
+ * US ZIP+4 cut to its five digits so `10001-1234` is in the `10001` zone.
110
+ */ export function normalizePostcode(value, country) {
111
+ const code = String(value != null ? value : '').toUpperCase().replace(/\s+/g, '').slice(0, 16);
112
+ if (String(country != null ? country : '').toUpperCase() === 'US') {
113
+ const zip = /^(\d{5})(?:-?\d{4})?$/.exec(code);
114
+ if (zip) return zip[1];
115
+ }
116
+ return code;
117
+ }
118
+ /** One zone entry as the console saves it: trimmed, upper-cased, spaces gone. */ function normalizePostcodePattern(value) {
119
+ return String(value != null ? value : '').toUpperCase().replace(/\s+/g, '').slice(0, 24);
120
+ }
121
+ /** Whether a postal code is one a zone entry names. */ export function postcodePatternMatches(pattern, postcode) {
122
+ const entry = normalizePostcodePattern(pattern);
123
+ const code = String(postcode != null ? postcode : '').toUpperCase().replace(/\s+/g, '');
124
+ if (!entry || !code) return false;
125
+ if (entry.endsWith('*')) {
126
+ const prefix = entry.slice(0, -1);
127
+ return prefix.length > 0 && code.startsWith(prefix);
128
+ }
129
+ const range = /^(\d+)-(\d+)$/.exec(entry);
130
+ if (range && range[1].length === range[2].length && /^\d+$/.test(code)) {
131
+ if (code.length !== range[1].length) return false;
132
+ const value = Number(code);
133
+ const low = Math.min(Number(range[1]), Number(range[2]));
134
+ const high = Math.max(Number(range[1]), Number(range[2]));
135
+ return value >= low && value <= high;
136
+ }
137
+ return entry === code;
138
+ }
139
+ /** A stored zone made safe, or `null` when it cannot deliver anywhere. */ function normalizeZone(value) {
140
+ if (!value || typeof value !== 'object') return null;
141
+ const raw = value;
142
+ const id = text(raw['id'], 60);
143
+ if (!id) return null;
144
+ const kind = raw['kind'] === 'radius' ? 'radius' : 'postcode';
145
+ const zone = {
146
+ id,
147
+ name: text(raw['name'], 80) || 'Local delivery',
148
+ kind,
149
+ feeCents: wholeCents(raw['feeCents'])
150
+ };
151
+ if (kind === 'postcode') {
152
+ const codes = Array.isArray(raw['postcodes']) ? raw['postcodes'] : [];
153
+ zone.postcodes = [
154
+ ...new Set(codes.map(normalizePostcodePattern).filter(Boolean))
155
+ ].slice(0, LOCAL_DELIVERY_POSTCODES_MAX);
156
+ } else {
157
+ const radius = Number(raw['radiusKm']);
158
+ zone.radiusKm = Number.isFinite(radius) && radius > 0 ? Math.min(Math.round(radius * 10) / 10, LOCAL_DELIVERY_RADIUS_MAX_KM) : 0;
159
+ }
160
+ const minimum = wholeCents(raw['minimumCents']);
161
+ if (minimum) zone.minimumCents = minimum;
162
+ const freeOver = wholeCents(raw['freeOverCents']);
163
+ if (freeOver) zone.freeOverCents = freeOver;
164
+ return zone;
165
+ }
166
+ /** The stored settings made safe; never throws. */ export function normalizeLocalDeliverySettings(value) {
167
+ var _raw_country;
168
+ if (!value || typeof value !== 'object') return {};
169
+ const raw = value;
170
+ const settings = {};
171
+ if (raw['enabled'] === true) settings.enabled = true;
172
+ const country = String((_raw_country = raw['country']) != null ? _raw_country : '').trim().toUpperCase();
173
+ if (/^[A-Z]{2}$/.test(country)) settings.country = country;
174
+ const locationId = text(raw['locationId'], 120);
175
+ if (locationId) settings.locationId = locationId;
176
+ const origin = coordinates(raw['origin']);
177
+ if (origin) settings.origin = origin;
178
+ const zones = (Array.isArray(raw['zones']) ? raw['zones'] : []).map(normalizeZone).filter((zone)=>Boolean(zone)).slice(0, LOCAL_DELIVERY_ZONES_MAX);
179
+ if (zones.length) settings.zones = zones;
180
+ const windows = text(raw['windows'], PICKUP_HOURS_MAX);
181
+ if (windows) settings.windows = windows;
182
+ const lead = Math.round(Number(raw['leadTimeMinutes']));
183
+ if (Number.isFinite(lead) && lead >= 0) settings.leadTimeMinutes = Math.min(lead, 14 * 24 * 60);
184
+ const days = Math.round(Number(raw['daysAhead']));
185
+ if (Number.isFinite(days) && days >= 1) settings.daysAhead = Math.min(days, LOCAL_DELIVERY_MAX_DAYS_AHEAD);
186
+ const instructions = text(raw['instructions'], PICKUP_INSTRUCTIONS_MAX);
187
+ if (instructions) settings.instructions = instructions;
188
+ return settings;
189
+ }
190
+ /** Great-circle distance in kilometers (haversine). */ export function distanceKm(a, b) {
191
+ const radians = (degrees)=>degrees * Math.PI / 180;
192
+ const dLat = radians(b.lat - a.lat);
193
+ const dLng = radians(b.lng - a.lng);
194
+ const h = Math.sin(dLat / 2) ** 2 + Math.cos(radians(a.lat)) * Math.cos(radians(b.lat)) * Math.sin(dLng / 2) ** 2;
195
+ return 2 * 6371 * Math.asin(Math.min(1, Math.sqrt(h)));
196
+ }
197
+ /** Whether any zone measures distance, so checkout needs the full address placed on a map. */ export function localDeliveryHasRadiusZones(settings) {
198
+ var _ref;
199
+ return Boolean(settings == null ? void 0 : settings.origin) && ((_ref = settings == null ? void 0 : settings.zones) != null ? _ref : []).some((zone)=>{
200
+ var _zone_radiusKm;
201
+ return zone.kind === 'radius' && ((_zone_radiusKm = zone.radiusKm) != null ? _zone_radiusKm : 0) > 0;
202
+ });
203
+ }
204
+ /**
205
+ * The zone a destination falls in, or `null`. Postal-code zones are asked
206
+ * first, in the order the store listed them, so a store can carve a cheaper
207
+ * neighbourhood out of a wider one by listing it above. Radius zones answer
208
+ * only with both ends on a map — the store's origin and the destination's
209
+ * coordinates — and the tightest radius that reaches wins.
210
+ */ export function matchLocalDeliveryZone(settings, destination) {
211
+ var _destination_country, _settings_zones, _zones_filter_sort_;
212
+ if (!(settings == null ? void 0 : settings.country)) return null;
213
+ const country = String((_destination_country = destination.country) != null ? _destination_country : settings.country).toUpperCase();
214
+ if (country !== settings.country) return null;
215
+ const postcode = normalizePostcode(destination.postalCode, settings.country);
216
+ const zones = (_settings_zones = settings.zones) != null ? _settings_zones : [];
217
+ if (postcode) {
218
+ for (const zone of zones){
219
+ var _zone_postcodes;
220
+ if (zone.kind !== 'postcode') continue;
221
+ if (((_zone_postcodes = zone.postcodes) != null ? _zone_postcodes : []).some((pattern)=>postcodePatternMatches(pattern, postcode))) return zone;
222
+ }
223
+ }
224
+ const at = destination.coordinates ? coordinates(destination.coordinates) : undefined;
225
+ if (!at || !settings.origin) return null;
226
+ const distance = distanceKm(settings.origin, at);
227
+ return (_zones_filter_sort_ = zones.filter((zone)=>{
228
+ var _zone_radiusKm, _zone_radiusKm1;
229
+ return zone.kind === 'radius' && ((_zone_radiusKm = zone.radiusKm) != null ? _zone_radiusKm : 0) > 0 && distance <= ((_zone_radiusKm1 = zone.radiusKm) != null ? _zone_radiusKm1 : 0);
230
+ }).sort((a, b)=>{
231
+ var _a_radiusKm, _b_radiusKm;
232
+ return ((_a_radiusKm = a.radiusKm) != null ? _a_radiusKm : 0) - ((_b_radiusKm = b.radiusKm) != null ? _b_radiusKm : 0);
233
+ })[0]) != null ? _zones_filter_sort_ : null;
234
+ }
235
+ /** What a zone charges for an order of `itemsCents`. */ export function localDeliveryFeeCents(zone, itemsCents) {
236
+ if (zone.freeOverCents && itemsCents >= zone.freeOverCents) return 0;
237
+ return Math.max(0, Math.round(zone.feeCents || 0));
238
+ }
239
+ /** How far an order of `itemsCents` is below the zone's minimum; 0 when it meets it. */ export function localDeliveryMinimumShortfall(zone, itemsCents) {
240
+ var _zone_minimumCents;
241
+ return Math.max(0, ((_zone_minimumCents = zone.minimumCents) != null ? _zone_minimumCents : 0) - Math.max(0, Math.round(itemsCents || 0)));
242
+ }
243
+ const DAY_NAMES = [
244
+ 'Sunday',
245
+ 'Monday',
246
+ 'Tuesday',
247
+ 'Wednesday',
248
+ 'Thursday',
249
+ 'Friday',
250
+ 'Saturday'
251
+ ];
252
+ /** The windows rows a store's settings parse to. Lines that do not read are dropped. */ export function localDeliveryWindowRows(settings) {
253
+ var _ref;
254
+ return parseOpeningHours((_ref = settings == null ? void 0 : settings.windows) != null ? _ref : '');
255
+ }
256
+ /**
257
+ * The windows a buyer may book now, soonest first: every row on every day
258
+ * from today to `daysAhead`, in the store's time zone, that opens at least
259
+ * the lead time from now. Pure in `nowMs`, so a spec can stand at any hour.
260
+ */ export function upcomingLocalDeliveryWindows(settings, context) {
261
+ var _ref, _ref1;
262
+ const rows = localDeliveryWindowRows(settings);
263
+ if (!rows.length) return [];
264
+ const lead = ((_ref = settings == null ? void 0 : settings.leadTimeMinutes) != null ? _ref : LOCAL_DELIVERY_DEFAULT_LEAD_MINUTES) * 60000;
265
+ const daysAhead = (_ref1 = settings == null ? void 0 : settings.daysAhead) != null ? _ref1 : LOCAL_DELIVERY_DEFAULT_DAYS_AHEAD;
266
+ const today = zonedDateTime(context.nowMs, context.timeZone);
267
+ const windows = [];
268
+ const seen = new Set();
269
+ for(let offset = 0; offset <= daysAhead; offset++){
270
+ // Noon of the day, so a daylight-saving change never lands it on the
271
+ // wrong calendar date.
272
+ const noon = zonedWallTimeToInstant({
273
+ year: today.year,
274
+ month: today.month,
275
+ day: today.day + offset,
276
+ hour: 12
277
+ }, context.timeZone);
278
+ const day = zonedDateTime(noon, context.timeZone);
279
+ const name = DAY_NAMES[day.weekday];
280
+ for (const row of rows){
281
+ if (!row.days.includes(name)) continue;
282
+ const [openHour, openMinute] = row.opens.split(':').map(Number);
283
+ const [closeHour, closeMinute] = row.closes.split(':').map(Number);
284
+ const startMs = zonedWallTimeToInstant({
285
+ year: day.year,
286
+ month: day.month,
287
+ day: day.day,
288
+ hour: openHour,
289
+ minute: openMinute
290
+ }, context.timeZone);
291
+ const overnight = closeHour * 60 + closeMinute <= openHour * 60 + openMinute;
292
+ const endMs = zonedWallTimeToInstant({
293
+ year: day.year,
294
+ month: day.month,
295
+ day: day.day + (overnight ? 1 : 0),
296
+ hour: closeHour,
297
+ minute: closeMinute
298
+ }, context.timeZone);
299
+ if (startMs < context.nowMs + lead || seen.has(startMs)) continue;
300
+ seen.add(startMs);
301
+ windows.push({
302
+ id: String(startMs),
303
+ startMs,
304
+ endMs
305
+ });
306
+ }
307
+ }
308
+ return windows.sort((a, b)=>a.startMs - b.startMs).slice(0, LOCAL_DELIVERY_WINDOWS_OFFERED_MAX);
309
+ }
310
+ /** The bookable window starting at `startMs`, or `null` when no such window is open now. */ export function findLocalDeliveryWindow(settings, startMs, context) {
311
+ var _upcomingLocalDeliveryWindows_find;
312
+ const wanted = Math.round(Number(startMs));
313
+ if (!Number.isFinite(wanted)) return null;
314
+ return (_upcomingLocalDeliveryWindows_find = upcomingLocalDeliveryWindows(settings, context).find((window)=>window.startMs === wanted)) != null ? _upcomingLocalDeliveryWindows_find : null;
315
+ }
316
+ /** Whether checkout can offer local delivery at all. */ export function localDeliveryOffered(settings) {
317
+ var _settings_zones;
318
+ return Boolean((settings == null ? void 0 : settings.enabled) && settings.country && ((_settings_zones = settings.zones) != null ? _settings_zones : []).length > 0 && localDeliveryWindowRows(settings).length > 0);
319
+ }
320
+ /**
321
+ * What stops saved settings from offering delivery, in the console's words.
322
+ * Empty when checkout will offer it (or when it is switched off).
323
+ */ export function localDeliveryProblems(settings) {
324
+ var _settings_zones;
325
+ if (!(settings == null ? void 0 : settings.enabled)) return [];
326
+ const problems = [];
327
+ if (!settings.country) problems.push('Choose the country you deliver in.');
328
+ const zones = (_settings_zones = settings.zones) != null ? _settings_zones : [];
329
+ if (!zones.length) problems.push('Add at least one delivery zone.');
330
+ for (const zone of zones){
331
+ var _zone_postcodes;
332
+ if (zone.kind === 'postcode' && !((_zone_postcodes = zone.postcodes) != null ? _zone_postcodes : []).length) {
333
+ problems.push(`"${zone.name}" lists no postal codes.`);
334
+ }
335
+ if (zone.kind === 'radius' && !settings.origin) {
336
+ problems.push(`"${zone.name}" measures distance, but your store has no map position yet.`);
337
+ }
338
+ }
339
+ if (!localDeliveryWindowRows(settings).length) problems.push('Add at least one delivery window.');
340
+ return problems;
341
+ }
342
+ /** "Tue, Oct 14, 9:00 AM – 12:00 PM" in the store's zone. */ export function formatLocalDeliveryWindow(window, timeZone) {
343
+ try {
344
+ const day = new Intl.DateTimeFormat('en-US', {
345
+ timeZone,
346
+ weekday: 'short',
347
+ month: 'short',
348
+ day: 'numeric'
349
+ }).format(new Date(window.startMs));
350
+ const time = new Intl.DateTimeFormat('en-US', {
351
+ timeZone,
352
+ hour: 'numeric',
353
+ minute: '2-digit'
354
+ });
355
+ return `${day}, ${time.format(new Date(window.startMs))} – ${time.format(new Date(window.endMs))}`;
356
+ } catch (unused) {
357
+ return new Date(window.startMs).toISOString();
358
+ }
359
+ }
360
+
361
+ //# sourceMappingURL=local-fulfillment-settings.js.map