@owlmeans/payment 0.1.18-rc.46 → 0.1.18-rc.48

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 (315) hide show
  1. package/README.md +21 -21
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/entitlements/SKILL.md +7 -6
  4. package/agent-meta/skills/payment/SKILL.md +150 -104
  5. package/build/advertise.js +1 -11
  6. package/build/advertise.js.map +1 -1
  7. package/build/checkout/consts.d.ts +2 -0
  8. package/build/checkout/consts.d.ts.map +1 -0
  9. package/build/checkout/consts.js +2 -0
  10. package/build/checkout/consts.js.map +1 -0
  11. package/build/checkout/index.d.ts +3 -0
  12. package/build/checkout/index.d.ts.map +1 -1
  13. package/build/checkout/index.js +1 -0
  14. package/build/checkout/index.js.map +1 -1
  15. package/build/checkout/narrow/types.d.ts +25 -0
  16. package/build/checkout/narrow/types.d.ts.map +1 -0
  17. package/build/checkout/narrow/types.js +2 -0
  18. package/build/checkout/narrow/types.js.map +1 -0
  19. package/build/checkout/narrow.d.ts +5 -22
  20. package/build/checkout/narrow.d.ts.map +1 -1
  21. package/build/checkout/narrow.js +43 -54
  22. package/build/checkout/narrow.js.map +1 -1
  23. package/build/checkout/protocols.d.ts +1 -25
  24. package/build/checkout/protocols.d.ts.map +1 -1
  25. package/build/checkout/protocols.js +1 -1
  26. package/build/checkout/protocols.js.map +1 -1
  27. package/build/checkout/types.d.ts +29 -0
  28. package/build/checkout/types.d.ts.map +1 -0
  29. package/build/checkout/types.js +2 -0
  30. package/build/checkout/types.js.map +1 -0
  31. package/build/consts.d.ts +82 -1
  32. package/build/consts.d.ts.map +1 -1
  33. package/build/consts.js +145 -1
  34. package/build/consts.js.map +1 -1
  35. package/build/consts.local.d.ts +20 -0
  36. package/build/consts.local.d.ts.map +1 -0
  37. package/build/consts.local.js +23 -0
  38. package/build/consts.local.js.map +1 -0
  39. package/build/consumer/cancel.d.ts +1 -1
  40. package/build/consumer/cancel.d.ts.map +1 -1
  41. package/build/consumer/cancel.js.map +1 -1
  42. package/build/consumer/consts.d.ts +20 -0
  43. package/build/consumer/consts.d.ts.map +1 -0
  44. package/build/consumer/consts.js +39 -0
  45. package/build/consumer/consts.js.map +1 -0
  46. package/build/consumer/consts.local.d.ts +7 -0
  47. package/build/consumer/consts.local.d.ts.map +1 -0
  48. package/build/consumer/consts.local.js +13 -0
  49. package/build/consumer/consts.local.js.map +1 -0
  50. package/build/consumer/copy/types.d.ts +56 -0
  51. package/build/consumer/copy/types.d.ts.map +1 -0
  52. package/build/consumer/copy/types.js +2 -0
  53. package/build/consumer/copy/types.js.map +1 -0
  54. package/build/consumer/copy.d.ts +13 -49
  55. package/build/consumer/copy.d.ts.map +1 -1
  56. package/build/consumer/copy.js +75 -79
  57. package/build/consumer/copy.js.map +1 -1
  58. package/build/consumer/deadline/types.d.ts +30 -0
  59. package/build/consumer/deadline/types.d.ts.map +1 -0
  60. package/build/consumer/deadline/types.js +2 -0
  61. package/build/consumer/deadline/types.js.map +1 -0
  62. package/build/consumer/deadline.d.ts +8 -39
  63. package/build/consumer/deadline.d.ts.map +1 -1
  64. package/build/consumer/deadline.js +41 -52
  65. package/build/consumer/deadline.js.map +1 -1
  66. package/build/consumer/fifo/types.d.ts +17 -0
  67. package/build/consumer/fifo/types.d.ts.map +1 -0
  68. package/build/consumer/fifo/types.js +2 -0
  69. package/build/consumer/fifo/types.js.map +1 -0
  70. package/build/consumer/fifo.d.ts +3 -39
  71. package/build/consumer/fifo.d.ts.map +1 -1
  72. package/build/consumer/fifo.js +30 -36
  73. package/build/consumer/fifo.js.map +1 -1
  74. package/build/consumer/index.d.ts +8 -0
  75. package/build/consumer/index.d.ts.map +1 -1
  76. package/build/consumer/index.js +1 -0
  77. package/build/consumer/index.js.map +1 -1
  78. package/build/consumer/policy/types.d.ts +20 -0
  79. package/build/consumer/policy/types.d.ts.map +1 -0
  80. package/build/consumer/policy/types.js +2 -0
  81. package/build/consumer/policy/types.js.map +1 -0
  82. package/build/consumer/policy.d.ts +8 -30
  83. package/build/consumer/policy.d.ts.map +1 -1
  84. package/build/consumer/policy.js +66 -97
  85. package/build/consumer/policy.js.map +1 -1
  86. package/build/consumer/protocols.d.ts +1 -86
  87. package/build/consumer/protocols.d.ts.map +1 -1
  88. package/build/consumer/protocols.js +1 -4
  89. package/build/consumer/protocols.js.map +1 -1
  90. package/build/consumer/refund/types.d.ts +27 -0
  91. package/build/consumer/refund/types.d.ts.map +1 -0
  92. package/build/consumer/refund/types.js +2 -0
  93. package/build/consumer/refund/types.js.map +1 -0
  94. package/build/consumer/refund.d.ts +6 -71
  95. package/build/consumer/refund.d.ts.map +1 -1
  96. package/build/consumer/refund.js +86 -97
  97. package/build/consumer/refund.js.map +1 -1
  98. package/build/consumer/refusal.d.ts.map +1 -1
  99. package/build/consumer/refusal.js +2 -7
  100. package/build/consumer/refusal.js.map +1 -1
  101. package/build/consumer/revive/types.d.ts +19 -0
  102. package/build/consumer/revive/types.d.ts.map +1 -0
  103. package/build/consumer/revive/types.js +2 -0
  104. package/build/consumer/revive/types.js.map +1 -0
  105. package/build/consumer/revive.d.ts +8 -8
  106. package/build/consumer/revive.d.ts.map +1 -1
  107. package/build/consumer/revive.js +40 -23
  108. package/build/consumer/revive.js.map +1 -1
  109. package/build/consumer/types.d.ts +196 -0
  110. package/build/consumer/types.d.ts.map +1 -0
  111. package/build/consumer/types.js +2 -0
  112. package/build/consumer/types.js.map +1 -0
  113. package/build/consumer/types.local.d.ts +11 -0
  114. package/build/consumer/types.local.d.ts.map +1 -0
  115. package/build/consumer/types.local.js +2 -0
  116. package/build/consumer/types.local.js.map +1 -0
  117. package/build/countries.d.ts +0 -19
  118. package/build/countries.d.ts.map +1 -1
  119. package/build/countries.js +1 -63
  120. package/build/countries.js.map +1 -1
  121. package/build/entitled.d.ts +14 -0
  122. package/build/entitled.d.ts.map +1 -0
  123. package/build/entitled.js +17 -0
  124. package/build/entitled.js.map +1 -0
  125. package/build/entitlement/types.d.ts +29 -0
  126. package/build/entitlement/types.d.ts.map +1 -0
  127. package/build/entitlement/types.js +2 -0
  128. package/build/entitlement/types.js.map +1 -0
  129. package/build/entitlement.d.ts +7 -72
  130. package/build/entitlement.d.ts.map +1 -1
  131. package/build/entitlement.js +55 -109
  132. package/build/entitlement.js.map +1 -1
  133. package/build/errors.d.ts +1 -27
  134. package/build/errors.d.ts.map +1 -1
  135. package/build/errors.js +1 -9
  136. package/build/errors.js.map +1 -1
  137. package/build/estimate/types.d.ts +34 -0
  138. package/build/estimate/types.d.ts.map +1 -0
  139. package/build/estimate/types.js +2 -0
  140. package/build/estimate/types.js.map +1 -0
  141. package/build/estimate.d.ts +7 -53
  142. package/build/estimate.d.ts.map +1 -1
  143. package/build/estimate.js +61 -87
  144. package/build/estimate.js.map +1 -1
  145. package/build/i18n/consumer-rights/be.json +12 -4
  146. package/build/i18n/consumer-rights/de.json +12 -4
  147. package/build/i18n/consumer-rights/en.json +12 -4
  148. package/build/i18n/consumer-rights/es.json +12 -4
  149. package/build/i18n/consumer-rights/fr.json +12 -4
  150. package/build/i18n/consumer-rights/pl.json +12 -4
  151. package/build/i18n/consumer-rights/ru.json +12 -4
  152. package/build/i18n/consumer-rights/uk.json +12 -4
  153. package/build/i18n.js +25 -25
  154. package/build/i18n.js.map +1 -1
  155. package/build/index.d.ts +8 -0
  156. package/build/index.d.ts.map +1 -1
  157. package/build/index.js +1 -0
  158. package/build/index.js.map +1 -1
  159. package/build/limit/types.d.ts +44 -0
  160. package/build/limit/types.d.ts.map +1 -0
  161. package/build/limit/types.js +2 -0
  162. package/build/limit/types.js.map +1 -0
  163. package/build/limit.d.ts +11 -38
  164. package/build/limit.d.ts.map +1 -1
  165. package/build/limit.js +80 -94
  166. package/build/limit.js.map +1 -1
  167. package/build/model/checkout.js +1 -1
  168. package/build/model/checkout.js.map +1 -1
  169. package/build/model/consts.d.ts +15 -0
  170. package/build/model/consts.d.ts.map +1 -0
  171. package/build/model/consts.js +193 -0
  172. package/build/model/consts.js.map +1 -0
  173. package/build/model/consts.local.d.ts +35 -0
  174. package/build/model/consts.local.d.ts.map +1 -0
  175. package/build/model/consts.local.js +65 -0
  176. package/build/model/consts.local.js.map +1 -0
  177. package/build/model/consumer.d.ts +1 -10
  178. package/build/model/consumer.d.ts.map +1 -1
  179. package/build/model/consumer.js +7 -160
  180. package/build/model/consumer.js.map +1 -1
  181. package/build/model/estimate.d.ts.map +1 -1
  182. package/build/model/estimate.js +2 -27
  183. package/build/model/estimate.js.map +1 -1
  184. package/build/model/index.d.ts +1 -0
  185. package/build/model/index.d.ts.map +1 -1
  186. package/build/model/index.js +1 -0
  187. package/build/model/index.js.map +1 -1
  188. package/build/model/plan.js +1 -1
  189. package/build/model/plan.js.map +1 -1
  190. package/build/model/view.d.ts +1 -6
  191. package/build/model/view.d.ts.map +1 -1
  192. package/build/model/view.js +2 -73
  193. package/build/model/view.js.map +1 -1
  194. package/build/pricing/types.d.ts +13 -0
  195. package/build/pricing/types.d.ts.map +1 -0
  196. package/build/pricing/types.js +2 -0
  197. package/build/pricing/types.js.map +1 -0
  198. package/build/pricing.d.ts +7 -1
  199. package/build/pricing.d.ts.map +1 -1
  200. package/build/pricing.js +70 -59
  201. package/build/pricing.js.map +1 -1
  202. package/build/promo/types.d.ts +14 -0
  203. package/build/promo/types.d.ts.map +1 -0
  204. package/build/promo/types.js +2 -0
  205. package/build/promo/types.js.map +1 -0
  206. package/build/promo.d.ts +5 -9
  207. package/build/promo.d.ts.map +1 -1
  208. package/build/promo.js +17 -18
  209. package/build/promo.js.map +1 -1
  210. package/build/regions/types.d.ts +32 -0
  211. package/build/regions/types.d.ts.map +1 -0
  212. package/build/regions/types.js +2 -0
  213. package/build/regions/types.js.map +1 -0
  214. package/build/regions.d.ts +8 -42
  215. package/build/regions.d.ts.map +1 -1
  216. package/build/regions.js +40 -82
  217. package/build/regions.js.map +1 -1
  218. package/build/service.d.ts.map +1 -1
  219. package/build/service.js +10 -12
  220. package/build/service.js.map +1 -1
  221. package/build/types.d.ts +71 -0
  222. package/build/types.d.ts.map +1 -1
  223. package/build/types.local.d.ts +4 -0
  224. package/build/types.local.d.ts.map +1 -0
  225. package/build/types.local.js +2 -0
  226. package/build/types.local.js.map +1 -0
  227. package/build/view/types.d.ts +33 -0
  228. package/build/view/types.d.ts.map +1 -0
  229. package/build/view/types.js +2 -0
  230. package/build/view/types.js.map +1 -0
  231. package/build/view.d.ts +7 -24
  232. package/build/view.d.ts.map +1 -1
  233. package/build/view.js +71 -84
  234. package/build/view.js.map +1 -1
  235. package/package.json +11 -11
  236. package/src/advertise.ts +1 -14
  237. package/src/checkout/consts.ts +1 -0
  238. package/src/checkout/index.ts +3 -0
  239. package/src/checkout/narrow/types.ts +27 -0
  240. package/src/checkout/narrow.ts +53 -62
  241. package/src/checkout/protocols.ts +3 -24
  242. package/src/checkout/types.ts +27 -0
  243. package/src/consts.local.ts +34 -0
  244. package/src/consts.ts +161 -1
  245. package/src/consumer/cancel.ts +1 -2
  246. package/src/consumer/consts.local.ts +16 -0
  247. package/src/consumer/consts.ts +46 -0
  248. package/src/consumer/copy/types.ts +54 -0
  249. package/src/consumer/copy.ts +96 -101
  250. package/src/consumer/deadline/types.ts +30 -0
  251. package/src/consumer/deadline.ts +47 -68
  252. package/src/consumer/fifo/types.ts +17 -0
  253. package/src/consumer/fifo.ts +34 -63
  254. package/src/consumer/index.ts +8 -0
  255. package/src/consumer/policy/types.ts +20 -0
  256. package/src/consumer/policy.ts +62 -92
  257. package/src/consumer/protocols.ts +4 -79
  258. package/src/consumer/refund/types.ts +27 -0
  259. package/src/consumer/refund.ts +97 -152
  260. package/src/consumer/refusal.ts +2 -8
  261. package/src/consumer/revive/types.ts +23 -0
  262. package/src/consumer/revive.ts +57 -34
  263. package/src/consumer/types.local.ts +10 -0
  264. package/src/consumer/types.ts +189 -0
  265. package/src/countries.ts +1 -67
  266. package/src/entitled.ts +20 -0
  267. package/src/entitlement/types.ts +29 -0
  268. package/src/entitlement.ts +67 -128
  269. package/src/errors.ts +2 -47
  270. package/src/estimate/types.ts +34 -0
  271. package/src/estimate.ts +68 -102
  272. package/src/i18n/consumer-rights/be.json +12 -4
  273. package/src/i18n/consumer-rights/de.json +12 -4
  274. package/src/i18n/consumer-rights/en.json +12 -4
  275. package/src/i18n/consumer-rights/es.json +12 -4
  276. package/src/i18n/consumer-rights/fr.json +12 -4
  277. package/src/i18n/consumer-rights/pl.json +12 -4
  278. package/src/i18n/consumer-rights/ru.json +12 -4
  279. package/src/i18n/consumer-rights/uk.json +12 -4
  280. package/src/i18n.ts +26 -25
  281. package/src/index.ts +8 -1
  282. package/src/limit/types.ts +41 -0
  283. package/src/limit.ts +102 -110
  284. package/src/model/checkout.ts +1 -1
  285. package/src/model/consts.local.ts +83 -0
  286. package/src/model/consts.ts +206 -0
  287. package/src/model/consumer.ts +8 -183
  288. package/src/model/estimate.ts +3 -30
  289. package/src/model/index.ts +1 -0
  290. package/src/model/plan.ts +1 -1
  291. package/src/model/view.ts +3 -82
  292. package/src/pricing/types.ts +13 -0
  293. package/src/pricing.ts +94 -71
  294. package/src/promo/types.ts +18 -0
  295. package/src/promo.ts +31 -26
  296. package/src/regions/types.ts +42 -0
  297. package/src/regions.ts +60 -90
  298. package/src/service.ts +12 -21
  299. package/src/types.local.ts +5 -0
  300. package/src/types.ts +73 -0
  301. package/src/view/types.ts +39 -0
  302. package/src/view.ts +100 -101
  303. package/tests/checkout-narrow.spec.ts +19 -19
  304. package/tests/consumer-copy.spec.ts +228 -43
  305. package/tests/consumer-deadline.spec.ts +21 -22
  306. package/tests/consumer-fifo.spec.ts +12 -12
  307. package/tests/consumer-refund.spec.ts +27 -29
  308. package/tests/consumer-regions.spec.ts +39 -39
  309. package/tests/consumer-wire.spec.ts +52 -10
  310. package/tests/contract.spec.ts +3 -3
  311. package/tests/entitlement.spec.ts +26 -28
  312. package/tests/estimate.spec.ts +26 -26
  313. package/tests/limit.spec.ts +33 -36
  314. package/tests/pricing.spec.ts +10 -13
  315. package/tests/view.spec.ts +24 -24
