@aglyn/plugins-commerce 1.0.0-beta.143

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 (417) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +10 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +38 -0
  5. package/src/index.js +38 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/account.d.ts +31 -0
  8. package/src/lib/components/account.js +645 -0
  9. package/src/lib/components/account.js.map +1 -0
  10. package/src/lib/components/cart.d.ts +38 -0
  11. package/src/lib/components/cart.js +851 -0
  12. package/src/lib/components/cart.js.map +1 -0
  13. package/src/lib/components/commerce-console-page.d.ts +32 -0
  14. package/src/lib/components/commerce-console-page.js +296 -0
  15. package/src/lib/components/commerce-console-page.js.map +1 -0
  16. package/src/lib/components/commerce-console-sections.d.ts +34 -0
  17. package/src/lib/components/commerce-console-sections.js +62 -0
  18. package/src/lib/components/commerce-console-sections.js.map +1 -0
  19. package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
  20. package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
  21. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
  22. package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
  23. package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
  24. package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
  25. package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
  26. package/src/lib/components/console/commerce-glance-card.component.js +340 -0
  27. package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
  28. package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
  29. package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
  30. package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
  31. package/src/lib/components/console/discounts-card.component.d.ts +14 -0
  32. package/src/lib/components/console/discounts-card.component.js +443 -0
  33. package/src/lib/components/console/discounts-card.component.js.map +1 -0
  34. package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
  35. package/src/lib/components/console/entitlement-gate.component.js +115 -0
  36. package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
  37. package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
  38. package/src/lib/components/console/gift-cards-card.component.js +379 -0
  39. package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
  40. package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
  41. package/src/lib/components/console/host-coupons-card.component.js +252 -0
  42. package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
  43. package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
  44. package/src/lib/components/console/host-orders-card.component.js +861 -0
  45. package/src/lib/components/console/host-orders-card.component.js.map +1 -0
  46. package/src/lib/components/console/locations-card.component.d.ts +14 -0
  47. package/src/lib/components/console/locations-card.component.js +256 -0
  48. package/src/lib/components/console/locations-card.component.js.map +1 -0
  49. package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
  50. package/src/lib/components/console/member-posts-card.component.js +283 -0
  51. package/src/lib/components/console/member-posts-card.component.js.map +1 -0
  52. package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
  53. package/src/lib/components/console/newest-site-users-card.component.js +126 -0
  54. package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
  55. package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
  56. package/src/lib/components/console/order-detail-dialog.component.js +976 -0
  57. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
  58. package/src/lib/components/console/paid-media.d.ts +127 -0
  59. package/src/lib/components/console/paid-media.js +397 -0
  60. package/src/lib/components/console/paid-media.js.map +1 -0
  61. package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
  62. package/src/lib/components/console/payments-settings-card.component.js +295 -0
  63. package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
  64. package/src/lib/components/console/pos-page.component.d.ts +13 -0
  65. package/src/lib/components/console/pos-page.component.js +916 -0
  66. package/src/lib/components/console/pos-page.component.js.map +1 -0
  67. package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
  68. package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
  69. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
  70. package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
  71. package/src/lib/components/console/products-hub-card.component.js +1280 -0
  72. package/src/lib/components/console/products-hub-card.component.js.map +1 -0
  73. package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
  74. package/src/lib/components/console/products-hub-zone.component.js +200 -0
  75. package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
  76. package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
  77. package/src/lib/components/console/recovery-queue-card.component.js +262 -0
  78. package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
  79. package/src/lib/components/console/registers-card.component.d.ts +21 -0
  80. package/src/lib/components/console/registers-card.component.js +296 -0
  81. package/src/lib/components/console/registers-card.component.js.map +1 -0
  82. package/src/lib/components/console/reservations-card.component.d.ts +14 -0
  83. package/src/lib/components/console/reservations-card.component.js +650 -0
  84. package/src/lib/components/console/reservations-card.component.js.map +1 -0
  85. package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
  86. package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
  87. package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
  88. package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
  89. package/src/lib/components/console/shipping-settings-card.component.js +560 -0
  90. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
  91. package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
  92. package/src/lib/components/console/stock-movements-card.component.js +333 -0
  93. package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
  94. package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
  95. package/src/lib/components/console/store-settings-card.component.js +300 -0
  96. package/src/lib/components/console/store-settings-card.component.js.map +1 -0
  97. package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
  98. package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
  99. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
  100. package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
  101. package/src/lib/components/console/suppliers-card.component.js +328 -0
  102. package/src/lib/components/console/suppliers-card.component.js.map +1 -0
  103. package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
  104. package/src/lib/components/console/tax-settings-card.component.js +473 -0
  105. package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
  106. package/src/lib/components/gate.d.ts +39 -0
  107. package/src/lib/components/gate.js +202 -0
  108. package/src/lib/components/gate.js.map +1 -0
  109. package/src/lib/components/gated-video.d.ts +40 -0
  110. package/src/lib/components/gated-video.js +366 -0
  111. package/src/lib/components/gated-video.js.map +1 -0
  112. package/src/lib/components/member-feed.d.ts +32 -0
  113. package/src/lib/components/member-feed.js +198 -0
  114. package/src/lib/components/member-feed.js.map +1 -0
  115. package/src/lib/components/member-recovery.d.ts +35 -0
  116. package/src/lib/components/member-recovery.js +313 -0
  117. package/src/lib/components/member-recovery.js.map +1 -0
  118. package/src/lib/components/member-signin.d.ts +35 -0
  119. package/src/lib/components/member-signin.js +257 -0
  120. package/src/lib/components/member-signin.js.map +1 -0
  121. package/src/lib/components/member-signup.d.ts +34 -0
  122. package/src/lib/components/member-signup.js +287 -0
  123. package/src/lib/components/member-signup.js.map +1 -0
  124. package/src/lib/components/newsletter-signup.d.ts +39 -0
  125. package/src/lib/components/newsletter-signup.js +229 -0
  126. package/src/lib/components/newsletter-signup.js.map +1 -0
  127. package/src/lib/components/product-detail.d.ts +38 -0
  128. package/src/lib/components/product-detail.js +1022 -0
  129. package/src/lib/components/product-detail.js.map +1 -0
  130. package/src/lib/components/product-grid.d.ts +67 -0
  131. package/src/lib/components/product-grid.js +909 -0
  132. package/src/lib/components/product-grid.js.map +1 -0
  133. package/src/lib/components/product-reviews.d.ts +32 -0
  134. package/src/lib/components/product-reviews.js +349 -0
  135. package/src/lib/components/product-reviews.js.map +1 -0
  136. package/src/lib/components/related-products.d.ts +33 -0
  137. package/src/lib/components/related-products.js +232 -0
  138. package/src/lib/components/related-products.js.map +1 -0
  139. package/src/lib/components/reservation-widget.d.ts +33 -0
  140. package/src/lib/components/reservation-widget.js +418 -0
  141. package/src/lib/components/reservation-widget.js.map +1 -0
  142. package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
  143. package/src/lib/components/storefront-payment-element-fallback.js +51 -0
  144. package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
  145. package/src/lib/components/storefront-payment-element.d.ts +78 -0
  146. package/src/lib/components/storefront-payment-element.js +156 -0
  147. package/src/lib/components/storefront-payment-element.js.map +1 -0
  148. package/src/lib/components/wishlist.d.ts +46 -0
  149. package/src/lib/components/wishlist.js +304 -0
  150. package/src/lib/components/wishlist.js.map +1 -0
  151. package/src/lib/constants/bundle-common.d.ts +18 -0
  152. package/src/lib/constants/bundle-common.js +18 -0
  153. package/src/lib/constants/bundle-common.js.map +1 -0
  154. package/src/lib/constants/product-filters.d.ts +35 -0
  155. package/src/lib/constants/product-filters.js +109 -0
  156. package/src/lib/constants/product-filters.js.map +1 -0
  157. package/src/lib/model/commerce-cart.d.ts +52 -0
  158. package/src/lib/model/commerce-cart.js +102 -0
  159. package/src/lib/model/commerce-cart.js.map +1 -0
  160. package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
  161. package/src/lib/model/commerce-connect-transfer.js +231 -0
  162. package/src/lib/model/commerce-connect-transfer.js.map +1 -0
  163. package/src/lib/model/commerce-discounts.d.ts +164 -0
  164. package/src/lib/model/commerce-discounts.js +231 -0
  165. package/src/lib/model/commerce-discounts.js.map +1 -0
  166. package/src/lib/model/commerce-dispute.d.ts +124 -0
  167. package/src/lib/model/commerce-dispute.js +225 -0
  168. package/src/lib/model/commerce-dispute.js.map +1 -0
  169. package/src/lib/model/commerce-gift-cards.d.ts +107 -0
  170. package/src/lib/model/commerce-gift-cards.js +121 -0
  171. package/src/lib/model/commerce-gift-cards.js.map +1 -0
  172. package/src/lib/model/commerce-io.d.ts +36 -0
  173. package/src/lib/model/commerce-io.js +245 -0
  174. package/src/lib/model/commerce-io.js.map +1 -0
  175. package/src/lib/model/commerce-orders.d.ts +1040 -0
  176. package/src/lib/model/commerce-orders.js +1022 -0
  177. package/src/lib/model/commerce-orders.js.map +1 -0
  178. package/src/lib/model/commerce-promotions.d.ts +188 -0
  179. package/src/lib/model/commerce-promotions.js +199 -0
  180. package/src/lib/model/commerce-promotions.js.map +1 -0
  181. package/src/lib/model/commerce-reservations.d.ts +175 -0
  182. package/src/lib/model/commerce-reservations.js +157 -0
  183. package/src/lib/model/commerce-reservations.js.map +1 -0
  184. package/src/lib/model/commerce-shipping.d.ts +316 -0
  185. package/src/lib/model/commerce-shipping.js +484 -0
  186. package/src/lib/model/commerce-shipping.js.map +1 -0
  187. package/src/lib/model/commerce-stock-holds.d.ts +199 -0
  188. package/src/lib/model/commerce-stock-holds.js +190 -0
  189. package/src/lib/model/commerce-stock-holds.js.map +1 -0
  190. package/src/lib/model/commerce-subscription-status.d.ts +67 -0
  191. package/src/lib/model/commerce-subscription-status.js +76 -0
  192. package/src/lib/model/commerce-subscription-status.js.map +1 -0
  193. package/src/lib/model/commerce-tax-decision.d.ts +222 -0
  194. package/src/lib/model/commerce-tax-decision.js +165 -0
  195. package/src/lib/model/commerce-tax-decision.js.map +1 -0
  196. package/src/lib/model/commerce-tax.d.ts +176 -0
  197. package/src/lib/model/commerce-tax.js +92 -0
  198. package/src/lib/model/commerce-tax.js.map +1 -0
  199. package/src/lib/model/commerce.d.ts +551 -0
  200. package/src/lib/model/commerce.js +739 -0
  201. package/src/lib/model/commerce.js.map +1 -0
  202. package/src/lib/model/index.d.ts +40 -0
  203. package/src/lib/model/index.js +40 -0
  204. package/src/lib/model/index.js.map +1 -0
  205. package/src/lib/model/order-figures.d.ts +48 -0
  206. package/src/lib/model/order-figures.js +74 -0
  207. package/src/lib/model/order-figures.js.map +1 -0
  208. package/src/lib/model/plugin-permissions.d.ts +23 -0
  209. package/src/lib/model/plugin-permissions.js +34 -0
  210. package/src/lib/model/plugin-permissions.js.map +1 -0
  211. package/src/lib/model/purchase-analytics.d.ts +186 -0
  212. package/src/lib/model/purchase-analytics.js +216 -0
  213. package/src/lib/model/purchase-analytics.js.map +1 -0
  214. package/src/lib/plugin-config.d.ts +62 -0
  215. package/src/lib/plugin-config.js +78 -0
  216. package/src/lib/plugin-config.js.map +1 -0
  217. package/src/lib/plugin.d.ts +28 -0
  218. package/src/lib/plugin.js +147 -0
  219. package/src/lib/plugin.js.map +1 -0
  220. package/src/lib/server/billing-webhook.d.ts +26 -0
  221. package/src/lib/server/billing-webhook.js +4011 -0
  222. package/src/lib/server/billing-webhook.js.map +1 -0
  223. package/src/lib/server/cancel-order.d.ts +87 -0
  224. package/src/lib/server/cancel-order.js +368 -0
  225. package/src/lib/server/cancel-order.js.map +1 -0
  226. package/src/lib/server/cart-checkout.d.ts +25 -0
  227. package/src/lib/server/cart-checkout.js +976 -0
  228. package/src/lib/server/cart-checkout.js.map +1 -0
  229. package/src/lib/server/cart-cookie.d.ts +32 -0
  230. package/src/lib/server/cart-cookie.js +77 -0
  231. package/src/lib/server/cart-cookie.js.map +1 -0
  232. package/src/lib/server/cart.d.ts +34 -0
  233. package/src/lib/server/cart.js +181 -0
  234. package/src/lib/server/cart.js.map +1 -0
  235. package/src/lib/server/catalog.d.ts +127 -0
  236. package/src/lib/server/catalog.js +277 -0
  237. package/src/lib/server/catalog.js.map +1 -0
  238. package/src/lib/server/checkout.d.ts +36 -0
  239. package/src/lib/server/checkout.js +915 -0
  240. package/src/lib/server/checkout.js.map +1 -0
  241. package/src/lib/server/connect.d.ts +26 -0
  242. package/src/lib/server/connect.js +238 -0
  243. package/src/lib/server/connect.js.map +1 -0
  244. package/src/lib/server/contact-refund.d.ts +117 -0
  245. package/src/lib/server/contact-refund.js +196 -0
  246. package/src/lib/server/contact-refund.js.map +1 -0
  247. package/src/lib/server/download.d.ts +39 -0
  248. package/src/lib/server/download.js +206 -0
  249. package/src/lib/server/download.js.map +1 -0
  250. package/src/lib/server/draft-order.d.ts +26 -0
  251. package/src/lib/server/draft-order.js +706 -0
  252. package/src/lib/server/draft-order.js.map +1 -0
  253. package/src/lib/server/feed.d.ts +24 -0
  254. package/src/lib/server/feed.js +59 -0
  255. package/src/lib/server/feed.js.map +1 -0
  256. package/src/lib/server/fulfill-order.d.ts +97 -0
  257. package/src/lib/server/fulfill-order.js +235 -0
  258. package/src/lib/server/fulfill-order.js.map +1 -0
  259. package/src/lib/server/gate.d.ts +36 -0
  260. package/src/lib/server/gate.js +112 -0
  261. package/src/lib/server/gate.js.map +1 -0
  262. package/src/lib/server/gift-cards.d.ts +42 -0
  263. package/src/lib/server/gift-cards.js +219 -0
  264. package/src/lib/server/gift-cards.js.map +1 -0
  265. package/src/lib/server/low-stock.d.ts +49 -0
  266. package/src/lib/server/low-stock.js +60 -0
  267. package/src/lib/server/low-stock.js.map +1 -0
  268. package/src/lib/server/manual-tax-rate.d.ts +82 -0
  269. package/src/lib/server/manual-tax-rate.js +113 -0
  270. package/src/lib/server/manual-tax-rate.js.map +1 -0
  271. package/src/lib/server/member-feed.d.ts +24 -0
  272. package/src/lib/server/member-feed.js +72 -0
  273. package/src/lib/server/member-feed.js.map +1 -0
  274. package/src/lib/server/member-name-search.d.ts +37 -0
  275. package/src/lib/server/member-name-search.js +42 -0
  276. package/src/lib/server/member-name-search.js.map +1 -0
  277. package/src/lib/server/member-post.d.ts +23 -0
  278. package/src/lib/server/member-post.js +166 -0
  279. package/src/lib/server/member-post.js.map +1 -0
  280. package/src/lib/server/membership-account.d.ts +37 -0
  281. package/src/lib/server/membership-account.js +148 -0
  282. package/src/lib/server/membership-account.js.map +1 -0
  283. package/src/lib/server/membership-admin-password.d.ts +33 -0
  284. package/src/lib/server/membership-admin-password.js +202 -0
  285. package/src/lib/server/membership-admin-password.js.map +1 -0
  286. package/src/lib/server/membership-content.d.ts +23 -0
  287. package/src/lib/server/membership-content.js +105 -0
  288. package/src/lib/server/membership-content.js.map +1 -0
  289. package/src/lib/server/membership-login.d.ts +19 -0
  290. package/src/lib/server/membership-login.js +137 -0
  291. package/src/lib/server/membership-login.js.map +1 -0
  292. package/src/lib/server/membership-logout.d.ts +19 -0
  293. package/src/lib/server/membership-logout.js +35 -0
  294. package/src/lib/server/membership-logout.js.map +1 -0
  295. package/src/lib/server/membership-recover.d.ts +60 -0
  296. package/src/lib/server/membership-recover.js +244 -0
  297. package/src/lib/server/membership-recover.js.map +1 -0
  298. package/src/lib/server/membership-register.d.ts +22 -0
  299. package/src/lib/server/membership-register.js +241 -0
  300. package/src/lib/server/membership-register.js.map +1 -0
  301. package/src/lib/server/membership-reset.d.ts +26 -0
  302. package/src/lib/server/membership-reset.js +88 -0
  303. package/src/lib/server/membership-reset.js.map +1 -0
  304. package/src/lib/server/membership-wishlist.d.ts +23 -0
  305. package/src/lib/server/membership-wishlist.js +89 -0
  306. package/src/lib/server/membership-wishlist.js.map +1 -0
  307. package/src/lib/server/membership.d.ts +96 -0
  308. package/src/lib/server/membership.js +222 -0
  309. package/src/lib/server/membership.js.map +1 -0
  310. package/src/lib/server/native-checkout.d.ts +170 -0
  311. package/src/lib/server/native-checkout.js +193 -0
  312. package/src/lib/server/native-checkout.js.map +1 -0
  313. package/src/lib/server/newsletter.d.ts +23 -0
  314. package/src/lib/server/newsletter.js +323 -0
  315. package/src/lib/server/newsletter.js.map +1 -0
  316. package/src/lib/server/notify-restock.d.ts +22 -0
  317. package/src/lib/server/notify-restock.js +84 -0
  318. package/src/lib/server/notify-restock.js.map +1 -0
  319. package/src/lib/server/order-analytics.d.ts +134 -0
  320. package/src/lib/server/order-analytics.js +263 -0
  321. package/src/lib/server/order-analytics.js.map +1 -0
  322. package/src/lib/server/order-figures.d.ts +33 -0
  323. package/src/lib/server/order-figures.js +220 -0
  324. package/src/lib/server/order-figures.js.map +1 -0
  325. package/src/lib/server/paid-media-delivery.d.ts +173 -0
  326. package/src/lib/server/paid-media-delivery.js +212 -0
  327. package/src/lib/server/paid-media-delivery.js.map +1 -0
  328. package/src/lib/server/pos-order.d.ts +54 -0
  329. package/src/lib/server/pos-order.js +1137 -0
  330. package/src/lib/server/pos-order.js.map +1 -0
  331. package/src/lib/server/process-abandoned.d.ts +54 -0
  332. package/src/lib/server/process-abandoned.js +222 -0
  333. package/src/lib/server/process-abandoned.js.map +1 -0
  334. package/src/lib/server/process-restock.d.ts +42 -0
  335. package/src/lib/server/process-restock.js +219 -0
  336. package/src/lib/server/process-restock.js.map +1 -0
  337. package/src/lib/server/product-card.d.ts +29 -0
  338. package/src/lib/server/product-card.js +54 -0
  339. package/src/lib/server/product-card.js.map +1 -0
  340. package/src/lib/server/product.d.ts +70 -0
  341. package/src/lib/server/product.js +105 -0
  342. package/src/lib/server/product.js.map +1 -0
  343. package/src/lib/server/promotion-hold.d.ts +144 -0
  344. package/src/lib/server/promotion-hold.js +174 -0
  345. package/src/lib/server/promotion-hold.js.map +1 -0
  346. package/src/lib/server/reconcile-stock.d.ts +106 -0
  347. package/src/lib/server/reconcile-stock.js +349 -0
  348. package/src/lib/server/reconcile-stock.js.map +1 -0
  349. package/src/lib/server/refund.d.ts +45 -0
  350. package/src/lib/server/refund.js +607 -0
  351. package/src/lib/server/refund.js.map +1 -0
  352. package/src/lib/server/related.d.ts +24 -0
  353. package/src/lib/server/related.js +104 -0
  354. package/src/lib/server/related.js.map +1 -0
  355. package/src/lib/server/reservation-availability.d.ts +23 -0
  356. package/src/lib/server/reservation-availability.js +111 -0
  357. package/src/lib/server/reservation-availability.js.map +1 -0
  358. package/src/lib/server/reserve-stock.d.ts +156 -0
  359. package/src/lib/server/reserve-stock.js +146 -0
  360. package/src/lib/server/reserve-stock.js.map +1 -0
  361. package/src/lib/server/reserve.d.ts +25 -0
  362. package/src/lib/server/reserve.js +426 -0
  363. package/src/lib/server/reserve.js.map +1 -0
  364. package/src/lib/server/restock-flag.d.ts +202 -0
  365. package/src/lib/server/restock-flag.js +449 -0
  366. package/src/lib/server/restock-flag.js.map +1 -0
  367. package/src/lib/server/reviews.d.ts +51 -0
  368. package/src/lib/server/reviews.js +132 -0
  369. package/src/lib/server/reviews.js.map +1 -0
  370. package/src/lib/server/site-page-enricher.d.ts +42 -0
  371. package/src/lib/server/site-page-enricher.js +149 -0
  372. package/src/lib/server/site-page-enricher.js.map +1 -0
  373. package/src/lib/server/site-page-resolver.d.ts +26 -0
  374. package/src/lib/server/site-page-resolver.js +223 -0
  375. package/src/lib/server/site-page-resolver.js.map +1 -0
  376. package/src/lib/server/stock-hold.d.ts +127 -0
  377. package/src/lib/server/stock-hold.js +258 -0
  378. package/src/lib/server/stock-hold.js.map +1 -0
  379. package/src/lib/server/storefront-tax-record.d.ts +22 -0
  380. package/src/lib/server/storefront-tax-record.js +218 -0
  381. package/src/lib/server/storefront-tax-record.js.map +1 -0
  382. package/src/lib/server/storefront-tax.d.ts +197 -0
  383. package/src/lib/server/storefront-tax.js +245 -0
  384. package/src/lib/server/storefront-tax.js.map +1 -0
  385. package/src/lib/server/stream.d.ts +25 -0
  386. package/src/lib/server/stream.js +191 -0
  387. package/src/lib/server/stream.js.map +1 -0
  388. package/src/lib/server/subscription-portal.d.ts +24 -0
  389. package/src/lib/server/subscription-portal.js +91 -0
  390. package/src/lib/server/subscription-portal.js.map +1 -0
  391. package/src/lib/server/supplier-outbox.d.ts +190 -0
  392. package/src/lib/server/supplier-outbox.js +342 -0
  393. package/src/lib/server/supplier-outbox.js.map +1 -0
  394. package/src/lib/server/supplier-update.d.ts +23 -0
  395. package/src/lib/server/supplier-update.js +289 -0
  396. package/src/lib/server/supplier-update.js.map +1 -0
  397. package/src/lib/server/tax-profile.d.ts +29 -0
  398. package/src/lib/server/tax-profile.js +40 -0
  399. package/src/lib/server/tax-profile.js.map +1 -0
  400. package/src/lib/server.d.ts +32 -0
  401. package/src/lib/server.js +311 -0
  402. package/src/lib/server.js.map +1 -0
  403. package/src/lib/site.d.ts +27 -0
  404. package/src/lib/site.js +134 -0
  405. package/src/lib/site.js.map +1 -0
  406. package/src/lib/utils/escape-html.d.ts +41 -0
  407. package/src/lib/utils/escape-html.js +41 -0
  408. package/src/lib/utils/escape-html.js.map +1 -0
  409. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  410. package/src/lib/utils/generate-preset-id.js +25 -0
  411. package/src/lib/utils/generate-preset-id.js.map +1 -0
  412. package/src/lib/utils/member-continue.d.ts +45 -0
  413. package/src/lib/utils/member-continue.js +49 -0
  414. package/src/lib/utils/member-continue.js.map +1 -0
  415. package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
  416. package/src/lib/utils/use-storefront-purchase-event.js +142 -0
  417. package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PluginApiHandler } from '@aglyn/aglyn/server';
