@owlmeans/server-payment 0.1.18-rc.30 → 0.1.18-rc.32
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 +35 -24
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-payment/SKILL.md +39 -39
- package/build/access/types.d.ts +46 -0
- package/build/access/types.d.ts.map +1 -0
- package/build/access/types.js +2 -0
- package/build/access/types.js.map +1 -0
- package/build/access.d.ts +6 -0
- package/build/access.d.ts.map +1 -0
- package/build/access.js +45 -0
- package/build/access.js.map +1 -0
- package/build/actions/resync-subscriptions.d.ts.map +1 -1
- package/build/actions/resync-subscriptions.js +3 -2
- package/build/actions/resync-subscriptions.js.map +1 -1
- package/build/actions/resync.d.ts.map +1 -1
- package/build/actions/resync.js +7 -5
- package/build/actions/resync.js.map +1 -1
- package/build/actions/webhook.d.ts.map +1 -1
- package/build/actions/webhook.js +5 -4
- package/build/actions/webhook.js.map +1 -1
- package/build/bootstrap/types.d.ts +16 -0
- package/build/bootstrap/types.d.ts.map +1 -0
- package/build/bootstrap/types.js +2 -0
- package/build/bootstrap/types.js.map +1 -0
- package/build/bootstrap.d.ts +6 -0
- package/build/bootstrap.d.ts.map +1 -0
- package/build/bootstrap.js +26 -0
- package/build/bootstrap.js.map +1 -0
- package/build/catalogue/types.d.ts +38 -0
- package/build/catalogue/types.d.ts.map +1 -0
- package/build/catalogue/types.js +2 -0
- package/build/catalogue/types.js.map +1 -0
- package/build/catalogue.d.ts +6 -0
- package/build/catalogue.d.ts.map +1 -0
- package/build/catalogue.js +110 -0
- package/build/catalogue.js.map +1 -0
- package/build/commit/types.d.ts +22 -0
- package/build/commit/types.d.ts.map +1 -0
- package/build/commit/types.js +2 -0
- package/build/commit/types.js.map +1 -0
- package/build/commit.d.ts +6 -0
- package/build/commit.d.ts.map +1 -0
- package/build/commit.js +125 -0
- package/build/commit.js.map +1 -0
- package/build/config.d.ts +1 -17
- package/build/config.d.ts.map +1 -1
- package/build/config.js +9 -46
- package/build/config.js.map +1 -1
- package/build/consumer/cancellation/types.d.ts +11 -0
- package/build/consumer/cancellation/types.d.ts.map +1 -0
- package/build/consumer/cancellation/types.js +2 -0
- package/build/consumer/cancellation/types.js.map +1 -0
- package/build/consumer/cancellation.d.ts +6 -0
- package/build/consumer/cancellation.d.ts.map +1 -0
- package/build/consumer/cancellation.js +33 -0
- package/build/consumer/cancellation.js.map +1 -0
- package/build/consumer/capture/types.d.ts +50 -0
- package/build/consumer/capture/types.d.ts.map +1 -0
- package/build/consumer/capture/types.js +2 -0
- package/build/consumer/capture/types.js.map +1 -0
- package/build/consumer/capture.d.ts +4 -59
- package/build/consumer/capture.d.ts.map +1 -1
- package/build/consumer/capture.js +277 -293
- package/build/consumer/capture.js.map +1 -1
- package/build/consumer/format/types.d.ts +30 -0
- package/build/consumer/format/types.d.ts.map +1 -0
- package/build/consumer/format/types.js +2 -0
- package/build/consumer/format/types.js.map +1 -0
- package/build/consumer/format.d.ts +3 -26
- package/build/consumer/format.d.ts.map +1 -1
- package/build/consumer/format.js +69 -77
- package/build/consumer/format.js.map +1 -1
- package/build/consumer/handlers.d.ts.map +1 -1
- package/build/consumer/handlers.js +8 -7
- package/build/consumer/handlers.js.map +1 -1
- package/build/consumer/index.d.ts +7 -4
- package/build/consumer/index.d.ts.map +1 -1
- package/build/consumer/index.js +3 -3
- package/build/consumer/index.js.map +1 -1
- package/build/consumer/mail/types.d.ts +29 -0
- package/build/consumer/mail/types.d.ts.map +1 -0
- package/build/consumer/mail/types.js +2 -0
- package/build/consumer/mail/types.js.map +1 -0
- package/build/consumer/mail.d.ts +4 -25
- package/build/consumer/mail.d.ts.map +1 -1
- package/build/consumer/mail.js +211 -212
- package/build/consumer/mail.js.map +1 -1
- package/build/consumer/observers/types.d.ts +15 -0
- package/build/consumer/observers/types.d.ts.map +1 -0
- package/build/consumer/observers/types.js +2 -0
- package/build/consumer/observers/types.js.map +1 -0
- package/build/consumer/observers.d.ts +6 -0
- package/build/consumer/observers.d.ts.map +1 -0
- package/build/consumer/observers.js +74 -0
- package/build/consumer/observers.js.map +1 -0
- package/build/consumer/origin/types.d.ts +17 -0
- package/build/consumer/origin/types.d.ts.map +1 -0
- package/build/consumer/origin/types.js +2 -0
- package/build/consumer/origin/types.js.map +1 -0
- package/build/consumer/origin.d.ts +4 -10
- package/build/consumer/origin.d.ts.map +1 -1
- package/build/consumer/origin.js +39 -42
- package/build/consumer/origin.js.map +1 -1
- package/build/consumer/reconcile/types.d.ts +13 -0
- package/build/consumer/reconcile/types.d.ts.map +1 -0
- package/build/consumer/reconcile/types.js +2 -0
- package/build/consumer/reconcile/types.js.map +1 -0
- package/build/consumer/reconcile.d.ts +2 -9
- package/build/consumer/reconcile.d.ts.map +1 -1
- package/build/consumer/reconcile.js +283 -279
- package/build/consumer/reconcile.js.map +1 -1
- package/build/consumer/records/types.d.ts +66 -0
- package/build/consumer/records/types.d.ts.map +1 -0
- package/build/consumer/records/types.js +2 -0
- package/build/consumer/records/types.js.map +1 -0
- package/build/consumer/records.d.ts +4 -106
- package/build/consumer/records.d.ts.map +1 -1
- package/build/consumer/records.js +225 -281
- package/build/consumer/records.js.map +1 -1
- package/build/consumer/service.d.ts +2 -18
- package/build/consumer/service.d.ts.map +1 -1
- package/build/consumer/service.js +203 -268
- package/build/consumer/service.js.map +1 -1
- package/build/consumer/types.d.ts +5 -8
- package/build/consumer/types.d.ts.map +1 -1
- package/build/consumer/types.local.d.ts +4 -3
- package/build/consumer/types.local.d.ts.map +1 -1
- package/build/consumer/withdrawal/types.d.ts +36 -0
- package/build/consumer/withdrawal/types.d.ts.map +1 -0
- package/build/consumer/withdrawal/types.js +2 -0
- package/build/consumer/withdrawal/types.js.map +1 -0
- package/build/consumer/withdrawal.d.ts +4 -32
- package/build/consumer/withdrawal.d.ts.map +1 -1
- package/build/consumer/withdrawal.js +204 -214
- package/build/consumer/withdrawal.js.map +1 -1
- package/build/entitlement.d.ts +1 -7
- package/build/entitlement.d.ts.map +1 -1
- package/build/entitlement.js +41 -38
- package/build/entitlement.js.map +1 -1
- package/build/entrypoints.js +1 -1
- package/build/entrypoints.js.map +1 -1
- package/build/gate/request.d.ts +4 -0
- package/build/gate/request.d.ts.map +1 -0
- package/build/gate/request.js +17 -0
- package/build/gate/request.js.map +1 -0
- package/build/gate/types.d.ts +15 -0
- package/build/gate/types.d.ts.map +1 -0
- package/build/gate/types.js +2 -0
- package/build/gate/types.js.map +1 -0
- package/build/gate.d.ts +4 -14
- package/build/gate.d.ts.map +1 -1
- package/build/gate.js +7 -32
- package/build/gate.js.map +1 -1
- package/build/index.d.ts +47 -17
- package/build/index.d.ts.map +1 -1
- package/build/index.js +26 -14
- package/build/index.js.map +1 -1
- package/build/limit.d.ts.map +1 -1
- package/build/limit.js +6 -6
- package/build/limit.js.map +1 -1
- package/build/model.d.ts +15 -0
- package/build/model.d.ts.map +1 -0
- package/build/model.js +247 -0
- package/build/model.js.map +1 -0
- package/build/models/declarations/types.d.ts +22 -0
- package/build/models/declarations/types.d.ts.map +1 -0
- package/build/models/declarations/types.js +2 -0
- package/build/models/declarations/types.js.map +1 -0
- package/build/models/declarations.d.ts +4 -0
- package/build/models/declarations.d.ts.map +1 -0
- package/build/models/declarations.js +26 -0
- package/build/models/declarations.js.map +1 -0
- package/build/models/purchase/types.d.ts +13 -0
- package/build/models/purchase/types.d.ts.map +1 -0
- package/build/models/purchase/types.js +2 -0
- package/build/models/purchase/types.js.map +1 -0
- package/build/models/purchase.d.ts +4 -0
- package/build/models/purchase.d.ts.map +1 -0
- package/build/models/purchase.js +37 -0
- package/build/models/purchase.js.map +1 -0
- package/build/plan/types.d.ts +21 -0
- package/build/plan/types.d.ts.map +1 -0
- package/build/plan/types.js +2 -0
- package/build/plan/types.js.map +1 -0
- package/build/plan.d.ts +5 -31
- package/build/plan.d.ts.map +1 -1
- package/build/plan.js +26 -98
- package/build/plan.js.map +1 -1
- package/build/plugins/checkout-plugins/types.d.ts +25 -0
- package/build/plugins/checkout-plugins/types.d.ts.map +1 -0
- package/build/plugins/checkout-plugins/types.js +2 -0
- package/build/plugins/checkout-plugins/types.js.map +1 -0
- package/build/plugins/checkout-plugins.d.ts +7 -36
- package/build/plugins/checkout-plugins.d.ts.map +1 -1
- package/build/plugins/checkout-plugins.js +62 -115
- package/build/plugins/checkout-plugins.js.map +1 -1
- package/build/plugins/checkout-policy/types.d.ts +18 -0
- package/build/plugins/checkout-policy/types.d.ts.map +1 -0
- package/build/plugins/checkout-policy/types.js +2 -0
- package/build/plugins/checkout-policy/types.js.map +1 -0
- package/build/plugins/checkout-policy.d.ts +4 -0
- package/build/plugins/checkout-policy.d.ts.map +1 -0
- package/build/plugins/checkout-policy.js +26 -0
- package/build/plugins/checkout-policy.js.map +1 -0
- package/build/plugins/checkout-registry/types.d.ts +7 -0
- package/build/plugins/checkout-registry/types.d.ts.map +1 -0
- package/build/plugins/checkout-registry/types.js +2 -0
- package/build/plugins/checkout-registry/types.js.map +1 -0
- package/build/plugins/checkout-registry.d.ts +8 -0
- package/build/plugins/checkout-registry.d.ts.map +1 -0
- package/build/plugins/checkout-registry.js +21 -0
- package/build/plugins/checkout-registry.js.map +1 -0
- package/build/plugins/customer-lock/types.d.ts +6 -0
- package/build/plugins/customer-lock/types.d.ts.map +1 -0
- package/build/plugins/customer-lock/types.js +2 -0
- package/build/plugins/customer-lock/types.js.map +1 -0
- package/build/plugins/customer-lock.d.ts +5 -0
- package/build/plugins/customer-lock.d.ts.map +1 -0
- package/build/plugins/customer-lock.js +22 -0
- package/build/plugins/customer-lock.js.map +1 -0
- package/build/plugins/estimate/cache.d.ts +4 -0
- package/build/plugins/estimate/cache.d.ts.map +1 -0
- package/build/plugins/estimate/cache.js +7 -0
- package/build/plugins/estimate/cache.js.map +1 -0
- package/build/plugins/estimate/types.d.ts +27 -0
- package/build/plugins/estimate/types.d.ts.map +1 -0
- package/build/plugins/estimate/types.js +2 -0
- package/build/plugins/estimate/types.js.map +1 -0
- package/build/plugins/estimate.d.ts +4 -16
- package/build/plugins/estimate.d.ts.map +1 -1
- package/build/plugins/estimate.js +168 -182
- package/build/plugins/estimate.js.map +1 -1
- package/build/plugins/events/types.d.ts +12 -0
- package/build/plugins/events/types.d.ts.map +1 -0
- package/build/plugins/events/types.js +2 -0
- package/build/plugins/events/types.js.map +1 -0
- package/build/plugins/events.d.ts +2 -30
- package/build/plugins/events.d.ts.map +1 -1
- package/build/plugins/events.js +92 -284
- package/build/plugins/events.js.map +1 -1
- package/build/plugins/fx/types.d.ts +31 -0
- package/build/plugins/fx/types.d.ts.map +1 -0
- package/build/plugins/fx/types.js +2 -0
- package/build/plugins/fx/types.js.map +1 -0
- package/build/plugins/fx.d.ts +4 -26
- package/build/plugins/fx.d.ts.map +1 -1
- package/build/plugins/fx.js +65 -66
- package/build/plugins/fx.js.map +1 -1
- package/build/plugins/portal/types.d.ts +44 -0
- package/build/plugins/portal/types.d.ts.map +1 -0
- package/build/plugins/portal/types.js +2 -0
- package/build/plugins/portal/types.js.map +1 -0
- package/build/plugins/portal.d.ts +4 -38
- package/build/plugins/portal.d.ts.map +1 -1
- package/build/plugins/portal.js +218 -241
- package/build/plugins/portal.js.map +1 -1
- package/build/plugins/refunds/types.d.ts +35 -0
- package/build/plugins/refunds/types.d.ts.map +1 -0
- package/build/plugins/refunds/types.js +2 -0
- package/build/plugins/refunds/types.js.map +1 -0
- package/build/plugins/refunds.d.ts +4 -11
- package/build/plugins/refunds.d.ts.map +1 -1
- package/build/plugins/refunds.js +71 -70
- package/build/plugins/refunds.js.map +1 -1
- package/build/plugins/session/types.d.ts +32 -0
- package/build/plugins/session/types.d.ts.map +1 -0
- package/build/plugins/session/types.js +2 -0
- package/build/plugins/session/types.js.map +1 -0
- package/build/plugins/session.d.ts +4 -0
- package/build/plugins/session.d.ts.map +1 -0
- package/build/plugins/session.js +58 -0
- package/build/plugins/session.js.map +1 -0
- package/build/plugins/status.d.ts +8 -0
- package/build/plugins/status.d.ts.map +1 -0
- package/build/plugins/status.js +21 -0
- package/build/plugins/status.js.map +1 -0
- package/build/plugins/stripe/types.d.ts +20 -0
- package/build/plugins/stripe/types.d.ts.map +1 -0
- package/build/plugins/stripe/types.js +2 -0
- package/build/plugins/stripe/types.js.map +1 -0
- package/build/plugins/stripe.d.ts +4 -52
- package/build/plugins/stripe.d.ts.map +1 -1
- package/build/plugins/stripe.js +385 -495
- package/build/plugins/stripe.js.map +1 -1
- package/build/plugins/subscriptions/types.d.ts +41 -0
- package/build/plugins/subscriptions/types.d.ts.map +1 -0
- package/build/plugins/subscriptions/types.js +2 -0
- package/build/plugins/subscriptions/types.js.map +1 -0
- package/build/plugins/subscriptions.d.ts +6 -0
- package/build/plugins/subscriptions.d.ts.map +1 -0
- package/build/plugins/subscriptions.js +169 -0
- package/build/plugins/subscriptions.js.map +1 -0
- package/build/plugins/types.d.ts +1 -76
- package/build/plugins/types.d.ts.map +1 -1
- package/build/plugins/types.local.d.ts +0 -1
- package/build/plugins/types.local.d.ts.map +1 -1
- package/build/plugins/webhook-manager/types.d.ts +62 -0
- package/build/plugins/webhook-manager/types.d.ts.map +1 -0
- package/build/plugins/webhook-manager/types.js +2 -0
- package/build/plugins/webhook-manager/types.js.map +1 -0
- package/build/plugins/webhook-manager.d.ts +5 -51
- package/build/plugins/webhook-manager.d.ts.map +1 -1
- package/build/plugins/webhook-manager.js +203 -200
- package/build/plugins/webhook-manager.js.map +1 -1
- package/build/protocol.d.ts +13 -0
- package/build/protocol.d.ts.map +1 -0
- package/build/protocol.js +17 -0
- package/build/protocol.js.map +1 -0
- package/build/reconcile/types.d.ts +17 -0
- package/build/reconcile/types.d.ts.map +1 -0
- package/build/reconcile/types.js +2 -0
- package/build/reconcile/types.js.map +1 -0
- package/build/reconcile.d.ts +6 -9
- package/build/reconcile.d.ts.map +1 -1
- package/build/reconcile.js +78 -76
- package/build/reconcile.js.map +1 -1
- package/build/resource.d.ts.map +1 -1
- package/build/resource.js +2 -3
- package/build/resource.js.map +1 -1
- package/build/schemas.d.ts +5 -1
- package/build/schemas.d.ts.map +1 -1
- package/build/schemas.js +16 -0
- package/build/schemas.js.map +1 -1
- package/build/service.d.ts +3 -17
- package/build/service.d.ts.map +1 -1
- package/build/service.js +32 -85
- package/build/service.js.map +1 -1
- package/build/subscription/types.d.ts +21 -0
- package/build/subscription/types.d.ts.map +1 -0
- package/build/subscription/types.js +2 -0
- package/build/subscription/types.js.map +1 -0
- package/build/subscription.d.ts +3 -26
- package/build/subscription.d.ts.map +1 -1
- package/build/subscription.js +75 -170
- package/build/subscription.js.map +1 -1
- package/build/sync/types.d.ts +25 -0
- package/build/sync/types.d.ts.map +1 -0
- package/build/sync/types.js +2 -0
- package/build/sync/types.js.map +1 -0
- package/build/sync.d.ts +4 -30
- package/build/sync.d.ts.map +1 -1
- package/build/sync.js +170 -194
- package/build/sync.js.map +1 -1
- package/build/types.d.ts +15 -15
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +4 -9
- package/build/types.local.d.ts.map +1 -1
- package/build/usage/types.d.ts +56 -0
- package/build/usage/types.d.ts.map +1 -0
- package/build/usage/types.js +2 -0
- package/build/usage/types.js.map +1 -0
- package/build/usage.d.ts +4 -50
- package/build/usage.d.ts.map +1 -1
- package/build/usage.js +291 -307
- package/build/usage.js.map +1 -1
- package/build/utils/types.d.ts +31 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/build/utils.d.ts +15 -69
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +54 -113
- package/build/utils.js.map +1 -1
- package/package.json +18 -18
- package/src/access/types.ts +52 -0
- package/src/access.ts +86 -0
- package/src/actions/resync-subscriptions.ts +3 -2
- package/src/actions/resync.ts +7 -5
- package/src/actions/webhook.ts +5 -4
- package/src/bootstrap/types.ts +16 -0
- package/src/bootstrap.ts +31 -0
- package/src/catalogue/types.ts +32 -0
- package/src/catalogue.ts +135 -0
- package/src/commit/types.ts +27 -0
- package/src/commit.ts +152 -0
- package/src/config.ts +10 -49
- package/src/consumer/cancellation/types.ts +13 -0
- package/src/consumer/cancellation.ts +43 -0
- package/src/consumer/capture/types.ts +53 -0
- package/src/consumer/capture.ts +289 -303
- package/src/consumer/format/types.ts +29 -0
- package/src/consumer/format.ts +64 -69
- package/src/consumer/handlers.ts +11 -7
- package/src/consumer/index.ts +7 -4
- package/src/consumer/mail/types.ts +31 -0
- package/src/consumer/mail.ts +233 -234
- package/src/consumer/observers/types.ts +22 -0
- package/src/consumer/observers.ts +97 -0
- package/src/consumer/origin/types.ts +17 -0
- package/src/consumer/origin.ts +48 -48
- package/src/consumer/reconcile/types.ts +13 -0
- package/src/consumer/reconcile.ts +274 -270
- package/src/consumer/records/types.ts +64 -0
- package/src/consumer/records.ts +248 -317
- package/src/consumer/service.ts +219 -306
- package/src/consumer/types.local.ts +2 -2
- package/src/consumer/types.ts +8 -10
- package/src/consumer/withdrawal/types.ts +37 -0
- package/src/consumer/withdrawal.ts +221 -226
- package/src/entitlement.ts +43 -42
- package/src/entrypoints.ts +1 -1
- package/src/gate/request.ts +24 -0
- package/src/gate/types.ts +13 -0
- package/src/gate.ts +12 -41
- package/src/index.ts +52 -24
- package/src/limit.ts +6 -6
- package/src/models/declarations/types.ts +22 -0
- package/src/models/declarations.ts +30 -0
- package/src/models/purchase/types.ts +13 -0
- package/src/models/purchase.ts +43 -0
- package/src/plan/types.ts +21 -0
- package/src/plan.ts +36 -114
- package/src/plugins/checkout-plugins/types.ts +25 -0
- package/src/plugins/checkout-plugins.ts +73 -128
- package/src/plugins/checkout-policy/types.ts +18 -0
- package/src/plugins/checkout-policy.ts +34 -0
- package/src/plugins/checkout-registry/types.ts +7 -0
- package/src/plugins/checkout-registry.ts +23 -0
- package/src/plugins/customer-lock/types.ts +5 -0
- package/src/plugins/customer-lock.ts +25 -0
- package/src/plugins/estimate/cache.ts +12 -0
- package/src/plugins/estimate/types.ts +28 -0
- package/src/plugins/estimate.ts +179 -200
- package/src/plugins/events/types.ts +11 -0
- package/src/plugins/events.ts +107 -326
- package/src/plugins/fx/types.ts +38 -0
- package/src/plugins/fx.ts +75 -76
- package/src/plugins/portal/types.ts +45 -0
- package/src/plugins/portal.ts +227 -256
- package/src/plugins/refunds/types.ts +31 -0
- package/src/plugins/refunds.ts +74 -72
- package/src/plugins/session/types.ts +28 -0
- package/src/plugins/session.ts +73 -0
- package/src/plugins/status.ts +22 -0
- package/src/plugins/stripe/types.ts +20 -0
- package/src/plugins/stripe.ts +402 -529
- package/src/plugins/subscriptions/types.ts +39 -0
- package/src/plugins/subscriptions.ts +195 -0
- package/src/plugins/types.local.ts +0 -1
- package/src/plugins/types.ts +1 -81
- package/src/plugins/webhook-manager/types.ts +63 -0
- package/src/plugins/webhook-manager.ts +215 -205
- package/src/protocol.ts +29 -0
- package/src/reconcile/types.ts +17 -0
- package/src/reconcile.ts +86 -78
- package/src/resource.ts +28 -19
- package/src/schemas.ts +25 -1
- package/src/service.ts +39 -94
- package/src/subscription/types.ts +23 -0
- package/src/subscription.ts +88 -192
- package/src/sync/types.ts +25 -0
- package/src/sync.ts +177 -204
- package/src/types.local.ts +2 -4
- package/src/types.ts +10 -12
- package/src/usage/types.ts +51 -0
- package/src/usage.ts +323 -342
- package/src/utils/types.ts +30 -0
- package/src/utils.ts +85 -181
- package/tests/checkout-consumer.spec.ts +27 -28
- package/tests/checkout-locks.spec.ts +18 -17
- package/tests/checkout-plugins.spec.ts +27 -27
- package/tests/checkout.spec.ts +15 -12
- package/tests/consumer-events.spec.ts +22 -24
- package/tests/consumer-fixtures.ts +6 -4
- package/tests/consumer-ops.spec.ts +38 -39
- package/tests/consumer-rights.integration.spec.ts +41 -43
- package/tests/consumer-rights.spec.ts +31 -36
- package/tests/context.ts +2 -2
- package/tests/entitlement.spec.ts +21 -21
- package/tests/estimate.spec.ts +27 -26
- package/tests/events.spec.ts +31 -30
- package/tests/fake-stripe.ts +19 -13
- package/tests/gate-handlers.spec.ts +2 -2
- package/tests/gate.spec.ts +5 -4
- package/tests/gateway-options.spec.ts +27 -28
- package/tests/limit-gate.spec.ts +13 -15
- package/tests/portal.spec.ts +31 -29
- package/tests/sync.spec.ts +12 -12
- package/tests/usage.integration.spec.ts +23 -25
- package/tests/usage.spec.ts +20 -22
- package/tests/webhook-manager.spec.ts +23 -26
package/build/actions/webhook.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { PaygateError, UnknownPaygate } from '@owlmeans/payment';
|
|
2
2
|
import { handlers } from '@owlmeans/server-api';
|
|
3
3
|
import { STRIPE_PAYGATE_ALIAS } from '../consts.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { paymentAccessOf } from '../access.js';
|
|
5
|
+
import { paymentGate } from '../protocol.js';
|
|
6
|
+
import { webhookOf } from '../plugins/webhook-manager.js';
|
|
6
7
|
const bind = handlers();
|
|
7
8
|
/** A Stripe delivery — only a managed gateway receives one; its secret is the `owner`'s stored one. */
|
|
8
9
|
export const webhook = bind.params(paymentGate.webhook, async ({ paygate }, context, request) => {
|
|
9
10
|
if (paygate !== STRIPE_PAYGATE_ALIAS)
|
|
10
11
|
throw new UnknownPaygate(paygate);
|
|
11
|
-
const service =
|
|
12
|
+
const service = paymentAccessOf(context).gateway();
|
|
12
13
|
if (!service.managed)
|
|
13
14
|
throw new PaygateError('unmanaged');
|
|
14
|
-
await handleStripeWebhook(
|
|
15
|
+
await webhookOf(context).handleStripeWebhook(await service.stripe(context), request);
|
|
15
16
|
});
|
|
16
17
|
//# sourceMappingURL=webhook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/actions/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/actions/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,MAAM,IAAI,GAAG,QAAQ,EAAW,CAAA;AAEhC,uGAAuG;AACvG,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC9F,IAAI,OAAO,KAAK,oBAAoB;QAAE,MAAM,IAAI,cAAc,CAAC,OAAO,CAAC,CAAA;IACvE,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;IAClD,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,MAAM,IAAI,YAAY,CAAC,WAAW,CAAC,CAAA;IACzD,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;AACtF,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type Stripe from 'stripe';
|
|
2
|
+
import type { StripeBootstrapOptions } from '../types.js';
|
|
3
|
+
/** What brings Stripe to a deployment's declaration. */
|
|
4
|
+
export interface StripeBootstrapHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Bring Stripe to what this deployment declares, each step on its own so one failing does not block
|
|
7
|
+
* the others: products and prices, the customer-portal configuration, the webhook endpoint.
|
|
8
|
+
*
|
|
9
|
+
* The webhook URL and the owner key come from the context's gateway (`webhookService`, `owner`), so
|
|
10
|
+
* every process of one deployment — the one bootstrapping at boot, a `resync`, an application's
|
|
11
|
+
* forced maintenance run — computes the same URL and rows; each step is fingerprinted, so running it
|
|
12
|
+
* from any of them is idempotent.
|
|
13
|
+
*/
|
|
14
|
+
bootstrapStripe: (stripe: Stripe, opts?: StripeBootstrapOptions) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/bootstrap/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;OAQG;IACH,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/bootstrap/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context as ApiContext } from '@owlmeans/server-api';
|
|
2
|
+
import type { StripeBootstrapHelper } from './bootstrap/types.js';
|
|
3
|
+
export declare const makeStripeBootstrapHelper: (ctx: ApiContext) => StripeBootstrapHelper;
|
|
4
|
+
/** The Stripe bootstrap of a context — one per context. */
|
|
5
|
+
export declare const stripeBootstrapOf: (target: ApiContext<import("@owlmeans/server-api").Config>) => StripeBootstrapHelper;
|
|
6
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAIjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAKjE,eAAO,MAAM,yBAAyB,QAAS,UAAU,KAAG,qBAiB3D,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,iBAAiB,sFAAgD,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { memoHelper } from '@owlmeans/context';
|
|
2
|
+
import { log } from './log.js';
|
|
3
|
+
import { productSyncOf } from './sync.js';
|
|
4
|
+
import { portalOf } from './plugins/portal.js';
|
|
5
|
+
import { webhookOf } from './plugins/webhook-manager.js';
|
|
6
|
+
export const makeStripeBootstrapHelper = (ctx) => {
|
|
7
|
+
const bootstrapStripe = async (stripe, opts = {}) => {
|
|
8
|
+
const steps = [
|
|
9
|
+
['products', async () => await productSyncOf(ctx).syncStripeProducts(stripe)],
|
|
10
|
+
['portal', async () => await portalOf(ctx).ensurePortalConfiguration(stripe, opts)],
|
|
11
|
+
['webhook', async () => await webhookOf(ctx).ensureWebhookEndpoint(stripe, opts)],
|
|
12
|
+
];
|
|
13
|
+
for (const [name, step] of steps) {
|
|
14
|
+
try {
|
|
15
|
+
await step();
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
log.error('Stripe bootstrap step failed', { step: name, error });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return { bootstrapStripe };
|
|
23
|
+
};
|
|
24
|
+
/** The Stripe bootstrap of a context — one per context. */
|
|
25
|
+
export const stripeBootstrapOf = memoHelper.oncePer(makeStripeBootstrapHelper);
|
|
26
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,GAAe,EAAyB,EAAE;IAClF,MAAM,eAAe,GAAG,KAAK,EAAE,MAAc,EAAE,IAAI,GAA2B,EAAE,EAAiB,EAAE;QACjG,MAAM,KAAK,GAA4C;YACrD,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC7E,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,yBAAyB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACnF,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;SAClF,CAAA;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,IAAI,EAAE,CAAA;YACd,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;YAClE,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,OAAO,EAAE,eAAe,EAAE,CAAA;AAC5B,CAAC,CAAA;AAED,2DAA2D;AAC3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PermissionSet } from '@owlmeans/auth';
|
|
2
|
+
import type { EffectivePlan, PaymentPlan, PaymentProduct } from '../types.js';
|
|
3
|
+
/** The catalogue a context declares, and the plan each entity holds in it. */
|
|
4
|
+
export interface CatalogueHelper {
|
|
5
|
+
/** A plan by sku, or `null` when the catalogue no longer declares it. */
|
|
6
|
+
findPlan: (planSku: string) => Promise<PaymentPlan | null>;
|
|
7
|
+
/** A product by sku, or `null`. */
|
|
8
|
+
findProduct: (productSku: string) => Promise<PaymentProduct | null>;
|
|
9
|
+
/** Every plan of every declared product. */
|
|
10
|
+
catalogPlans: () => Promise<PaymentPlan[]>;
|
|
11
|
+
/** The declared free plan an entity falls back to: the lowest rank, then the sku. */
|
|
12
|
+
freePlanOf: () => Promise<PaymentPlan | null>;
|
|
13
|
+
/**
|
|
14
|
+
* The plan an entity holds: its highest-ranked subscription in an entitling status (the catalogue
|
|
15
|
+
* rank, the stored one for a plan the catalogue no longer declares; the newest first on a tie),
|
|
16
|
+
* else the declared free plan. The plan answered carries the winning row's `overrides`
|
|
17
|
+
* (`overriddenPlan`), so every reader — ceilings, the view, the gates — sees one answer.
|
|
18
|
+
*
|
|
19
|
+
* @throws PlanRequired when there is neither.
|
|
20
|
+
*/
|
|
21
|
+
resolveEffectivePlan: (entityId: string, at?: Date) => Promise<EffectivePlan>;
|
|
22
|
+
/**
|
|
23
|
+
* The capability sets an entity's effective plan grants now — sets behind a lapsed promo left out.
|
|
24
|
+
* Empty when the plan is not of one of `productSkus`.
|
|
25
|
+
*/
|
|
26
|
+
entitlementsOf: (entityId: string, productSkus?: string[]) => Promise<PermissionSet[]>;
|
|
27
|
+
/** Every product sold through Stripe with the plans it sells there. */
|
|
28
|
+
stripePlansOf: () => Promise<Array<{
|
|
29
|
+
product: PaymentProduct;
|
|
30
|
+
plans: PaymentPlan[];
|
|
31
|
+
}>>;
|
|
32
|
+
/** The plan an amount/quantity checkout of a consumable product sells: the named one, else the first. */
|
|
33
|
+
consumablePlanOf: (productSku: string, planSku?: string) => Promise<{
|
|
34
|
+
product: PaymentProduct;
|
|
35
|
+
plan: PaymentPlan;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/catalogue/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE7E,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC1D,mCAAmC;IACnC,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACnE,4CAA4C;IAC5C,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IAC1C,qFAAqF;IACrF,UAAU,EAAE,MAAM,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC7C;;;;;;;OAOG;IACH,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;IAC7E;;;OAGG;IACH,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IACtF,uEAAuE;IACvE,aAAa,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC,CAAC,CAAA;IACtF,yGAAyG;IACzG,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC,CAAA;CACpH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/catalogue/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context as ApiContext } from '@owlmeans/server-api';
|
|
2
|
+
import type { CatalogueHelper } from './catalogue/types.js';
|
|
3
|
+
export declare const makeCatalogueHelper: (ctx: ApiContext) => CatalogueHelper;
|
|
4
|
+
/** The catalogue of a context — one per context. */
|
|
5
|
+
export declare const catalogueOf: (target: ApiContext<import("@owlmeans/server-api").Config>) => CatalogueHelper;
|
|
6
|
+
//# sourceMappingURL=catalogue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../src/catalogue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAOjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAS3D,eAAO,MAAM,mBAAmB,QAAS,UAAU,KAAG,eAiHrD,CAAA;AAED,oDAAoD;AACpD,eAAO,MAAM,WAAW,gFAA0C,CAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ENTITLING_STATUSES, INTERNAL_PAYGATE, PlanRequired, ProductError, promoHelper } from '@owlmeans/payment';
|
|
2
|
+
import { memoHelper } from '@owlmeans/context';
|
|
3
|
+
import { STRIPE_PAYGATE_ALIAS } from './consts.js';
|
|
4
|
+
import { paymentAccessOf } from './access.js';
|
|
5
|
+
import { planHelper } from './plan.js';
|
|
6
|
+
import { log } from './log.js';
|
|
7
|
+
/** The plan skus already reported unknown — process-wide, so each is warned about once. */
|
|
8
|
+
const unknownPlans = new Set();
|
|
9
|
+
/** An internal grant with a period end stops entitling at that instant; a paygate row never does. */
|
|
10
|
+
const stillEntitles = (row, at) => row.paygate !== INTERNAL_PAYGATE || row.periodEnd == null || new Date(row.periodEnd).getTime() > at.getTime();
|
|
11
|
+
export const makeCatalogueHelper = (ctx) => {
|
|
12
|
+
const access = paymentAccessOf(ctx);
|
|
13
|
+
const findPlan = async (planSku) => {
|
|
14
|
+
try {
|
|
15
|
+
return await access.payment().plan(planSku);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const findProduct = async (productSku) => {
|
|
22
|
+
try {
|
|
23
|
+
return await access.payment().product(productSku);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const catalogPlans = async () => {
|
|
30
|
+
const products = await access.payment().products();
|
|
31
|
+
const plans = [];
|
|
32
|
+
for (const product of products) {
|
|
33
|
+
plans.push(...await access.payment().allPlans(product.sku));
|
|
34
|
+
}
|
|
35
|
+
return plans;
|
|
36
|
+
};
|
|
37
|
+
const freePlanOf = async () => (await catalogPlans())
|
|
38
|
+
.filter(plan => plan.free === true)
|
|
39
|
+
.sort((a, b) => planHelper.planRank(a) - planHelper.planRank(b) || a.sku.localeCompare(b.sku))[0] ?? null;
|
|
40
|
+
const resolveEffectivePlan = async (entityId, at = new Date()) => {
|
|
41
|
+
const fallback = await freePlanOf();
|
|
42
|
+
const { items } = await access.subscriptions().list({ entityId, status: [...ENTITLING_STATUSES] }, { size: 0 });
|
|
43
|
+
const candidates = [];
|
|
44
|
+
for (const row of items.filter(item => stillEntitles(item, at))) {
|
|
45
|
+
const plan = await findPlan(row.planSku);
|
|
46
|
+
if (plan == null) {
|
|
47
|
+
if (!unknownPlans.has(row.planSku)) {
|
|
48
|
+
unknownPlans.add(row.planSku);
|
|
49
|
+
log.warn('Subscription names an unknown plan; ignored', { subscriptionId: row.externalId, planSku: row.planSku });
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
candidates.push({ plan, row, rank: planHelper.planRank(plan) });
|
|
54
|
+
}
|
|
55
|
+
candidates.sort((a, b) => b.rank - a.rank
|
|
56
|
+
|| new Date(b.row.createdAt).getTime() - new Date(a.row.createdAt).getTime());
|
|
57
|
+
const best = candidates[0];
|
|
58
|
+
if (best != null) {
|
|
59
|
+
return { plan: planHelper.overriddenPlan(best.plan, best.row), subscription: best.row, fallback };
|
|
60
|
+
}
|
|
61
|
+
if (fallback != null) {
|
|
62
|
+
return { plan: fallback, subscription: null, fallback };
|
|
63
|
+
}
|
|
64
|
+
throw new PlanRequired(entityId);
|
|
65
|
+
};
|
|
66
|
+
const entitlementsOf = async (entityId, productSkus) => {
|
|
67
|
+
const { plan, subscription } = await resolveEffectivePlan(entityId);
|
|
68
|
+
if (productSkus != null && !productSkus.includes(plan.productSku)) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const at = new Date();
|
|
72
|
+
return (plan.capabilities ?? [])
|
|
73
|
+
.filter(set => promoHelper.promoActive(set.promo, subscription?.createdAt, at))
|
|
74
|
+
.map(({ promo: _promo, ...set }) => set);
|
|
75
|
+
};
|
|
76
|
+
const stripePlansOf = async () => {
|
|
77
|
+
const products = await access.payment().products();
|
|
78
|
+
const result = [];
|
|
79
|
+
for (const product of products) {
|
|
80
|
+
if (!(product.gateways ?? []).includes(STRIPE_PAYGATE_ALIAS)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const plans = (await access.payment().allPlans(product.sku))
|
|
84
|
+
.filter(plan => planHelper.isSoldThrough(product, plan, STRIPE_PAYGATE_ALIAS));
|
|
85
|
+
if (plans.length > 0) {
|
|
86
|
+
result.push({ product, plans });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
};
|
|
91
|
+
const consumablePlanOf = async (productSku, planSku) => {
|
|
92
|
+
const product = await access.payment().product(productSku);
|
|
93
|
+
const plans = (await access.payment().allPlans(product.sku))
|
|
94
|
+
.filter(plan => planHelper.isSoldThrough(product, plan, STRIPE_PAYGATE_ALIAS));
|
|
95
|
+
if (planSku != null && !plans.some(plan => plan.sku === planSku)) {
|
|
96
|
+
throw new ProductError(`plan:${planSku}`);
|
|
97
|
+
}
|
|
98
|
+
const plan = plans.find(item => item.sku === planSku) ?? plans[0];
|
|
99
|
+
if (plan == null)
|
|
100
|
+
throw new ProductError('plan');
|
|
101
|
+
return { product, plan };
|
|
102
|
+
};
|
|
103
|
+
return {
|
|
104
|
+
findPlan, findProduct, catalogPlans, freePlanOf, resolveEffectivePlan, entitlementsOf, stripePlansOf,
|
|
105
|
+
consumablePlanOf,
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
/** The catalogue of a context — one per context. */
|
|
109
|
+
export const catalogueOf = memoHelper.oncePer(makeCatalogueHelper);
|
|
110
|
+
//# sourceMappingURL=catalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.js","sourceRoot":"","sources":["../src/catalogue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CommitOptions, CommitResult, GrantInternalPlanOptions, PaymentSubscriptionRecord, PropagatedState, SubscriptionSnapshot } from '../types.js';
|
|
2
|
+
/** A context's subscription rows: what observers see of them, how a new state is committed, internal grants. */
|
|
3
|
+
export interface SubscriptionCommitHelper {
|
|
4
|
+
/** A subscription as observers see it; `state` overlays what was last propagated. */
|
|
5
|
+
snapshotOf: (record: PaymentSubscriptionRecord, state?: PropagatedState) => Promise<SubscriptionSnapshot>;
|
|
6
|
+
/**
|
|
7
|
+
* Store a subscription's new state, tell observers what changed, then record what was told.
|
|
8
|
+
*
|
|
9
|
+
* The state is written BEFORE observers run, so an observer reading entitlements sees the new plan.
|
|
10
|
+
* What classification compares against is the state last PROPAGATED (`propagated`), stamped only
|
|
11
|
+
* after every observer succeeded — so an observer that throws leaves the change to be classified
|
|
12
|
+
* again, identically, when the paygate retries. `lastEventId` is stamped with it.
|
|
13
|
+
*/
|
|
14
|
+
commitSubscription: (previous: PaymentSubscriptionRecord | null, next: PaymentSubscriptionRecord, opts?: CommitOptions) => Promise<CommitResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Grant a plan without a paygate — the free plan every entity holds, or a complimentary one
|
|
17
|
+
* (`force`). One row per grant (`free:<entityId>` / `internal:<planSku>:<entityId>`), upserted: its
|
|
18
|
+
* `createdAt` survives a re-grant, and observers hear `created` once.
|
|
19
|
+
*/
|
|
20
|
+
grantInternalPlan: (entityId: string, planSku: string, opts?: GrantInternalPlanOptions) => Promise<PaymentSubscriptionRecord>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/commit/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAAE,YAAY,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,eAAe,EACjG,oBAAoB,EACrB,MAAM,aAAa,CAAA;AAEpB,gHAAgH;AAChH,MAAM,WAAW,wBAAwB;IACvC,qFAAqF;IACrF,UAAU,EAAE,CAAC,MAAM,EAAE,yBAAyB,EAAE,KAAK,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACzG;;;;;;;OAOG;IACH,kBAAkB,EAAE,CAClB,QAAQ,EAAE,yBAAyB,GAAG,IAAI,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,CAAC,EAAE,aAAa,KAC9F,OAAO,CAAC,YAAY,CAAC,CAAA;IAC1B;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAA;CAC9H"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/commit/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context as ApiContext } from '@owlmeans/server-api';
|
|
2
|
+
import type { SubscriptionCommitHelper } from './commit/types.js';
|
|
3
|
+
export declare const makeSubscriptionCommitHelper: (ctx: ApiContext) => SubscriptionCommitHelper;
|
|
4
|
+
/** The subscription store of a context — one per context. */
|
|
5
|
+
export declare const subscriptionCommitOf: (target: ApiContext<import("@owlmeans/server-api").Config>) => SubscriptionCommitHelper;
|
|
6
|
+
//# sourceMappingURL=commit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../src/commit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAajE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAEjE,eAAO,MAAM,4BAA4B,QAAS,UAAU,KAAG,wBAoI9D,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB,yFAAmD,CAAA"}
|
package/build/commit.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { ENTITLING_STATUSES, INTERNAL_PAYGATE, ProductError, SubscriptionStatus, UnknownPlan } from '@owlmeans/payment';
|
|
2
|
+
import { memoHelper } from '@owlmeans/context';
|
|
3
|
+
import { log } from './log.js';
|
|
4
|
+
import { SUBSCRIPTION_LOG_EVENTS } from './consts.local.js';
|
|
5
|
+
import { paymentAccessOf } from './access.js';
|
|
6
|
+
import { paymentUtils } from './utils.js';
|
|
7
|
+
import { catalogueOf } from './catalogue.js';
|
|
8
|
+
import { planHelper } from './plan.js';
|
|
9
|
+
import { subscriptionHelper } from './subscription.js';
|
|
10
|
+
export const makeSubscriptionCommitHelper = (ctx) => {
|
|
11
|
+
const access = paymentAccessOf(ctx);
|
|
12
|
+
const snapshotOf = async (record, state) => {
|
|
13
|
+
const planSku = state?.planSku ?? record.planSku;
|
|
14
|
+
const declared = await catalogueOf(ctx).findPlan(planSku);
|
|
15
|
+
const plan = declared != null ? planHelper.overriddenPlan(declared, record) : null;
|
|
16
|
+
return paymentUtils.compact({
|
|
17
|
+
entityId: record.entityId,
|
|
18
|
+
planSku,
|
|
19
|
+
productSku: plan?.productSku ?? record.productSku,
|
|
20
|
+
rank: state?.rank ?? record.rank,
|
|
21
|
+
status: state?.status ?? record.status,
|
|
22
|
+
paygate: record.paygate,
|
|
23
|
+
subscriptionId: record.externalId,
|
|
24
|
+
service: record.service,
|
|
25
|
+
periodStart: record.periodStart ?? undefined,
|
|
26
|
+
periodEnd: record.periodEnd ?? undefined,
|
|
27
|
+
cancelAtPeriodEnd: state != null ? state.cancelAtPeriodEnd : record.cancelAtPeriodEnd ?? undefined,
|
|
28
|
+
trialEnd: record.trialEnd ?? undefined,
|
|
29
|
+
pausedAt: state != null ? state.pausedAt : record.pausedAt ?? undefined,
|
|
30
|
+
createdAt: record.createdAt ?? undefined,
|
|
31
|
+
capabilities: plan?.capabilities,
|
|
32
|
+
limits: plan?.limits,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const commitSubscription = async (previous, next, opts = {}) => {
|
|
36
|
+
const resource = access.subscriptions();
|
|
37
|
+
const updated = previous == null || subscriptionHelper.materiallyDiffers(previous, next);
|
|
38
|
+
const prior = previous?.propagated ?? null;
|
|
39
|
+
const change = subscriptionHelper.classifySubscriptionChange(prior, next, opts);
|
|
40
|
+
const at = new Date();
|
|
41
|
+
const finalize = (record) => {
|
|
42
|
+
const tracked = prior != null || change === 'created';
|
|
43
|
+
return {
|
|
44
|
+
...record,
|
|
45
|
+
...(opts.eventId != null ? { lastEventId: opts.eventId } : {}),
|
|
46
|
+
...(tracked ? {
|
|
47
|
+
propagated: subscriptionHelper.propagatedStateOf(record, change === 'renewed' ? opts.invoiceId : prior?.renewedInvoiceId),
|
|
48
|
+
} : {}),
|
|
49
|
+
...(change === 'created' && record.initialPropagatedAt == null ? { initialPropagatedAt: at } : {}),
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const write = async (record) => {
|
|
53
|
+
if (record.id != null) {
|
|
54
|
+
return await resource.update(record);
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return await resource.create(record);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (!paymentUtils.isDuplicateKey(error)) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
const winner = await resource.byExternalId(record.externalId, record.paygate);
|
|
64
|
+
return await resource.update({ ...record, id: winner?.id });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
if (change == null) {
|
|
68
|
+
const quiet = previous != null && !updated && (opts.eventId == null || previous.lastEventId === opts.eventId)
|
|
69
|
+
&& (prior == null || !subscriptionHelper.stateDiffers(prior, next));
|
|
70
|
+
return { record: quiet ? previous : await write(finalize(next)), change: null, updated };
|
|
71
|
+
}
|
|
72
|
+
const stored = await write(next);
|
|
73
|
+
await opts.beforePropagate?.(stored, change);
|
|
74
|
+
await access.observer().propagateSubscription({
|
|
75
|
+
change,
|
|
76
|
+
previous: prior != null && previous != null ? await snapshotOf(previous, prior) : null,
|
|
77
|
+
current: await snapshotOf(stored),
|
|
78
|
+
active: ENTITLING_STATUSES.includes(stored.status),
|
|
79
|
+
eventKey: subscriptionHelper.subscriptionEventKey(stored, change, opts),
|
|
80
|
+
...(opts.invoiceId != null ? { invoiceId: opts.invoiceId } : {}),
|
|
81
|
+
...(opts.eventId != null ? { externalEventId: opts.eventId } : {}),
|
|
82
|
+
}, ctx);
|
|
83
|
+
const record = await resource.update(finalize(stored));
|
|
84
|
+
log.info('Subscription changed', paymentUtils.compact({
|
|
85
|
+
entityId: stored.entityId, subscriptionId: stored.externalId, change, planSku: stored.planSku,
|
|
86
|
+
previousPlanSku: prior != null && prior.planSku !== stored.planSku ? prior.planSku : undefined,
|
|
87
|
+
status: stored.status, currency: stored.currency ?? undefined, invoiceId: opts.invoiceId, eventId: opts.eventId,
|
|
88
|
+
}), { event: SUBSCRIPTION_LOG_EVENTS[change] ?? 'subscription.updated' });
|
|
89
|
+
return { record, change, updated };
|
|
90
|
+
};
|
|
91
|
+
const grantInternalPlan = async (entityId, planSku, opts = {}) => {
|
|
92
|
+
const plan = await catalogueOf(ctx).findPlan(planSku);
|
|
93
|
+
if (plan == null) {
|
|
94
|
+
throw new UnknownPlan(planSku);
|
|
95
|
+
}
|
|
96
|
+
if (plan.free !== true && opts.force !== true) {
|
|
97
|
+
throw new ProductError(`internal-grant:${planSku}`);
|
|
98
|
+
}
|
|
99
|
+
const product = await catalogueOf(ctx).findProduct(plan.productSku);
|
|
100
|
+
const externalId = plan.free === true ? `free:${entityId}` : `internal:${planSku}:${entityId}`;
|
|
101
|
+
const previous = await access.subscriptions().byExternalId(externalId, INTERNAL_PAYGATE);
|
|
102
|
+
const now = new Date();
|
|
103
|
+
const { periodEnd: _periodEnd, endedAt: _endedAt, canceledAt: _canceledAt, ...kept } = previous ?? {};
|
|
104
|
+
const next = {
|
|
105
|
+
...kept,
|
|
106
|
+
entityId,
|
|
107
|
+
planSku,
|
|
108
|
+
productSku: plan.productSku,
|
|
109
|
+
service: previous?.service ?? product?.services?.[0] ?? ctx.cfg.service,
|
|
110
|
+
paygate: INTERNAL_PAYGATE,
|
|
111
|
+
externalId,
|
|
112
|
+
status: SubscriptionStatus.Active,
|
|
113
|
+
rank: planHelper.planRank(plan),
|
|
114
|
+
...(opts.periodEnd != null ? { periodEnd: opts.periodEnd } : {}),
|
|
115
|
+
createdAt: previous?.createdAt ?? now,
|
|
116
|
+
updatedAt: now,
|
|
117
|
+
};
|
|
118
|
+
const { record } = await commitSubscription(previous, next);
|
|
119
|
+
return record ?? next;
|
|
120
|
+
};
|
|
121
|
+
return { snapshotOf, commitSubscription, grantInternalPlan };
|
|
122
|
+
};
|
|
123
|
+
/** The subscription store of a context — one per context. */
|
|
124
|
+
export const subscriptionCommitOf = memoHelper.oncePer(makeSubscriptionCommitHelper);
|
|
125
|
+
//# sourceMappingURL=commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../src/commit.ts"],"names":[],"mappings":"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"}
|
package/build/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ConsumerRightsPolicy } from '@owlmeans/payment';
|
|
2
|
-
import type { Config, ConsumerRightsDef,
|
|
2
|
+
import type { Config, ConsumerRightsDef, PaymentPlanDef, PaymentProductDef, PortalBrandingDef, PricingDef, StripeSecretsDef } from './types.js';
|
|
3
3
|
export declare const declarePaymentProduct: (cfg: Config, def: PaymentProductDef) => void;
|
|
4
4
|
/**
|
|
5
5
|
* Declare a plan into the configuration catalogue.
|
|
@@ -10,22 +10,6 @@ export declare const declarePaymentProduct: (cfg: Config, def: PaymentProductDef
|
|
|
10
10
|
* integer, a promo ends at a real `Date`). Amount and quantity policies are asserted as before.
|
|
11
11
|
*/
|
|
12
12
|
export declare const declarePaymentPlan: (cfg: Config, def: PaymentPlanDef) => void;
|
|
13
|
-
/** Every plan declared into a configuration. */
|
|
14
|
-
export declare const declaredPlansOf: (cfg: Config) => PaymentPlan[];
|
|
15
|
-
/**
|
|
16
|
-
* Cross-plan rules a single declaration cannot see:
|
|
17
|
-
*
|
|
18
|
-
* - at most one free plan per rank;
|
|
19
|
-
* - no two paid plans of one product at the same rank (one-time `consumable` plans are never an
|
|
20
|
-
* entity's plan and are not ranked against each other).
|
|
21
|
-
*
|
|
22
|
-
* A limit key MAY change kind between plans (lifetime on one, a monthly window on another): counters
|
|
23
|
-
* are keyed by `(entity, key, window)` and the window is derived from the kind, so each kind keeps its
|
|
24
|
-
* own counter and a lifetime count still sticks to the entity across plan changes.
|
|
25
|
-
*
|
|
26
|
-
* @throws PlanRankConflict
|
|
27
|
-
*/
|
|
28
|
-
export declare const assertPlanDeclarations: (cfg: Config) => void;
|
|
29
13
|
/**
|
|
30
14
|
* Where the Stripe secrets live. A value that looks like a path is read into the configuration at
|
|
31
15
|
* boot. The webhook secret is an optional override of the one the managed endpoint stores.
|
package/build/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqX,KAAK,oBAAoB,EAAmG,MAAM,mBAAmB,CAAA;AAKjhB,OAAO,KAAK,EACV,MAAM,EAAE,iBAAiB,EAAe,cAAc,EAAkB,iBAAiB,EAAE,iBAAiB,EAC5G,UAAU,EAAE,gBAAgB,EAC7B,MAAM,YAAY,CAAA;AAGnB,eAAO,MAAM,qBAAqB,QAAS,MAAM,OAAO,iBAAiB,KAAG,IAS3E,CAAA;AA2BD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAAS,MAAM,OAAO,cAAc,KAAG,IA+CrE,CAAA;AA8CD;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,SAAS,gBAAgB,KAAG,IAIpE,CAAA;AAED,wFAAwF;AACxF,eAAO,MAAM,cAAc,QAAS,MAAM,OAAO,iBAAiB,KAAG,IAOpE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,QAAS,MAAM,OAAO,UAAU,KAAG,IAqCpE,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,QAAS,MAAM,OAAO,iBAAiB,KAAG,oBAsC3E,CAAA"}
|
package/build/config.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { assertAmountCheckoutPolicy, assertPricingPolicy, assertQuantityCheckoutPolicy, CAPABILITY_LIMIT_SCOPE, CheckoutPricingMode, CONSUMER_RIGHTS_RECORD_ID, CONSUMER_RIGHTS_RECORD_TYPE, ConsumerRightsError, LimitKind, LimitMisdeclared, makeConsumerRightsPolicy, PLAN_RECORD_PREFIX, PLAN_RECORD_TYPE, PaymentError, PlanDuration, PlanRankConflict, PlanStatus, PRICING_POLICY_RECORD_ID, PRICING_POLICY_RECORD_TYPE, PRODUCT_RECORD_PREFIX, PRODUCT_RECORD_TYPE, ProductError } from '@owlmeans/payment';
|
|
1
|
+
import { plugin, PLUGIN_RECORD, configHelper } from '@owlmeans/config';
|
|
2
|
+
import { CAPABILITY_LIMIT_SCOPE, CheckoutPricingMode, CONSUMER_RIGHTS_RECORD_ID, CONSUMER_RIGHTS_RECORD_TYPE, ConsumerRightsError, LimitKind, LimitMisdeclared, makeConsumerRightsPolicy, PLAN_RECORD_PREFIX, PLAN_RECORD_TYPE, PaymentError, PlanRankConflict, PlanStatus, PRICING_POLICY_RECORD_ID, PRICING_POLICY_RECORD_TYPE, PRODUCT_RECORD_PREFIX, PRODUCT_RECORD_TYPE, ProductError, checkoutPricingHelper, priceEstimateHelper } from '@owlmeans/payment';
|
|
4
3
|
import { CONSUMER_RIGHTS_MAIL_PLUGIN_CONFIG, STRIPE_PAYGATE_ALIAS, STRIPE_PLUGIN_CONFIG, STRIPE_PORTAL_PLUGIN_CONFIG, STRIPE_PRICING_PLUGIN_CONFIG, } from './consts.js';
|
|
5
4
|
import { CURRENCY, LIMIT_KINDS, LIMIT_WINDOWS } from './consts.local.js';
|
|
6
5
|
export const declarePaymentProduct = (cfg, def) => {
|
|
@@ -11,7 +10,7 @@ export const declarePaymentProduct = (cfg, def) => {
|
|
|
11
10
|
gateways: def.gateways ?? [STRIPE_PAYGATE_ALIAS], capabilities: def.capabilities,
|
|
12
11
|
taxCode: def.taxCode, unitLabel: def.unitLabel,
|
|
13
12
|
};
|
|
14
|
-
cfg.records.push({ ...toConfigRecord(product), recordType: PRODUCT_RECORD_TYPE, id: `${PRODUCT_RECORD_PREFIX}:${def.sku}` });
|
|
13
|
+
cfg.records.push({ ...configHelper.toConfigRecord(product), recordType: PRODUCT_RECORD_TYPE, id: `${PRODUCT_RECORD_PREFIX}:${def.sku}` });
|
|
15
14
|
};
|
|
16
15
|
const isSafeCount = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
17
16
|
const assertLimitDeclaration = (key, limit) => {
|
|
@@ -61,7 +60,7 @@ export const declarePaymentPlan = (cfg, def) => {
|
|
|
61
60
|
if (pricingMode === CheckoutPricingMode.Amount) {
|
|
62
61
|
if (def.amountPolicy == null)
|
|
63
62
|
throw new TypeError(`Amount checkout plan '${def.sku}' requires amountPolicy`);
|
|
64
|
-
assertAmountCheckoutPolicy(def.amountPolicy);
|
|
63
|
+
checkoutPricingHelper.assertAmountCheckoutPolicy(def.amountPolicy);
|
|
65
64
|
}
|
|
66
65
|
const quantityPolicy = def.quantityPolicy ?? (def.minQuantity != null || def.maxQuantity != null || def.defaultQuantity != null
|
|
67
66
|
? {
|
|
@@ -71,7 +70,7 @@ export const declarePaymentPlan = (cfg, def) => {
|
|
|
71
70
|
}
|
|
72
71
|
: undefined);
|
|
73
72
|
if (quantityPolicy != null)
|
|
74
|
-
assertQuantityCheckoutPolicy(quantityPolicy);
|
|
73
|
+
checkoutPricingHelper.assertQuantityCheckoutPolicy(quantityPolicy);
|
|
75
74
|
const currencyPrices = currencyPricesOf(def);
|
|
76
75
|
assertWithdrawalComponents(def);
|
|
77
76
|
cfg.records = cfg.records ?? [];
|
|
@@ -88,7 +87,7 @@ export const declarePaymentPlan = (cfg, def) => {
|
|
|
88
87
|
...(currencyPrices != null ? { currencyPrices } : {}),
|
|
89
88
|
...(def.withdrawal != null ? { withdrawal: { components: def.withdrawal.components.map(item => ({ ...item })) } } : {}),
|
|
90
89
|
};
|
|
91
|
-
cfg.records.push({ ...toConfigRecord(plan), recordType: PLAN_RECORD_TYPE, id: `${PLAN_RECORD_PREFIX}:${def.sku}` });
|
|
90
|
+
cfg.records.push({ ...configHelper.toConfigRecord(plan), recordType: PLAN_RECORD_TYPE, id: `${PLAN_RECORD_PREFIX}:${def.sku}` });
|
|
92
91
|
};
|
|
93
92
|
/** `currencyPrices` normalized to lowercase codes; each a positive amount of whole minor units. */
|
|
94
93
|
const currencyPricesOf = (def) => {
|
|
@@ -131,42 +130,6 @@ const assertWithdrawalComponents = (def) => {
|
|
|
131
130
|
throw new ProductError(`withdrawal:${def.sku}:shares`);
|
|
132
131
|
}
|
|
133
132
|
};
|
|
134
|
-
/** Every plan declared into a configuration. */
|
|
135
|
-
export const declaredPlansOf = (cfg) => (cfg.records ?? []).filter(record => record.recordType === PLAN_RECORD_TYPE);
|
|
136
|
-
/**
|
|
137
|
-
* Cross-plan rules a single declaration cannot see:
|
|
138
|
-
*
|
|
139
|
-
* - at most one free plan per rank;
|
|
140
|
-
* - no two paid plans of one product at the same rank (one-time `consumable` plans are never an
|
|
141
|
-
* entity's plan and are not ranked against each other).
|
|
142
|
-
*
|
|
143
|
-
* A limit key MAY change kind between plans (lifetime on one, a monthly window on another): counters
|
|
144
|
-
* are keyed by `(entity, key, window)` and the window is derived from the kind, so each kind keeps its
|
|
145
|
-
* own counter and a lifetime count still sticks to the entity across plan changes.
|
|
146
|
-
*
|
|
147
|
-
* @throws PlanRankConflict
|
|
148
|
-
*/
|
|
149
|
-
export const assertPlanDeclarations = (cfg) => {
|
|
150
|
-
const plans = declaredPlansOf(cfg);
|
|
151
|
-
const freeRanks = new Set();
|
|
152
|
-
const paidRanks = new Set();
|
|
153
|
-
for (const plan of plans) {
|
|
154
|
-
const rank = plan.rank ?? 0;
|
|
155
|
-
if (plan.free === true) {
|
|
156
|
-
if (freeRanks.has(rank)) {
|
|
157
|
-
throw new PlanRankConflict(`free:${rank}`);
|
|
158
|
-
}
|
|
159
|
-
freeRanks.add(rank);
|
|
160
|
-
}
|
|
161
|
-
else if (plan.duration !== PlanDuration.Consumable) {
|
|
162
|
-
const key = `${plan.productSku}:${rank}`;
|
|
163
|
-
if (paidRanks.has(key)) {
|
|
164
|
-
throw new PlanRankConflict(key);
|
|
165
|
-
}
|
|
166
|
-
paidRanks.add(key);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
133
|
/**
|
|
171
134
|
* Where the Stripe secrets live. A value that looks like a path is read into the configuration at
|
|
172
135
|
* boot. The webhook secret is an optional override of the one the managed endpoint stores.
|
|
@@ -200,10 +163,10 @@ export const portalBranding = (cfg, def) => {
|
|
|
200
163
|
*/
|
|
201
164
|
export const declarePaymentPricing = (cfg, def) => {
|
|
202
165
|
const { stripe, ...policy } = def;
|
|
203
|
-
assertPricingPolicy(policy);
|
|
166
|
+
priceEstimateHelper.assertPricingPolicy(policy);
|
|
204
167
|
cfg.records = (cfg.records ?? []).filter(record => record.id !== PRICING_POLICY_RECORD_ID);
|
|
205
168
|
cfg.records.push({
|
|
206
|
-
...toConfigRecord(policy), recordType: PRICING_POLICY_RECORD_TYPE, id: PRICING_POLICY_RECORD_ID,
|
|
169
|
+
...configHelper.toConfigRecord(policy), recordType: PRICING_POLICY_RECORD_TYPE, id: PRICING_POLICY_RECORD_ID,
|
|
207
170
|
});
|
|
208
171
|
if (stripe != null) {
|
|
209
172
|
const settlementCurrency = stripe.settlementCurrency?.toLowerCase();
|
|
@@ -261,7 +224,7 @@ export const declareConsumerRights = (cfg, def) => {
|
|
|
261
224
|
}
|
|
262
225
|
cfg.records = (cfg.records ?? []).filter(record => record.id !== CONSUMER_RIGHTS_RECORD_ID);
|
|
263
226
|
cfg.records.push({
|
|
264
|
-
...toConfigRecord(policy), recordType: CONSUMER_RIGHTS_RECORD_TYPE, id: CONSUMER_RIGHTS_RECORD_ID,
|
|
227
|
+
...configHelper.toConfigRecord(policy), recordType: CONSUMER_RIGHTS_RECORD_TYPE, id: CONSUMER_RIGHTS_RECORD_ID,
|
|
265
228
|
});
|
|
266
229
|
const plugins = cfg[PLUGIN_RECORD];
|
|
267
230
|
if (plugins != null) {
|