package/README.md CHANGED
@@ -8,7 +8,7 @@ server integration (`@owlmeans/server-payment`) implements against these contrac
8
8
  ## Installation
9
9
 
10
10
  ```bash
11
- bun add @owlmeans/payment@^0.1.18-rc.46
11
+ bun add @owlmeans/payment@^0.1.18-rc.48
12
12
  ```
13
13
 
14
14
  ## Concepts
@@ -49,25 +49,23 @@ const proMonthly: ProductPlan = {
49
49
  Gate a route on a capability or on a limit:
50
50
 
51
51
  ```typescript
52
- import { ENTITLEMENT_GATE, LIMIT_GATE, entitled, formatLimitParam } from '@owlmeans/payment'
52
+ import { ENTITLEMENT_GATE, LIMIT_GATE, entitled, planLimitHelper } from '@owlmeans/payment'
53
53
 
54
54
  protocol(route(WHITELABEL, '/whitelabel', backend(BASE, RouteMethod.POST)), contract(typed()),
55
55
  entitled('feature:whitelabel'))
56
56
  protocol(route(INVITE, '/invite', backend(BASE, RouteMethod.POST)), contract(typed()),
57
- { gate: { alias: LIMIT_GATE, params: [formatLimitParam('seats')] } })
57
+ { gate: { alias: LIMIT_GATE, params: [planLimitHelper.formatLimitParam('seats')] } })
58
58
  ```
59
59
 
60
60
  Build and read an entitlement view:
61
61
 
62
62
  ```typescript
63
- import {
64
- capabilityOf, entitlementViewOf, hasLimitRoom, limitOf, reviveEntitlementView,
65
- } from '@owlmeans/payment'
66
-
67
- const view = entitlementViewOf(plan, planView, usage) // server
68
- const fromWire = reviveEntitlementView(await response.json()) // browser: ISO strings → Dates
69
- capabilityOf(fromWire, 'feature:whitelabel')
70
- hasLimitRoom(limitOf(fromWire, 'seats'))
63
+ import { entitlementViewHelper, planLimitHelper } from '@owlmeans/payment'
64
+
65
+ const view = entitlementViewHelper.entitlementViewOf(plan, planView, usage) // server
66
+ const fromWire = entitlementViewHelper.reviveEntitlementView(await response.json()) // browser: ISO strings → Dates
67
+ planLimitHelper.capabilityOf(fromWire, 'feature:whitelabel')
68
+ planLimitHelper.hasLimitRoom(planLimitHelper.limitOf(fromWire, 'seats'))
71
69
  ```
72
70
 
73
71
  Refuse and recover the fields on the other side of a service hop:
@@ -88,20 +86,22 @@ if (error instanceof LimitExhausted) { error.limitKey; error.used; error.limit;
88
86
  (`product`, `products`, `plans`, `plan`, `allPlans`, `localize`, `shallowAuthentication`),
89
87
  `l10nToId`, record types/prefixes.
90
88
  - Checkout: `CheckoutPricingMode`, `AmountCheckoutPolicy`/`QuantityCheckoutPolicy` (+ schemas),
91
- `assertAmountCheckoutPolicy`, `assertQuantityCheckoutPolicy`, `assertCheckoutAmount`,
92
- `chargeAmountMinor`, `CreateCheckoutBody` (`planSku`) / `CreateCheckoutResponse` (+ schemas),
89
+ `checkoutPricingHelper` (`assertAmountCheckoutPolicy`, `assertQuantityCheckoutPolicy`,
90
+ `assertCheckoutAmount`, `chargeAmountMinor`), `CreateCheckoutBody` (`planSku`) / `CreateCheckoutResponse` (+ schemas),
93
91
  `PortalFlow`, `PortalLinkBody` / `PortalLinkResponse` (+ schemas).
94
92
  - Entitlement grammar: `ENTITLEMENT_GATE`, `LIMIT_GATE`, `CAPABILITY_FEATURE_SCOPE`,
95
- `CAPABILITY_LIMIT_SCOPE`, `entitled`, `parseEntitlementParam`, `formatEntitlementParam`,
96
- `hasEntitlement`, `entitlementList`, `parseLimitParam`, `formatLimitParam`.
93
+ `CAPABILITY_LIMIT_SCOPE`, `entitled`, `entitlementParamHelper` (`parseEntitlementParam`,
94
+ `formatEntitlementParam`, `hasEntitlement`, `entitlementList`), `planLimitHelper`
95
+ (`parseLimitParam`, `formatLimitParam`).
97
96
  - Statuses: `SubscriptionStatus` (incl. `PastDue`), `ENTITLING_STATUSES`, `TERMINAL_STATUSES`,
98
97
  `INTERNAL_PAYGATE`.
99
98
  - Limits and promos: `LimitKind`, `LimitWindow`, `LimitDeclaration`, `PlanCapability`,
100
- `PromoDeclaration` (+ schemas), `windowKeyOf`, `windowBoundsOf`, `LIFETIME_WINDOW`,
101
- `OCCUPANCY_WINDOW`, `promoActive`, `promoViewOf`.
99
+ `PromoDeclaration` (+ schemas), `planLimitHelper` (`windowKeyOf`, `windowBoundsOf`),
100
+ `LIFETIME_WINDOW`, `OCCUPANCY_WINDOW`, `promoHelper` (`promoActive`, `promoViewOf`).
102
101
  - Views: `EntitlementView`, `EntitlementPlanView`, `CapabilityView`, `LimitView`, `PromoView`,
103
- `LimitUsage` (+ wire schemas), `capabilityViewsOf`, `limitViewsOf`, `entitlementViewOf`,
104
- `reviveEntitlementView`, `capabilityOf`, `limitOf`, `hasLimitRoom`.
102
+ `LimitUsage` (+ wire schemas), `entitlementViewHelper` (`capabilityViewsOf`, `limitViewsOf`,
103
+ `entitlementViewOf`, `reviveEntitlementView`), `planLimitHelper` (`capabilityOf`, `limitOf`,
104
+ `hasLimitRoom`).
105
105
  - Errors: `EntitlementRefusal` → `CapabilityRequired`, `LimitExhausted` (all `AuthForbidden`);
106
106
  `PaymentError` family incl. `LimitUnknown`, `LimitMisdeclared`, `PlanRequired`,
107
107
  `PlanRankConflict`, `WebhookSetupError`, `PortalUnavailable` (declares `httpStatus = 409`, so an
@@ -110,7 +110,7 @@ if (error instanceof LimitExhausted) { error.limitKey; error.used; error.limit;
110
110
 
111
111
  ## Common pitfalls
112
112
 
113
- - A limit parameter is never a capability: `hasEntitlement(sets, 'limit:x')` is always `false`.
113
+ - A limit parameter is never a capability: `entitlementParamHelper.hasEntitlement(sets, 'limit:x')` is always `false`.
114
114
  - A view's dates are ISO strings on the wire — revive before calling date methods.
115
115
  - A promo ends AT `until`; grandfathering needs the subscription's creation date on the plan view.
116
116
  - A refusal's fields survive a hop only through its message; catch the class, not the text.
@@ -129,7 +129,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
129
129
  your project's skill store (`.agents/skills/`):
130
130
 
131
131
  ```sh
132
- npx @owlmeans/agent-skills@^0.1.18-rc.46
132
+ npx @owlmeans/agent-skills@^0.1.18-rc.49
133
133
  ```
134
134
 
135
135
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/payment",
4
- "version": "0.1.18-rc.46",
5
- "generatedAt": "2026-10-03T15:33:53.023Z",
4
+ "version": "0.1.18-rc.48",
5
+ "generatedAt": "2026-10-05T21:03:06.402Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -116,7 +116,8 @@ Limits are event-sourced with synchronous admission:
116
116
 
117
117
  ## The entitlement view
118
118
 
119
- One read of an entity's position, built by `entitlementViewOf(plan, planView, usage, at)`:
119
+ One read of an entity's position, built by
120
+ `entitlementViewHelper.entitlementViewOf(plan, planView, usage, at)`:
120
121
 
121
122
  - `plan` — sku, rank, free, status, paygate, period, trial, cancel-at-period-end, past-due,
122
123
  fallback plan;
@@ -125,11 +126,11 @@ One read of an entity's position, built by `entitlementViewOf(plan, planView, us
125
126
  `windowStart`/`resetsAt` for window limits;
126
127
  - `at` — when it was computed.
127
128
 
128
- The server serves it; the browser reads it with the same `capabilityOf` / `limitOf` /
129
- `hasLimitRoom` the gate logic uses. On the wire every date is an ISO string — revive
130
- (`reviveEntitlementView`) before using a date. In the browser `null` means "not known yet": render
131
- paid controls disabled rather than enabled-then-refused, and an application with its own store
132
- reads the view through the pure selectors rather than polling it a second time.
129
+ The server serves it; the browser reads it with the same `planLimitHelper.capabilityOf` /
130
+ `limitOf` / `hasLimitRoom` the gate logic uses. On the wire every date is an ISO string — revive
131
+ (`entitlementViewHelper.reviveEntitlementView`) before using a date. In the browser `null` means
132
+ "not known yet": render paid controls disabled rather than enabled-then-refused, and an application
133
+ with its own store reads the view through the pure selectors rather than polling it a second time.
133
134
 
134
135
  ## Refusals
135
136
 
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/payment
9
9
 
10
10
  **Layer:** Core
11
- **Install:** `"@owlmeans/payment": "^0.1.18-rc.46"` in `dependencies`
11
+ **Install:** `"@owlmeans/payment": "^0.1.18-rc.48"` in `dependencies`
12
12
 
13
13
  The contracts half of payments: the catalogue (products, plans, localizations), amount- and
14
14
  quantity-priced checkout, the entitlement model — plan capabilities, counted limits, promos,
@@ -30,27 +30,27 @@ admission, the usage ledger, the two gate services — is the `entitlements` ski
30
30
  | `SubscriptionStatus` · `ENTITLING_STATUSES` · `TERMINAL_STATUSES` · `INTERNAL_PAYGATE` | Lifecycle vocabulary. `Active`/`Trial`/`PastDue` entitle; `Canceled`/`Expired`/`Ended`/`Blocked` are terminal; `Suspended` is revoked until resumed. |
31
31
  | `LimitKind` · `LimitWindow` · `PortalFlow` (+ schemas) | `window`/`lifetime`/`occupancy`; `day`/`month`; `manage`/`cancel`/`update`/`change`/`payment-method`. |
32
32
  | `ENTITLEMENT_GATE` · `LIMIT_GATE` · `CAPABILITY_FEATURE_SCOPE` · `CAPABILITY_LIMIT_SCOPE` | The two gate aliases and the two reserved scopes (`feature` for flags, `limit` for limit parameters). |
33
- | `entitled` · `parseEntitlementParam` · `formatEntitlementParam` · `hasEntitlement` · `entitlementList` | The capability grammar and predicate. |
34
- | `parseLimitParam` · `formatLimitParam` · `windowKeyOf` · `windowBoundsOf` · `LIFETIME_WINDOW` · `OCCUPANCY_WINDOW` | The limit grammar and window algebra. |
35
- | `promoActive` · `promoViewOf` | Whether a promo is in force for one subscription at one instant. |
33
+ | `entitled` · `entitlementParamHelper` (`parseEntitlementParam` · `formatEntitlementParam` · `hasEntitlement` · `entitlementList`) | The capability grammar and predicate. |
34
+ | `planLimitHelper` (`parseLimitParam` · `formatLimitParam` · `windowKeyOf` · `windowBoundsOf`) · `LIFETIME_WINDOW` · `OCCUPANCY_WINDOW` | The limit grammar and window algebra. |
35
+ | `promoHelper` (`promoActive` · `promoViewOf`) | Whether a promo is in force for one subscription at one instant. |
36
36
  | `EntitlementView` · `EntitlementPlanView` · `CapabilityView` · `LimitView` · `PromoView` · `LimitUsage` (+ wire schemas) | The entitlement view and its rows. |
37
- | `capabilityViewsOf` · `limitViewsOf` · `entitlementViewOf` · `reviveEntitlementView` · `capabilityOf` · `limitOf` · `hasLimitRoom` | Pure view builders and readers. |
37
+ | `entitlementViewHelper` (`capabilityViewsOf` · `limitViewsOf` · `entitlementViewOf` · `reviveEntitlementView`) · `planLimitHelper` (`capabilityOf` · `limitOf` · `hasLimitRoom`) | Pure view builders and readers. |
38
38
  | `CreateCheckoutBody` (`planSku`, `country`, `startRequestId`) · `CreateCheckoutResponse` · `PortalLinkBody` · `PortalLinkResponse` (+ schemas) | Wire shapes an application's own checkout and portal protocols use. |
39
- | `CheckoutPricingMode` · `AmountCheckoutPolicy` / `QuantityCheckoutPolicy` (+ schemas) · `assertAmountCheckoutPolicy` · `assertQuantityCheckoutPolicy` · `assertCheckoutAmount` · `chargeAmountMinor` | Checkout pricing policies and their validation. |
40
- | `PricingPolicy` (+ schema) · `DEFAULT_PRICING_POLICY` · `assertPricingPolicy` · `TaxBehavior` · `TaxEstimateStatus` · `TaxType` (+ schemas) | Declared tax/currency behaviour (see § Pricing policy and tax estimate). |
41
- | `PriceEstimate` · `PriceEstimateBody` · `TaxEstimate` · `TaxRateEstimate` (+ schemas) · `estimateOf` · `ratePpmOf` | The tax/local-currency estimate read model and its pure math. |
39
+ | `CheckoutPricingMode` · `AmountCheckoutPolicy` / `QuantityCheckoutPolicy` (+ schemas) · `checkoutPricingHelper` (`assertAmountCheckoutPolicy` · `assertQuantityCheckoutPolicy` · `assertCheckoutAmount` · `chargeAmountMinor`) | Checkout pricing policies and their validation. |
40
+ | `PricingPolicy` (+ schema) · `DEFAULT_PRICING_POLICY` · `priceEstimateHelper.assertPricingPolicy` · `TaxBehavior` · `TaxEstimateStatus` · `TaxType` (+ schemas) | Declared tax/currency behaviour (see § Pricing policy and tax estimate). |
41
+ | `PriceEstimate` · `PriceEstimateBody` · `TaxEstimate` · `TaxRateEstimate` (+ schemas) · `priceEstimateHelper` (`estimateOf` · `ratePpmOf`) | The tax/local-currency estimate read model and its pure math. |
42
42
  | `COUNTRY_CURRENCIES` · `currencyOfCountry` · `COUNTRY_CODES` · `CountrySchema` | ISO 3166-1 → ISO 4217 reference map for a country picker. |
43
43
  | `EntitlementRefusal` · `CapabilityRequired` · `LimitExhausted` | Entitlement refusals — all `AuthForbidden` (403). |
44
44
  | `PaymentError` · `PaygateError` · `UnknownPaygate` · `PaygateMappingError` · `WebhookSetupError` · `PortalUnavailable` · `ProductError` · `UnknownProduct` · `UnknownPlan` · `PlanRequired` · `PlanRankConflict` · `LimitUnknown` · `LimitMisdeclared` · `PaymentIdentificationError` · `SubscriptionError` · `UnknownSubscription` · `ConsumerRightsError` | Faults (500), except `PortalUnavailable` (409). Importing the package registers every type's message under `errors.<type>` in eight languages (the seven of `SUPPORTED_LNGS` plus `fr`). |
45
45
  | `ConsumerRightsRefusal` · `PerformanceConsentRequired` · `SubscriptionStartRequired` (428) · `BillingCountryLocked` · `WithdrawalUnavailable` · `CancellationUnavailable` · `CheckoutLimitExceeded` (409) · `consentRefusalOf` | Consumer-rights and checkout-limit refusals — declared statuses, never `AuthForbidden` (§ Consumer rights). |
46
46
  | `ConsumerRegion` · `PurchaseKind` · `ConsentKind` · `DeclarationKind` · `DeclarationChannel` · `CancellationKind` · `WithdrawalStatus` · `CancellationStatus` · `WithdrawalUnavailableReason` · `CancellationUnavailableReason` (+ schemas) | Consumer-rights vocabulary. |
47
- | `EU_COUNTRIES` · `EU_CONSUMER_TERRITORIES` · `EEA_EXTRA` · `CONSUMER_RIGHTS_TERRITORIES` · `COUNTRY_LANGUAGES` · `isEuCountry` · `isEeaCountry` · `regionOf` · `inScope` · `chargeCurrencyOf` · `billingLanguageOf` | Territories, region, scope, charge currency, legal language. |
48
- | `ConsumerRightsPolicy` (+ `Links`, `Mechanisms`, schemas) · `DEFAULT_CONSUMER_RIGHTS` · `makeConsumerRightsPolicy` · `assertConsumerRightsPolicy` · `linksOf` · `CONSUMER_RIGHTS_RECORD_TYPE`/`_ID` | The consumer-rights policy record. |
49
- | `BillingProfileView` · `PurchaseView`/`List` · `PerformanceConsentView`/`Body`/`Response` · `SubscriptionStartView`/`Query`/`Body`/`Response` · `WithdrawalEstimate` · `WithdrawalCandidate`/`List` · `WithdrawalBody` · `DeclarationReceipt` · `WithdrawalReceipt` · `CancellationBody` · `CancellationReceipt` · `ConsumerRightsPublicView` (+ schemas) · `revive*` | Consumer-rights wire shapes (ISO dates) and their revivers. |
50
- | `withdrawalDeadlineOf` · `lastWithdrawalDayOf` · `withdrawalOpen` · `oneTimeWithdrawalRefund` · `subscriptionWithdrawalRefund` · `splitByShares` · `allocateFifo` · `unitsUsedAfter` · `cancellationEffectiveAt` | Pure calculators. |
51
- | `CONSUMER_RIGHTS_RESOURCE` · `CONSUMER_RIGHTS_COPY_VERSION` · `consumerRightsCopy` · `consumerText` · `consentStatementOf` · `legalLabelsOf` · `placeholdersOf` | The legal copy. |
47
+ | `EU_COUNTRIES` · `EU_CONSUMER_TERRITORIES` · `EEA_EXTRA` · `CONSUMER_RIGHTS_TERRITORIES` · `COUNTRY_LANGUAGES` · `consumerRegionHelper` (`isEuCountry` · `isEeaCountry` · `regionOf` · `inScope` · `chargeCurrencyOf` · `billingLanguageOf`) | Territories, region, scope, charge currency, legal language. |
48
+ | `ConsumerRightsPolicy` (+ `Links`, `Mechanisms`, schemas) · `DEFAULT_CONSUMER_RIGHTS` · `makeConsumerRightsPolicy` · `consumerRightsPolicyHelper` (`assertConsumerRightsPolicy` · `linksOf`) · `CONSUMER_RIGHTS_RECORD_TYPE`/`_ID` | The consumer-rights policy record. |
49
+ | `BillingProfileView` · `PurchaseView`/`List` · `PerformanceConsentView`/`Body`/`Response` · `SubscriptionStartView`/`Query`/`Body`/`Response` · `WithdrawalEstimate` · `WithdrawalCandidate`/`List` · `WithdrawalBody` · `DeclarationReceipt` · `WithdrawalReceipt` · `CancellationBody` · `CancellationReceipt` · `ConsumerRightsPublicView` (+ schemas) · `consumerReviveHelper.revive*` | Consumer-rights wire shapes (ISO dates) and their revivers. |
50
+ | `withdrawalDeadlineHelper` (`withdrawalDeadlineOf` · `lastWithdrawalDayOf` · `withdrawalOpen`) · `withdrawalRefundHelper` (`oneTimeWithdrawalRefund` · `subscriptionWithdrawalRefund` · `splitByShares`) · `fifoHelper` (`allocateFifo` · `unitsUsedAfter`) · `cancellationEffectiveAt` | Pure calculators. |
51
+ | `CONSUMER_RIGHTS_RESOURCE` · `CONSUMER_RIGHTS_COPY_VERSION` · `consumerCopyHelper` (`consumerRightsCopy` · `consumerText` · `consentStatementOf` · `startContextOf` · `legalLabelsOf` · `placeholdersOf`) | The legal copy and the start statement's variant. |
52
52
  | `makeConsumerRightsProtocols` · `makeCheckoutReadProtocols` | Protocol factories. |
53
- | `AmountNarrowing` · `narrowAmountPolicy` · `amountAllowed` · `CheckoutLimitView` · `AmountPolicyView`/`Query` · `PlanPriceView`/`List`/`PlanPricesQuery` (+ schemas) | Per-entity narrowing of an amount checkout, and synced plan prices. |
53
+ | `AmountNarrowing` · `amountNarrowingHelper` (`narrowAmountPolicy` · `amountAllowed`) · `CheckoutLimitView` · `AmountPolicyView`/`Query` · `PlanPriceView`/`List`/`PlanPricesQuery` (+ schemas) | Per-entity narrowing of an amount checkout, and synced plan prices. |
54
54
 
55
55
  Subpath: `./utils` — the `Config` / `Context` aliases to type your own context against.
56
56
 
@@ -99,13 +99,14 @@ A **limit** is counted: a `LimitDeclaration` under a key in `plan.limits`, asked
99
99
  limit:<key>[>=<n>]
100
100
 
101
101
  - **`limit` is a reserved scope.** A plan never declares a capability set under it,
102
- `hasEntitlement` answers `false` for any `limit:` parameter, and the view builders skip such a
103
- set. A limit requirement can therefore never be satisfied by a capability grant.
102
+ `entitlementParamHelper.hasEntitlement` answers `false` for any `limit:` parameter, and the view
103
+ builders skip such a set. A limit requirement can therefore never be satisfied by a capability
104
+ grant.
104
105
  - **One grammar, two gate services.** Capability parameters go to `ENTITLEMENT_GATE`
105
106
  (`entitled(params)` is sugar for it), limit parameters to `LIMIT_GATE`
106
- (`{ gate: { alias: LIMIT_GATE, params: [formatLimitParam(key)] } }`). The aliases differ because
107
- the framework collects an entrypoint's gates per gate service — one alias would let one
108
- requirement hide the other.
107
+ (`{ gate: { alias: LIMIT_GATE, params: [planLimitHelper.formatLimitParam(key)] } }`). The aliases
108
+ differ because the framework collects an entrypoint's gates per gate service — one alias would let
109
+ one requirement hide the other.
109
110
  - **`@` is deliberately not part of the grammar.** That is `@owlmeans/iam`'s resource-selector
110
111
  syntax; reusing it would make two different things look identical in a route declaration.
111
112
  - **Keep flags, magnitudes and counts apart.** `CAPABILITY_FEATURE_SCOPE` carries booleans; a
@@ -114,16 +115,17 @@ A **limit** is counted: a `LimitDeclaration` under a key in `plan.limits`, asked
114
115
  with it.
115
116
  - **A floor is a numeric question.** `>=n` passes only for a number at least that big — a boolean
116
117
  flag, however true, does not answer it. For a limit, `>=n` asks for `n` units of room.
117
- - **A malformed parameter answers `false` / `null`, it never throws.** `hasEntitlement` refuses,
118
- `parseLimitParam` returns `null` for a capability parameter, a bare key, an empty key or a floor
119
- that is not positive. A gate that crashed on a typo would take down the endpoint it guards.
118
+ - **A malformed parameter answers `false` / `null`, it never throws.**
119
+ `entitlementParamHelper.hasEntitlement` refuses, `planLimitHelper.parseLimitParam` returns `null`
120
+ for a capability parameter, a bare key, an empty key or a floor that is not positive. A gate that
121
+ crashed on a typo would take down the endpoint it guards.
120
122
  - **Declare the requirement on the protocol, not in the handler.** The framework asserts gates
121
123
  before the handler is entered, so the route table states what a feature costs. Several
122
124
  parameters of one gate are OR'd. The gate services themselves live in the server integration.
123
125
 
124
126
  ## The three limit kinds
125
127
 
126
- | Kind | Window key (`windowKeyOf`) | Renews | Typical use |
128
+ | Kind | Window key (`planLimitHelper.windowKeyOf`) | Renews | Typical use |
127
129
  |---|---|---|---|
128
130
  | `window` + `day` | `YYYY-MM-DD` | at UTC midnight | per-day actions |
129
131
  | `window` + `month` | `YYYY-MM` | on the 1st, UTC | per-month actions |
@@ -132,8 +134,8 @@ A **limit** is counted: a `LimitDeclaration` under a key in `plan.limits`, asked
132
134
 
133
135
  - Windows are **calendar UTC**, never rolling and never local: two servers in two zones must agree
134
136
  on which counter a unit lands in.
135
- - `windowBoundsOf(window, at)` returns `start` inclusive and `resetsAt` **exclusive** — `resetsAt`
136
- is the first instant of the next window and already belongs to it.
137
+ - `planLimitHelper.windowBoundsOf(window, at)` returns `start` inclusive and `resetsAt`
138
+ **exclusive** — `resetsAt` is the first instant of the next window and already belongs to it.
137
139
  - A `window` limit without a known `window` (or an unknown kind) throws `LimitMisdeclared`: a
138
140
  misdeclared plan is loud, not a silently unlimited one.
139
141
  - `limit: 0` means "not included" — a declared key with no room, which a UI renders as such.
@@ -147,30 +149,32 @@ A **limit** is counted: a `LimitDeclaration` under a key in `plan.limits`, asked
147
149
  - A lapsed promo makes a capability `granted: false` and a limit's `limit: 0` — the row stays in
148
150
  the view with `promo.active: false`, so a UI can say the promotion ended rather than pretend the
149
151
  feature never existed.
150
- - `promoViewOf` → `{ until, grandfathered, active }` is what a UI inscribes: active and not
151
- grandfathered ⇒ "free until"; grandfathered ⇒ "kept for your plan"; inactive ⇒ "ended".
152
+ - `promoHelper.promoViewOf` → `{ until, grandfathered, active }` is what a UI inscribes: active and
153
+ not grandfathered ⇒ "free until"; grandfathered ⇒ "kept for your plan"; inactive ⇒ "ended".
152
154
  - An unparseable `until` is never in force.
153
155
 
154
156
  ## The entitlement view
155
157
 
156
- `entitlementViewOf(plan, planView, usage, at?)` is the one read of what an entity may do:
158
+ `entitlementViewHelper.entitlementViewOf(plan, planView, usage, at?)` is the one read of what an
159
+ entity may do:
157
160
 
158
161
  - `plan` — the `EntitlementPlanView` the caller resolved (sku, rank, free, status, paygate,
159
162
  period, trial, cancel-at-period-end, past-due, fallback). **Promos are measured against
160
163
  `planView.subscribedAt`** — set it to the subscription's creation date, or nothing is
161
164
  grandfathered.
162
- - `capabilities` — `capabilityViewsOf`: one row per non-null, non-false permission, `param`
165
+ - `capabilities` — its `capabilityViewsOf`: one row per non-null, non-false permission, `param`
163
166
  exactly as the capability gate takes it.
164
- - `limits` — `limitViewsOf`: one row per declared key; `used` from the `LimitUsage` row of the
167
+ - `limits` — its `limitViewsOf`: one row per declared key; `used` from the `LimitUsage` row of the
165
168
  CURRENT window (none ⇒ `0`); `remaining = max(0, limit - used)`; `windowStart`/`resetsAt` only
166
169
  for a window limit.
167
- - Read it with `capabilityOf(view, param)` (the same predicate as the gate, over granted rows),
168
- `limitOf(view, key)` and `hasLimitRoom(limitView, atLeast)`. The server gate and the browser
169
- call the same functions, so the UI's "disabled" and the server's refusal cannot disagree.
170
+ - Read it with `planLimitHelper.capabilityOf(view, param)` (the same predicate as the gate, over
171
+ granted rows), `planLimitHelper.limitOf(view, key)` and
172
+ `planLimitHelper.hasLimitRoom(limitView, atLeast)`. The server gate and the browser call the same
173
+ functions, so the UI's "disabled" and the server's refusal cannot disagree.
170
174
  - **The wire carries dates as ISO strings.** The view schemas describe that
171
175
  (`{ type: 'string', format: 'date-time' }`): a response serializer writes a `Date` through it as
172
176
  ISO, while the record convention (`DateSchema`, an object) would serialize it as `{}`. A browser
173
- calls `reviveEntitlementView` before touching a date.
177
+ calls `entitlementViewHelper.reviveEntitlementView` before touching a date.
174
178
 
175
179
  ## Refusals and faults
176
180
 
@@ -229,9 +233,9 @@ infer a pricing mode from the presence of `amountMinor`.
229
233
 
230
234
  The plan's `amountPolicy` is the same for everyone; what one entity may buy NOW is narrower when a
231
235
  checkout plugin (a spending tier, a rolling cap, a fraud hold) answers an `AmountNarrowing`
232
- `{ maximumMinor, reason, resetsAt?, remainingMinor? }`. `narrowAmountPolicy(base, narrowings,
233
- { productSku?, planSku? })` is the one computation the server's refusal and the dialog's control
234
- share, so they cannot disagree:
236
+ `{ maximumMinor, reason, resetsAt?, remainingMinor? }`.
237
+ `amountNarrowingHelper.narrowAmountPolicy(base, narrowings, { productSku?, planSku? })` is the one
238
+ computation the server's refusal and the dialog's control share, so they cannot disagree:
235
239
 
236
240
  - the maximum is the smallest of the base maximum and every narrowing's (negative or fractional
237
241
  values floor at 0); `reason`/`resetsAt`/`remainingMinor` come from the narrowing that set it,
@@ -239,10 +243,11 @@ share, so they cannot disagree:
239
243
  - presets above the maximum are dropped, the default is clamped into `[minimum, maximum]`;
240
244
  - `limit` is `null` when nothing lowered the base maximum — no note to show;
241
245
  - **`limit.blocked`** (`limit.maximumMinor < base.minimumMinor`) means no amount may be bought now.
242
- The returned `policy` is then still a VALID policy (`assertAmountCheckoutPolicy` accepts it),
243
- pinned to the minimum with no presets, so a validator never throws — but it is NOT an offer of
244
- the minimum: a UI disables the input and the confirm button on `blocked`, and a server refuses
245
- every amount with `CheckoutLimitExceeded`. `amountAllowed(view, amount)` answers exactly that.
246
+ The returned `policy` is then still a VALID policy
247
+ (`checkoutPricingHelper.assertAmountCheckoutPolicy` accepts it), pinned to the minimum with no
248
+ presets, so a validator never throws — but it is NOT an offer of the minimum: a UI disables the
249
+ input and the confirm button on `blocked`, and a server refuses every amount with
250
+ `CheckoutLimitExceeded`. `amountNarrowingHelper.amountAllowed(view, amount)` answers exactly that.
246
251
 
247
252
  `CheckoutLimitExceeded` (409) packs `checkout-limit-exceeded:<encodeURIComponent(reason)>:
248
253
  <maximumMinor>:<currency>[:<resetsAt ISO>]` and rebuilds `reason`, `maximumMinor`, `currency`,
@@ -267,17 +272,18 @@ billing country is locked and overrides the request — a picker then shows it a
267
272
  it), `region`, `currency`, `behavior`, `tax: TaxEstimate` (`status`
268
273
  one of `TaxEstimateStatus` — `taxed`/`reverse-charge`/`none`/`at-checkout`/`location-required` —
269
274
  plus `subtotalMinor`/`taxMinor`/`totalMinor`, `scalable`, and `rates: TaxRateEstimate[]` with
270
- `ratePpm` parsed by `ratePpmOf` from Stripe's `percentage_decimal`, never `Number(x) * 10_000`),
271
- and an optional `local` (currency + `exchangeRate`, from Stripe's FX Quotes). The pure helper
272
- `estimateOf(amountMinor, estimate)` re-derives tax and a total for a DIFFERENT amount than the
273
- estimate's own reference one — exact only when `scalable` and the behavior is `Exclusive`; both
274
- `taxMinor`/`totalMinor` come back `null` otherwise, meaning "computed at checkout", never a wrong
275
- number. When the source estimate carries `local`, the result's own `local` gives the subtotal, tax
276
- and total in THAT currency (`subtotalAmount`/`taxAmount`/`totalAmount`, major units) alongside the
277
- integration-currency ones — a UI shows one or the other, marking the local figures `≈`, never both
278
- side by side. `COUNTRY_CURRENCIES` / `currencyOfCountry` / `COUNTRY_CODES` is a reference ISO 3166-1 →
279
- ISO 4217 map for a country picker and the local-currency lookup — not a Stripe list, and a country
280
- absent from it still gets a tax estimate, just no local-currency line.
275
+ `ratePpm` parsed by `priceEstimateHelper.ratePpmOf` from Stripe's `percentage_decimal`, never
276
+ `Number(x) * 10_000`), and an optional `local` (currency + `exchangeRate`, from Stripe's FX Quotes).
277
+ The pure helper `priceEstimateHelper.estimateOf(amountMinor, estimate)` re-derives tax and a total
278
+ for a DIFFERENT amount than the estimate's own reference one — exact only when `scalable` and the
279
+ behavior is `Exclusive`; both `taxMinor`/`totalMinor` come back `null` otherwise, meaning "computed
280
+ at checkout", never a wrong number. When the source estimate carries `local`, the result's own
281
+ `local` gives the subtotal, tax and total in THAT currency
282
+ (`subtotalAmount`/`taxAmount`/`totalAmount`, major units) alongside the integration-currency ones —
283
+ a UI shows one or the other, marking the local figures `≈`, never both side by side.
284
+ `COUNTRY_CURRENCIES` / `currencyOfCountry` / `COUNTRY_CODES` is a reference ISO 3166-1 → ISO 4217
285
+ map for a country picker and the local-currency lookup — not a Stripe list, and a country absent
286
+ from it still gets a tax estimate, just no local-currency line.
281
287
 
282
288
  ## Consumer rights (EU withdrawal, cancellation, country lock)
283
289
 
@@ -291,13 +297,14 @@ Nothing here is product copy — the trader, plan and product names are placehol
291
297
  - `EU_COUNTRIES` (27, Greece is `GR`), `EU_CONSUMER_TERRITORIES` (plus AX, GF, GP, MQ, RE, YT, MF —
292
298
  consumer law applies there even where EU VAT does not), `EEA_EXTRA` (IS, LI, NO) and their union
293
299
  `CONSUMER_RIGHTS_TERRITORIES`, the default `policy.countries`.
294
- - `regionOf(country, policy?)`: `Eu` inside the policy's territories, `Other` outside, `null` for no
295
- country. `inScope(region, country, policy)`: a known country decides by the territories, else a
296
- known region, else `unknownCountry` — `'protect'` by default, so an unknown buyer is protected.
297
- - `chargeCurrencyOf(region, policy, fallback)`: the policy's currency for the region; an unknown
298
- region reads as `Eu`. The display currency is the charge currency, everywhere.
299
- - `billingLanguageOf(country, policy?, fallback?)`: `policy.languages`, then `COUNTRY_LANGUAGES`
300
- (unambiguous countries only — BE, LU, CH are absent), then `fallback`, then
300
+ - `consumerRegionHelper.regionOf(country, policy?)`: `Eu` inside the policy's territories, `Other`
301
+ outside, `null` for no country. `consumerRegionHelper.inScope(region, country, policy)`: a known
302
+ country decides by the territories, else a known region, else `unknownCountry` — `'protect'` by
303
+ default, so an unknown buyer is protected.
304
+ - `consumerRegionHelper.chargeCurrencyOf(region, policy, fallback)`: the policy's currency for the
305
+ region; an unknown region reads as `Eu`. The display currency is the charge currency, everywhere.
306
+ - `consumerRegionHelper.billingLanguageOf(country, policy?, fallback?)`: `policy.languages`, then
307
+ `COUNTRY_LANGUAGES` (unambiguous countries only — BE, LU, CH are absent), then `fallback`, then
301
308
  `policy.defaultLanguage`. Legal copy is shown in this language, with a toggle to the UI language.
302
309
 
303
310
  ### The policy record
@@ -307,56 +314,66 @@ server integration through `makeConsumerRightsPolicy(def)` — `DEFAULT_CONSUMER
307
314
  (14 days, weekend rollover, margin 5 — a period ending on a public holiday runs to the next working
308
315
  day and holiday clusters need up to five, no per-country calendar is kept —, every mechanism OFF,
309
316
  `defaultLanguage: 'en'`, start requests
310
- usable 3600 s) — and `assertConsumerRightsPolicy` (non-empty `textVersion`, `^[A-Z]{2}$`
311
- countries, `withdrawalDays >= 14`, margin 0..7, lowercase currencies, https links, the default
312
- language present, `withdrawalInformation` required while `withdrawal` or `performanceConsent` is
313
- on; throws `ConsumerRightsError('policy:<field>')`). It carries only public links, territories
314
- and switches — mail options live in a backend-only plugin config — so it is ADVERTISED to the
315
- browser like the pricing policy. `PaymentService.consumerRightsPolicy()` answers `null` when none
316
- is declared: no consumer-rights behaviour at all. `linksOf(policy, lng)` merges a language's links
317
- field by field over the default language's (`de-AT` reads `de`).
317
+ usable 3600 s) — and `consumerRightsPolicyHelper.assertConsumerRightsPolicy` (non-empty
318
+ `textVersion`, `^[A-Z]{2}$` countries, `withdrawalDays >= 14`, margin 0..7, lowercase currencies,
319
+ https links, the default language present, `withdrawalInformation` required while `withdrawal` or
320
+ `performanceConsent` is on, `consentContext` a lowercase key `^[a-z][a-z0-9-]*$`; throws
321
+ `ConsumerRightsError('policy:<field>')`). It carries only public links, territories, switches and
322
+ the consent context — mail options live in a backend-only plugin config — so it is ADVERTISED to the
323
+ browser like the pricing policy. **`consentContext`** names the copy variant of the performance
324
+ consent (`'included'`: the credit limits included in a plan are used first, so the consent covers
325
+ topped-up credits once those limits have run out): the server records and mails, and the dialog
326
+ shows, the `_<context>` texts (§ The legal copy); absent, the base texts.
327
+ `PaymentService.consumerRightsPolicy()` answers `null` when none is declared: no consumer-rights
328
+ behaviour at all. `consumerRightsPolicyHelper.linksOf(policy, lng)` merges a language's links field
329
+ by field over the default language's (`de-AT` reads `de`).
318
330
 
319
331
  `ProductPlan.withdrawal.components: PlanWithdrawalComponent[]` (`{ key, basis: 'time' | 'units',
320
332
  shareMinor }`) states the separately priced parts of a subscription (CJEU C-641/19 PE Digital:
321
- without them the whole price is pro rata by time).
333
+ without them the whole price is pro rata by time). The same declaration picks the subscription start
334
+ statement: a `units` part makes it the `_units` variant (`consumerCopyHelper.startContextOf`, § The
335
+ legal copy).
322
336
 
323
337
  ### Wire views
324
338
 
325
339
  Every view schema carries dates as ISO strings (as `model/view.ts` does) and is revived with its
326
- `revive*` helper (`reviveConsentView`, `revivePurchase`/`List`, `reviveBillingProfile`,
327
- `reviveConsentResponse`, `reviveStartResponse`, `reviveWithdrawalList`, `reviveReceipt`,
328
- `reviveCheckoutLimit`, `reviveAmountPolicyView`) — idempotent. A nullable enum on the wire lists
329
- `null` in its enum (ajv rejects `null` otherwise). The consent and start views carry `trader`, the
330
- name the statement is rendered with, so the server's record and the dialog's text are identical.
331
- `WithdrawalBody` and `CancellationBody` ask only for name, contract and e-mail (plus the
332
- cancellation kind, reason and date) and accept an optional `honeypot` a person never fills. A
333
- public declaration answers `DeclarationReceipt` — what was declared and when, never whether a
334
- contract matched.
340
+ `consumerReviveHelper.revive*` member (`reviveConsentView`, `revivePurchase`/`List`,
341
+ `reviveBillingProfile`, `reviveConsentResponse`, `reviveStartResponse`, `reviveWithdrawalList`,
342
+ `reviveReceipt`, `reviveCheckoutLimit`, `reviveAmountPolicyView`) — idempotent. A nullable enum on
343
+ the wire lists `null` in its enum (ajv rejects `null` otherwise). The consent and start views carry
344
+ `trader`, the name the statement is rendered with, and `context`, the variant it is rendered with —
345
+ the consent view the policy's `consentContext`, the start view
346
+ `consumerCopyHelper.startContextOf(plan)` (`'units'`), each absent for the base — so the server's
347
+ record and the dialog's text are identical. `WithdrawalBody` and `CancellationBody` ask only for
348
+ name, contract and e-mail (plus the cancellation kind, reason and date) and accept an optional
349
+ `honeypot` a person never fills. A public declaration answers `DeclarationReceipt` — what was
350
+ declared and when, never whether a contract matched.
335
351
 
336
352
  ### Calculators — always in the consumer's favour
337
353
 
338
354
  All amounts in BigInt; a deduction rounds DOWN, a refund rounds UP, a refund never exceeds what is
339
355
  still unrefunded.
340
356
 
341
- - `withdrawalDeadlineOf(purchasedAt, rule | policy)` → the EXCLUSIVE end: the purchase's UTC day +
342
- `days`, a Saturday/Sunday last day moved to Monday, + `marginDays`, start of the next UTC day.
343
- Wed 2026-09-23 → 2026-10-13T00:00Z; Sat 2026-09-26 → 2026-10-18T00:00Z; Sun 2026-12-20 →
344
- 2027-01-10T00:00Z (margin 5). `withdrawalOpen(window, at)` — before the deadline, not withdrawn,
345
- not refunded. **A person is shown the last included day**, `lastWithdrawalDayOf(deadline)` (the
346
- UTC day of `deadline − 1 ms`), phrased "until the end of <date>" — never the exclusive instant.
347
- - `oneTimeWithdrawalRefund({ paidMinor, refundedMinor?, unitsGranted, unitsUsed })` →
348
- `min(paid − refunded, ceil(paid × (granted − used) / granted))`; `unitsUsed` is the deduction —
357
+ - `withdrawalDeadlineHelper.withdrawalDeadlineOf(purchasedAt, rule | policy)` → the EXCLUSIVE end:
358
+ the purchase's UTC day + `days`, a Saturday/Sunday last day moved to Monday, + `marginDays`, start
359
+ of the next UTC day. Wed 2026-09-23 → 2026-10-13T00:00Z; Sat 2026-09-26 → 2026-10-18T00:00Z; Sun
360
+ 2026-12-20 → 2027-01-10T00:00Z (margin 5). `withdrawalDeadlineHelper.withdrawalOpen(window, at)` —
361
+ before the deadline, not withdrawn, not refunded. **A person is shown the last included day**,
362
+ `withdrawalDeadlineHelper.lastWithdrawalDayOf(deadline)` (the UTC day of `deadline − 1 ms`),
363
+ phrased "until the end of <date>" — never the exclusive instant.
364
+ - `withdrawalRefundHelper.oneTimeWithdrawalRefund({ paidMinor, refundedMinor?, unitsGranted, unitsUsed })`
365
+ → `min(paid − refunded, ceil(paid × (granted − used) / granted))`; `unitsUsed` is the deduction —
349
366
  units used AFTER consent (none before it) plus debt settled from the lot plus units already
350
367
  clawed back (`@owlmeans/server-payment` passes the meter's `usedAfter + settled + clawed`);
351
368
  returns `unitsReturned`. 1256 paid, 125k of 500k used → 942.
352
- - `subscriptionWithdrawalRefund(...)` splits `netMinor` by the components (`splitByShares`, largest
353
- remainder); a `time` part loses `floor(c × elapsedDays / periodDays)` counted from
354
- `max(periodStart, servicesRequestedAt)` — NOTHING without a start request; a `units` part loses
355
- `floor(c × used / granted)`; gross = `ceil(paid × refundNet / net)`. Net 2000 / paid 2460, 3 of 30
356
- days and 100k of 500k used → 2091.
357
- - `allocateFifo(lots, spends)` — a spend takes the oldest lot granted at or before it; overflow is
358
- `unallocated`. `unitsUsedAfter(lot, consentedAt)` counts slices strictly after the consent, `0`
359
- without one.
369
+ - `withdrawalRefundHelper.subscriptionWithdrawalRefund(...)` splits `netMinor` by the components
370
+ (its `splitByShares`, largest remainder); a `time` part loses
371
+ `floor(c × elapsedDays / periodDays)` counted from `max(periodStart, servicesRequestedAt)` —
372
+ NOTHING without a start request; a `units` part loses `floor(c × used / granted)`; gross =
373
+ `ceil(paid × refundNet / net)`. Net 2000 / paid 2460, 3 of 30 days and 100k of 500k used → 2091.
374
+ - `fifoHelper.allocateFifo(lots, spends)` — a spend takes the oldest lot granted at or before it;
375
+ overflow is `unallocated`. `fifoHelper.unitsUsedAfter(lot, consentedAt)` counts slices strictly
376
+ after the consent, `0` without one.
360
377
  - `cancellationEffectiveAt(periodEnd, 'month' | 'year', requested?)` — the period end, or the first
361
378
  boundary on or after a later requested date (end-of-month clamped from the anchor).
362
379
 
@@ -386,10 +403,11 @@ The i18n resource `payment-consumer-rights` (`CONSUMER_RIGHTS_RESOURCE`, library
386
403
  namespace), in en pl ru be uk es de fr, versioned by `CONSUMER_RIGHTS_COPY_VERSION` (bump it on ANY
387
404
  change to a bundle). Branches: `performance-consent`, `subscription-start` (`title`, `intro`,
388
405
  `request`, `acknowledgement`, `checkbox` = request + space + acknowledgement, `confirm`,
389
- `decline`; the consent branch also `purchase`), `withdrawal`, `cancellation` (form labels and the
406
+ `decline`; the consent branch also `purchase`; the start branch's `request`/`acknowledgement`/
407
+ `checkbox` also as `_units`), `withdrawal`, `cancellation` (form labels and the
390
408
  statutory buttons `function` / `confirm`), `links`, `checkout` (`terms-acceptance.{in-scope,
391
409
  other}` markdown, `renewal.{month, year, after-submit}`, `price.{exclusive, inclusive, exclusive-tax}` (VAT wording for the territories, "applicable tax" for a buyer outside them), `top-up`,
392
- `top-up-note`), `email.{common, consent, start, purchase, withdrawal, cancellation}` (the purchase
410
+ `top-up-note`), `email.{common, consent, start (`rule` + `rule_units`), purchase, withdrawal, cancellation}` (the purchase
393
411
  mail carries the CRD Annex I(A) withdrawal information with the function's address and the Annex
394
412
  I(B) model form, per language from the national models; there `{{trader}}` is the trader's whole
395
413
  identity — legal name, address, e-mail; a `review` withdrawal receipt promises the reimbursement
@@ -397,12 +415,38 @@ within the statutory 14 days; `email.cancellation.review` answers an extraordina
397
415
  whose status is `CancellationStatus.Review`), `credit-note.memo`. In the consent and start
398
416
  STATEMENTS `{{trader}}` is the trader's short name.
399
417
 
400
- - Read it with `consumerRightsCopy(lng)` (any language, merged key by key over English, no i18next
401
- instance, never drains a bundle — `resolveI18nResource`), `consumerText(lng, path, vars)` (fills
402
- `{{name}}`; throws `ConsumerRightsError('copy:<path>[:<name>]')` on a missing text or value — a
403
- legal text never goes out with a hole), `consentStatementOf(lng, kind, { trader, plan? })` (the
404
- exact statement the dialog shows, the server records and the mail repeats) and
405
- `legalLabelsOf(lng)`.
418
+ - Read it with `consumerCopyHelper.consumerRightsCopy(lng)` (any language, merged key by key over
419
+ English, no i18next instance, never drains a bundle — `i18nHelper.resolveI18nResource`),
420
+ `consumerCopyHelper.consumerText(lng, path, vars, context?)` (fills `{{name}}`; throws
421
+ `ConsumerRightsError('copy:<path>[:<name>]')` on a missing text or value — a legal text never goes
422
+ out with a hole), `consumerCopyHelper.consentStatementOf(lng, kind, { trader, plan?, context? })`
423
+ (the exact statement the dialog shows, the server records and the mail repeats) and
424
+ `consumerCopyHelper.legalLabelsOf(lng)`.
425
+ - **Context variants** (the i18next context suffix): with a `context`,
426
+ `consumerCopyHelper.consumerText` reads `<path>_<context>` first and the base `path` only where no
427
+ such variant exists (a missing value then names the variant: `copy:<path>_<context>:<name>`); an
428
+ empty context is none. `consumerCopyHelper.consentStatementOf` passes its `context` to all three
429
+ texts. Shipped variants, all eight languages, same placeholders as the base keys, each request
430
+ keeping the base request's statutory opening verbatim; a new variant lands in every language at
431
+ once, with its base key's placeholders:
432
+ - `performance-consent.{title,intro,request,checkbox}_included` — the consuming platform's
433
+ vocabulary: "topped-up credits" (pl doładowane, ru пополненные, be папоўненыя, uk поповнені, es
434
+ recargados, de aufgeladene, fr rechargés) are spent once "the credit limits included in my plan"
435
+ (a plan's non-monetary credits) have run out; `checkbox_included` = `request_included` + space +
436
+ the BASE `acknowledgement` (generic "credits", so `acknowledgement` has no variant).
437
+ - **The subscription start statement follows the plan's withdrawal arithmetic.** The BASE
438
+ `subscription-start.{request,acknowledgement,checkbox}` and `email.start.rule` describe the
439
+ common case — the plan withdrawn pro rata by the DAYS ELAPSED only ("starts the {{plan}}
440
+ services — including the AI work within the usage the plan includes — now …; … I pay for the
441
+ services provided until then, pro rata by the days elapsed, and everything else is
442
+ reimbursed"); `…_units` (`checkbox_units` = `request_units` + space + `acknowledgement_units`)
443
+ describe the split — services pro rata by time, the right of withdrawal expiring for the
444
+ included units used. `consumerCopyHelper.startContextOf(plan)` is the ONE decision: `'units'`
445
+ exactly when the plan's `withdrawal.components` has a `basis: 'units'` part, else `undefined`.
446
+ Every renderer takes the context from it — the server's start view, the recorded statement and
447
+ the start mail, and the dialog (from the view's `context`) — so the statement on screen is the
448
+ one recorded. `title`, `intro`, `confirm`, `decline` have no `_units` variant. Generic statutory
449
+ text (the purchase mail's withdrawal information) stays generic.
406
450
  - Statutory labels are pinned by a test: en "Withdraw from contract here" / "Confirm withdrawal",
407
451
  "Cancel contracts here" / "Cancel now"; de "Vertrag widerrufen" / "Widerruf bestätigen",
408
452
  "Verträge hier kündigen" / "Jetzt kündigen"; fr "Renoncer au contrat ici" / "Confirmer la
@@ -412,13 +456,15 @@ STATEMENTS `{{trader}}` is the trader's short name.
412
456
  "Cancelar ahora"; uk/ru/be are courtesy translations.
413
457
  - The express request uses the statutory verbs (PL "Żądam i wyrażam wyraźną zgodę … Przyjmuję do
414
458
  wiadomości …", DE "Ich verlange ausdrücklich und stimme ausdrücklich zu … Mir ist bekannt …", FR
415
- "Je demande expressément et j’accepte expressément … Je reconnais perdre …").
459
+ "Je demande expressément et j’accepte expressément … Je reconnais perdre …"). Every start
460
+ request — base and `_units`, every language — opens with the same three words as that language's
461
+ performance request (pinned by the copy spec).
416
462
  - Wording rule, enforced by a scan of every language: say "the right of withdrawal expires" and
417
463
  "only unused credits are reimbursed" — never non-refundable / nicht erstattungsfähig / non
418
464
  remboursable / bezzwrotny / no reembolsable / невозвратный / неповоротний / незваротны.
419
465
  - Paygate texts (`checkout.*`) stay within 1200 characters after interpolating long URLs.
420
- - An application overrides a text with `addI18nApp(lng, CONSUMER_RIGHTS_RESOURCE, data, { ns:
421
- LIB_NAMESPACE })`; every placeholder of a text must match its English master.
466
+ - An application overrides a text with `i18nHelper.addI18nApp(lng, CONSUMER_RIGHTS_RESOURCE, data,
467
+ { ns: LIB_NAMESPACE })`; every placeholder of a text must match its English master.
422
468
 
423
469
  ### Protocol factories
424
470
 
@@ -1,16 +1,6 @@
1
1
  import { CONFIG_RECORD } from '@owlmeans/context';
2
2
  import { apiConfigPlugin, every } from '@owlmeans/api-config';
3
- import { CONSUMER_RIGHTS_RECORD_TYPE, L10N_RECORD_TYPE, PLAN_RECORD_TYPE, PRICING_POLICY_RECORD_TYPE, PRODUCT_RECORD_TYPE, } from './consts.js';
4
- /**
5
- * The pricing policy record carries only flags and TTLs (never a Stripe secret, an API version, or
6
- * a migration switch — those stay in a backend-only plugin), so advertising it to the browser is
7
- * safe. The consumer-rights policy record carries only public links, territories and switches
8
- * (the mail options — sender, archive copy — stay in a backend-only plugin config), so the browser
9
- * renders the same links and switches the server enforces.
10
- */
11
- const advertisedRecordTypes = new Set([
12
- L10N_RECORD_TYPE, PLAN_RECORD_TYPE, PRODUCT_RECORD_TYPE, PRICING_POLICY_RECORD_TYPE, CONSUMER_RIGHTS_RECORD_TYPE,
13
- ]);
3
+ import { advertisedRecordTypes } from './consts.local.js';
14
4
  apiConfigPlugin({
15
5
  allow: {
16
6
  [CONFIG_RECORD]: every(true, value => value != null && typeof value === 'object'
@@ -1 +1 @@
1
- {"version":3,"file":"advertise.js","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EACL,2BAA2B,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,mBAAmB,GACjH,MAAM,aAAa,CAAA;AAEpB;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,2BAA2B;CACjH,CAAC,CAAA;AAEF,eAAe,CAAC;IACd,KAAK,EAAE;QACL,CAAC,aAAa,CAAC,EAAE,KAAK,CACpB,IAAI,EACJ,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;eAC9C,qBAAqB,CAAC,GAAG,CAAE,KAAiC,CAAC,UAAU,IAAI,EAAE,CAAC,CACpF;KACF;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"advertise.js","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,eAAe,CAAC;IACd,KAAK,EAAE;QACL,CAAC,aAAa,CAAC,EAAE,KAAK,CACpB,IAAI,EACJ,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;eAC9C,qBAAqB,CAAC,GAAG,CAAE,KAAiC,CAAC,UAAU,IAAI,EAAE,CAAC,CACpF;KACF;CACF,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const CHECKOUT_READ_API_PATH = "/checkout";
2
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/checkout/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,cAAc,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const CHECKOUT_READ_API_PATH = '/checkout';
2
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/checkout/consts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAA"}
@@ -1,3 +1,6 @@
1
1
  export * from './narrow.js';
2
+ export type * from './types.js';
3
+ export type * from './narrow/types.js';
2
4
  export * from './protocols.js';
5
+ export * from './consts.js';
3
6
  //# sourceMappingURL=index.d.ts.map