@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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/plugins/commerce/src/lib/tenant-emails.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\nimport type { TenantEmailEntry } from '@aglyn/shared-util-email'\n\n/** The human order number every buyer order email names (AGL-3610). */\nconst ORDER_NUMBER_TOKEN = {\n name: 'order.number',\n description: 'The order number, as the store shows it',\n sample: '#1042',\n} as const\n\n/**\n * The buyer's private order-status page (AGL-3610): a signed link, so it\n * opens without an account and only for this order.\n */\nconst ORDER_STATUS_URL_TOKEN = {\n name: 'order.statusUrl',\n description:\n 'Link to the order status page: status, shipments and tracking. Private ' +\n 'to the buyer; it needs no account',\n sample: 'https://shop.example.com/order-status?o=ord_123&t=…',\n} as const\n\nconst ORDER_FOOTER_REASON =\n 'You’re receiving this because you placed an order with {{host.businessName}}.'\n\n/**\n * The emails a site sends its own customers through Commerce (AGL-769/770).\n *\n * Declared here, by the plugin that sends them, and compiled into the\n * platform's tenant email catalog (`TENANT_EMAILS` in\n * `@aglyn/shared-util-email`) by `tools/scripts/generate-plugin-manifests.mjs`\n * (AGL-3080): the catalog's readers include the send path, which loads no\n * plugin code, so a runtime registry it had not filled would quietly send\n * the text card in place of the site's designed email. Regenerate after\n * changing an entry; `--check` refuses a stale catalog.\n *\n * Most commerce sends are designable in the email besigner; a `fixed` entry\n * flips to `besigner` when its send site is wired to `renderHostEmail`\n * (AGL-770).\n */\nexport function commerceTenantEmails(): readonly TenantEmailEntry[] {\n return [\n {\n key: 'order-receipt',\n name: 'Order receipt',\n description: 'Sent to the buyer after a successful order or checkout.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Receipt for your order',\n mergeTokens: [\n {\n name: 'order.summary',\n description: 'The ordered items, one per line (with any license/download links)',\n sample: 'House Blend × 2 — $24.00',\n },\n {\n name: 'order.total',\n description: 'Order total',\n sample: '$24.00',\n },\n {\n name: 'order.ref',\n description: 'Order reference id',\n sample: 'cs_test_123',\n },\n {\n name: 'store.receiptFooter',\n description:\n 'The Receipt footer from the store settings; empty when none is set',\n sample: 'Returns are accepted within 30 days.',\n },\n ORDER_NUMBER_TOKEN,\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Thanks for your purchase!', variant: 'heading' },\n {\n block: 'text',\n text: 'Here is the receipt for your order from {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: 'Total charged: {{order.total}}', variant: 'body' },\n { block: 'text', text: '{{store.receiptFooter}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n {\n block: 'text',\n text: 'Order reference: {{order.ref}}',\n variant: 'caption',\n },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-shipped',\n name: 'Order shipped',\n description:\n 'Tells the buyer part or all of their order is on its way, with the ' +\n 'carrier and a tracking link when the shipment has one. Sent once per ' +\n 'shipment.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} has shipped',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'shipment.summary',\n description: 'The items in this shipment, one per line',\n sample: '2× House Blend',\n },\n {\n name: 'shipment.carrier',\n description: 'The carrier; empty when none was recorded',\n sample: 'UPS',\n },\n {\n name: 'shipment.trackingNumber',\n description: 'The tracking number; empty when none was recorded',\n sample: '1Z999AA10123456784',\n },\n {\n name: 'shipment.tracking',\n description:\n 'A sentence with the carrier, tracking number and tracking link; ' +\n 'empty when the shipment has no tracking number',\n sample:\n 'Tracking: UPS 1Z999AA10123456784 — https://www.ups.com/track?tracknum=1Z999AA10123456784',\n },\n {\n name: 'shipment.remaining',\n description:\n 'A sentence saying how many items are still to ship; empty when ' +\n 'this shipment completes the order',\n sample: '1 more item will ship separately.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order is on its way', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} shipped items from order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{shipment.summary}}', variant: 'body' },\n { block: 'text', text: '{{shipment.tracking}}', variant: 'body' },\n { block: 'text', text: '{{shipment.remaining}}', variant: 'body' },\n { block: 'button', label: 'Track your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-delivered',\n name: 'Order delivered',\n description: 'Tells the buyer their order was marked delivered.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} was delivered',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order was delivered', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} marked order {{order.number}} as delivered.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n {\n block: 'text',\n text:\n 'If something is missing or not right, reply to this email or ' +\n 'contact {{host.businessName}}.',\n variant: 'caption',\n },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-refunded',\n name: 'Order refunded',\n description:\n 'Tells the buyer a refund was issued, for how much and, when the ' +\n 'store refunded named items, which ones. Sent once per refund.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Refund for your order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'refund.amount',\n description: 'The amount of this refund',\n sample: '$12.00',\n },\n {\n name: 'refund.summary',\n description:\n 'The refunded items, one per line; empty when the refund was by ' +\n 'amount only',\n sample: '1× House Blend',\n },\n {\n name: 'refund.note',\n description:\n 'Whether the order is now fully refunded, as a sentence',\n sample: 'Your order has been refunded in full.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your refund is on its way', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} refunded {{refund.amount}} on order ' +\n '{{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{refund.summary}}', variant: 'body' },\n { block: 'text', text: '{{refund.note}}', variant: 'body' },\n {\n block: 'text',\n text:\n 'Refunds go back to the original payment method and usually ' +\n 'appear within 5 to 10 business days, depending on your bank.',\n variant: 'caption',\n },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-cancelled',\n name: 'Order canceled',\n description: 'Tells the buyer their order was canceled.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} was canceled',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n {\n name: 'cancel.note',\n description:\n 'What happens to the payment, as a sentence; empty when nothing ' +\n 'was paid',\n sample:\n 'Any payment you made will be refunded, and you will get a ' +\n 'separate email when it is.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order was canceled', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} canceled order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: '{{cancel.note}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'sale-notification',\n name: 'New sale',\n description: 'Notifies the seller when an order is placed.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'New order on {{site.name}}',\n mergeTokens: [\n {\n name: 'site.name',\n description: 'The site the sale happened on',\n sample: 'Northwind Coffee',\n },\n {\n name: 'order.summary',\n description: 'The ordered items',\n sample: 'House Blend — $12.00',\n },\n { name: 'order.total', description: 'Order total', sample: '$12.00' },\n {\n name: 'buyer.email',\n description: \"The buyer's email\",\n sample: 'buyer@example.com',\n },\n {\n name: 'order.ref',\n description: 'Order reference id',\n sample: 'cs_test_123',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'You made a sale', variant: 'heading' },\n {\n block: 'text',\n text: 'A new order came in on {{site.name}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: 'Total: {{order.total}}', variant: 'body' },\n {\n block: 'text',\n text: 'Buyer: {{buyer.email}} · Order {{order.ref}}',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you manage {{host.businessName}}.',\n },\n {\n key: 'reservation-confirmed',\n name: 'Reservation confirmed',\n description: 'Confirms a paid reservation to the customer.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Reservation confirmed',\n mergeTokens: [\n {\n name: 'reservation.checkIn',\n description: 'Check-in date',\n sample: 'Mon, 01 Jun 2026',\n },\n {\n name: 'reservation.nights',\n description: 'Number of nights',\n sample: '2',\n },\n {\n name: 'reservation.paid',\n description:\n 'What the guest was charged today, lodging tax included; a ' +\n 'charge that carried lodging tax names it, as in “$254.40, ' +\n 'including $14.40 lodging tax”',\n sample: '$240.00',\n },\n {\n name: 'reservation.balance',\n description:\n 'What is still owed for the stay and where it is paid, as a ' +\n 'sentence; empty when the stay is paid in full',\n sample: 'Still to pay: $360.00, at the property. It has not been charged.',\n },\n {\n name: 'reservation.ref',\n description: 'Reservation reference id',\n sample: 'resv_123',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Reservation confirmed', variant: 'heading' },\n {\n block: 'text',\n text: 'Your stay at {{host.businessName}} is confirmed.',\n variant: 'body',\n },\n {\n block: 'text',\n text: 'Check-in: {{reservation.checkIn}}',\n variant: 'body',\n },\n { block: 'text', text: 'Nights: {{reservation.nights}}', variant: 'body' },\n {\n block: 'text',\n text: 'Paid today: {{reservation.paid}}',\n variant: 'body',\n },\n { block: 'text', text: '{{reservation.balance}}', variant: 'body' },\n {\n block: 'text',\n text: 'Reference: {{reservation.ref}}',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you made a reservation with {{host.businessName}}.',\n },\n {\n key: 'gift-card',\n name: 'Gift card delivery',\n description: 'Delivers a purchased gift card to its recipient.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your gift card for {{host.businessName}}',\n mergeTokens: [\n {\n name: 'giftcard.code',\n description: 'The gift card code',\n sample: 'GC-ABC123DEF456',\n },\n {\n name: 'giftcard.value',\n description: 'The gift card value',\n sample: '$25.00',\n },\n {\n name: 'giftcard.note',\n description:\n 'The note written when the card was issued by hand; empty for a ' +\n 'card bought at checkout',\n sample: 'Happy birthday, Sam!',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Your gift card', variant: 'heading' },\n {\n block: 'text',\n text: 'You have a {{giftcard.value}} gift card for {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{giftcard.note}}', variant: 'body' },\n {\n block: 'text',\n text: 'Gift card code: {{giftcard.code}}',\n variant: 'body',\n },\n {\n block: 'text',\n text: 'Enter the code at checkout on {{host.url}} to use its balance.',\n variant: 'body',\n },\n {\n block: 'button',\n label: 'Visit {{host.businessName}}',\n href: '{{host.url}}',\n },\n ],\n footerReason:\n 'You’re receiving this because a gift card from {{host.businessName}} was sent to this address.',\n },\n {\n key: 'supplier-fulfillment',\n name: 'Supplier fulfillment',\n description: 'Tells a dropship supplier there is a new order to fulfill.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'fixed',\n },\n {\n key: 'back-in-stock',\n name: 'Back in stock',\n description: 'Tells a customer a product they watched is available again.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Back in stock: {{product.name}}',\n mergeTokens: [\n {\n name: 'product.name',\n description: 'The product that restocked',\n sample: 'House Blend',\n },\n {\n name: 'product.url',\n description: 'Link to the product page',\n sample: 'https://shop.example.com/products/house-blend',\n },\n ],\n defaultBody: [\n {\n block: 'text',\n text: '{{product.name}} is back in stock at {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'button', label: 'View product', href: '{{product.url}}' },\n ],\n footerReason:\n 'You’re receiving this because you asked {{host.businessName}} to tell you when this was back.',\n },\n {\n key: 'abandoned-cart',\n name: 'Abandoned cart',\n description: 'Reminds a shopper of items left in their cart.',\n // The cron refuses to send this without the entitlement\n // (`process-abandoned.ts:92`), so the console has to say so (AGL-2081).\n requiresFeature: 'abandonedCart',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'You left something in your cart',\n mergeTokens: [\n {\n name: 'cart.url',\n description: 'Link back to the shopper cart',\n sample: 'https://shop.example.com/cart',\n },\n ],\n defaultBody: [\n {\n block: 'text',\n text:\n 'You left items in your cart at {{host.businessName}}. Pick up ' +\n 'where you left off.',\n variant: 'body',\n },\n { block: 'button', label: 'Return to cart', href: '{{cart.url}}' },\n {\n block: 'text',\n text: 'Nothing in your cart is held for you.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you started a checkout with {{host.businessName}}.',\n },\n {\n key: 'member-post',\n name: 'New member post',\n description: 'Notifies members when new members-only content is posted.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: '{{post.title}}',\n mergeTokens: [\n { name: 'post.title', description: 'The post’s title', sample: 'This month in the studio' },\n {\n name: 'post.body',\n description: 'The post, as its author wrote it',\n sample: 'Three new pieces are up for members first.',\n },\n ],\n defaultBody: [\n { block: 'text', text: '{{post.title}}', variant: 'heading' },\n { block: 'text', text: '{{post.body}}', variant: 'body' },\n ],\n footerReason: 'You’re receiving this because you’re a member of {{host.businessName}}.',\n },\n {\n key: 'member-password-reset',\n name: 'Member password reset',\n description:\n \"Resets a site member's password — a store-member account, separate \" +\n 'from a console login. Sent when the member asks, and when a site ' +\n 'administrator starts a reset for them.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Reset your {{site.name}} password',\n mergeTokens: [\n { name: 'site.name', description: 'The site’s name', sample: 'Northwind Coffee' },\n {\n name: 'reset.intro',\n description: 'Who started the reset',\n sample: 'Someone asked to reset the password for your Northwind Coffee account.',\n },\n {\n name: 'resetUrl',\n description: 'The one-time reset link',\n sample: 'https://shop.example.com/recover?token=…',\n },\n {\n name: 'reset.note',\n description: 'How long the link lasts, and what to do if unexpected',\n sample:\n 'The link works once and expires in 1 hour. If you did not ask for ' +\n 'this, you can safely ignore this email — your password is unchanged.',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Reset your password', variant: 'heading' },\n { block: 'text', text: '{{reset.intro}}', variant: 'body' },\n { block: 'button', label: 'Set a new password', href: '{{resetUrl}}' },\n { block: 'text', text: '{{reset.note}}', variant: 'caption' },\n ],\n footerReason:\n 'You’re receiving this because a password reset was started for your ' +\n '{{host.businessName}} account.',\n },\n {\n key: 'member-password-changed',\n name: 'Member password changed',\n description:\n 'Tells a site member that a site administrator set a new password on ' +\n 'their account.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your {{site.name}} password was changed',\n mergeTokens: [\n { name: 'site.name', description: 'The site’s name', sample: 'Northwind Coffee' },\n {\n name: 'signInUrl',\n description: 'Where the member signs back in',\n sample: 'https://shop.example.com',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Your password was changed', variant: 'heading' },\n {\n block: 'text',\n text:\n 'An administrator of {{site.name}} set a new password on your ' +\n 'account and signed you out on every device. To sign back in, ' +\n 'get the new password from them, or choose \"Forgot password?\" on ' +\n 'the sign-in page to set your own.',\n variant: 'body',\n },\n { block: 'button', label: 'Sign in', href: '{{signInUrl}}' },\n {\n block: 'text',\n text: 'If you did not expect this, contact the site owner.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because the password on your ' +\n '{{host.businessName}} account was changed.',\n },\n {\n key: 'newsletter-confirmation',\n name: 'Subscription confirmation',\n description:\n 'Asks someone who signed up for a site’s emails to confirm the address ' +\n 'before anything is sent to it.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Confirm your subscription',\n mergeTokens: [\n {\n name: 'stream.name',\n description: 'What they signed up for',\n sample: 'Newsletter',\n },\n {\n name: 'confirmUrl',\n description: 'The confirmation link',\n sample: 'https://shop.example.com/subscribe/confirm?token=…',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Confirm your subscription', variant: 'heading' },\n {\n block: 'text',\n text:\n 'Please confirm that you want to get {{stream.name}} emails from ' +\n '{{host.businessName}} at this address.',\n variant: 'body',\n },\n { block: 'button', label: 'Confirm my subscription', href: '{{confirmUrl}}' },\n {\n block: 'text',\n text:\n 'The link works for three days. If you did not sign up, ignore this ' +\n 'message — nothing will be sent.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because this address was entered on ' +\n '{{host.businessName}}’s signup form.',\n },\n ...returnTenantEmails(),\n ]\n}\n\n/** The items a return covers, one per line. */\nconst RETURN_ITEMS_TOKEN = {\n name: 'return.items',\n description: 'The items being returned, one per line, with the reason',\n sample: '1× House Blend — Arrived damaged',\n} as const\n\n/** The merchant's note on a return; empty when they left none. */\nconst RETURN_NOTE_TOKEN = {\n name: 'return.note',\n description: 'The store’s note to the buyer on this return; empty when none',\n sample: 'Please include the original packaging.',\n} as const\n\n/**\n * The return emails (AGL-3611): one to the store when a buyer asks, and one\n * to the buyer at each answer. Their own block, beside the order emails\n * rather than among them, because those belong to the order notifications.\n */\nfunction returnTenantEmails(): readonly TenantEmailEntry[] {\n return [\n {\n key: 'return-requested',\n name: 'Return requested',\n description:\n 'Tells the store a buyer asked to return items, with what and why, so ' +\n 'someone can approve or decline it.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Return requested for order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n {\n name: 'buyer.email',\n description: 'The buyer’s email',\n sample: 'buyer@example.com',\n },\n {\n name: 'return.customerNote',\n description: 'What the buyer wrote; empty when they wrote nothing',\n sample: 'The lid was cracked.',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'A buyer asked for a return', variant: 'heading' },\n {\n block: 'text',\n text: '{{buyer.email}} wants to return items from order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.customerNote}}', variant: 'body' },\n {\n block: 'text',\n text: 'Approve or decline it under Products → Returns.',\n variant: 'caption',\n },\n ],\n footerReason: 'You’re receiving this because you manage {{host.businessName}}.',\n },\n {\n key: 'return-approved',\n name: 'Return approved',\n description:\n 'Tells the buyer their return was approved and how to send the items ' +\n 'back, with the return label when the store attached one.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your return for order {{order.number}} is approved',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n RETURN_NOTE_TOKEN,\n {\n name: 'return.label',\n description:\n 'A sentence with the return label link and its tracking; empty ' +\n 'when the store attached no label',\n sample: 'Print your return label: https://labels.example.com/r/123',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your return is approved', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} approved the return of:',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.note}}', variant: 'body' },\n { block: 'text', text: '{{return.label}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'return-declined',\n name: 'Return declined',\n description: 'Tells the buyer their return was declined, with the store’s note.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'About your return for order {{order.number}}',\n mergeTokens: [ORDER_NUMBER_TOKEN, RETURN_ITEMS_TOKEN, RETURN_NOTE_TOKEN, ORDER_STATUS_URL_TOKEN],\n defaultBody: [\n { block: 'text', text: 'We could not accept this return', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} declined the return of:',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.note}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'return-refunded',\n name: 'Return refunded',\n description: 'Tells the buyer their return was received and refunded, and how much.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your refund for order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n {\n name: 'return.refundTotal',\n description: 'The amount refunded for this return',\n sample: '$24.00',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your return is refunded', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} received your return and refunded ' +\n '{{return.refundTotal}} to your original payment method.',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n ]\n}\n"],"names":["ORDER_NUMBER_TOKEN","name","description","sample","ORDER_STATUS_URL_TOKEN","ORDER_FOOTER_REASON","commerceTenantEmails","key","pluginId","plugin","control","defaultSubject","mergeTokens","defaultBody","block","text","variant","label","href","footerReason","requiresFeature","returnTenantEmails","RETURN_ITEMS_TOKEN","RETURN_NOTE_TOKEN"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../libs/plugins/commerce/src/lib/tenant-emails.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\nimport type { TenantEmailEntry } from '@aglyn/shared-util-email'\n\n/** The human order number every buyer order email names (AGL-3610). */\nconst ORDER_NUMBER_TOKEN = {\n name: 'order.number',\n description: 'The order number, as the store shows it',\n sample: '#1042',\n} as const\n\n/**\n * The buyer's private order-status page (AGL-3610): a signed link, so it\n * opens without an account and only for this order.\n */\nconst ORDER_STATUS_URL_TOKEN = {\n name: 'order.statusUrl',\n description:\n 'Link to the order status page: status, shipments and tracking. Private ' +\n 'to the buyer; it needs no account',\n sample: 'https://shop.example.com/order-status?o=ord_123&t=…',\n} as const\n\n/** Where a pickup order is collected (AGL-3624). */\nconst PICKUP_LOCATION_TOKEN = {\n name: 'pickup.location',\n description: 'The pickup location’s name and address',\n sample: 'Main Street shop, 12 Main St, Springfield',\n} as const\n\nconst ORDER_FOOTER_REASON =\n 'You’re receiving this because you placed an order with {{host.businessName}}.'\n\n/**\n * The emails a site sends its own customers through Commerce (AGL-769/770).\n *\n * Declared here, by the plugin that sends them, and compiled into the\n * platform's tenant email catalog (`TENANT_EMAILS` in\n * `@aglyn/shared-util-email`) by `tools/scripts/generate-plugin-manifests.mjs`\n * (AGL-3080): the catalog's readers include the send path, which loads no\n * plugin code, so a runtime registry it had not filled would quietly send\n * the text card in place of the site's designed email. Regenerate after\n * changing an entry; `--check` refuses a stale catalog.\n *\n * Most commerce sends are designable in the email besigner; a `fixed` entry\n * flips to `besigner` when its send site is wired to `renderHostEmail`\n * (AGL-770).\n */\nexport function commerceTenantEmails(): readonly TenantEmailEntry[] {\n return [\n {\n key: 'order-receipt',\n name: 'Order receipt',\n description: 'Sent to the buyer after a successful order or checkout.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Receipt for your order',\n mergeTokens: [\n {\n name: 'order.summary',\n description: 'The ordered items, one per line (with any license/download links)',\n sample: 'House Blend × 2 — $24.00',\n },\n {\n name: 'order.total',\n description: 'Order total',\n sample: '$24.00',\n },\n {\n name: 'order.ref',\n description: 'Order reference id',\n sample: 'cs_test_123',\n },\n {\n name: 'store.receiptFooter',\n description:\n 'The Receipt footer from the store settings; empty when none is set',\n sample: 'Returns are accepted within 30 days.',\n },\n ORDER_NUMBER_TOKEN,\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Thanks for your purchase!', variant: 'heading' },\n {\n block: 'text',\n text: 'Here is the receipt for your order from {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: 'Total charged: {{order.total}}', variant: 'body' },\n { block: 'text', text: '{{store.receiptFooter}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n {\n block: 'text',\n text: 'Order reference: {{order.ref}}',\n variant: 'caption',\n },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-shipped',\n name: 'Order shipped',\n description:\n 'Tells the buyer part or all of their order is on its way, with the ' +\n 'carrier and a tracking link when the shipment has one. Sent once per ' +\n 'shipment.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} has shipped',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'shipment.summary',\n description: 'The items in this shipment, one per line',\n sample: '2× House Blend',\n },\n {\n name: 'shipment.carrier',\n description: 'The carrier; empty when none was recorded',\n sample: 'UPS',\n },\n {\n name: 'shipment.trackingNumber',\n description: 'The tracking number; empty when none was recorded',\n sample: '1Z999AA10123456784',\n },\n {\n name: 'shipment.tracking',\n description:\n 'A sentence with the carrier, tracking number and tracking link; ' +\n 'empty when the shipment has no tracking number',\n sample:\n 'Tracking: UPS 1Z999AA10123456784 — https://www.ups.com/track?tracknum=1Z999AA10123456784',\n },\n {\n name: 'shipment.remaining',\n description:\n 'A sentence saying how many items are still to ship; empty when ' +\n 'this shipment completes the order',\n sample: '1 more item will ship separately.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order is on its way', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} shipped items from order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{shipment.summary}}', variant: 'body' },\n { block: 'text', text: '{{shipment.tracking}}', variant: 'body' },\n { block: 'text', text: '{{shipment.remaining}}', variant: 'body' },\n { block: 'button', label: 'Track your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-delivered',\n name: 'Order delivered',\n description: 'Tells the buyer their order was marked delivered.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} was delivered',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order was delivered', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} marked order {{order.number}} as delivered.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n {\n block: 'text',\n text:\n 'If something is missing or not right, reply to this email or ' +\n 'contact {{host.businessName}}.',\n variant: 'caption',\n },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-refunded',\n name: 'Order refunded',\n description:\n 'Tells the buyer a refund was issued, for how much and, when the ' +\n 'store refunded named items, which ones. Sent once per refund.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Refund for your order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'refund.amount',\n description: 'The amount of this refund',\n sample: '$12.00',\n },\n {\n name: 'refund.summary',\n description:\n 'The refunded items, one per line; empty when the refund was by ' +\n 'amount only',\n sample: '1× House Blend',\n },\n {\n name: 'refund.note',\n description:\n 'Whether the order is now fully refunded, as a sentence',\n sample: 'Your order has been refunded in full.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your refund is on its way', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} refunded {{refund.amount}} on order ' +\n '{{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{refund.summary}}', variant: 'body' },\n { block: 'text', text: '{{refund.note}}', variant: 'body' },\n {\n block: 'text',\n text:\n 'Refunds go back to the original payment method and usually ' +\n 'appear within 5 to 10 business days, depending on your bank.',\n variant: 'caption',\n },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-cancelled',\n name: 'Order canceled',\n description: 'Tells the buyer their order was canceled.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} was canceled',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n {\n name: 'cancel.note',\n description:\n 'What happens to the payment, as a sentence; empty when nothing ' +\n 'was paid',\n sample:\n 'Any payment you made will be refunded, and you will get a ' +\n 'separate email when it is.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order was canceled', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} canceled order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: '{{cancel.note}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n // Pickup and the store's own delivery (AGL-3624).\n {\n key: 'order-ready-for-pickup',\n name: 'Order ready for pickup',\n description:\n 'Tells the buyer their pickup order is ready, where to collect it, ' +\n 'the pickup hours and any arrival instructions.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} is ready for pickup',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n PICKUP_LOCATION_TOKEN,\n {\n name: 'pickup.hours',\n description: 'The location’s pickup hours; empty when it lists none',\n sample: 'Pickup hours:\\nMo-Fr 09:00-17:00',\n },\n {\n name: 'pickup.instructions',\n description: 'What to do on arrival, as the store wrote it; empty when it wrote none',\n sample: 'Ring the bell at the side door.',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order is ready for pickup', variant: 'heading' },\n {\n block: 'text',\n text: 'Order {{order.number}} is ready at {{pickup.location}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: '{{pickup.hours}}', variant: 'body' },\n { block: 'text', text: '{{pickup.instructions}}', variant: 'body' },\n {\n block: 'text',\n text: 'Bring your order number, {{order.number}}.',\n variant: 'caption',\n },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-picked-up',\n name: 'Order picked up',\n description: 'Confirms to the buyer that their pickup order was collected.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'You picked up order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n PICKUP_LOCATION_TOKEN,\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Thanks for picking up your order', variant: 'heading' },\n {\n block: 'text',\n text: 'Order {{order.number}} was picked up from {{pickup.location}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n {\n block: 'text',\n text:\n 'If something is missing or not right, reply to this email or ' +\n 'contact {{host.businessName}}.',\n variant: 'caption',\n },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'order-out-for-delivery',\n name: 'Order out for delivery',\n description:\n 'Tells the buyer the store’s own driver is on the way with their ' +\n 'local delivery, in the window they booked.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your order {{order.number}} is out for delivery',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n {\n name: 'order.summary',\n description: 'The ordered items, one per line',\n sample: '2× House Blend',\n },\n {\n name: 'delivery.window',\n description: 'The delivery window the buyer booked',\n sample: 'Tue, Oct 14, 9:00 AM – 12:00 PM',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your order is on its way', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} is out delivering order {{order.number}}. ' +\n 'Your window: {{delivery.window}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'sale-notification',\n name: 'New sale',\n description: 'Notifies the seller when an order is placed.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'New order on {{site.name}}',\n mergeTokens: [\n {\n name: 'site.name',\n description: 'The site the sale happened on',\n sample: 'Northwind Coffee',\n },\n {\n name: 'order.summary',\n description: 'The ordered items',\n sample: 'House Blend — $12.00',\n },\n { name: 'order.total', description: 'Order total', sample: '$12.00' },\n {\n name: 'buyer.email',\n description: \"The buyer's email\",\n sample: 'buyer@example.com',\n },\n {\n name: 'order.ref',\n description: 'Order reference id',\n sample: 'cs_test_123',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'You made a sale', variant: 'heading' },\n {\n block: 'text',\n text: 'A new order came in on {{site.name}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{order.summary}}', variant: 'body' },\n { block: 'text', text: 'Total: {{order.total}}', variant: 'body' },\n {\n block: 'text',\n text: 'Buyer: {{buyer.email}} · Order {{order.ref}}',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you manage {{host.businessName}}.',\n },\n {\n key: 'reservation-confirmed',\n name: 'Reservation confirmed',\n description: 'Confirms a paid reservation to the customer.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Reservation confirmed',\n mergeTokens: [\n {\n name: 'reservation.checkIn',\n description: 'Check-in date',\n sample: 'Mon, 01 Jun 2026',\n },\n {\n name: 'reservation.nights',\n description: 'Number of nights',\n sample: '2',\n },\n {\n name: 'reservation.paid',\n description:\n 'What the guest was charged today, lodging tax included; a ' +\n 'charge that carried lodging tax names it, as in “$254.40, ' +\n 'including $14.40 lodging tax”',\n sample: '$240.00',\n },\n {\n name: 'reservation.balance',\n description:\n 'What is still owed for the stay and where it is paid, as a ' +\n 'sentence; empty when the stay is paid in full',\n sample: 'Still to pay: $360.00, at the property. It has not been charged.',\n },\n {\n name: 'reservation.ref',\n description: 'Reservation reference id',\n sample: 'resv_123',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Reservation confirmed', variant: 'heading' },\n {\n block: 'text',\n text: 'Your stay at {{host.businessName}} is confirmed.',\n variant: 'body',\n },\n {\n block: 'text',\n text: 'Check-in: {{reservation.checkIn}}',\n variant: 'body',\n },\n { block: 'text', text: 'Nights: {{reservation.nights}}', variant: 'body' },\n {\n block: 'text',\n text: 'Paid today: {{reservation.paid}}',\n variant: 'body',\n },\n { block: 'text', text: '{{reservation.balance}}', variant: 'body' },\n {\n block: 'text',\n text: 'Reference: {{reservation.ref}}',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you made a reservation with {{host.businessName}}.',\n },\n {\n key: 'gift-card',\n name: 'Gift card delivery',\n description: 'Delivers a purchased gift card to its recipient.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your gift card for {{host.businessName}}',\n mergeTokens: [\n {\n name: 'giftcard.code',\n description: 'The gift card code',\n sample: 'GC-ABC123DEF456',\n },\n {\n name: 'giftcard.value',\n description: 'The gift card value',\n sample: '$25.00',\n },\n {\n name: 'giftcard.note',\n description:\n 'The note written when the card was issued by hand; empty for a ' +\n 'card bought at checkout',\n sample: 'Happy birthday, Sam!',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Your gift card', variant: 'heading' },\n {\n block: 'text',\n text: 'You have a {{giftcard.value}} gift card for {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{giftcard.note}}', variant: 'body' },\n {\n block: 'text',\n text: 'Gift card code: {{giftcard.code}}',\n variant: 'body',\n },\n {\n block: 'text',\n text: 'Enter the code at checkout on {{host.url}} to use its balance.',\n variant: 'body',\n },\n {\n block: 'button',\n label: 'Visit {{host.businessName}}',\n href: '{{host.url}}',\n },\n ],\n footerReason:\n 'You’re receiving this because a gift card from {{host.businessName}} was sent to this address.',\n },\n {\n key: 'supplier-fulfillment',\n name: 'Supplier fulfillment',\n description: 'Tells a dropship supplier there is a new order to fulfill.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'fixed',\n },\n {\n key: 'back-in-stock',\n name: 'Back in stock',\n description: 'Tells a customer a product they watched is available again.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Back in stock: {{product.name}}',\n mergeTokens: [\n {\n name: 'product.name',\n description: 'The product that restocked',\n sample: 'House Blend',\n },\n {\n name: 'product.url',\n description: 'Link to the product page',\n sample: 'https://shop.example.com/products/house-blend',\n },\n ],\n defaultBody: [\n {\n block: 'text',\n text: '{{product.name}} is back in stock at {{host.businessName}}.',\n variant: 'body',\n },\n { block: 'button', label: 'View product', href: '{{product.url}}' },\n ],\n footerReason:\n 'You’re receiving this because you asked {{host.businessName}} to tell you when this was back.',\n },\n {\n key: 'abandoned-cart',\n name: 'Abandoned cart',\n description: 'Reminds a shopper of items left in their cart.',\n // The cron refuses to send this without the entitlement\n // (`process-abandoned.ts:92`), so the console has to say so (AGL-2081).\n requiresFeature: 'abandonedCart',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'You left something in your cart',\n mergeTokens: [\n {\n name: 'cart.url',\n description: 'Link back to the shopper cart',\n sample: 'https://shop.example.com/cart',\n },\n ],\n defaultBody: [\n {\n block: 'text',\n text:\n 'You left items in your cart at {{host.businessName}}. Pick up ' +\n 'where you left off.',\n variant: 'body',\n },\n { block: 'button', label: 'Return to cart', href: '{{cart.url}}' },\n {\n block: 'text',\n text: 'Nothing in your cart is held for you.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because you started a checkout with {{host.businessName}}.',\n },\n {\n key: 'member-post',\n name: 'New member post',\n description: 'Notifies members when new members-only content is posted.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: '{{post.title}}',\n mergeTokens: [\n { name: 'post.title', description: 'The post’s title', sample: 'This month in the studio' },\n {\n name: 'post.body',\n description: 'The post, as its author wrote it',\n sample: 'Three new pieces are up for members first.',\n },\n ],\n defaultBody: [\n { block: 'text', text: '{{post.title}}', variant: 'heading' },\n { block: 'text', text: '{{post.body}}', variant: 'body' },\n ],\n footerReason: 'You’re receiving this because you’re a member of {{host.businessName}}.',\n },\n {\n key: 'member-password-reset',\n name: 'Member password reset',\n description:\n \"Resets a site member's password — a store-member account, separate \" +\n 'from a console login. Sent when the member asks, and when a site ' +\n 'administrator starts a reset for them.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Reset your {{site.name}} password',\n mergeTokens: [\n { name: 'site.name', description: 'The site’s name', sample: 'Northwind Coffee' },\n {\n name: 'reset.intro',\n description: 'Who started the reset',\n sample: 'Someone asked to reset the password for your Northwind Coffee account.',\n },\n {\n name: 'resetUrl',\n description: 'The one-time reset link',\n sample: 'https://shop.example.com/recover?token=…',\n },\n {\n name: 'reset.note',\n description: 'How long the link lasts, and what to do if unexpected',\n sample:\n 'The link works once and expires in 1 hour. If you did not ask for ' +\n 'this, you can safely ignore this email — your password is unchanged.',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Reset your password', variant: 'heading' },\n { block: 'text', text: '{{reset.intro}}', variant: 'body' },\n { block: 'button', label: 'Set a new password', href: '{{resetUrl}}' },\n { block: 'text', text: '{{reset.note}}', variant: 'caption' },\n ],\n footerReason:\n 'You’re receiving this because a password reset was started for your ' +\n '{{host.businessName}} account.',\n },\n {\n key: 'member-password-changed',\n name: 'Member password changed',\n description:\n 'Tells a site member that a site administrator set a new password on ' +\n 'their account.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your {{site.name}} password was changed',\n mergeTokens: [\n { name: 'site.name', description: 'The site’s name', sample: 'Northwind Coffee' },\n {\n name: 'signInUrl',\n description: 'Where the member signs back in',\n sample: 'https://shop.example.com',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Your password was changed', variant: 'heading' },\n {\n block: 'text',\n text:\n 'An administrator of {{site.name}} set a new password on your ' +\n 'account and signed you out on every device. To sign back in, ' +\n 'get the new password from them, or choose \"Forgot password?\" on ' +\n 'the sign-in page to set your own.',\n variant: 'body',\n },\n { block: 'button', label: 'Sign in', href: '{{signInUrl}}' },\n {\n block: 'text',\n text: 'If you did not expect this, contact the site owner.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because the password on your ' +\n '{{host.businessName}} account was changed.',\n },\n {\n key: 'newsletter-confirmation',\n name: 'Subscription confirmation',\n description:\n 'Asks someone who signed up for a site’s emails to confirm the address ' +\n 'before anything is sent to it.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Confirm your subscription',\n mergeTokens: [\n {\n name: 'stream.name',\n description: 'What they signed up for',\n sample: 'Newsletter',\n },\n {\n name: 'confirmUrl',\n description: 'The confirmation link',\n sample: 'https://shop.example.com/subscribe/confirm?token=…',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'Confirm your subscription', variant: 'heading' },\n {\n block: 'text',\n text:\n 'Please confirm that you want to get {{stream.name}} emails from ' +\n '{{host.businessName}} at this address.',\n variant: 'body',\n },\n { block: 'button', label: 'Confirm my subscription', href: '{{confirmUrl}}' },\n {\n block: 'text',\n text:\n 'The link works for three days. If you did not sign up, ignore this ' +\n 'message — nothing will be sent.',\n variant: 'caption',\n },\n ],\n footerReason:\n 'You’re receiving this because this address was entered on ' +\n '{{host.businessName}}’s signup form.',\n },\n ...returnTenantEmails(),\n ]\n}\n\n/** The items a return covers, one per line. */\nconst RETURN_ITEMS_TOKEN = {\n name: 'return.items',\n description: 'The items being returned, one per line, with the reason',\n sample: '1× House Blend — Arrived damaged',\n} as const\n\n/** The merchant's note on a return; empty when they left none. */\nconst RETURN_NOTE_TOKEN = {\n name: 'return.note',\n description: 'The store’s note to the buyer on this return; empty when none',\n sample: 'Please include the original packaging.',\n} as const\n\n/**\n * The return emails (AGL-3611): one to the store when a buyer asks, and one\n * to the buyer at each answer. Their own block, beside the order emails\n * rather than among them, because those belong to the order notifications.\n */\nfunction returnTenantEmails(): readonly TenantEmailEntry[] {\n return [\n {\n key: 'return-requested',\n name: 'Return requested',\n description:\n 'Tells the store a buyer asked to return items, with what and why, so ' +\n 'someone can approve or decline it.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Return requested for order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n {\n name: 'buyer.email',\n description: 'The buyer’s email',\n sample: 'buyer@example.com',\n },\n {\n name: 'return.customerNote',\n description: 'What the buyer wrote; empty when they wrote nothing',\n sample: 'The lid was cracked.',\n },\n ],\n defaultBody: [\n { block: 'text', text: 'A buyer asked for a return', variant: 'heading' },\n {\n block: 'text',\n text: '{{buyer.email}} wants to return items from order {{order.number}}.',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.customerNote}}', variant: 'body' },\n {\n block: 'text',\n text: 'Approve or decline it under Products → Returns.',\n variant: 'caption',\n },\n ],\n footerReason: 'You’re receiving this because you manage {{host.businessName}}.',\n },\n {\n key: 'return-approved',\n name: 'Return approved',\n description:\n 'Tells the buyer their return was approved and how to send the items ' +\n 'back, with the return label when the store attached one.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your return for order {{order.number}} is approved',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n RETURN_NOTE_TOKEN,\n {\n name: 'return.label',\n description:\n 'A sentence with the return label link and its tracking; empty ' +\n 'when the store attached no label',\n sample: 'Print your return label: https://labels.example.com/r/123',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your return is approved', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} approved the return of:',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.note}}', variant: 'body' },\n { block: 'text', text: '{{return.label}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'return-declined',\n name: 'Return declined',\n description: 'Tells the buyer their return was declined, with the store’s note.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'About your return for order {{order.number}}',\n mergeTokens: [ORDER_NUMBER_TOKEN, RETURN_ITEMS_TOKEN, RETURN_NOTE_TOKEN, ORDER_STATUS_URL_TOKEN],\n defaultBody: [\n { block: 'text', text: 'We could not accept this return', variant: 'heading' },\n {\n block: 'text',\n text: '{{host.businessName}} declined the return of:',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'text', text: '{{return.note}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n {\n key: 'return-refunded',\n name: 'Return refunded',\n description: 'Tells the buyer their return was received and refunded, and how much.',\n pluginId: 'commerce',\n plugin: 'Commerce',\n control: 'besigner',\n defaultSubject: 'Your refund for order {{order.number}}',\n mergeTokens: [\n ORDER_NUMBER_TOKEN,\n RETURN_ITEMS_TOKEN,\n {\n name: 'return.refundTotal',\n description: 'The amount refunded for this return',\n sample: '$24.00',\n },\n ORDER_STATUS_URL_TOKEN,\n ],\n defaultBody: [\n { block: 'text', text: 'Your return is refunded', variant: 'heading' },\n {\n block: 'text',\n text:\n '{{host.businessName}} received your return and refunded ' +\n '{{return.refundTotal}} to your original payment method.',\n variant: 'body',\n },\n { block: 'text', text: '{{return.items}}', variant: 'body' },\n { block: 'button', label: 'View your order', href: '{{order.statusUrl}}' },\n ],\n footerReason: ORDER_FOOTER_REASON,\n },\n ]\n}\n"],"names":["ORDER_NUMBER_TOKEN","name","description","sample","ORDER_STATUS_URL_TOKEN","PICKUP_LOCATION_TOKEN","ORDER_FOOTER_REASON","commerceTenantEmails","key","pluginId","plugin","control","defaultSubject","mergeTokens","defaultBody","block","text","variant","label","href","footerReason","requiresFeature","returnTenantEmails","RETURN_ITEMS_TOKEN","RETURN_NOTE_TOKEN"],"mappings":"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"}
@@ -24,7 +24,8 @@
24
24
  * interleave, which is what a race spec needs.
25
25
  *
26
26
  * Supports: `collection().doc()`, `get`, `set` (with `merge`), `create`,
27
- * `update`, `delete`; queries with `==` and `in`, `orderBy`, `limit`;
27
+ * `update`, `delete`; queries with `==`, `in` and `array-contains`, `orderBy`, `limit`,
28
+ * and a collection's `count()`;
28
29
  * `runTransaction` with `get` (document or query), `set`, `update`;
29
30
  * `batch()`. Field paths are top-level only.
30
31
  */
@@ -59,13 +60,18 @@ export declare class MemoryCollection {
59
60
  readonly path: string;
60
61
  constructor(store: MemoryFirestore, path: string);
61
62
  doc(id?: string): MemoryDoc;
62
- where(field: string, op: '==' | 'in', value: unknown): MemoryQuery;
63
+ where(field: string, op: MemoryFilterOp, value: unknown): MemoryQuery;
63
64
  orderBy(field: string, direction?: 'asc' | 'desc'): MemoryQuery;
64
65
  limit(count: number): MemoryQuery;
66
+ /** The aggregate: its result's `data().count`. */
67
+ count(): MemoryQuery;
65
68
  get(): Promise<{
66
69
  docs: MemoryDocSnapshot[];
67
70
  size: number;
68
71
  empty: boolean;
72
+ data: () => {
73
+ count: number;
74
+ };
69
75
  }>;
70
76
  }
71
77
  /** What a {@link MemoryDoc} read returns, shaped like a Firestore snapshot. */
@@ -96,6 +102,7 @@ export declare class MemoryDoc {
96
102
  update(data: Record<string, any>): Promise<void>;
97
103
  delete(): Promise<void>;
98
104
  }
105
+ export type MemoryFilterOp = '==' | 'in' | 'array-contains';
99
106
  export declare class MemoryQuery {
100
107
  readonly store: MemoryFirestore;
101
108
  readonly path: string;
@@ -104,13 +111,16 @@ export declare class MemoryQuery {
104
111
  private max;
105
112
  constructor(store: MemoryFirestore, path: string);
106
113
  private clone;
107
- where(field: string, op: '==' | 'in', value: unknown): MemoryQuery;
114
+ where(field: string, op: MemoryFilterOp, value: unknown): MemoryQuery;
108
115
  orderBy(field: string, direction?: 'asc' | 'desc'): MemoryQuery;
109
116
  limit(count: number): MemoryQuery;
110
117
  run(): {
111
118
  docs: MemoryDocSnapshot[];
112
119
  size: number;
113
120
  empty: boolean;
121
+ data: () => {
122
+ count: number;
123
+ };
114
124
  };
115
125
  /** The paths and versions this query matches now, to detect a changed result. */
116
126
  signature(): string;
@@ -118,6 +128,9 @@ export declare class MemoryQuery {
118
128
  docs: MemoryDocSnapshot[];
119
129
  size: number;
120
130
  empty: boolean;
131
+ data: () => {
132
+ count: number;
133
+ };
121
134
  }>;
122
135
  }
123
136
  export {};
@@ -23,7 +23,8 @@
23
23
  * interleave, which is what a race spec needs.
24
24
  *
25
25
  * Supports: `collection().doc()`, `get`, `set` (with `merge`), `create`,
26
- * `update`, `delete`; queries with `==` and `in`, `orderBy`, `limit`;
26
+ * `update`, `delete`; queries with `==`, `in` and `array-contains`, `orderBy`, `limit`,
27
+ * and a collection's `count()`;
27
28
  * `runTransaction` with `get` (document or query), `set`, `update`;
28
29
  * `batch()`. Field paths are top-level only.
29
30
  */ import { _ as _extends } from "@swc/helpers/_/_extends";
@@ -132,6 +133,9 @@ export class MemoryCollection {
132
133
  limit(count) {
133
134
  return new MemoryQuery(this.store, this.path).limit(count);
134
135
  }
136
+ /** The aggregate: its result's `data().count`. */ count() {
137
+ return new MemoryQuery(this.store, this.path);
138
+ }
135
139
  get() {
136
140
  return Promise.resolve(new MemoryQuery(this.store, this.path).run());
137
141
  }
@@ -241,7 +245,7 @@ export class MemoryQuery {
241
245
  const prefix = `${this.path}/`;
242
246
  let rows = [
243
247
  ...this.store.docs.entries()
244
- ].filter(([path])=>path.startsWith(prefix) && !path.slice(prefix.length).includes('/')).filter(([, stored])=>this.filters.every(({ field, op, value })=>op === 'in' ? value.includes(stored.data[field]) : stored.data[field] === value));
248
+ ].filter(([path])=>path.startsWith(prefix) && !path.slice(prefix.length).includes('/')).filter(([, stored])=>this.filters.every(({ field, op, value })=>op === 'in' ? value.includes(stored.data[field]) : op === 'array-contains' ? Array.isArray(stored.data[field]) && stored.data[field].includes(value) : stored.data[field] === value));
245
249
  if (this.order) {
246
250
  const { field, direction } = this.order;
247
251
  rows = rows.sort(([, a], [, b])=>{
@@ -250,10 +254,14 @@ export class MemoryQuery {
250
254
  });
251
255
  }
252
256
  const docs = rows.slice(0, this.max).map(([path])=>new MemoryDoc(this.store, path).snapshot());
257
+ // `data()` answers a `count()` aggregate read through the same query.
253
258
  return {
254
259
  docs,
255
260
  size: docs.length,
256
- empty: docs.length === 0
261
+ empty: docs.length === 0,
262
+ data: ()=>({
263
+ count: docs.length
264
+ })
257
265
  };
258
266
  }
259
267
  /** The paths and versions this query matches now, to detect a changed result. */ signature() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/testing/memory-firestore.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 * A small in-memory stand-in for the firebase-admin Firestore surface the\n * print queue uses (AGL-3619), for specs. Transactions are OPTIMISTIC, as\n * Firestore's server SDK effectively is under contention: every read records\n * the version it saw, the commit re-checks them (and re-runs any query read\n * in the transaction), and a conflict retries the whole function. Each read\n * yields to the event loop, so two transactions started together really do\n * interleave, which is what a race spec needs.\n *\n * Supports: `collection().doc()`, `get`, `set` (with `merge`), `create`,\n * `update`, `delete`; queries with `==` and `in`, `orderBy`, `limit`;\n * `runTransaction` with `get` (document or query), `set`, `update`;\n * `batch()`. Field paths are top-level only.\n */\n\ninterface Stored {\n data: Record<string, any>\n version: number\n}\n\nconst tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0))\n\nexport class MemoryFirestore {\n readonly docs = new Map<string, Stored>()\n private autoId = 0\n private clock = 0\n /** Committed transactions that had to retry, for specs that assert contention happened. */\n retries = 0\n\n collection(path: string): MemoryCollection {\n return new MemoryCollection(this, path)\n }\n\n /** The document at a slash path, for assertions. */\n read(path: string): Record<string, any> | undefined {\n const stored = this.docs.get(path)\n return stored ? { ...stored.data } : undefined\n }\n\n nextId(): string {\n this.autoId += 1\n return `auto${String(this.autoId).padStart(4, '0')}`\n }\n\n write(path: string, data: Record<string, any> | null): void {\n this.clock += 1\n if (data === null) this.docs.delete(path)\n else this.docs.set(path, { data: { ...data }, version: this.clock })\n }\n\n version(path: string): number {\n return this.docs.get(path)?.version ?? 0\n }\n\n batch() {\n const ops: Array<() => void> = []\n return {\n set: (ref: MemoryDoc, data: any, options?: { merge?: boolean }) =>\n ops.push(() => ref.applySet(data, options)),\n update: (ref: MemoryDoc, data: any) => ops.push(() => ref.applyUpdate(data)),\n delete: (ref: MemoryDoc) => ops.push(() => this.write(ref.path, null)),\n commit: async () => {\n await tick()\n for (const op of ops) op()\n },\n }\n }\n\n async runTransaction<T>(fn: (transaction: any) => Promise<T>): Promise<T> {\n for (let attempt = 0; attempt < 10; attempt += 1) {\n const seen = new Map<string, number>()\n const queries: Array<{ query: MemoryQuery; snapshot: string }> = []\n const writes: Array<() => void> = []\n const transaction = {\n get: async (target: MemoryDoc | MemoryQuery) => {\n await tick()\n if (target instanceof MemoryDoc) {\n seen.set(target.path, this.version(target.path))\n return target.snapshot()\n }\n const result = target.run()\n queries.push({ query: target, snapshot: target.signature() })\n for (const doc of result.docs) seen.set(doc.ref.path, this.version(doc.ref.path))\n return result\n },\n set: (ref: MemoryDoc, data: any, options?: { merge?: boolean }) => {\n writes.push(() => ref.applySet(data, options))\n return transaction\n },\n update: (ref: MemoryDoc, data: any) => {\n writes.push(() => ref.applyUpdate(data))\n return transaction\n },\n create: (ref: MemoryDoc, data: any) => {\n writes.push(() => ref.applyCreate(data))\n return transaction\n },\n }\n const result = await fn(transaction)\n await tick()\n const conflicted =\n [...seen].some(([path, version]) => this.version(path) !== version) ||\n queries.some(({ query, snapshot }) => query.signature() !== snapshot)\n if (conflicted) {\n this.retries += 1\n continue\n }\n for (const write of writes) write()\n return result\n }\n throw new Error('transaction contention: too many retries')\n }\n}\n\nexport class MemoryCollection {\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n doc(id?: string): MemoryDoc {\n return new MemoryDoc(this.store, `${this.path}/${id ?? this.store.nextId()}`)\n }\n\n where(field: string, op: '==' | 'in', value: unknown): MemoryQuery {\n return new MemoryQuery(this.store, this.path).where(field, op, value)\n }\n\n orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): MemoryQuery {\n return new MemoryQuery(this.store, this.path).orderBy(field, direction)\n }\n\n limit(count: number): MemoryQuery {\n return new MemoryQuery(this.store, this.path).limit(count)\n }\n\n get() {\n return Promise.resolve(new MemoryQuery(this.store, this.path).run())\n }\n}\n\n/** What a {@link MemoryDoc} read returns, shaped like a Firestore snapshot. */\nexport interface MemoryDocSnapshot {\n id: string\n ref: MemoryDoc\n exists: boolean\n data: () => Record<string, any> | undefined\n get: (field: string) => unknown\n}\n\nexport class MemoryDoc {\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n get id(): string {\n return this.path.split('/').pop() ?? ''\n }\n\n collection(name: string): MemoryCollection {\n return new MemoryCollection(this.store, `${this.path}/${name}`)\n }\n\n snapshot(): MemoryDocSnapshot {\n const stored = this.store.docs.get(this.path)\n const data = stored ? { ...stored.data } : undefined\n return {\n id: this.id,\n ref: this,\n exists: Boolean(stored),\n data: () => (data ? { ...data } : undefined),\n get: (field: string) => data?.[field],\n }\n }\n\n async get(): Promise<MemoryDocSnapshot> {\n await tick()\n return this.snapshot()\n }\n\n applySet(data: Record<string, any>, options?: { merge?: boolean }): void {\n const previous = this.store.docs.get(this.path)?.data\n this.store.write(this.path, options?.merge && previous ? { ...previous, ...data } : data)\n }\n\n applyUpdate(data: Record<string, any>): void {\n const previous = this.store.docs.get(this.path)?.data\n if (!previous) throw Object.assign(new Error('NOT_FOUND'), { code: 5 })\n this.store.write(this.path, { ...previous, ...data })\n }\n\n applyCreate(data: Record<string, any>): void {\n if (this.store.docs.has(this.path)) {\n throw Object.assign(new Error('Document already exists'), { code: 6 })\n }\n this.store.write(this.path, data)\n }\n\n async set(data: Record<string, any>, options?: { merge?: boolean }): Promise<void> {\n await tick()\n this.applySet(data, options)\n }\n\n async create(data: Record<string, any>): Promise<void> {\n await tick()\n this.applyCreate(data)\n }\n\n async update(data: Record<string, any>): Promise<void> {\n await tick()\n this.applyUpdate(data)\n }\n\n async delete(): Promise<void> {\n await tick()\n this.store.write(this.path, null)\n }\n}\n\nexport class MemoryQuery {\n private filters: Array<{ field: string; op: '==' | 'in'; value: unknown }> = []\n private order: { field: string; direction: 'asc' | 'desc' } | null = null\n private max = Infinity\n\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n private clone(): MemoryQuery {\n const next = new MemoryQuery(this.store, this.path)\n next.filters = [...this.filters]\n next.order = this.order\n next.max = this.max\n return next\n }\n\n where(field: string, op: '==' | 'in', value: unknown): MemoryQuery {\n const next = this.clone()\n next.filters.push({ field, op, value })\n return next\n }\n\n orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): MemoryQuery {\n const next = this.clone()\n next.order = { field, direction }\n return next\n }\n\n limit(count: number): MemoryQuery {\n const next = this.clone()\n next.max = count\n return next\n }\n\n run() {\n const prefix = `${this.path}/`\n let rows = [...this.store.docs.entries()]\n .filter(([path]) => path.startsWith(prefix) && !path.slice(prefix.length).includes('/'))\n .filter(([, stored]) =>\n this.filters.every(({ field, op, value }) =>\n op === 'in'\n ? (value as unknown[]).includes(stored.data[field])\n : stored.data[field] === value,\n ),\n )\n if (this.order) {\n const { field, direction } = this.order\n rows = rows.sort(([, a], [, b]) => {\n const delta = a.data[field] < b.data[field] ? -1 : a.data[field] > b.data[field] ? 1 : 0\n return direction === 'asc' ? delta : -delta\n })\n }\n const docs = rows\n .slice(0, this.max)\n .map(([path]) => new MemoryDoc(this.store, path).snapshot())\n return { docs, size: docs.length, empty: docs.length === 0 }\n }\n\n /** The paths and versions this query matches now, to detect a changed result. */\n signature(): string {\n return this.run()\n .docs.map((doc) => `${doc.ref.path}@${this.store.version(doc.ref.path)}`)\n .join('|')\n }\n\n get() {\n return tick().then(() => this.run())\n }\n}\n"],"names":["tick","Promise","resolve","setTimeout","MemoryFirestore","collection","path","MemoryCollection","read","stored","docs","get","data","undefined","nextId","autoId","String","padStart","write","clock","delete","set","version","batch","ops","ref","options","push","applySet","update","applyUpdate","commit","op","runTransaction","fn","attempt","seen","Map","queries","writes","transaction","target","MemoryDoc","snapshot","result","run","query","signature","doc","create","applyCreate","conflicted","some","retries","Error","id","store","where","field","value","MemoryQuery","orderBy","direction","limit","count","split","pop","name","exists","Boolean","previous","merge","Object","assign","code","has","clone","next","filters","order","max","prefix","rows","entries","filter","startsWith","slice","length","includes","every","sort","a","b","delta","map","size","empty","join","then","Infinity"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/testing/memory-firestore.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 * A small in-memory stand-in for the firebase-admin Firestore surface the\n * print queue uses (AGL-3619), for specs. Transactions are OPTIMISTIC, as\n * Firestore's server SDK effectively is under contention: every read records\n * the version it saw, the commit re-checks them (and re-runs any query read\n * in the transaction), and a conflict retries the whole function. Each read\n * yields to the event loop, so two transactions started together really do\n * interleave, which is what a race spec needs.\n *\n * Supports: `collection().doc()`, `get`, `set` (with `merge`), `create`,\n * `update`, `delete`; queries with `==`, `in` and `array-contains`, `orderBy`, `limit`,\n * and a collection's `count()`;\n * `runTransaction` with `get` (document or query), `set`, `update`;\n * `batch()`. Field paths are top-level only.\n */\n\ninterface Stored {\n data: Record<string, any>\n version: number\n}\n\nconst tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0))\n\nexport class MemoryFirestore {\n readonly docs = new Map<string, Stored>()\n private autoId = 0\n private clock = 0\n /** Committed transactions that had to retry, for specs that assert contention happened. */\n retries = 0\n\n collection(path: string): MemoryCollection {\n return new MemoryCollection(this, path)\n }\n\n /** The document at a slash path, for assertions. */\n read(path: string): Record<string, any> | undefined {\n const stored = this.docs.get(path)\n return stored ? { ...stored.data } : undefined\n }\n\n nextId(): string {\n this.autoId += 1\n return `auto${String(this.autoId).padStart(4, '0')}`\n }\n\n write(path: string, data: Record<string, any> | null): void {\n this.clock += 1\n if (data === null) this.docs.delete(path)\n else this.docs.set(path, { data: { ...data }, version: this.clock })\n }\n\n version(path: string): number {\n return this.docs.get(path)?.version ?? 0\n }\n\n batch() {\n const ops: Array<() => void> = []\n return {\n set: (ref: MemoryDoc, data: any, options?: { merge?: boolean }) =>\n ops.push(() => ref.applySet(data, options)),\n update: (ref: MemoryDoc, data: any) => ops.push(() => ref.applyUpdate(data)),\n delete: (ref: MemoryDoc) => ops.push(() => this.write(ref.path, null)),\n commit: async () => {\n await tick()\n for (const op of ops) op()\n },\n }\n }\n\n async runTransaction<T>(fn: (transaction: any) => Promise<T>): Promise<T> {\n for (let attempt = 0; attempt < 10; attempt += 1) {\n const seen = new Map<string, number>()\n const queries: Array<{ query: MemoryQuery; snapshot: string }> = []\n const writes: Array<() => void> = []\n const transaction = {\n get: async (target: MemoryDoc | MemoryQuery) => {\n await tick()\n if (target instanceof MemoryDoc) {\n seen.set(target.path, this.version(target.path))\n return target.snapshot()\n }\n const result = target.run()\n queries.push({ query: target, snapshot: target.signature() })\n for (const doc of result.docs) seen.set(doc.ref.path, this.version(doc.ref.path))\n return result\n },\n set: (ref: MemoryDoc, data: any, options?: { merge?: boolean }) => {\n writes.push(() => ref.applySet(data, options))\n return transaction\n },\n update: (ref: MemoryDoc, data: any) => {\n writes.push(() => ref.applyUpdate(data))\n return transaction\n },\n create: (ref: MemoryDoc, data: any) => {\n writes.push(() => ref.applyCreate(data))\n return transaction\n },\n }\n const result = await fn(transaction)\n await tick()\n const conflicted =\n [...seen].some(([path, version]) => this.version(path) !== version) ||\n queries.some(({ query, snapshot }) => query.signature() !== snapshot)\n if (conflicted) {\n this.retries += 1\n continue\n }\n for (const write of writes) write()\n return result\n }\n throw new Error('transaction contention: too many retries')\n }\n}\n\nexport class MemoryCollection {\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n doc(id?: string): MemoryDoc {\n return new MemoryDoc(this.store, `${this.path}/${id ?? this.store.nextId()}`)\n }\n\n where(field: string, op: MemoryFilterOp, value: unknown): MemoryQuery {\n return new MemoryQuery(this.store, this.path).where(field, op, value)\n }\n\n orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): MemoryQuery {\n return new MemoryQuery(this.store, this.path).orderBy(field, direction)\n }\n\n limit(count: number): MemoryQuery {\n return new MemoryQuery(this.store, this.path).limit(count)\n }\n\n /** The aggregate: its result's `data().count`. */\n count(): MemoryQuery {\n return new MemoryQuery(this.store, this.path)\n }\n\n get() {\n return Promise.resolve(new MemoryQuery(this.store, this.path).run())\n }\n}\n\n/** What a {@link MemoryDoc} read returns, shaped like a Firestore snapshot. */\nexport interface MemoryDocSnapshot {\n id: string\n ref: MemoryDoc\n exists: boolean\n data: () => Record<string, any> | undefined\n get: (field: string) => unknown\n}\n\nexport class MemoryDoc {\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n get id(): string {\n return this.path.split('/').pop() ?? ''\n }\n\n collection(name: string): MemoryCollection {\n return new MemoryCollection(this.store, `${this.path}/${name}`)\n }\n\n snapshot(): MemoryDocSnapshot {\n const stored = this.store.docs.get(this.path)\n const data = stored ? { ...stored.data } : undefined\n return {\n id: this.id,\n ref: this,\n exists: Boolean(stored),\n data: () => (data ? { ...data } : undefined),\n get: (field: string) => data?.[field],\n }\n }\n\n async get(): Promise<MemoryDocSnapshot> {\n await tick()\n return this.snapshot()\n }\n\n applySet(data: Record<string, any>, options?: { merge?: boolean }): void {\n const previous = this.store.docs.get(this.path)?.data\n this.store.write(this.path, options?.merge && previous ? { ...previous, ...data } : data)\n }\n\n applyUpdate(data: Record<string, any>): void {\n const previous = this.store.docs.get(this.path)?.data\n if (!previous) throw Object.assign(new Error('NOT_FOUND'), { code: 5 })\n this.store.write(this.path, { ...previous, ...data })\n }\n\n applyCreate(data: Record<string, any>): void {\n if (this.store.docs.has(this.path)) {\n throw Object.assign(new Error('Document already exists'), { code: 6 })\n }\n this.store.write(this.path, data)\n }\n\n async set(data: Record<string, any>, options?: { merge?: boolean }): Promise<void> {\n await tick()\n this.applySet(data, options)\n }\n\n async create(data: Record<string, any>): Promise<void> {\n await tick()\n this.applyCreate(data)\n }\n\n async update(data: Record<string, any>): Promise<void> {\n await tick()\n this.applyUpdate(data)\n }\n\n async delete(): Promise<void> {\n await tick()\n this.store.write(this.path, null)\n }\n}\n\nexport type MemoryFilterOp = '==' | 'in' | 'array-contains'\n\nexport class MemoryQuery {\n private filters: Array<{ field: string; op: MemoryFilterOp; value: unknown }> = []\n private order: { field: string; direction: 'asc' | 'desc' } | null = null\n private max = Infinity\n\n constructor(\n readonly store: MemoryFirestore,\n readonly path: string,\n ) {}\n\n private clone(): MemoryQuery {\n const next = new MemoryQuery(this.store, this.path)\n next.filters = [...this.filters]\n next.order = this.order\n next.max = this.max\n return next\n }\n\n where(field: string, op: MemoryFilterOp, value: unknown): MemoryQuery {\n const next = this.clone()\n next.filters.push({ field, op, value })\n return next\n }\n\n orderBy(field: string, direction: 'asc' | 'desc' = 'asc'): MemoryQuery {\n const next = this.clone()\n next.order = { field, direction }\n return next\n }\n\n limit(count: number): MemoryQuery {\n const next = this.clone()\n next.max = count\n return next\n }\n\n run() {\n const prefix = `${this.path}/`\n let rows = [...this.store.docs.entries()]\n .filter(([path]) => path.startsWith(prefix) && !path.slice(prefix.length).includes('/'))\n .filter(([, stored]) =>\n this.filters.every(({ field, op, value }) =>\n op === 'in'\n ? (value as unknown[]).includes(stored.data[field])\n : op === 'array-contains'\n ? Array.isArray(stored.data[field]) && stored.data[field].includes(value)\n : stored.data[field] === value,\n ),\n )\n if (this.order) {\n const { field, direction } = this.order\n rows = rows.sort(([, a], [, b]) => {\n const delta = a.data[field] < b.data[field] ? -1 : a.data[field] > b.data[field] ? 1 : 0\n return direction === 'asc' ? delta : -delta\n })\n }\n const docs = rows\n .slice(0, this.max)\n .map(([path]) => new MemoryDoc(this.store, path).snapshot())\n // `data()` answers a `count()` aggregate read through the same query.\n return { docs, size: docs.length, empty: docs.length === 0, data: () => ({ count: docs.length }) }\n }\n\n /** The paths and versions this query matches now, to detect a changed result. */\n signature(): string {\n return this.run()\n .docs.map((doc) => `${doc.ref.path}@${this.store.version(doc.ref.path)}`)\n .join('|')\n }\n\n get() {\n return tick().then(() => this.run())\n }\n}\n"],"names":["tick","Promise","resolve","setTimeout","MemoryFirestore","collection","path","MemoryCollection","read","stored","docs","get","data","undefined","nextId","autoId","String","padStart","write","clock","delete","set","version","batch","ops","ref","options","push","applySet","update","applyUpdate","commit","op","runTransaction","fn","attempt","seen","Map","queries","writes","transaction","target","MemoryDoc","snapshot","result","run","query","signature","doc","create","applyCreate","conflicted","some","retries","Error","id","store","where","field","value","MemoryQuery","orderBy","direction","limit","count","split","pop","name","exists","Boolean","previous","merge","Object","assign","code","has","clone","next","filters","order","max","prefix","rows","entries","filter","startsWith","slice","length","includes","every","Array","isArray","sort","a","b","delta","map","size","empty","join","then","Infinity"],"mappings":"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"}
@@ -17,8 +17,13 @@
17
17
  import { type BuildTransferPlanInput, type MatchLookupRequest, type TransferChunk, type TransferPlan, type TransferUndoSnapshot } from '@aglyn/aglyn/data-transfer';
18
18
  import type { PicklistValue } from '@aglyn/aglyn/app-utils/picklists';
19
19
  import type { TransferApplyResult, TransferApplyWriter, TransferLookupResult, TransferPicklistList, TransferReadOptions, TransferReadPage, TransferResourceContext, TransferRevertDecisions, TransferRevertResult } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources';
20
+ import { type HostProduct, type SmartCollectionRules } from '../model/commerce';
20
21
  import { type ProductPlannedRow } from './product-transfer';
21
22
  import { type Firestore } from './server-common';
23
+ /** The smart collections a product's write answers (AGL-3321). */
24
+ export declare function readSmartCollections(firestore: Firestore, ctx: TransferResourceContext): Promise<SmartCollectionRules[]>;
25
+ /** The keys every product write derives, from the product as it will stand. */
26
+ export declare function derivedKeys(product: HostProduct, smart: readonly SmartCollectionRules[]): Record<string, unknown>;
22
27
  /** The rows of one page of products. A product is as many rows as it has variants (or images). */
23
28
  export declare function readProductsPage(ctx: TransferResourceContext, cursor: string | null, fieldIds: readonly string[], options?: TransferReadOptions, firestore?: Firestore): Promise<TransferReadPage>;
24
29
  /** How many rows the export writes: every live product's variant (or image) rows. */
@@ -66,7 +66,7 @@ const isLive = (data)=>Boolean(data) && ((data == null ? void 0 : data['deletedA
66
66
  return ids;
67
67
  };
68
68
  }
69
- /** The smart collections a product's write answers (AGL-3321). */ async function readSmartCollections(firestore, ctx) {
69
+ /** The smart collections a product's write answers (AGL-3321). */ export async function readSmartCollections(firestore, ctx) {
70
70
  const snapshot = await hostRefOf(firestore, ctx).collection('collections').where('kind', '==', 'catalog').where('mode', '==', 'smart').get();
71
71
  return snapshot.docs.map((doc)=>{
72
72
  var _doc_get;
@@ -77,7 +77,7 @@ const isLive = (data)=>Boolean(data) && ((data == null ? void 0 : data['deletedA
77
77
  };
78
78
  });
79
79
  }
80
- /** The keys every product write derives, from the product as it will stand. */ function derivedKeys(product, smart) {
80
+ /** The keys every product write derives, from the product as it will stand. */ export function derivedKeys(product, smart) {
81
81
  var _ref, _ref1;
82
82
  var _product_variants_, _product_mediaUrls;
83
83
  return _extends({}, productSearchFields(product), productStockFields(product), {