18
+ import * as CommerceModel from '../model';
19
+ export interface AccountOrderView {
20
+ id: string;
21
+ number: string;
22
+ status: CommerceModel.OrderStatus;
23
+ totalCents: number;
24
+ createdAtMs: number;
25
+ itemsSummary: string;
26
+ tracking?: {
27
+ carrier?: string;
28
+ trackingNumber?: string;
29
+ };
30
+ }
31
+ /**
32
+ * Member account (AGL-294): profile + address book + order history for
33
+ * the signed-in site member (AGL-109 session cookie). Orders match by
34
+ * the member's email — guest purchases made with the same address show
35
+ * up too, which is what buyers expect.
36
+ */
37
+ export declare const membershipAccountHandler: PluginApiHandler;
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { memberNameSearchFields } from "./member-name-search.js";
18
+ import * as CommerceModel from "../model/index.js";
19
+ import { firebaseAdmin } from "@aglyn/tenant-data-admin";
20
+ import { mintDownloadToken } from "./download.js";
21
+ import { requireActiveMember } from "./membership.js";
22
+ /**
23
+ * Member account (AGL-294): profile + address book + order history for
24
+ * the signed-in site member (AGL-109 session cookie). Orders match by
25
+ * the member's email — guest purchases made with the same address show
26
+ * up too, which is what buyers expect.
27
+ */ export const membershipAccountHandler = async (req, res)=>{
28
+ var _ref;
29
+ var _req_body;
30
+ const hostId = String((_ref = req.method === 'GET' ? req.query.hostId : (_req_body = req.body) == null ? void 0 : _req_body.hostId) != null ? _ref : '');
31
+ if (!hostId) return res.status(400).json({
32
+ error: 'Missing hostId'
33
+ });
34
+ try {
35
+ var _memberSnapshot_get, _memberSnapshot_get1, _memberSnapshot_get2;
36
+ // Suspension gate (AGL-546/550): the shared guard 401s stale
37
+ // sessions and 403s suspended members with the cookie cleared, so
38
+ // the site stops presenting a signed-in shell; the account block
39
+ // treats any non-OK response as signed-out, the graceful path here.
40
+ const auth = await requireActiveMember(req, res, hostId);
41
+ if (!auth) return;
42
+ const { memberId, member: memberSnapshot } = auth;
43
+ const firestore = firebaseAdmin.app().firestore();
44
+ const hostRef = firestore.collection('hosts').doc(hostId);
45
+ const memberRef = hostRef.collection('siteMembers').doc(memberId);
46
+ if (req.method === 'POST') {
47
+ var _ref1;
48
+ var _req_body1, _req_body2;
49
+ const displayName = String((_ref1 = (_req_body1 = req.body) == null ? void 0 : _req_body1.displayName) != null ? _ref1 : '').slice(0, 80);
50
+ const addresses = Array.isArray((_req_body2 = req.body) == null ? void 0 : _req_body2.addresses) ? req.body.addresses.slice(0, 5).map((address)=>{
51
+ var _address_name, _address_line1, _address_line2, _address_city, _address_state, _address_postalCode, _address_country;
52
+ return {
53
+ name: String((_address_name = address.name) != null ? _address_name : '').slice(0, 80),
54
+ line1: String((_address_line1 = address.line1) != null ? _address_line1 : '').slice(0, 120),
55
+ line2: String((_address_line2 = address.line2) != null ? _address_line2 : '').slice(0, 120),
56
+ city: String((_address_city = address.city) != null ? _address_city : '').slice(0, 80),
57
+ state: String((_address_state = address.state) != null ? _address_state : '').slice(0, 40),
58
+ postalCode: String((_address_postalCode = address.postalCode) != null ? _address_postalCode : '').slice(0, 20),
59
+ country: String((_address_country = address.country) != null ? _address_country : '').slice(0, 2).toUpperCase()
60
+ };
61
+ }) : undefined;
62
+ await memberRef.set(_extends({}, displayName ? memberNameSearchFields(displayName) : {}, addresses ? {
63
+ addresses
64
+ } : {}), {
65
+ merge: true
66
+ });
67
+ }
68
+ const email = String((_memberSnapshot_get = memberSnapshot.get('email')) != null ? _memberSnapshot_get : '');
69
+ const ordersSnapshot = await hostRef.collection('orders').where('customerEmail', '==', email).limit(25).get();
70
+ const orders = ordersSnapshot.docs.map((docSnapshot)=>{
71
+ var _order_fulfillments, _ref, _order_amountCents, _order_createdAtMs, _ref1, _order_lineItems;
72
+ var _order_totals, _docSnapshot_get;
73
+ const order = CommerceModel.liftLegacyOrder(docSnapshot.data());
74
+ const latestFulfillment = ((_order_fulfillments = order.fulfillments) != null ? _order_fulfillments : []).slice(-1)[0];
75
+ return _extends({
76
+ id: docSnapshot.id,
77
+ number: CommerceModel.formatOrderNumber(order, docSnapshot.id),
78
+ status: order.status,
79
+ totalCents: (_ref = (_order_totals = order.totals) == null ? void 0 : _order_totals.totalCents) != null ? _ref : Number((_order_amountCents = order.amountCents) != null ? _order_amountCents : 0),
80
+ createdAtMs: (_order_createdAtMs = order.createdAtMs) != null ? _order_createdAtMs : ((_ref1 = (_docSnapshot_get = docSnapshot.get('createdAt')) == null ? void 0 : _docSnapshot_get.seconds) != null ? _ref1 : 0) * 1000 || 0,
81
+ itemsSummary: ((_order_lineItems = order.lineItems) != null ? _order_lineItems : []).map((line)=>`${line.quantity}× ${line.name}`).join(', ').slice(0, 140)
82
+ }, (latestFulfillment == null ? void 0 : latestFulfillment.trackingNumber) ? {
83
+ tracking: {
84
+ carrier: latestFulfillment.carrier,
85
+ trackingNumber: latestFulfillment.trackingNumber
86
+ }
87
+ } : {});
88
+ }).sort((a, b)=>b.createdAtMs - a.createdAtMs);
89
+ // Digital downloads (AGL-302): tokened links for digital lines on
90
+ // paid orders; files resolve to the product's current list.
91
+ const downloads = [];
92
+ for (const docSnapshot of ordersSnapshot.docs){
93
+ var _docSnapshot_get, _order_lineItems;
94
+ const order = CommerceModel.liftLegacyOrder(docSnapshot.data());
95
+ if (!CommerceModel.orderEntitlesProduct(order, 'any')) continue;
96
+ const orderKeys = (_docSnapshot_get = docSnapshot.get('licenseKeys')) != null ? _docSnapshot_get : {};
97
+ for (const line of (_order_lineItems = order.lineItems) != null ? _order_lineItems : []){
98
+ var _orderKeys_line_productId;
99
+ if (line.productType !== 'digital') continue;
100
+ // PER LINE (AGL-2454). The status test above only ever moved on a FULL
101
+ // refund, so this page went on listing the download link AND the
102
+ // licence key for a line the merchant had refunded. The key string is
103
+ // the one thing here that cannot be taken back once mailed — which is
104
+ // exactly why it is retired from the pool rather than reissued — so
105
+ // removing it from the account page is the only withdrawal available.
106
+ if (!CommerceModel.orderEntitlesProduct(order, line.productId)) continue;
107
+ downloads.push(_extends({
108
+ orderId: docSnapshot.id,
109
+ productId: line.productId,
110
+ productName: line.name
111
+ }, ((_orderKeys_line_productId = orderKeys[line.productId]) == null ? void 0 : _orderKeys_line_productId.length) ? {
112
+ licenseKeys: orderKeys[line.productId]
113
+ } : {}, {
114
+ url: `/api/commerce/download?hostId=${encodeURIComponent(hostId)}` + `&orderId=${encodeURIComponent(docSnapshot.id)}` + `&productId=${encodeURIComponent(line.productId)}` + `&token=${mintDownloadToken(hostId, docSnapshot.id)}`
115
+ }));
116
+ }
117
+ }
118
+ // Storefront subscriptions (AGL-303) with product names resolved.
119
+ const subscriptionsSnapshot = await hostRef.collection('subscriptions').where('customerEmail', '==', email).limit(10).get();
120
+ const subscriptions = await Promise.all(subscriptionsSnapshot.docs.map(async (docSnapshot)=>{
121
+ var _docSnapshot_get, _productSnapshot_get, _docSnapshot_get1, _docSnapshot_get2;
122
+ const productSnapshot = await hostRef.collection('products').doc(String((_docSnapshot_get = docSnapshot.get('productId')) != null ? _docSnapshot_get : '')).get();
123
+ return {
124
+ id: docSnapshot.id,
125
+ productName: String((_productSnapshot_get = productSnapshot.get('name')) != null ? _productSnapshot_get : 'Subscription'),
126
+ status: String((_docSnapshot_get1 = docSnapshot.get('status')) != null ? _docSnapshot_get1 : 'active'),
127
+ currentPeriodEndMs: (_docSnapshot_get2 = docSnapshot.get('currentPeriodEndMs')) != null ? _docSnapshot_get2 : null
128
+ };
129
+ }));
130
+ return res.status(200).json({
131
+ member: {
132
+ email,
133
+ displayName: (_memberSnapshot_get1 = memberSnapshot.get('displayName')) != null ? _memberSnapshot_get1 : '',
134
+ addresses: (_memberSnapshot_get2 = memberSnapshot.get('addresses')) != null ? _memberSnapshot_get2 : []
135
+ },
136
+ orders,
137
+ downloads,
138
+ subscriptions
139
+ });
140
+ } catch (error) {
141
+ console.error(error);
142
+ return res.status(500).json({
143
+ error: 'Account unavailable'
144
+ });
145
+ }
146
+ };
147
+
148
+ //# sourceMappingURL=membership-account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/membership-account.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 { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { memberNameSearchFields } from './member-name-search'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport * as CommerceModel from '../model'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { mintDownloadToken } from './download'\nimport { requireActiveMember } from './membership'\n\nexport interface AccountOrderView {\n id: string\n number: string\n status: CommerceModel.OrderStatus\n totalCents: number\n createdAtMs: number\n itemsSummary: string\n tracking?: { carrier?: string; trackingNumber?: string }\n}\n\n/**\n * Member account (AGL-294): profile + address book + order history for\n * the signed-in site member (AGL-109 session cookie). Orders match by\n * the member's email — guest purchases made with the same address show\n * up too, which is what buyers expect.\n */\nexport const membershipAccountHandler: PluginApiHandler = async (req, res) => {\n const hostId = String(\n (req.method === 'GET' ? req.query.hostId : req.body?.hostId) ?? '',\n )\n if (!hostId) return res.status(400).json({ error: 'Missing hostId' })\n\n try {\n // Suspension gate (AGL-546/550): the shared guard 401s stale\n // sessions and 403s suspended members with the cookie cleared, so\n // the site stops presenting a signed-in shell; the account block\n // treats any non-OK response as signed-out, the graceful path here.\n const auth = await requireActiveMember(req, res, hostId)\n if (!auth) return\n const { memberId, member: memberSnapshot } = auth\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const memberRef = hostRef.collection('siteMembers').doc(memberId)\n\n if (req.method === 'POST') {\n const displayName = String(req.body?.displayName ?? '').slice(0, 80)\n const addresses = Array.isArray(req.body?.addresses)\n ? (req.body.addresses as CommerceModel.OrderAddress[]).slice(0, 5).map(\n (address) => ({\n name: String(address.name ?? '').slice(0, 80),\n line1: String(address.line1 ?? '').slice(0, 120),\n line2: String(address.line2 ?? '').slice(0, 120),\n city: String(address.city ?? '').slice(0, 80),\n state: String(address.state ?? '').slice(0, 40),\n postalCode: String(address.postalCode ?? '').slice(0, 20),\n country: String(address.country ?? '').slice(0, 2).toUpperCase(),\n }),\n )\n : undefined\n await memberRef.set(\n {\n ...(displayName ? memberNameSearchFields(displayName) : {}),\n ...(addresses ? { addresses } : {}),\n },\n { merge: true },\n )\n }\n\n const email = String(memberSnapshot.get('email') ?? '')\n const ordersSnapshot = await hostRef\n .collection('orders')\n .where('customerEmail', '==', email)\n .limit(25)\n .get()\n const orders: AccountOrderView[] = ordersSnapshot.docs\n .map((docSnapshot) => {\n const order = CommerceModel.liftLegacyOrder(docSnapshot.data() as any)\n const latestFulfillment = (order.fulfillments ?? []).slice(-1)[0]\n return {\n id: docSnapshot.id,\n number: CommerceModel.formatOrderNumber(order, docSnapshot.id),\n status: order.status,\n totalCents:\n order.totals?.totalCents ?? Number(order.amountCents ?? 0),\n createdAtMs:\n order.createdAtMs ??\n ((docSnapshot.get('createdAt')?.seconds ?? 0) * 1000 || 0),\n itemsSummary: (order.lineItems ?? [])\n .map((line) => `${line.quantity}× ${line.name}`)\n .join(', ')\n .slice(0, 140),\n ...(latestFulfillment?.trackingNumber\n ? {\n tracking: {\n carrier: latestFulfillment.carrier,\n trackingNumber: latestFulfillment.trackingNumber,\n },\n }\n : {}),\n }\n })\n .sort((a, b) => b.createdAtMs - a.createdAtMs)\n\n // Digital downloads (AGL-302): tokened links for digital lines on\n // paid orders; files resolve to the product's current list.\n const downloads: Array<{\n orderId: string\n productId: string\n productName: string\n url: string\n licenseKeys?: string[]\n }> = []\n for (const docSnapshot of ordersSnapshot.docs) {\n const order = CommerceModel.liftLegacyOrder(docSnapshot.data() as any)\n if (!CommerceModel.orderEntitlesProduct(order, 'any')) continue\n const orderKeys = (docSnapshot.get('licenseKeys') ?? {}) as Record<\n string,\n string[]\n >\n for (const line of order.lineItems ?? []) {\n if (line.productType !== 'digital') continue\n // PER LINE (AGL-2454). The status test above only ever moved on a FULL\n // refund, so this page went on listing the download link AND the\n // licence key for a line the merchant had refunded. The key string is\n // the one thing here that cannot be taken back once mailed — which is\n // exactly why it is retired from the pool rather than reissued — so\n // removing it from the account page is the only withdrawal available.\n if (!CommerceModel.orderEntitlesProduct(order, line.productId)) continue\n downloads.push({\n orderId: docSnapshot.id,\n productId: line.productId,\n productName: line.name,\n ...(orderKeys[line.productId]?.length\n ? { licenseKeys: orderKeys[line.productId] }\n : {}),\n url:\n `/api/commerce/download?hostId=${encodeURIComponent(hostId)}` +\n `&orderId=${encodeURIComponent(docSnapshot.id)}` +\n `&productId=${encodeURIComponent(line.productId)}` +\n `&token=${mintDownloadToken(hostId, docSnapshot.id)}`,\n })\n }\n }\n\n // Storefront subscriptions (AGL-303) with product names resolved.\n const subscriptionsSnapshot = await hostRef\n .collection('subscriptions')\n .where('customerEmail', '==', email)\n .limit(10)\n .get()\n const subscriptions = await Promise.all(\n subscriptionsSnapshot.docs.map(async (docSnapshot) => {\n const productSnapshot = await hostRef\n .collection('products')\n .doc(String(docSnapshot.get('productId') ?? ''))\n .get()\n return {\n id: docSnapshot.id,\n productName: String(productSnapshot.get('name') ?? 'Subscription'),\n status: String(docSnapshot.get('status') ?? 'active'),\n currentPeriodEndMs: docSnapshot.get('currentPeriodEndMs') ?? null,\n }\n }),\n )\n\n return res.status(200).json({\n member: {\n email,\n displayName: memberSnapshot.get('displayName') ?? '',\n addresses: memberSnapshot.get('addresses') ?? [],\n },\n orders,\n downloads,\n subscriptions,\n })\n } catch (error) {\n console.error(error)\n return res.status(500).json({ error: 'Account unavailable' })\n }\n}\n"],"names":["memberNameSearchFields","CommerceModel","firebaseAdmin","mintDownloadToken","requireActiveMember","membershipAccountHandler","req","res","hostId","String","method","query","body","status","json","error","memberSnapshot","auth","memberId","member","firestore","app","hostRef","collection","doc","memberRef","displayName","slice","addresses","Array","isArray","map","address","name","line1","line2","city","state","postalCode","country","toUpperCase","undefined","set","merge","email","get","ordersSnapshot","where","limit","orders","docs","docSnapshot","order","liftLegacyOrder","data","latestFulfillment","fulfillments","id","number","formatOrderNumber","totalCents","totals","Number","amountCents","createdAtMs","seconds","itemsSummary","lineItems","line","quantity","join","trackingNumber","tracking","carrier","sort","a","b","downloads","orderEntitlesProduct","orderKeys","productType","productId","push","orderId","productName","length","licenseKeys","url","encodeURIComponent","subscriptionsSnapshot","subscriptions","Promise","all","productSnapshot","currentPeriodEndMs","console"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PluginApiHandler } from '@aglyn/aglyn/server';
18
+ /**
19
+ * Console-side password help for a SITE MEMBER (AGL-914) — a visitor account
20
+ * on a published site, not an Aglyn console user.
21
+ *
22
+ * Sibling to `membership-recover`, and deliberately its opposite in tone.
23
+ * That endpoint is public, so it answers `{ok:true}` no matter what to avoid
24
+ * confirming whether an address has an account. This one is driven by a site
25
+ * admin looking straight at the member's record — they already know the
26
+ * account exists, so hiding failures would only leave them guessing whether
27
+ * their click did anything. Every outcome here is reported honestly.
28
+ *
29
+ * Auth is the console id-token check `hosts/members` uses (site admin via
30
+ * the `memberRoles` projection, or an org role carrying manageMembers) — NOT
31
+ * the visitor session cookie the rest of the membership endpoints take.
32
+ */
33
+ export declare const membershipAdminPasswordHandler: PluginApiHandler;
@@ -0,0 +1,202 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { resolveBrandingProfile, validateNewPassword } from "@aglyn/aglyn/server";
17
+ import { hostPublicOrigin } from "@aglyn/aglyn/server";
18
+ import { isEmailConfigured, sendEmail } from "@aglyn/shared-util-email";
19
+ import { consumePasswordResetSend, firebaseAdmin, getOrgForHost, hostSendingIdentity, isImpersonationSession, meterHostEmail, passwordResetThrottleMessage } from "@aglyn/tenant-data-admin";
20
+ import { resolveOrgPermissions } from "@aglyn/tenant-runtime/org-permissions";
21
+ import { hashMemberPassword, MEMBER_SESSIONS_VALID_FROM_FIELD, mintPasswordResetToken } from "./membership.js";
22
+ /**
23
+ * Console-side password help for a SITE MEMBER (AGL-914) — a visitor account
24
+ * on a published site, not an Aglyn console user.
25
+ *
26
+ * Sibling to `membership-recover`, and deliberately its opposite in tone.
27
+ * That endpoint is public, so it answers `{ok:true}` no matter what to avoid
28
+ * confirming whether an address has an account. This one is driven by a site
29
+ * admin looking straight at the member's record — they already know the
30
+ * account exists, so hiding failures would only leave them guessing whether
31
+ * their click did anything. Every outcome here is reported honestly.
32
+ *
33
+ * Auth is the console id-token check `hosts/members` uses (site admin via
34
+ * the `memberRoles` projection, or an org role carrying manageMembers) — NOT
35
+ * the visitor session cookie the rest of the membership endpoints take.
36
+ */ export const membershipAdminPasswordHandler = async (req, res)=>{
37
+ var _req_headers_authorization, _ref, _ref1, _ref2;
38
+ var _req_body, _req_body1, _req_body2;
39
+ if (req.method !== 'POST') {
40
+ return res.status(405).json({
41
+ error: 'Method not allowed'
42
+ });
43
+ }
44
+ const authorization = String((_req_headers_authorization = req.headers['authorization']) != null ? _req_headers_authorization : '');
45
+ const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : '';
46
+ if (!idToken) return res.status(401).json({
47
+ error: 'Unauthenticated'
48
+ });
49
+ const hostId = String((_ref = (_req_body = req.body) == null ? void 0 : _req_body.hostId) != null ? _ref : '');
50
+ const memberId = String((_ref1 = (_req_body1 = req.body) == null ? void 0 : _req_body1.memberId) != null ? _ref1 : '');
51
+ const action = String((_ref2 = (_req_body2 = req.body) == null ? void 0 : _req_body2.action) != null ? _ref2 : '');
52
+ if (!hostId || !memberId) {
53
+ return res.status(400).json({
54
+ error: 'Missing hostId or memberId'
55
+ });
56
+ }
57
+ if (action !== 'sendPasswordReset' && action !== 'setPassword') {
58
+ return res.status(400).json({
59
+ error: 'Unknown action'
60
+ });
61
+ }
62
+ try {
63
+ var _ref3, _memberSnapshot_get, _hostPublicOrigin, _ref4, _hostSnapshot_get;
64
+ var _this, _req_body3;
65
+ const app = firebaseAdmin.app();
66
+ const decoded = await app.auth().verifyIdToken(idToken);
67
+ if (!decoded.email_verified && !isImpersonationSession(decoded)) {
68
+ // Same shape as emailUnverifiedResponse (AGL-479), written by hand
69
+ // because that helper returns a fetch `Response` and this is a
70
+ // (req, res) plugin handler.
71
+ return res.status(403).json({
72
+ error: 'Verify your email to continue',
73
+ reason: 'email-unverified'
74
+ });
75
+ }
76
+ const firestore = app.firestore();
77
+ const hostRef = firestore.collection('hosts').doc(hostId);
78
+ const hostSnapshot = await hostRef.get();
79
+ const host = hostSnapshot.data();
80
+ const memberRole = ((_ref3 = host == null ? void 0 : host['memberRoles']) != null ? _ref3 : {})[decoded.uid];
81
+ const orgPermissions = await resolveOrgPermissions(decoded.uid, {
82
+ hostId
83
+ });
84
+ if (!host || memberRole !== 'admin' && !orgPermissions.permissions.manageMembers) {
85
+ return res.status(403).json({
86
+ error: 'Not a site admin'
87
+ });
88
+ }
89
+ const memberRef = hostRef.collection('siteMembers').doc(memberId);
90
+ const memberSnapshot = await memberRef.get();
91
+ if (!memberSnapshot.exists) {
92
+ return res.status(404).json({
93
+ error: 'Unknown member'
94
+ });
95
+ }
96
+ const email = String((_memberSnapshot_get = memberSnapshot.get('email')) != null ? _memberSnapshot_get : '');
97
+ if (!email) {
98
+ return res.status(400).json({
99
+ error: 'This member has no email address'
100
+ });
101
+ }
102
+ // `hostPublicOrigin`, not a hand-rolled apex (AGL-2195). This URL is
103
+ // minted server-side and mailed out, so a wrong apex is not a display
104
+ // bug — it is a live link on somebody else's domain.
105
+ const siteBase = (_hostPublicOrigin = hostPublicOrigin({
106
+ cname: hostSnapshot.get('cname'),
107
+ subdomain: hostSnapshot.get('subdomain')
108
+ })) != null ? _hostPublicOrigin : '';
109
+ const siteName = String((_ref4 = (_hostSnapshot_get = hostSnapshot.get('displayName')) != null ? _hostSnapshot_get : hostSnapshot.get('subdomain')) != null ? _ref4 : 'the site');
110
+ // White-label sender identity (White-Label Phase 3): the store's brand via
111
+ // the one shared resolver; the copy already uses the site name.
112
+ const branding = resolveBrandingProfile((_this = await getOrgForHost(hostId).catch(()=>null)) == null ? void 0 : _this.org);
113
+ if (action === 'sendPasswordReset') {
114
+ // Throttled per recipient and per actor (AGL-920). Same caps as the
115
+ // console surfaces — a site member's inbox is no less worth protecting
116
+ // than a console user's.
117
+ const throttle = await consumePasswordResetSend({
118
+ actorKey: decoded.uid,
119
+ recipientKey: email
120
+ });
121
+ if (!throttle.allowed) {
122
+ res.setHeader('Retry-After', String(throttle.retryAfterSeconds));
123
+ return res.status(429).json({
124
+ error: passwordResetThrottleMessage(throttle)
125
+ });
126
+ }
127
+ if (!isEmailConfigured()) {
128
+ return res.status(502).json({
129
+ error: 'Email is not configured, so no reset link could be sent'
130
+ });
131
+ }
132
+ // Same single-use, hash-bound token the self-serve flow mints
133
+ // (AGL-552) — completing the reset rewrites `passwordScrypt`, which
134
+ // retires the token without any server-side storage.
135
+ const token = mintPasswordResetToken(hostId, memberId, memberSnapshot.get('passwordScrypt'));
136
+ const resetUrl = `${siteBase}/recover?token=${encodeURIComponent(token)}`;
137
+ const result = await sendEmail({
138
+ to: email,
139
+ subject: `Reset your ${siteName} password`,
140
+ text: `An administrator of ${siteName} started a password reset for ` + 'your account. Set a new password here:\n\n' + `${resetUrl}\n\n` + 'The link works once and expires in 1 hour. Your current ' + 'password keeps working until you use it.',
141
+ fromName: branding.fromName,
142
+ sendingIdentity: await hostSendingIdentity(hostId),
143
+ audience: 'tenant',
144
+ context: 'membership admin recovery'
145
+ });
146
+ if (!result.sent) {
147
+ return res.status(502).json({
148
+ error: 'The reset email could not be delivered'
149
+ });
150
+ }
151
+ // Cost meter (AGL-1438). Transactional: a reset a quota refused leaves
152
+ // the member locked out of a site they pay for.
153
+ await meterHostEmail(hostId);
154
+ return res.status(200).json({
155
+ ok: true
156
+ });
157
+ }
158
+ const validated = validateNewPassword((_req_body3 = req.body) == null ? void 0 : _req_body3.password);
159
+ if (validated.error) {
160
+ return res.status(400).json({
161
+ error: validated.error
162
+ });
163
+ }
164
+ // Rewriting the hash alone would NOT sign the member out: their session
165
+ // is an HMAC cookie that never encodes the password (unlike a reset
166
+ // token, which binds to it on purpose). The cut-off field is what
167
+ // actually revokes the old sessions — see readActiveMemberSession.
168
+ await memberRef.update({
169
+ passwordScrypt: hashMemberPassword(validated.password),
170
+ [MEMBER_SESSIONS_VALID_FROM_FIELD]: Date.now()
171
+ });
172
+ // Best-effort: the password has already changed, so a mail failure must
173
+ // not fail the request and send the admin round again. Report it so
174
+ // they know to reach the member another way.
175
+ let notified = false;
176
+ if (isEmailConfigured()) {
177
+ const result = await sendEmail({
178
+ to: email,
179
+ subject: `Your ${siteName} password was changed`,
180
+ text: `An administrator of ${siteName} set a new password on your ` + 'account. You have been signed out on every device and will need ' + `the new password to sign back in at ${siteBase}.\n\n` + 'If you did not expect this, contact the site owner.',
181
+ fromName: branding.fromName,
182
+ sendingIdentity: await hostSendingIdentity(hostId),
183
+ audience: 'tenant',
184
+ context: 'membership admin password change'
185
+ });
186
+ notified = result.sent;
187
+ // Cost meter (AGL-1438). Transactional: a security notice.
188
+ if (result.sent) await meterHostEmail(hostId);
189
+ }
190
+ return res.status(200).json({
191
+ ok: true,
192
+ notified
193
+ });
194
+ } catch (error) {
195
+ console.error(error);
196
+ return res.status(500).json({
197
+ error: 'Password operation failed'
198
+ });
199
+ }
200
+ };
201
+
202
+ //# sourceMappingURL=membership-admin-password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/membership-admin-password.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 { PluginApiHandler } from '@aglyn/aglyn/server'\nimport { resolveBrandingProfile, validateNewPassword } from '@aglyn/aglyn/server'\nimport { hostPublicOrigin } from '@aglyn/aglyn/server'\nimport { isEmailConfigured, sendEmail } from '@aglyn/shared-util-email'\nimport {\n consumePasswordResetSend,\n firebaseAdmin,\n getOrgForHost,\n hostSendingIdentity,\n isImpersonationSession,\n meterHostEmail,\n passwordResetThrottleMessage,\n} from '@aglyn/tenant-data-admin'\nimport { resolveOrgPermissions } from '@aglyn/tenant-runtime/org-permissions'\nimport {\n hashMemberPassword,\n MEMBER_SESSIONS_VALID_FROM_FIELD,\n mintPasswordResetToken,\n} from './membership'\n\n/**\n * Console-side password help for a SITE MEMBER (AGL-914) — a visitor account\n * on a published site, not an Aglyn console user.\n *\n * Sibling to `membership-recover`, and deliberately its opposite in tone.\n * That endpoint is public, so it answers `{ok:true}` no matter what to avoid\n * confirming whether an address has an account. This one is driven by a site\n * admin looking straight at the member's record — they already know the\n * account exists, so hiding failures would only leave them guessing whether\n * their click did anything. Every outcome here is reported honestly.\n *\n * Auth is the console id-token check `hosts/members` uses (site admin via\n * the `memberRoles` projection, or an org role carrying manageMembers) — NOT\n * the visitor session cookie the rest of the membership endpoints take.\n */\nexport const membershipAdminPasswordHandler: PluginApiHandler = async (\n req,\n res,\n) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const authorization = String(req.headers['authorization'] ?? '')\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : ''\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n\n const hostId = String(req.body?.hostId ?? '')\n const memberId = String(req.body?.memberId ?? '')\n const action = String(req.body?.action ?? '')\n if (!hostId || !memberId) {\n return res.status(400).json({ error: 'Missing hostId or memberId' })\n }\n if (action !== 'sendPasswordReset' && action !== 'setPassword') {\n return res.status(400).json({ error: 'Unknown action' })\n }\n\n try {\n const app = firebaseAdmin.app()\n const decoded = await app.auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) {\n // Same shape as emailUnverifiedResponse (AGL-479), written by hand\n // because that helper returns a fetch `Response` and this is a\n // (req, res) plugin handler.\n return res.status(403).json({\n error: 'Verify your email to continue',\n reason: 'email-unverified',\n })\n }\n const firestore = app.firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const hostSnapshot = await hostRef.get()\n const host = hostSnapshot.data()\n const memberRole = (host?.['memberRoles'] ?? {})[decoded.uid]\n const orgPermissions = await resolveOrgPermissions(decoded.uid, { hostId })\n if (\n !host ||\n (memberRole !== 'admin' && !orgPermissions.permissions.manageMembers)\n ) {\n return res.status(403).json({ error: 'Not a site admin' })\n }\n\n const memberRef = hostRef.collection('siteMembers').doc(memberId)\n const memberSnapshot = await memberRef.get()\n if (!memberSnapshot.exists) {\n return res.status(404).json({ error: 'Unknown member' })\n }\n const email = String(memberSnapshot.get('email') ?? '')\n if (!email) {\n return res.status(400).json({ error: 'This member has no email address' })\n }\n\n // `hostPublicOrigin`, not a hand-rolled apex (AGL-2195). This URL is\n // minted server-side and mailed out, so a wrong apex is not a display\n // bug — it is a live link on somebody else's domain.\n const siteBase =\n hostPublicOrigin({\n cname: hostSnapshot.get('cname'),\n subdomain: hostSnapshot.get('subdomain'),\n }) ?? ''\n const siteName = String(\n hostSnapshot.get('displayName') ?? hostSnapshot.get('subdomain') ?? 'the site',\n )\n // White-label sender identity (White-Label Phase 3): the store's brand via\n // the one shared resolver; the copy already uses the site name.\n const branding = resolveBrandingProfile(\n (await getOrgForHost(hostId).catch(() => null))?.org as never,\n )\n\n if (action === 'sendPasswordReset') {\n // Throttled per recipient and per actor (AGL-920). Same caps as the\n // console surfaces — a site member's inbox is no less worth protecting\n // than a console user's.\n const throttle = await consumePasswordResetSend({\n actorKey: decoded.uid,\n recipientKey: email,\n })\n if (!throttle.allowed) {\n res.setHeader('Retry-After', String(throttle.retryAfterSeconds))\n return res\n .status(429)\n .json({ error: passwordResetThrottleMessage(throttle) })\n }\n if (!isEmailConfigured()) {\n return res.status(502).json({\n error: 'Email is not configured, so no reset link could be sent',\n })\n }\n // Same single-use, hash-bound token the self-serve flow mints\n // (AGL-552) — completing the reset rewrites `passwordScrypt`, which\n // retires the token without any server-side storage.\n const token = mintPasswordResetToken(\n hostId,\n memberId,\n memberSnapshot.get('passwordScrypt'),\n )\n const resetUrl = `${siteBase}/recover?token=${encodeURIComponent(token)}`\n const result = await sendEmail({\n to: email,\n subject: `Reset your ${siteName} password`,\n text:\n `An administrator of ${siteName} started a password reset for ` +\n 'your account. Set a new password here:\\n\\n' +\n `${resetUrl}\\n\\n` +\n 'The link works once and expires in 1 hour. Your current ' +\n 'password keeps working until you use it.',\n fromName: branding.fromName,\n sendingIdentity: await hostSendingIdentity(hostId),\n audience: 'tenant',\n context: 'membership admin recovery',\n })\n if (!result.sent) {\n return res.status(502).json({\n error: 'The reset email could not be delivered',\n })\n }\n // Cost meter (AGL-1438). Transactional: a reset a quota refused leaves\n // the member locked out of a site they pay for.\n await meterHostEmail(hostId)\n return res.status(200).json({ ok: true })\n }\n\n const validated = validateNewPassword(req.body?.password)\n if (validated.error) {\n return res.status(400).json({ error: validated.error })\n }\n // Rewriting the hash alone would NOT sign the member out: their session\n // is an HMAC cookie that never encodes the password (unlike a reset\n // token, which binds to it on purpose). The cut-off field is what\n // actually revokes the old sessions — see readActiveMemberSession.\n await memberRef.update({\n passwordScrypt: hashMemberPassword(validated.password),\n [MEMBER_SESSIONS_VALID_FROM_FIELD]: Date.now(),\n })\n // Best-effort: the password has already changed, so a mail failure must\n // not fail the request and send the admin round again. Report it so\n // they know to reach the member another way.\n let notified = false\n if (isEmailConfigured()) {\n const result = await sendEmail({\n to: email,\n subject: `Your ${siteName} password was changed`,\n text:\n `An administrator of ${siteName} set a new password on your ` +\n 'account. You have been signed out on every device and will need ' +\n `the new password to sign back in at ${siteBase}.\\n\\n` +\n 'If you did not expect this, contact the site owner.',\n fromName: branding.fromName,\n sendingIdentity: await hostSendingIdentity(hostId),\n audience: 'tenant',\n context: 'membership admin password change',\n })\n notified = result.sent\n // Cost meter (AGL-1438). Transactional: a security notice.\n if (result.sent) await meterHostEmail(hostId)\n }\n return res.status(200).json({ ok: true, notified })\n } catch (error) {\n console.error(error)\n return res.status(500).json({ error: 'Password operation failed' })\n }\n}\n"],"names":["resolveBrandingProfile","validateNewPassword","hostPublicOrigin","isEmailConfigured","sendEmail","consumePasswordResetSend","firebaseAdmin","getOrgForHost","hostSendingIdentity","isImpersonationSession","meterHostEmail","passwordResetThrottleMessage","resolveOrgPermissions","hashMemberPassword","MEMBER_SESSIONS_VALID_FROM_FIELD","mintPasswordResetToken","membershipAdminPasswordHandler","req","res","method","status","json","error","authorization","String","headers","idToken","startsWith","slice","length","hostId","body","memberId","action","memberSnapshot","hostSnapshot","app","decoded","auth","verifyIdToken","email_verified","reason","firestore","hostRef","collection","doc","get","host","data","memberRole","uid","orgPermissions","permissions","manageMembers","memberRef","exists","email","siteBase","cname","subdomain","siteName","branding","catch","org","throttle","actorKey","recipientKey","allowed","setHeader","retryAfterSeconds","token","resetUrl","encodeURIComponent","result","to","subject","text","fromName","sendingIdentity","audience","context","sent","ok","validated","password","update","passwordScrypt","Date","now","notified","console"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PluginApiHandler } from '@aglyn/aglyn/server';
18
+ /**
19
+ * Members-only screen content (AGL-109/309): like the AGL-87 unlock API,
20
+ * the node tree never ships in static HTML — it is returned here only when
21
+ * the visitor's session cookie verifies for this host.
22
+ */
23
+ export declare const membershipContentHandler: PluginApiHandler;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import composeScreenNodes from "@aglyn/tenant-runtime/compose-screen-nodes";
18
+ import { enrichGatedScreenPage } from "@aglyn/tenant-runtime/enrich-gated-page";
19
+ import getScreen from "@aglyn/tenant-runtime/get-screen";
20
+ import { getHostDocAdmin } from "@aglyn/tenant-data-admin";
21
+ import { hostHasContentGating } from "./gate.js";
22
+ import { requireActiveMember } from "./membership.js";
23
+ /**
24
+ * Members-only screen content (AGL-109/309): like the AGL-87 unlock API,
25
+ * the node tree never ships in static HTML — it is returned here only when
26
+ * the visitor's session cookie verifies for this host.
27
+ */ export const membershipContentHandler = async (req, res)=>{
28
+ var _ref, _ref1;
29
+ var _req_body, _req_body1;
30
+ if (req.method !== 'POST') {
31
+ return res.status(405).json({
32
+ error: 'Method not allowed'
33
+ });
34
+ }
35
+ const hostId = String((_ref = (_req_body = req.body) == null ? void 0 : _req_body.hostId) != null ? _ref : '');
36
+ const screenId = String((_ref1 = (_req_body1 = req.body) == null ? void 0 : _req_body1.screenId) != null ? _ref1 : '');
37
+ if (!hostId || !screenId) {
38
+ return res.status(400).json({
39
+ error: 'Invalid request'
40
+ });
41
+ }
42
+ try {
43
+ // Suspension gate (AGL-550): the cookie alone no longer unlocks the
44
+ // node tree — a suspended member (AGL-546) is 403'd, cookie cleared.
45
+ const auth = await requireActiveMember(req, res, hostId, 'Sign in required');
46
+ if (!auth) return;
47
+ // Org-level gate (AGL-481): members-only screens are a Business+
48
+ // feature. If the host's plan doesn't include content gating, the
49
+ // protected node tree is never served — fail closed. (These nodes
50
+ // never ship in static HTML, so this endpoint is the runtime gate.)
51
+ if (!await hostHasContentGating(hostId)) {
52
+ return res.status(403).json({
53
+ error: 'Members-only content is unavailable'
54
+ });
55
+ }
56
+ const screenRes = await getScreen({
57
+ hostId,
58
+ screenId
59
+ });
60
+ if (!screenRes.screen) {
61
+ return res.status(404).json({
62
+ error: 'Unknown screen'
63
+ });
64
+ }
65
+ // The site document (AGL-2883): the tree's host variables fill in from
66
+ // it, and the enricher slice below reads the same copy. A failed read
67
+ // composes with no site, which renders those variables as nothing — the
68
+ // member's content without its business name still beats no content.
69
+ const host = await getHostDocAdmin(hostId).catch((error)=>{
70
+ console.error(error);
71
+ return null;
72
+ });
73
+ const nodes = await composeScreenNodes({
74
+ hostId,
75
+ screenId,
76
+ screen: screenRes.screen,
77
+ host
78
+ });
79
+ if (!nodes) return res.status(404).json({
80
+ error: 'No published version'
81
+ });
82
+ // The page's behavior travels with its nodes (AGL-2510). The loader ships
83
+ // `nodes: null` for a members-only screen, so its enricher slice — the
84
+ // interactions the shared layout's nav opens on, above all — has nowhere
85
+ // else to arrive from, and the member saw a nav that did not open.
86
+ const enriched = await enrichGatedScreenPage(_extends({
87
+ hostId,
88
+ screenId,
89
+ screen: screenRes.screen,
90
+ nodes
91
+ }, host ? {
92
+ host
93
+ } : {}));
94
+ return res.status(200).json(_extends({
95
+ nodes
96
+ }, enriched));
97
+ } catch (error) {
98
+ console.error(error);
99
+ return res.status(500).json({
100
+ error: 'Content fetch failed'
101
+ });
102
+ }
103
+ };
104
+
105
+ //# sourceMappingURL=membership-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/membership-content.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 { PluginApiHandler } from '@aglyn/aglyn/server'\nimport composeScreenNodes from '@aglyn/tenant-runtime/compose-screen-nodes'\nimport { enrichGatedScreenPage } from '@aglyn/tenant-runtime/enrich-gated-page'\nimport getScreen from '@aglyn/tenant-runtime/get-screen'\nimport { getHostDocAdmin } from '@aglyn/tenant-data-admin'\nimport { hostHasContentGating } from './gate'\nimport { requireActiveMember } from './membership'\n\n/**\n * Members-only screen content (AGL-109/309): like the AGL-87 unlock API,\n * the node tree never ships in static HTML — it is returned here only when\n * the visitor's session cookie verifies for this host.\n */\nexport const membershipContentHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const hostId = String(req.body?.hostId ?? '')\n const screenId = String(req.body?.screenId ?? '')\n if (!hostId || !screenId) {\n return res.status(400).json({ error: 'Invalid request' })\n }\n try {\n // Suspension gate (AGL-550): the cookie alone no longer unlocks the\n // node tree — a suspended member (AGL-546) is 403'd, cookie cleared.\n const auth = await requireActiveMember(req, res, hostId, 'Sign in required')\n if (!auth) return\n // Org-level gate (AGL-481): members-only screens are a Business+\n // feature. If the host's plan doesn't include content gating, the\n // protected node tree is never served — fail closed. (These nodes\n // never ship in static HTML, so this endpoint is the runtime gate.)\n if (!(await hostHasContentGating(hostId))) {\n return res.status(403).json({ error: 'Members-only content is unavailable' })\n }\n const screenRes = await getScreen({ hostId, screenId })\n if (!screenRes.screen) {\n return res.status(404).json({ error: 'Unknown screen' })\n }\n // The site document (AGL-2883): the tree's host variables fill in from\n // it, and the enricher slice below reads the same copy. A failed read\n // composes with no site, which renders those variables as nothing — the\n // member's content without its business name still beats no content.\n const host = await getHostDocAdmin(hostId).catch((error) => {\n console.error(error)\n return null\n })\n const nodes = await composeScreenNodes({\n hostId,\n screenId,\n screen: screenRes.screen,\n host,\n })\n if (!nodes) return res.status(404).json({ error: 'No published version' })\n // The page's behavior travels with its nodes (AGL-2510). The loader ships\n // `nodes: null` for a members-only screen, so its enricher slice — the\n // interactions the shared layout's nav opens on, above all — has nowhere\n // else to arrive from, and the member saw a nav that did not open.\n const enriched = await enrichGatedScreenPage({\n hostId,\n screenId,\n screen: screenRes.screen,\n nodes,\n ...(host ? { host } : {}),\n })\n return res.status(200).json({ nodes, ...enriched })\n } catch (error) {\n console.error(error)\n return res.status(500).json({ error: 'Content fetch failed' })\n }\n}\n"],"names":["composeScreenNodes","enrichGatedScreenPage","getScreen","getHostDocAdmin","hostHasContentGating","requireActiveMember","membershipContentHandler","req","res","method","status","json","error","hostId","String","body","screenId","auth","screenRes","screen","host","catch","console","nodes","enriched"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,OAAOA,wBAAwB,6CAA4C;AAC3E,SAASC,qBAAqB,QAAQ,0CAAyC;AAC/E,OAAOC,eAAe,mCAAkC;AACxD,SAASC,eAAe,QAAQ,2BAA0B;AAC1D,SAASC,oBAAoB,QAAQ,YAAQ;AAC7C,SAASC,mBAAmB,QAAQ,kBAAc;AAElD;;;;CAIC,GACD,OAAO,MAAMC,2BAA6C,OAAOC,KAAKC;;QAI9CD,WACEA;IAJxB,IAAIA,IAAIE,MAAM,KAAK,QAAQ;QACzB,OAAOD,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAqB;IAC5D;IACA,MAAMC,SAASC,gBAAOP,YAAAA,IAAIQ,IAAI,qBAARR,UAAUM,MAAM,mBAAI;IAC1C,MAAMG,WAAWF,iBAAOP,aAAAA,IAAIQ,IAAI,qBAARR,WAAUS,QAAQ,oBAAI;IAC9C,IAAI,CAACH,UAAU,CAACG,UAAU;QACxB,OAAOR,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAkB;IACzD;IACA,IAAI;QACF,oEAAoE;QACpE,qEAAqE;QACrE,MAAMK,OAAO,MAAMZ,oBAAoBE,KAAKC,KAAKK,QAAQ;QACzD,IAAI,CAACI,MAAM;QACX,iEAAiE;QACjE,kEAAkE;QAClE,kEAAkE;QAClE,oEAAoE;QACpE,IAAI,CAAE,MAAMb,qBAAqBS,SAAU;YACzC,OAAOL,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;gBAAEC,OAAO;YAAsC;QAC7E;QACA,MAAMM,YAAY,MAAMhB,UAAU;YAAEW;YAAQG;QAAS;QACrD,IAAI,CAACE,UAAUC,MAAM,EAAE;YACrB,OAAOX,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;gBAAEC,OAAO;YAAiB;QACxD;QACA,uEAAuE;QACvE,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,MAAMQ,OAAO,MAAMjB,gBAAgBU,QAAQQ,KAAK,CAAC,CAACT;YAChDU,QAAQV,KAAK,CAACA;YACd,OAAO;QACT;QACA,MAAMW,QAAQ,MAAMvB,mBAAmB;YACrCa;YACAG;YACAG,QAAQD,UAAUC,MAAM;YACxBC;QACF;QACA,IAAI,CAACG,OAAO,OAAOf,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAuB;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,yEAAyE;QACzE,mEAAmE;QACnE,MAAMY,WAAW,MAAMvB,sBAAsB;YAC3CY;YACAG;YACAG,QAAQD,UAAUC,MAAM;YACxBI;WACIH,OAAO;YAAEA;QAAK,IAAI,CAAC;QAEzB,OAAOZ,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEY;WAAUC;IAC1C,EAAE,OAAOZ,OAAO;QACdU,QAAQV,KAAK,CAACA;QACd,OAAOJ,IAAIE,MAAM,CAAC,KAAKC,IAAI,CAAC;YAAEC,OAAO;QAAuB;IAC9D;AACF,EAAC"}