@owlmeans/payment 0.1.18-rc.8 → 0.1.18
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.
- package/README.md +95 -57
- package/agent-meta/manifest.json +10 -3
- package/agent-meta/skills/entitlements/SKILL.md +159 -0
- package/agent-meta/skills/payment/SKILL.md +491 -28
- package/build/advertise.d.ts +2 -0
- package/build/advertise.d.ts.map +1 -0
- package/build/advertise.js +10 -0
- package/build/advertise.js.map +1 -0
- package/build/checkout/consts.d.ts +2 -0
- package/build/checkout/consts.d.ts.map +1 -0
- package/build/checkout/consts.js +2 -0
- package/build/checkout/consts.js.map +1 -0
- package/build/checkout/index.d.ts +6 -0
- package/build/checkout/index.d.ts.map +1 -0
- package/build/checkout/index.js +4 -0
- package/build/checkout/index.js.map +1 -0
- package/build/checkout/narrow/types.d.ts +25 -0
- package/build/checkout/narrow/types.d.ts.map +1 -0
- package/build/checkout/narrow/types.js +2 -0
- package/build/checkout/narrow/types.js.map +1 -0
- package/build/checkout/narrow.d.ts +8 -0
- package/build/checkout/narrow.d.ts.map +1 -0
- package/build/checkout/narrow.js +47 -0
- package/build/checkout/narrow.js.map +1 -0
- package/build/checkout/protocols.d.ts +8 -0
- package/build/checkout/protocols.d.ts.map +1 -0
- package/build/checkout/protocols.js +28 -0
- package/build/checkout/protocols.js.map +1 -0
- package/build/checkout/types.d.ts +29 -0
- package/build/checkout/types.d.ts.map +1 -0
- package/build/checkout/types.js +2 -0
- package/build/checkout/types.js.map +1 -0
- package/build/consts.d.ts +242 -25
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +377 -24
- package/build/consts.js.map +1 -1
- package/build/consts.local.d.ts +20 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +23 -0
- package/build/consts.local.js.map +1 -0
- package/build/consumer/cancel.d.ts +11 -0
- package/build/consumer/cancel.d.ts.map +1 -0
- package/build/consumer/cancel.js +33 -0
- package/build/consumer/cancel.js.map +1 -0
- package/build/consumer/consts.d.ts +20 -0
- package/build/consumer/consts.d.ts.map +1 -0
- package/build/consumer/consts.js +39 -0
- package/build/consumer/consts.js.map +1 -0
- package/build/consumer/consts.local.d.ts +7 -0
- package/build/consumer/consts.local.d.ts.map +1 -0
- package/build/consumer/consts.local.js +13 -0
- package/build/consumer/consts.local.js.map +1 -0
- package/build/consumer/copy/types.d.ts +56 -0
- package/build/consumer/copy/types.d.ts.map +1 -0
- package/build/consumer/copy/types.js +2 -0
- package/build/consumer/copy/types.js.map +1 -0
- package/build/consumer/copy.d.ts +22 -0
- package/build/consumer/copy.d.ts.map +1 -0
- package/build/consumer/copy.js +87 -0
- package/build/consumer/copy.js.map +1 -0
- package/build/consumer/deadline/types.d.ts +30 -0
- package/build/consumer/deadline/types.d.ts.map +1 -0
- package/build/consumer/deadline/types.js +2 -0
- package/build/consumer/deadline/types.js.map +1 -0
- package/build/consumer/deadline.d.ts +12 -0
- package/build/consumer/deadline.d.ts.map +1 -0
- package/build/consumer/deadline.js +44 -0
- package/build/consumer/deadline.js.map +1 -0
- package/build/consumer/fifo/types.d.ts +17 -0
- package/build/consumer/fifo/types.d.ts.map +1 -0
- package/build/consumer/fifo/types.js +2 -0
- package/build/consumer/fifo/types.js.map +1 -0
- package/build/consumer/fifo.d.ts +4 -0
- package/build/consumer/fifo.d.ts.map +1 -0
- package/build/consumer/fifo.js +34 -0
- package/build/consumer/fifo.js.map +1 -0
- package/build/consumer/index.d.ts +18 -0
- package/build/consumer/index.d.ts.map +1 -0
- package/build/consumer/index.js +11 -0
- package/build/consumer/index.js.map +1 -0
- package/build/consumer/policy/types.d.ts +20 -0
- package/build/consumer/policy/types.d.ts.map +1 -0
- package/build/consumer/policy/types.js +2 -0
- package/build/consumer/policy/types.js.map +1 -0
- package/build/consumer/policy.d.ts +17 -0
- package/build/consumer/policy.d.ts.map +1 -0
- package/build/consumer/policy.js +91 -0
- package/build/consumer/policy.js.map +1 -0
- package/build/consumer/protocols.d.ts +20 -0
- package/build/consumer/protocols.d.ts.map +1 -0
- package/build/consumer/protocols.js +70 -0
- package/build/consumer/protocols.js.map +1 -0
- package/build/consumer/refund/types.d.ts +27 -0
- package/build/consumer/refund/types.d.ts.map +1 -0
- package/build/consumer/refund/types.js +2 -0
- package/build/consumer/refund/types.js.map +1 -0
- package/build/consumer/refund.d.ts +9 -0
- package/build/consumer/refund.d.ts.map +1 -0
- package/build/consumer/refund.js +112 -0
- package/build/consumer/refund.js.map +1 -0
- package/build/consumer/refusal.d.ts +10 -0
- package/build/consumer/refusal.d.ts.map +1 -0
- package/build/consumer/refusal.js +35 -0
- package/build/consumer/refusal.js.map +1 -0
- package/build/consumer/revive/types.d.ts +19 -0
- package/build/consumer/revive/types.d.ts.map +1 -0
- package/build/consumer/revive/types.js +2 -0
- package/build/consumer/revive/types.js.map +1 -0
- package/build/consumer/revive.d.ts +13 -0
- package/build/consumer/revive.d.ts.map +1 -0
- package/build/consumer/revive.js +43 -0
- package/build/consumer/revive.js.map +1 -0
- package/build/consumer/types.d.ts +196 -0
- package/build/consumer/types.d.ts.map +1 -0
- package/build/consumer/types.js +2 -0
- package/build/consumer/types.js.map +1 -0
- package/build/consumer/types.local.d.ts +11 -0
- package/build/consumer/types.local.d.ts.map +1 -0
- package/build/consumer/types.local.js +2 -0
- package/build/consumer/types.local.js.map +1 -0
- package/build/countries.d.ts +3 -0
- package/build/countries.d.ts.map +1 -0
- package/build/countries.js +4 -0
- package/build/countries.js.map +1 -0
- package/build/entitled.d.ts +14 -0
- package/build/entitled.d.ts.map +1 -0
- package/build/entitled.js +17 -0
- package/build/entitled.js.map +1 -0
- package/build/entitlement/types.d.ts +29 -0
- package/build/entitlement/types.d.ts.map +1 -0
- package/build/entitlement/types.js +2 -0
- package/build/entitlement/types.js.map +1 -0
- package/build/entitlement.d.ts +12 -0
- package/build/entitlement.d.ts.map +1 -0
- package/build/entitlement.js +64 -0
- package/build/entitlement.js.map +1 -0
- package/build/errors.d.ts +189 -0
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js +361 -0
- package/build/errors.js.map +1 -1
- package/build/estimate/types.d.ts +34 -0
- package/build/estimate/types.d.ts.map +1 -0
- package/build/estimate/types.js +2 -0
- package/build/estimate/types.js.map +1 -0
- package/build/estimate.d.ts +11 -0
- package/build/estimate.d.ts.map +1 -0
- package/build/estimate.js +76 -0
- package/build/estimate.js.map +1 -0
- package/build/i18n/consumer-rights/be.json +131 -0
- package/build/i18n/consumer-rights/de.json +131 -0
- package/build/i18n/consumer-rights/en.json +131 -0
- package/build/i18n/consumer-rights/es.json +131 -0
- package/build/i18n/consumer-rights/fr.json +131 -0
- package/build/i18n/consumer-rights/pl.json +131 -0
- package/build/i18n/consumer-rights/ru.json +131 -0
- package/build/i18n/consumer-rights/uk.json +131 -0
- package/build/i18n/errors/be.json +30 -0
- package/build/i18n/errors/de.json +30 -0
- package/build/i18n/errors/en.json +30 -0
- package/build/i18n/errors/es.json +30 -0
- package/build/i18n/errors/fr.json +30 -0
- package/build/i18n/errors/pl.json +30 -0
- package/build/i18n/errors/ru.json +30 -0
- package/build/i18n/errors/uk.json +30 -0
- package/build/i18n/fr.json +39 -0
- package/build/i18n.js +53 -8
- package/build/i18n.js.map +1 -1
- package/build/index.d.ts +19 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +12 -1
- package/build/index.js.map +1 -1
- package/build/limit/types.d.ts +44 -0
- package/build/limit/types.d.ts.map +1 -0
- package/build/limit/types.js +2 -0
- package/build/limit/types.js.map +1 -0
- package/build/limit.d.ts +23 -0
- package/build/limit.d.ts.map +1 -0
- package/build/limit.js +97 -0
- package/build/limit.js.map +1 -0
- package/build/model/checkout.d.ts +2 -3
- package/build/model/checkout.d.ts.map +1 -1
- package/build/model/checkout.js +12 -7
- package/build/model/checkout.js.map +1 -1
- package/build/model/consts.d.ts +15 -0
- package/build/model/consts.d.ts.map +1 -0
- package/build/model/consts.js +193 -0
- package/build/model/consts.js.map +1 -0
- package/build/model/consts.local.d.ts +35 -0
- package/build/model/consts.local.d.ts.map +1 -0
- package/build/model/consts.local.js +65 -0
- package/build/model/consts.local.js.map +1 -0
- package/build/model/consumer.d.ts +23 -0
- package/build/model/consumer.d.ts.map +1 -0
- package/build/model/consumer.js +272 -0
- package/build/model/consumer.js.map +1 -0
- package/build/model/estimate.d.ts +5 -0
- package/build/model/estimate.d.ts.map +1 -0
- package/build/model/estimate.js +69 -0
- package/build/model/estimate.js.map +1 -0
- package/build/model/index.d.ts +7 -2
- package/build/model/index.d.ts.map +1 -1
- package/build/model/index.js +7 -2
- package/build/model/index.js.map +1 -1
- package/build/model/limit.d.ts +7 -0
- package/build/model/limit.d.ts.map +1 -0
- package/build/model/limit.js +32 -0
- package/build/model/limit.js.map +1 -0
- package/build/model/plan.d.ts.map +1 -1
- package/build/model/plan.js +24 -11
- package/build/model/plan.js.map +1 -1
- package/build/model/portal.d.ts +4 -0
- package/build/model/portal.d.ts.map +1 -0
- package/build/model/portal.js +22 -0
- package/build/model/portal.js.map +1 -0
- package/build/model/pricing.d.ts +4 -0
- package/build/model/pricing.d.ts.map +1 -0
- package/build/model/pricing.js +31 -0
- package/build/model/pricing.js.map +1 -0
- package/build/model/view.d.ts +3 -0
- package/build/model/view.d.ts.map +1 -0
- package/build/model/view.js +15 -0
- package/build/model/view.js.map +1 -0
- package/build/pricing/types.d.ts +13 -0
- package/build/pricing/types.d.ts.map +1 -0
- package/build/pricing/types.js +2 -0
- package/build/pricing/types.js.map +1 -0
- package/build/pricing.d.ts +13 -0
- package/build/pricing.d.ts.map +1 -0
- package/build/pricing.js +74 -0
- package/build/pricing.js.map +1 -0
- package/build/promo/types.d.ts +14 -0
- package/build/promo/types.d.ts.map +1 -0
- package/build/promo/types.js +2 -0
- package/build/promo/types.js.map +1 -0
- package/build/promo.d.ts +7 -0
- package/build/promo.d.ts.map +1 -0
- package/build/promo.js +25 -0
- package/build/promo.js.map +1 -0
- package/build/regions/types.d.ts +32 -0
- package/build/regions/types.d.ts.map +1 -0
- package/build/regions/types.js +2 -0
- package/build/regions/types.js.map +1 -0
- package/build/regions.d.ts +15 -0
- package/build/regions.d.ts.map +1 -0
- package/build/regions.js +43 -0
- package/build/regions.js.map +1 -0
- package/build/service.d.ts.map +1 -1
- package/build/service.js +24 -9
- package/build/service.js.map +1 -1
- package/build/types.d.ts +619 -52
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +4 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/view/types.d.ts +33 -0
- package/build/view/types.d.ts.map +1 -0
- package/build/view/types.js +2 -0
- package/build/view/types.js.map +1 -0
- package/build/view.d.ts +13 -0
- package/build/view.d.ts.map +1 -0
- package/build/view.js +78 -0
- package/build/view.js.map +1 -0
- package/package.json +14 -12
- package/src/advertise.ts +13 -0
- package/src/checkout/consts.ts +1 -0
- package/src/checkout/index.ts +5 -0
- package/src/checkout/narrow/types.ts +27 -0
- package/src/checkout/narrow.ts +63 -0
- package/src/checkout/protocols.ts +39 -0
- package/src/checkout/types.ts +27 -0
- package/src/consts.local.ts +34 -0
- package/src/consts.ts +417 -24
- package/src/consumer/cancel.ts +40 -0
- package/src/consumer/consts.local.ts +16 -0
- package/src/consumer/consts.ts +46 -0
- package/src/consumer/copy/types.ts +54 -0
- package/src/consumer/copy.ts +121 -0
- package/src/consumer/deadline/types.ts +30 -0
- package/src/consumer/deadline.ts +61 -0
- package/src/consumer/fifo/types.ts +17 -0
- package/src/consumer/fifo.ts +42 -0
- package/src/consumer/index.ts +17 -0
- package/src/consumer/policy/types.ts +20 -0
- package/src/consumer/policy.ts +101 -0
- package/src/consumer/protocols.ts +116 -0
- package/src/consumer/refund/types.ts +27 -0
- package/src/consumer/refund.ts +136 -0
- package/src/consumer/refusal.ts +35 -0
- package/src/consumer/revive/types.ts +23 -0
- package/src/consumer/revive.ts +82 -0
- package/src/consumer/types.local.ts +10 -0
- package/src/consumer/types.ts +189 -0
- package/src/countries.ts +5 -0
- package/src/entitled.ts +20 -0
- package/src/entitlement/types.ts +29 -0
- package/src/entitlement.ts +86 -0
- package/src/errors.ts +445 -0
- package/src/estimate/types.ts +34 -0
- package/src/estimate.ts +90 -0
- package/src/i18n/consumer-rights/be.json +131 -0
- package/src/i18n/consumer-rights/de.json +131 -0
- package/src/i18n/consumer-rights/en.json +131 -0
- package/src/i18n/consumer-rights/es.json +131 -0
- package/src/i18n/consumer-rights/fr.json +131 -0
- package/src/i18n/consumer-rights/pl.json +131 -0
- package/src/i18n/consumer-rights/ru.json +131 -0
- package/src/i18n/consumer-rights/uk.json +131 -0
- package/src/i18n/errors/be.json +30 -0
- package/src/i18n/errors/de.json +30 -0
- package/src/i18n/errors/en.json +30 -0
- package/src/i18n/errors/es.json +30 -0
- package/src/i18n/errors/fr.json +30 -0
- package/src/i18n/errors/pl.json +30 -0
- package/src/i18n/errors/ru.json +30 -0
- package/src/i18n/errors/uk.json +30 -0
- package/src/i18n/fr.json +39 -0
- package/src/i18n.ts +58 -8
- package/src/index.ts +19 -2
- package/src/limit/types.ts +41 -0
- package/src/limit.ts +132 -0
- package/src/model/checkout.ts +12 -7
- package/src/model/consts.local.ts +83 -0
- package/src/model/consts.ts +206 -0
- package/src/model/consumer.ts +294 -0
- package/src/model/estimate.ts +73 -0
- package/src/model/index.ts +7 -2
- package/src/model/limit.ts +36 -0
- package/src/model/plan.ts +25 -12
- package/src/model/portal.ts +25 -0
- package/src/model/pricing.ts +34 -0
- package/src/model/view.ts +17 -0
- package/src/pricing/types.ts +13 -0
- package/src/pricing.ts +110 -0
- package/src/promo/types.ts +18 -0
- package/src/promo.ts +46 -0
- package/src/regions/types.ts +42 -0
- package/src/regions.ts +85 -0
- package/src/service.ts +32 -15
- package/src/types.local.ts +5 -0
- package/src/types.ts +669 -49
- package/src/view/types.ts +39 -0
- package/src/view.ts +119 -0
- package/tests/checkout-narrow.spec.ts +75 -0
- package/tests/consumer-copy.spec.ts +378 -0
- package/tests/consumer-deadline.spec.ts +85 -0
- package/tests/consumer-fifo.spec.ts +61 -0
- package/tests/consumer-protocols.spec.ts +103 -0
- package/tests/consumer-refund.spec.ts +134 -0
- package/tests/consumer-regions.spec.ts +140 -0
- package/tests/consumer-wire.spec.ts +170 -0
- package/tests/contract.spec.ts +183 -0
- package/tests/entitlement.spec.ts +103 -0
- package/tests/errors.spec.ts +168 -0
- package/tests/estimate.spec.ts +139 -0
- package/tests/limit.spec.ts +117 -0
- package/tests/pricing.spec.ts +30 -0
- package/tests/tsconfig.json +11 -0
- package/tests/view.spec.ts +130 -0
- package/tsconfig.json +6 -1
- package/build/.gitkeep +0 -0
- package/src/model/subscription.ts +0 -63
- package/src/model/utils.ts +0 -32
- package/src/modules.ts +0 -43
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: payment
|
|
3
|
-
description: How to use @owlmeans/payment — payment
|
|
3
|
+
description: "How to use @owlmeans/payment — provider-agnostic payment contracts, immutable payment protocols, amount/quantity checkout policies, per-entity checkout narrowing and pricing, catalogue records, entitlement gates, and the EU consumer-rights contracts (billing regions, the policy record, withdrawal/cancellation views, refund calculators, 428/409 refusals, the legal copy, protocol factories). Auto-invoked when importing payment types or errors, declaring paid routes, creating checkout, or touching consent, withdrawal or cancellation."
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,44 +8,507 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/payment
|
|
9
9
|
|
|
10
10
|
**Layer:** Core
|
|
11
|
-
**Install:** `"@owlmeans/payment": "^0.1.18
|
|
11
|
+
**Install:** `"@owlmeans/payment": "^0.1.18"` in `dependencies`
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The contracts half of payments: the catalogue (products, plans, localizations), amount- and
|
|
14
|
+
quantity-priced checkout, the entitlement model — plan capabilities, counted limits, promos,
|
|
15
|
+
and the entitlement view the server gate and the browser both read — and the EU consumer-rights
|
|
16
|
+
contracts (billing regions, the policy record, withdrawal and cancellation views, the refund
|
|
17
|
+
calculators, the refusals, the legal copy, the protocol factories). It talks to no paygate: a
|
|
18
|
+
server-side integration (`@owlmeans/server-payment`) implements against these, and
|
|
19
|
+
`@owlmeans/client-payment` adapts the catalogue service for a browser. The model as a whole —
|
|
20
|
+
admission, the usage ledger, the two gate services — is the `entitlements` skill.
|
|
21
|
+
|
|
22
|
+
## Key exports
|
|
14
23
|
|
|
15
24
|
| Export | Description |
|
|
16
|
-
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
| `
|
|
23
|
-
|
|
|
25
|
+
|---|---|
|
|
26
|
+
| `makePaymentService(alias?)` · `appendPaymentService(ctx, alias?)` | The catalogue reader, registered under `DEFAULT_ALIAS` / `PAYMENT_SERVICE` (`'payment'`). |
|
|
27
|
+
| `PaymentService` | `product(sku)` · `products()` · `plans(productSku, duration)` · `plan(planSku)` · `allPlans(productSku)` · `localize(lng, entity)` · `shallowAuthentication(token)` · `pricingPolicy()` · `consumerRightsPolicy()` (`null` when undeclared). |
|
|
28
|
+
| `Product` · `ProductPlan` · `Localization` (+ schemas) | Catalogue records. `ProductPlan` carries `rank`, `free`, `gateways`, `suspendedAt`, `capabilities: PlanCapability[]`, `limits: { [key]: LimitDeclaration }`, `withdrawal.components` (§ Consumer rights). |
|
|
29
|
+
| `PlanCapability` · `LimitDeclaration` · `PromoDeclaration` (+ schemas) | What a plan grants: a permission set, a counted allowance, a time box on either. |
|
|
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
|
+
| `LimitKind` · `LimitWindow` · `PortalFlow` (+ schemas) | `window`/`lifetime`/`occupancy`; `day`/`month`; `manage`/`cancel`/`update`/`change`/`payment-method`. |
|
|
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` · `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
|
+
| `EntitlementView` · `EntitlementPlanView` · `CapabilityView` · `LimitView` · `PromoView` · `LimitUsage` (+ wire schemas) | The entitlement view and its rows. |
|
|
37
|
+
| `entitlementViewHelper` (`capabilityViewsOf` · `limitViewsOf` · `entitlementViewOf` · `reviveEntitlementView`) · `planLimitHelper` (`capabilityOf` · `limitOf` · `hasLimitRoom`) | Pure view builders and readers. |
|
|
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) · `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
|
+
| `COUNTRY_CURRENCIES` · `currencyOfCountry` · `COUNTRY_CODES` · `CountrySchema` | ISO 3166-1 → ISO 4217 reference map for a country picker. |
|
|
43
|
+
| `EntitlementRefusal` · `CapabilityRequired` · `LimitExhausted` | Entitlement refusals — all `AuthForbidden` (403). |
|
|
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
|
+
| `ConsumerRightsRefusal` · `PerformanceConsentRequired` · `SubscriptionStartRequired` (428) · `BillingCountryLocked` · `WithdrawalUnavailable` · `CancellationUnavailable` · `CheckoutLimitExceeded` (409) · `consentRefusalOf` | Consumer-rights and checkout-limit refusals — declared statuses, never `AuthForbidden` (§ Consumer rights). |
|
|
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` · `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
|
+
| `makeConsumerRightsProtocols` · `makeCheckoutReadProtocols` | Protocol factories. |
|
|
53
|
+
| `AmountNarrowing` · `amountNarrowingHelper` (`narrowAmountPolicy` · `amountAllowed`) · `CheckoutLimitView` · `AmountPolicyView`/`Query` · `PlanPriceView`/`List`/`PlanPricesQuery` (+ schemas) | Per-entity narrowing of an amount checkout, and synced plan prices. |
|
|
54
|
+
|
|
55
|
+
Subpath: `./utils` — the `Config` / `Context` aliases to type your own context against.
|
|
56
|
+
|
|
57
|
+
## The catalogue is config, not a table
|
|
58
|
+
|
|
59
|
+
`PaymentService` reads everything through the context's config resource, so a deployment ships its
|
|
60
|
+
catalogue the same way it ships any other configuration:
|
|
61
|
+
|
|
62
|
+
| Record | Id | Type |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| product | `product:<sku>` | `PRODUCT_RECORD_TYPE` |
|
|
65
|
+
| plan | `plan:<planSku>` | `PLAN_RECORD_TYPE` |
|
|
66
|
+
| localization | `l10nToId(l10n, true)` → `l10n:<entityType>:<sku>:<lng>` | `L10N_RECORD_TYPE` |
|
|
67
|
+
|
|
68
|
+
`product` and `plan` read the record with the config resource's `get`, which **throws
|
|
69
|
+
`UnknownRecordError`** (`@owlmeans/resource`) when the id is absent rather than returning null — so
|
|
70
|
+
that, not `UnknownProduct` / `UnknownPlan`, is what a checkout for a sku outside the catalogue
|
|
71
|
+
raises. `localize` is the opposite: it reads with `load`, tries the asked-for language, falls back
|
|
72
|
+
to the default one, and returns `null` when neither exists, because a missing translation is a
|
|
73
|
+
display problem and never a reason to fail a call.
|
|
74
|
+
|
|
75
|
+
## Declaring plans
|
|
76
|
+
|
|
77
|
+
- **Every plan of a product has a `rank`; a higher rank is an upgrade.** An absent rank reads as
|
|
78
|
+
`0`. Plan changes are classified by rank, and the effective plan of an entity is its
|
|
79
|
+
highest-ranked entitling subscription — two plans of one product at one rank make both
|
|
80
|
+
questions unanswerable.
|
|
81
|
+
- **The free tier is a real plan**: `free: true`, `price: 0`, `gateways: []`, usually `rank: 0`.
|
|
82
|
+
Every entity holds some plan, so a gate never has to special-case "no subscription".
|
|
83
|
+
- **`gateways`** names the paygates a plan is sold through; a free plan has none.
|
|
84
|
+
- **`status` is a `PlanStatus`** (active, hidden, archived …) — the catalogue state of the plan,
|
|
85
|
+
never a subscription's lifecycle.
|
|
86
|
+
- Plan records use the record date convention (`DateSchema` from `@owlmeans/auth`, a `Date`
|
|
87
|
+
object); wire shapes do not (below).
|
|
88
|
+
|
|
89
|
+
## Capabilities and limits are different things
|
|
90
|
+
|
|
91
|
+
A **capability** is granted: a permission in a `PlanCapability` set, asked for as
|
|
92
|
+
|
|
93
|
+
[<scope>:]<permission>[>=<n>]
|
|
94
|
+
|
|
95
|
+
`feature:branding--whitelabel` · `renewable:credits>=100` · `production--standalone`
|
|
96
|
+
|
|
97
|
+
A **limit** is counted: a `LimitDeclaration` under a key in `plan.limits`, asked for as
|
|
98
|
+
|
|
99
|
+
limit:<key>[>=<n>]
|
|
100
|
+
|
|
101
|
+
- **`limit` is a reserved scope.** A plan never declares a capability set under it,
|
|
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.
|
|
105
|
+
- **One grammar, two gate services.** Capability parameters go to `ENTITLEMENT_GATE`
|
|
106
|
+
(`entitled(params)` is sugar for it), limit parameters to `LIMIT_GATE`
|
|
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.
|
|
110
|
+
- **`@` is deliberately not part of the grammar.** That is `@owlmeans/iam`'s resource-selector
|
|
111
|
+
syntax; reusing it would make two different things look identical in a route declaration.
|
|
112
|
+
- **Keep flags, magnitudes and counts apart.** `CAPABILITY_FEATURE_SCOPE` carries booleans; a
|
|
113
|
+
granted magnitude nothing spends (`renewable:credits>=100`) lives under its own scope; anything
|
|
114
|
+
spent against a ceiling is a limit. Merged, the purchase that spends a quota takes the feature
|
|
115
|
+
with it.
|
|
116
|
+
- **A floor is a numeric question.** `>=n` passes only for a number at least that big — a boolean
|
|
117
|
+
flag, however true, does not answer it. For a limit, `>=n` asks for `n` units of room.
|
|
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.
|
|
122
|
+
- **Declare the requirement on the protocol, not in the handler.** The framework asserts gates
|
|
123
|
+
before the handler is entered, so the route table states what a feature costs. Several
|
|
124
|
+
parameters of one gate are OR'd. The gate services themselves live in the server integration.
|
|
125
|
+
|
|
126
|
+
## The three limit kinds
|
|
24
127
|
|
|
25
|
-
|
|
128
|
+
| Kind | Window key (`planLimitHelper.windowKeyOf`) | Renews | Typical use |
|
|
129
|
+
|---|---|---|---|
|
|
130
|
+
| `window` + `day` | `YYYY-MM-DD` | at UTC midnight | per-day actions |
|
|
131
|
+
| `window` + `month` | `YYYY-MM` | on the 1st, UTC | per-month actions |
|
|
132
|
+
| `lifetime` | `lifetime` | never — the count belongs to the entity and survives plan changes | "N ever" |
|
|
133
|
+
| `occupancy` | `occupancy` | never — held `+1` / released `-1`, reconciled against reality | "N at once" |
|
|
26
134
|
|
|
27
|
-
-
|
|
135
|
+
- Windows are **calendar UTC**, never rolling and never local: two servers in two zones must agree
|
|
136
|
+
on which counter a unit lands in.
|
|
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.
|
|
139
|
+
- A `window` limit without a known `window` (or an unknown kind) throws `LimitMisdeclared`: a
|
|
140
|
+
misdeclared plan is loud, not a silently unlimited one.
|
|
141
|
+
- `limit: 0` means "not included" — a declared key with no room, which a UI renders as such.
|
|
28
142
|
|
|
29
|
-
##
|
|
143
|
+
## Promos
|
|
30
144
|
|
|
31
|
-
|
|
145
|
+
`promo: { until: Date, grandfather?: boolean }` on a capability set or a limit.
|
|
32
146
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
147
|
+
- In force while `at < until`. **`at === until` is over.**
|
|
148
|
+
- With `grandfather: true`, also in force for a subscription created before `until`, forever.
|
|
149
|
+
- A lapsed promo makes a capability `granted: false` and a limit's `limit: 0` — the row stays in
|
|
150
|
+
the view with `promo.active: false`, so a UI can say the promotion ended rather than pretend the
|
|
151
|
+
feature never existed.
|
|
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".
|
|
154
|
+
- An unparseable `until` is never in force.
|
|
37
155
|
|
|
38
|
-
|
|
156
|
+
## The entitlement view
|
|
157
|
+
|
|
158
|
+
`entitlementViewHelper.entitlementViewOf(plan, planView, usage, at?)` is the one read of what an
|
|
159
|
+
entity may do:
|
|
160
|
+
|
|
161
|
+
- `plan` — the `EntitlementPlanView` the caller resolved (sku, rank, free, status, paygate,
|
|
162
|
+
period, trial, cancel-at-period-end, past-due, fallback). **Promos are measured against
|
|
163
|
+
`planView.subscribedAt`** — set it to the subscription's creation date, or nothing is
|
|
164
|
+
grandfathered.
|
|
165
|
+
- `capabilities` — its `capabilityViewsOf`: one row per non-null, non-false permission, `param`
|
|
166
|
+
exactly as the capability gate takes it.
|
|
167
|
+
- `limits` — its `limitViewsOf`: one row per declared key; `used` from the `LimitUsage` row of the
|
|
168
|
+
CURRENT window (none ⇒ `0`); `remaining = max(0, limit - used)`; `windowStart`/`resetsAt` only
|
|
169
|
+
for a window limit.
|
|
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.
|
|
174
|
+
- **The wire carries dates as ISO strings.** The view schemas describe that
|
|
175
|
+
(`{ type: 'string', format: 'date-time' }`): a response serializer writes a `Date` through it as
|
|
176
|
+
ISO, while the record convention (`DateSchema`, an object) would serialize it as `{}`. A browser
|
|
177
|
+
calls `entitlementViewHelper.reviveEntitlementView` before touching a date.
|
|
178
|
+
|
|
179
|
+
## Refusals and faults
|
|
180
|
+
|
|
181
|
+
- **A refusal extends `AuthForbidden`** (through `EntitlementRefusal`), so an HTTP boundary answers
|
|
182
|
+
403.
|
|
183
|
+
- `CapabilityRequired(params)` — message marker `capability-required:<a|b>`, field `params`.
|
|
184
|
+
- `LimitExhausted({ key, used, limit, resetsAt? })` — marker
|
|
185
|
+
`limit-exhausted:<key>:<used>/<limit>[:<ISO>]`, fields `limitKey`, `used`, `limit`,
|
|
186
|
+
`resetsAt`.
|
|
187
|
+
- **Only `type` and `message` survive a marshal.** Both refusals pack their fields into the
|
|
188
|
+
message and rebuild them in `finalizeUnmarshal()`; catch the class after
|
|
189
|
+
`ResilientError.ensure`, never parse the text yourself.
|
|
190
|
+
- **Consumer-rights and checkout-limit refusals are not entitlement refusals**: they declare
|
|
191
|
+
428/409 and never extend `AuthForbidden` (§ Consumer rights).
|
|
192
|
+
- **Faults are not refusals**: `LimitUnknown` (a key no plan declares), `LimitMisdeclared`,
|
|
193
|
+
`PlanRequired` (no plan resolvable, not even a free one), `PlanRankConflict`,
|
|
194
|
+
`WebhookSetupError` are `PaymentError`s — a configuration or setup problem, not the user's plan
|
|
195
|
+
saying no — and declare no status, so an HTTP boundary answers 500.
|
|
196
|
+
- **`PortalUnavailable` is the entity's state, not a fault**: no paygate customer, no entitling
|
|
197
|
+
subscription, no plan or item for the flow. It is a `PaymentError` declaring
|
|
198
|
+
`static httpStatus = 409`, which `@owlmeans/server-api` answers as 409 Conflict. A new payment
|
|
199
|
+
error that is the caller's condition declares its 4xx the same way; one that is a fault declares
|
|
200
|
+
nothing.
|
|
201
|
+
- A UI phrases any of them from `errors.<type>`; the package registers those messages.
|
|
202
|
+
|
|
203
|
+
## Checkout
|
|
204
|
+
|
|
205
|
+
`CreateCheckoutBody` is the wire body of a checkout: `productSku`, `planSku` for a subscription,
|
|
206
|
+
`entitySlug` (the only organization value on a public body — a server resolves the stable
|
|
207
|
+
`entityId` before persisting anything), `service`, `amountMinor` for an amount checkout, return
|
|
208
|
+
URLs, `country` (the declared billing country; a locked profile overrides it) and
|
|
209
|
+
`startRequestId` (the subscription start request recorded just before). The package declares no
|
|
210
|
+
fixed checkout protocols: an application declares its own checkout and portal protocols over
|
|
211
|
+
`CreateCheckoutBodySchema` / `PortalLinkBodySchema`; `PortalLinkBody.flow` picks the portal flow
|
|
212
|
+
and `planSku` names the target of a `change`. The read side and the consumer-rights surface come
|
|
213
|
+
as factories (§ Protocol factories).
|
|
214
|
+
|
|
215
|
+
### Amount checkout
|
|
216
|
+
|
|
217
|
+
`amountMinor` is the net value credited to the customer, in integer currency minor units. The
|
|
218
|
+
policy bounds that value; fees and tax do not enlarge the credit. Gross up the pre-tax charge with:
|
|
39
219
|
|
|
40
|
-
// In a handler:
|
|
41
|
-
const [result] = await ctx.entrypoint<ClientEntrypoint<CreateCheckoutResponse>>(
|
|
42
|
-
paymentApi.service.checkout.session.external.create
|
|
43
|
-
).call({
|
|
44
|
-
body: { productSku: 'tokens', entityId, service: VIB_ALIAS, successUrl: helper.makeUrl(service) }
|
|
45
|
-
})
|
|
46
220
|
```
|
|
221
|
+
ceil((amountMinor + fixedMinor) * 10_000 / (10_000 - rateBps))
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Validate the whole policy when configuration is declared, then validate every selected amount at
|
|
225
|
+
the backend boundary. Minimum, default, maximum, preset entries, fixed adjustment and basis-point
|
|
226
|
+
rate are safe integers; presets are unique/in-range and the rate is below 100%. The maximum applies
|
|
227
|
+
to `amountMinor`, not the adjusted checkout subtotal or tax-inclusive total.
|
|
228
|
+
|
|
229
|
+
Quantity checkout remains supported. It uses its reusable unit price and quantity policy; do not
|
|
230
|
+
infer a pricing mode from the presence of `amountMinor`.
|
|
231
|
+
|
|
232
|
+
### Narrowing an amount checkout per entity
|
|
233
|
+
|
|
234
|
+
The plan's `amountPolicy` is the same for everyone; what one entity may buy NOW is narrower when a
|
|
235
|
+
checkout plugin (a spending tier, a rolling cap, a fraud hold) answers an `AmountNarrowing`
|
|
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:
|
|
239
|
+
|
|
240
|
+
- the maximum is the smallest of the base maximum and every narrowing's (negative or fractional
|
|
241
|
+
values floor at 0); `reason`/`resetsAt`/`remainingMinor` come from the narrowing that set it,
|
|
242
|
+
the first on a tie;
|
|
243
|
+
- presets above the maximum are dropped, the default is clamped into `[minimum, maximum]`;
|
|
244
|
+
- `limit` is `null` when nothing lowered the base maximum — no note to show;
|
|
245
|
+
- **`limit.blocked`** (`limit.maximumMinor < base.minimumMinor`) means no amount may be bought now.
|
|
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.
|
|
251
|
+
|
|
252
|
+
`CheckoutLimitExceeded` (409) packs `checkout-limit-exceeded:<encodeURIComponent(reason)>:
|
|
253
|
+
<maximumMinor>:<currency>[:<resetsAt ISO>]` and rebuilds `reason`, `maximumMinor`, `currency`,
|
|
254
|
+
`resetsAt`. It is a payment refusal, not an entitlement one.
|
|
255
|
+
|
|
256
|
+
## Pricing policy and tax estimate
|
|
257
|
+
|
|
258
|
+
`PricingPolicy` (a `PRICING_POLICY_RECORD_ID` singleton config record, `declarePaymentPricing` in
|
|
259
|
+
`@owlmeans/server-payment`) is what a checkout-owning application declares once for tax and
|
|
260
|
+
currency behaviour: `tax.automatic` (Stripe Tax on the session), `tax.behavior` (a synced price's
|
|
261
|
+
`TaxBehavior.Exclusive`/`Inclusive`, absent = leave it `unspecified`), `tax.collectTaxId`,
|
|
262
|
+
`tax.estimate` / `currency.estimate` (serve a tax/local-currency estimate endpoint — the estimate
|
|
263
|
+
requires `tax.automatic`, the currency one requires `currency.adaptive`), `currency.adaptive`
|
|
264
|
+
(Stripe Adaptive Pricing on the session), `currency.adaptiveFeeRate` (the conversion fee Adaptive
|
|
265
|
+
Pricing adds to Stripe's base rate, a fraction in `[0, 1)` — Stripe says 2–4% and picks it per
|
|
266
|
+
currency; it needs `currency.adaptive`; absent, an estimate keeps the FX Quotes' own 2% fee, which
|
|
267
|
+
is NOT what Checkout charges). `PaymentService.pricingPolicy()` reads the declared record
|
|
268
|
+
or `DEFAULT_PRICING_POLICY` — the fixed behaviour every checkout had before this policy existed
|
|
269
|
+
(automatic tax and tax-id collection on, no forced behavior, no Adaptive Pricing, no estimate), so
|
|
270
|
+
an application that declares nothing sees no change.
|
|
271
|
+
|
|
272
|
+
`PriceEstimate` (built by `@owlmeans/server-payment`'s gateway, `estimatePrice`) is the read model:
|
|
273
|
+
`country`/`source` (`'request'`/`'customer'`, or `'profile'` with `locked: true` when the entity's
|
|
274
|
+
billing country is locked and overrides the request — a picker then shows it and does not change
|
|
275
|
+
it), `region`, `currency`, `behavior`, `tax: TaxEstimate` (`status`
|
|
276
|
+
one of `TaxEstimateStatus` — `taxed`/`reverse-charge`/`none`/`at-checkout`/`location-required` —
|
|
277
|
+
plus `subtotalMinor`/`taxMinor`/`totalMinor`, `scalable`, and `rates: TaxRateEstimate[]` with
|
|
278
|
+
`ratePpm` parsed by `priceEstimateHelper.ratePpmOf` from Stripe's `percentage_decimal`, never
|
|
279
|
+
`Number(x) * 10_000`), and an optional `local` (currency + `exchangeRate`, from Stripe's FX Quotes:
|
|
280
|
+
the quote's `base_rate / (1 + currency.adaptiveFeeRate)` when the fee is declared, else its
|
|
281
|
+
`exchange_rate`; `fxFeeRate` is the fee that rate includes).
|
|
282
|
+
The pure helper `priceEstimateHelper.estimateOf(amountMinor, estimate)` re-derives tax and a total
|
|
283
|
+
for a DIFFERENT amount than the estimate's own reference one — exact only when `scalable` and the
|
|
284
|
+
behavior is `Exclusive`; both `taxMinor`/`totalMinor` come back `null` otherwise, meaning "computed
|
|
285
|
+
at checkout", never a wrong number. When the source estimate carries `local`, the result's own
|
|
286
|
+
`local` gives the subtotal, tax and total in THAT currency
|
|
287
|
+
(`subtotalAmount`/`taxAmount`/`totalAmount`, major units) alongside the integration-currency ones —
|
|
288
|
+
a UI shows one or the other, marking the local figures `≈`, never both side by side.
|
|
289
|
+
`COUNTRY_CURRENCIES` / `currencyOfCountry` / `COUNTRY_CODES` is a reference ISO 3166-1 → ISO 4217
|
|
290
|
+
map for a country picker and the local-currency lookup — not a Stripe list, and a country absent
|
|
291
|
+
from it still gets a tax estimate, just no local-currency line.
|
|
292
|
+
|
|
293
|
+
## Consumer rights (EU withdrawal, cancellation, country lock)
|
|
294
|
+
|
|
295
|
+
The contracts behind the right of withdrawal (CRD Art. 9–16, the Art. 11a withdrawal function),
|
|
296
|
+
the cancellation function (§ 312k BGB / L215-1-1) and a billing country fixed at the first
|
|
297
|
+
purchase. `@owlmeans/server-payment` records, enforces and mails; `@owlmeans/web-payment` renders.
|
|
298
|
+
Nothing here is product copy — the trader, plan and product names are placeholders.
|
|
299
|
+
|
|
300
|
+
### Territories, region, scope
|
|
301
|
+
|
|
302
|
+
- `EU_COUNTRIES` (27, Greece is `GR`), `EU_CONSUMER_TERRITORIES` (plus AX, GF, GP, MQ, RE, YT, MF —
|
|
303
|
+
consumer law applies there even where EU VAT does not), `EEA_EXTRA` (IS, LI, NO) and their union
|
|
304
|
+
`CONSUMER_RIGHTS_TERRITORIES`, the default `policy.countries`.
|
|
305
|
+
- `consumerRegionHelper.regionOf(country, policy?)`: `Eu` inside the policy's territories, `Other`
|
|
306
|
+
outside, `null` for no country. `consumerRegionHelper.inScope(region, country, policy)`: a known
|
|
307
|
+
country decides by the territories, else a known region, else `unknownCountry` — `'protect'` by
|
|
308
|
+
default, so an unknown buyer is protected.
|
|
309
|
+
- `consumerRegionHelper.chargeCurrencyOf(region, policy, fallback)`: the policy's currency for the
|
|
310
|
+
region; an unknown region reads as `Eu`. The display currency is the charge currency, everywhere.
|
|
311
|
+
- `consumerRegionHelper.billingLanguageOf(country, policy?, fallback?)`: `policy.languages`, then
|
|
312
|
+
`COUNTRY_LANGUAGES` (unambiguous countries only — BE, LU, CH are absent), then `fallback`, then
|
|
313
|
+
`policy.defaultLanguage`. Legal copy is shown in this language, with a toggle to the UI language.
|
|
314
|
+
|
|
315
|
+
### The policy record
|
|
316
|
+
|
|
317
|
+
`ConsumerRightsPolicy` is a singleton config record (`CONSUMER_RIGHTS_RECORD_ID`), declared by the
|
|
318
|
+
server integration through `makeConsumerRightsPolicy(def)` — `DEFAULT_CONSUMER_RIGHTS` filled in
|
|
319
|
+
(14 days, weekend rollover, margin 5 — a period ending on a public holiday runs to the next working
|
|
320
|
+
day and holiday clusters need up to five, no per-country calendar is kept —, every mechanism OFF,
|
|
321
|
+
`defaultLanguage: 'en'`, start requests
|
|
322
|
+
usable 3600 s) — and `consumerRightsPolicyHelper.assertConsumerRightsPolicy` (non-empty
|
|
323
|
+
`textVersion`, `^[A-Z]{2}$` countries, `withdrawalDays >= 14`, margin 0..7, lowercase currencies,
|
|
324
|
+
https links, the default language present, `withdrawalInformation` required while `withdrawal` or
|
|
325
|
+
`performanceConsent` is on, `consentContext` a lowercase key `^[a-z][a-z0-9-]*$`; throws
|
|
326
|
+
`ConsumerRightsError('policy:<field>')`). It carries only public links, territories, switches and
|
|
327
|
+
the consent context — mail options live in a backend-only plugin config — so it is ADVERTISED to the
|
|
328
|
+
browser like the pricing policy. **`consentContext`** names the copy variant of the performance
|
|
329
|
+
consent (`'included'`: the credit limits included in a plan are used first, so the consent covers
|
|
330
|
+
topped-up credits once those limits have run out): the server records and mails, and the dialog
|
|
331
|
+
shows, the `_<context>` texts (§ The legal copy); absent, the base texts.
|
|
332
|
+
`PaymentService.consumerRightsPolicy()` answers `null` when none is declared: no consumer-rights
|
|
333
|
+
behaviour at all. `consumerRightsPolicyHelper.linksOf(policy, lng)` merges a language's links field
|
|
334
|
+
by field over the default language's (`de-AT` reads `de`).
|
|
335
|
+
|
|
336
|
+
`ProductPlan.withdrawal.components: PlanWithdrawalComponent[]` (`{ key, basis: 'time' | 'units',
|
|
337
|
+
shareMinor }`) states the separately priced parts of a subscription (CJEU C-641/19 PE Digital:
|
|
338
|
+
without them the whole price is pro rata by time). The same declaration picks the subscription start
|
|
339
|
+
statement: a `units` part makes it the `_units` variant (`consumerCopyHelper.startContextOf`, § The
|
|
340
|
+
legal copy).
|
|
341
|
+
|
|
342
|
+
### Wire views
|
|
343
|
+
|
|
344
|
+
Every view schema carries dates as ISO strings (as `model/view.ts` does) and is revived with its
|
|
345
|
+
`consumerReviveHelper.revive*` member (`reviveConsentView`, `revivePurchase`/`List`,
|
|
346
|
+
`reviveBillingProfile`, `reviveConsentResponse`, `reviveStartResponse`, `reviveWithdrawalList`,
|
|
347
|
+
`reviveReceipt`, `reviveCheckoutLimit`, `reviveAmountPolicyView`) — idempotent. A nullable enum on
|
|
348
|
+
the wire lists `null` in its enum (ajv rejects `null` otherwise). The consent and start views carry
|
|
349
|
+
`trader`, the name the statement is rendered with, and `context`, the variant it is rendered with —
|
|
350
|
+
the consent view the policy's `consentContext`, the start view
|
|
351
|
+
`consumerCopyHelper.startContextOf(plan)` (`'units'`), each absent for the base — so the server's
|
|
352
|
+
record and the dialog's text are identical. `WithdrawalBody` and `CancellationBody` ask only for
|
|
353
|
+
name, contract and e-mail (plus the cancellation kind, reason and date) and accept an optional
|
|
354
|
+
`honeypot` a person never fills. A public declaration answers `DeclarationReceipt` — what was
|
|
355
|
+
declared and when, never whether a contract matched.
|
|
356
|
+
|
|
357
|
+
### Calculators — always in the consumer's favour
|
|
358
|
+
|
|
359
|
+
All amounts in BigInt; a deduction rounds DOWN, a refund rounds UP, a refund never exceeds what is
|
|
360
|
+
still unrefunded.
|
|
361
|
+
|
|
362
|
+
- `withdrawalDeadlineHelper.withdrawalDeadlineOf(purchasedAt, rule | policy)` → the EXCLUSIVE end:
|
|
363
|
+
the purchase's UTC day + `days`, a Saturday/Sunday last day moved to Monday, + `marginDays`, start
|
|
364
|
+
of the next UTC day. Wed 2026-09-23 → 2026-10-13T00:00Z; Sat 2026-09-26 → 2026-10-18T00:00Z; Sun
|
|
365
|
+
2026-12-20 → 2027-01-10T00:00Z (margin 5). `withdrawalDeadlineHelper.withdrawalOpen(window, at)` —
|
|
366
|
+
before the deadline, not withdrawn, not refunded. **A person is shown the last included day**,
|
|
367
|
+
`withdrawalDeadlineHelper.lastWithdrawalDayOf(deadline)` (the UTC day of `deadline − 1 ms`),
|
|
368
|
+
phrased "until the end of <date>" — never the exclusive instant.
|
|
369
|
+
- `withdrawalRefundHelper.oneTimeWithdrawalRefund({ paidMinor, refundedMinor?, unitsGranted, unitsUsed })`
|
|
370
|
+
→ `min(paid − refunded, ceil(paid × (granted − used) / granted))`; `unitsUsed` is the deduction —
|
|
371
|
+
units used AFTER consent (none before it) plus debt settled from the lot plus units already
|
|
372
|
+
clawed back (`@owlmeans/server-payment` passes the meter's `usedAfter + settled + clawed`);
|
|
373
|
+
returns `unitsReturned`. 1256 paid, 125k of 500k used → 942.
|
|
374
|
+
- `withdrawalRefundHelper.subscriptionWithdrawalRefund(...)` splits `netMinor` by the components
|
|
375
|
+
(its `splitByShares`, largest remainder); a `time` part loses
|
|
376
|
+
`floor(c × elapsedDays / periodDays)` counted from `max(periodStart, servicesRequestedAt)` —
|
|
377
|
+
NOTHING without a start request; a `units` part loses `floor(c × used / granted)`; gross =
|
|
378
|
+
`ceil(paid × refundNet / net)`. Net 2000 / paid 2460, 3 of 30 days and 100k of 500k used → 2091.
|
|
379
|
+
- `fifoHelper.allocateFifo(lots, spends)` — a spend takes the oldest lot granted at or before it;
|
|
380
|
+
overflow is `unallocated`. `fifoHelper.unitsUsedAfter(lot, consentedAt)` counts slices strictly
|
|
381
|
+
after the consent, `0` without one.
|
|
382
|
+
- `cancellationEffectiveAt(periodEnd, 'month' | 'year', requested?)` — the period end, or the first
|
|
383
|
+
boundary on or after a later requested date (end-of-month clamped from the anchor).
|
|
384
|
+
|
|
385
|
+
### Refusals
|
|
386
|
+
|
|
387
|
+
`ConsumerRightsRefusal` extends `ConsumerRightsError` (a `PaymentError`), NEVER `AuthForbidden`:
|
|
388
|
+
an HTTP boundary tests that family first, and a 403 would hide the status a client acts on. Each
|
|
389
|
+
refusal declares `static httpStatus`, packs its fields into the message and rebuilds them in
|
|
390
|
+
`finalizeUnmarshal()` (the marker is read after its LAST occurrence, so a registry rebuild of a
|
|
391
|
+
doubled prefix still parses):
|
|
392
|
+
|
|
393
|
+
| Class | Status | Marker (after `payment:consumer-rights:`) | Fields |
|
|
394
|
+
|---|---|---|---|
|
|
395
|
+
| `PerformanceConsentRequired` | 428 | `performance-consent-required:<pending>[:<deadline ISO>]` | `pending`, `deadline` |
|
|
396
|
+
| `SubscriptionStartRequired` | 428 | `subscription-start-required:<encodeURIComponent(planSku)>` | `planSku` (pass it raw) |
|
|
397
|
+
| `BillingCountryLocked` | 409 | `billing-country-locked:<country>[:<requested>]` | `country`, `requested` |
|
|
398
|
+
| `WithdrawalUnavailable` | 409 | `withdrawal-unavailable:<WithdrawalUnavailableReason>` | `reason` |
|
|
399
|
+
| `CancellationUnavailable` | 409 | `cancellation-unavailable:<CancellationUnavailableReason>` | `reason` |
|
|
400
|
+
|
|
401
|
+
`consentRefusalOf(e)` → `'performance' | 'subscription-start' | null`: the class after
|
|
402
|
+
`ResilientError.ensure`, else the marker or type name in `message`/`type`. A production body
|
|
403
|
+
carries only an incident id — a bare 428 is the caller's to read with `@owlmeans/api/status`.
|
|
404
|
+
|
|
405
|
+
### The legal copy
|
|
406
|
+
|
|
407
|
+
The i18n resource `payment-consumer-rights` (`CONSUMER_RIGHTS_RESOURCE`, library tier, `lib`
|
|
408
|
+
namespace), in en pl ru be uk es de fr, versioned by `CONSUMER_RIGHTS_COPY_VERSION` (bump it on ANY
|
|
409
|
+
change to a bundle). Branches: `performance-consent`, `subscription-start` (`title`, `intro`,
|
|
410
|
+
`request`, `acknowledgement`, `checkbox` = request + space + acknowledgement, `confirm`,
|
|
411
|
+
`decline`; the consent branch also `purchase`; the start branch's `request`/`acknowledgement`/
|
|
412
|
+
`checkbox` also as `_units`), `withdrawal`, `cancellation` (form labels and the
|
|
413
|
+
statutory buttons `function` / `confirm`), `links`, `checkout` (`terms-acceptance.{in-scope,
|
|
414
|
+
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`,
|
|
415
|
+
`top-up-note`), `email.{common, consent, start (`rule` + `rule_units`), purchase, withdrawal, cancellation}` (the purchase
|
|
416
|
+
mail carries the CRD Annex I(A) withdrawal information with the function's address and the Annex
|
|
417
|
+
I(B) model form, per language from the national models; there `{{trader}}` is the trader's whole
|
|
418
|
+
identity — legal name, address, e-mail; a `review` withdrawal receipt promises the reimbursement
|
|
419
|
+
within the statutory 14 days; `email.cancellation.review` answers an extraordinary cancellation,
|
|
420
|
+
whose status is `CancellationStatus.Review`), `credit-note.memo`. In the consent and start
|
|
421
|
+
STATEMENTS `{{trader}}` is the trader's short name.
|
|
422
|
+
|
|
423
|
+
- Read it with `consumerCopyHelper.consumerRightsCopy(lng)` (any language, merged key by key over
|
|
424
|
+
English, no i18next instance, never drains a bundle — `i18nHelper.resolveI18nResource`),
|
|
425
|
+
`consumerCopyHelper.consumerText(lng, path, vars, context?)` (fills `{{name}}`; throws
|
|
426
|
+
`ConsumerRightsError('copy:<path>[:<name>]')` on a missing text or value — a legal text never goes
|
|
427
|
+
out with a hole), `consumerCopyHelper.consentStatementOf(lng, kind, { trader, plan?, context? })`
|
|
428
|
+
(the exact statement the dialog shows, the server records and the mail repeats) and
|
|
429
|
+
`consumerCopyHelper.legalLabelsOf(lng)`.
|
|
430
|
+
- **Context variants** (the i18next context suffix): with a `context`,
|
|
431
|
+
`consumerCopyHelper.consumerText` reads `<path>_<context>` first and the base `path` only where no
|
|
432
|
+
such variant exists (a missing value then names the variant: `copy:<path>_<context>:<name>`); an
|
|
433
|
+
empty context is none. `consumerCopyHelper.consentStatementOf` passes its `context` to all three
|
|
434
|
+
texts. Shipped variants, all eight languages, same placeholders as the base keys, each request
|
|
435
|
+
keeping the base request's statutory opening verbatim; a new variant lands in every language at
|
|
436
|
+
once, with its base key's placeholders:
|
|
437
|
+
- `performance-consent.{title,intro,request,checkbox}_included` — the consuming platform's
|
|
438
|
+
vocabulary: "topped-up credits" (pl doładowane, ru пополненные, be папоўненыя, uk поповнені, es
|
|
439
|
+
recargados, de aufgeladene, fr rechargés) are spent once "the credit limits included in my plan"
|
|
440
|
+
(a plan's non-monetary credits) have run out; `checkbox_included` = `request_included` + space +
|
|
441
|
+
the BASE `acknowledgement` (generic "credits", so `acknowledgement` has no variant).
|
|
442
|
+
- **The subscription start statement follows the plan's withdrawal arithmetic.** The BASE
|
|
443
|
+
`subscription-start.{request,acknowledgement,checkbox}` and `email.start.rule` describe the
|
|
444
|
+
common case — the plan withdrawn pro rata by the DAYS ELAPSED only ("starts the {{plan}}
|
|
445
|
+
services — including the AI work within the usage the plan includes — now …; … I pay for the
|
|
446
|
+
services provided until then, pro rata by the days elapsed, and everything else is
|
|
447
|
+
reimbursed"); `…_units` (`checkbox_units` = `request_units` + space + `acknowledgement_units`)
|
|
448
|
+
describe the split — services pro rata by time, the right of withdrawal expiring for the
|
|
449
|
+
included units used. `consumerCopyHelper.startContextOf(plan)` is the ONE decision: `'units'`
|
|
450
|
+
exactly when the plan's `withdrawal.components` has a `basis: 'units'` part, else `undefined`.
|
|
451
|
+
Every renderer takes the context from it — the server's start view, the recorded statement and
|
|
452
|
+
the start mail, and the dialog (from the view's `context`) — so the statement on screen is the
|
|
453
|
+
one recorded. `title`, `intro`, `confirm`, `decline` have no `_units` variant. Generic statutory
|
|
454
|
+
text (the purchase mail's withdrawal information) stays generic.
|
|
455
|
+
- Statutory labels are pinned by a test: en "Withdraw from contract here" / "Confirm withdrawal",
|
|
456
|
+
"Cancel contracts here" / "Cancel now"; de "Vertrag widerrufen" / "Widerruf bestätigen",
|
|
457
|
+
"Verträge hier kündigen" / "Jetzt kündigen"; fr "Renoncer au contrat ici" / "Confirmer la
|
|
458
|
+
rétractation", "Résilier votre contrat" / "Notification de la résiliation"; pl "Odstąp od umowy
|
|
459
|
+
tutaj" / "Potwierdź odstąpienie od umowy", "Wypowiedz umowę tutaj" / "Wypowiedz teraz"; es
|
|
460
|
+
"Desistir del contrato aquí" / "Confirmar el desistimiento", "Cancelar contratos aquí" /
|
|
461
|
+
"Cancelar ahora"; uk/ru/be are courtesy translations.
|
|
462
|
+
- The express request uses the statutory verbs (PL "Żądam i wyrażam wyraźną zgodę … Przyjmuję do
|
|
463
|
+
wiadomości …", DE "Ich verlange ausdrücklich und stimme ausdrücklich zu … Mir ist bekannt …", FR
|
|
464
|
+
"Je demande expressément et j’accepte expressément … Je reconnais perdre …"). Every start
|
|
465
|
+
request — base and `_units`, every language — opens with the same three words as that language's
|
|
466
|
+
performance request (pinned by the copy spec).
|
|
467
|
+
- Wording rule, enforced by a scan of every language: say "the right of withdrawal expires" and
|
|
468
|
+
"only unused credits are reimbursed" — never non-refundable / nicht erstattungsfähig / non
|
|
469
|
+
remboursable / bezzwrotny / no reembolsable / невозвратный / неповоротний / незваротны.
|
|
470
|
+
- Paygate texts (`checkout.*`) stay within 1200 characters after interpolating long URLs.
|
|
471
|
+
- An application overrides a text with `i18nHelper.addI18nApp(lng, CONSUMER_RIGHTS_RESOURCE, data,
|
|
472
|
+
{ ns: LIB_NAMESPACE })`; every placeholder of a text must match its English master.
|
|
473
|
+
|
|
474
|
+
### Protocol factories
|
|
475
|
+
|
|
476
|
+
`makeConsumerRightsProtocols({ prefix, parent | guards (+ gate), path = '/consumer-rights',
|
|
477
|
+
public?: false | { path = '/public/consumer-rights', parent?, screens?: { withdrawal?,
|
|
478
|
+
cancellation?, parent? } } })`, the `makeMarketingConsentProtocols` way:
|
|
479
|
+
|
|
480
|
+
- account subtree under the app's GUARDED parent (its guards and gate inherited): `base`,
|
|
481
|
+
`profile` GET `/profile`, `purchases` GET `/purchases`, `consent` GET / `giveConsent` POST
|
|
482
|
+
`/consent`, `start` GET `/start?planSku` / `requestStart` POST `/start`, `withdrawals` GET /
|
|
483
|
+
`withdraw` POST `/withdrawal`, `cancel` POST `/cancellation`; aliases `<prefix>:<name>`
|
|
484
|
+
(`consent:give`, `start:request`);
|
|
485
|
+
- `public` (only when declared): `base`, `policy` GET `/policy`, `withdraw` POST `/withdrawal`,
|
|
486
|
+
`cancel` POST `/cancellation` — NO guard and NO gate (like `paymentGate.webhook`; a public
|
|
487
|
+
`parent` must be unguarded), receipts typed `DeclarationReceipt`; `screens` declares BOTH sticky
|
|
488
|
+
frontend routes (`/legal/withdraw`, `/legal/cancel` by default); aliases `<prefix>:public:<name>`;
|
|
489
|
+
- neither `parent` nor `guards` is a `SyntaxError`; absent parts are left OUT of the tree (never
|
|
490
|
+
`undefined`), so `protocols(tree)` and `mapProtocols` walk it as is.
|
|
491
|
+
|
|
492
|
+
`makeCheckoutReadProtocols({ prefix, parent | guards })` → `base` (`/checkout`), `amountPolicy`
|
|
493
|
+
GET `/amount-policy?productSku&planSku` (`AmountPolicyView`) and `planPrices` GET
|
|
494
|
+
`/plan-prices?productSku` (`PlanPriceList`).
|
|
495
|
+
|
|
496
|
+
## `shallowAuthentication` identifies, it does not authorize
|
|
497
|
+
|
|
498
|
+
It reads the `profileId` out of an envelope token WITHOUT verifying the signature, and throws
|
|
499
|
+
`PaymentIdentificationError` when there is no token or no profile in it. Use it to correlate a
|
|
500
|
+
checkout return with a visitor; never as the basis of an access decision — that is a gate's job.
|
|
47
501
|
|
|
48
502
|
## Depends On
|
|
49
503
|
|
|
50
|
-
- `@owlmeans/entrypoint
|
|
51
|
-
- `@owlmeans/auth`, `@owlmeans/
|
|
504
|
+
- `@owlmeans/entrypoint` · `@owlmeans/route` · `@owlmeans/config` · `@owlmeans/resource`
|
|
505
|
+
- `@owlmeans/auth` (`PermissionSet`, `AuthForbidden`) · `@owlmeans/basic-envelope` · `@owlmeans/context`
|
|
506
|
+
- `@owlmeans/error` · `@owlmeans/i18n` · `@owlmeans/api-config` · peer `ajv`
|
|
507
|
+
|
|
508
|
+
## Related
|
|
509
|
+
|
|
510
|
+
- [[entitlements]] — the model across packages: admission, the usage ledger, the gates
|
|
511
|
+
- [[server-payment]] — the Stripe gateway, subscription store, usage ledger and gate services
|
|
512
|
+
- [[web-payment]] — hooks and pieces over the entitlement view
|
|
513
|
+
- [[client-payment]] — the browser-side adaptation of the catalogue service
|
|
514
|
+
- [[iam]] — `PermissionSet` and the resource-selector syntax entitlements deliberately avoid
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advertise.d.ts","sourceRoot":"","sources":["../src/advertise.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CONFIG_RECORD } from '@owlmeans/context';
|
|
2
|
+
import { apiConfigPlugin, every } from '@owlmeans/api-config';
|
|
3
|
+
import { advertisedRecordTypes } from './consts.local.js';
|
|
4
|
+
apiConfigPlugin({
|
|
5
|
+
allow: {
|
|
6
|
+
[CONFIG_RECORD]: every(true, value => value != null && typeof value === 'object'
|
|
7
|
+
&& advertisedRecordTypes.has(value.recordType ?? '')),
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=advertise.js.map
|
|
@@ -0,0 +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,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 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/checkout/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,cAAc,CAAA"}
|
|
@@ -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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/checkout/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,mBAAmB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/checkout/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAG3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA"}
|