@volter/twin-stripe 2.0.38 → 3.0.0
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 +82 -207
- package/dist/generated/pack-facts.json +94 -0
- package/dist/spec/SOURCE.md +14 -0
- package/dist/spec/fixtures3.json.gz +0 -0
- package/dist/spec/openapi.json.gz +0 -0
- package/dist/spec/patches.json +34 -0
- package/dist/spec/sources.json +378 -0
- package/dist/src/cli.js +12 -30
- package/dist/src/engine/after-payment.d.ts +9 -0
- package/dist/src/engine/after-payment.js +28 -0
- package/dist/src/engine/apps-secrets.d.ts +1 -0
- package/dist/src/engine/apps-secrets.js +3 -0
- package/dist/src/engine/balance.d.ts +5 -0
- package/dist/src/engine/balance.js +15 -0
- package/dist/src/engine/billing.d.ts +5 -0
- package/dist/src/engine/billing.js +6 -0
- package/dist/src/engine/charges.d.ts +6 -0
- package/dist/src/engine/charges.js +13 -0
- package/dist/src/engine/checkout.d.ts +24 -0
- package/dist/src/engine/checkout.js +30 -0
- package/dist/src/engine/common.d.ts +19 -0
- package/dist/src/engine/common.js +32 -0
- package/dist/src/{screens → engine}/connect-settings.d.ts +1 -7
- package/dist/src/engine/connect-settings.js +26 -0
- package/dist/src/engine/connect.d.ts +66 -0
- package/dist/src/engine/connect.js +189 -0
- package/dist/src/engine/coupons.d.ts +0 -0
- package/dist/src/engine/coupons.js +5 -0
- package/dist/src/engine/credit-notes.d.ts +1 -0
- package/dist/src/engine/credit-notes.js +5 -0
- package/dist/src/engine/customers.d.ts +12 -0
- package/dist/src/engine/customers.js +30 -0
- package/dist/src/engine/display.d.ts +14 -0
- package/dist/src/engine/display.js +16 -0
- package/dist/src/engine/disputes.d.ts +0 -0
- package/dist/src/engine/disputes.js +9 -0
- package/dist/src/engine/entitlements.d.ts +1 -0
- package/dist/src/engine/entitlements.js +4 -0
- package/dist/src/engine/ephemeral-keys.d.ts +0 -0
- package/dist/src/engine/ephemeral-keys.js +4 -0
- package/dist/src/engine/files.d.ts +18 -0
- package/dist/src/engine/files.js +33 -0
- package/dist/src/engine/front.d.ts +5 -0
- package/dist/src/engine/front.js +25 -0
- package/dist/src/engine/invoices.d.ts +24 -0
- package/dist/src/engine/invoices.js +57 -0
- package/dist/src/engine/issuing.d.ts +35 -0
- package/dist/src/engine/issuing.js +45 -0
- package/dist/src/engine/ledger.d.ts +9 -0
- package/dist/src/engine/ledger.js +9 -0
- package/dist/src/engine/oauth.d.ts +4 -0
- package/dist/src/engine/oauth.js +25 -0
- package/dist/src/engine/onboarding.d.ts +13 -0
- package/dist/src/engine/onboarding.js +42 -0
- package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
- package/dist/src/{stripe-params.js → engine/params.js} +7 -60
- package/dist/src/engine/payment-intents.d.ts +10 -0
- package/dist/src/engine/payment-intents.js +27 -0
- package/dist/src/engine/payment-links.d.ts +1 -0
- package/dist/src/engine/payment-links.js +5 -0
- package/dist/src/engine/payment-methods.d.ts +16 -0
- package/dist/src/engine/payment-methods.js +22 -0
- package/dist/src/engine/plans.d.ts +6 -0
- package/dist/src/engine/plans.js +26 -0
- package/dist/src/engine/platform.d.ts +39 -0
- package/dist/src/engine/platform.js +34 -0
- package/dist/src/engine/products.d.ts +0 -0
- package/dist/src/engine/products.js +4 -0
- package/dist/src/engine/radar.d.ts +2 -0
- package/dist/src/engine/radar.js +5 -0
- package/dist/src/engine/refunds.d.ts +1 -0
- package/dist/src/engine/refunds.js +28 -0
- package/dist/src/engine/renewals.d.ts +36 -0
- package/dist/src/engine/renewals.js +65 -0
- package/dist/src/engine/setup-intents.d.ts +1 -0
- package/dist/src/engine/setup-intents.js +4 -0
- package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +11 -39
- package/dist/src/{stripe-twin.js → engine/stripe.js} +25 -310
- package/dist/src/engine/subscription-schedules.d.ts +3 -0
- package/dist/src/engine/subscription-schedules.js +1 -0
- package/dist/src/engine/subscriptions.d.ts +12 -0
- package/dist/src/engine/subscriptions.js +31 -0
- package/dist/src/engine/tax.d.ts +7 -0
- package/dist/src/engine/tax.js +28 -0
- package/dist/src/engine/terminal.d.ts +4 -0
- package/dist/src/engine/terminal.js +20 -0
- package/dist/src/engine/test-clocks.d.ts +5 -0
- package/dist/src/engine/test-clocks.js +9 -0
- package/dist/src/engine/tokens.d.ts +7 -0
- package/dist/src/engine/tokens.js +20 -0
- package/dist/src/engine/transfers.d.ts +2 -0
- package/dist/src/engine/transfers.js +1 -0
- package/dist/src/engine/treasury.d.ts +23 -0
- package/dist/src/engine/treasury.js +45 -0
- package/dist/src/{stripe-version.js → engine/version.js} +4 -3
- package/dist/src/engine/webhook-endpoints.d.ts +1 -0
- package/dist/src/engine/webhook-endpoints.js +12 -0
- package/dist/src/engine/webhooks.d.ts +31 -0
- package/dist/src/engine/webhooks.js +68 -0
- package/dist/src/fetch.d.ts +2 -0
- package/dist/src/fetch.js +26 -0
- package/dist/src/generated/surface.gen.json +1 -1
- package/dist/src/generated/ui.gen.json +1 -1
- package/dist/src/index.d.ts +5 -14
- package/dist/src/index.js +8 -75
- package/dist/src/manifest.js +232 -758
- package/dist/src/screens/billing-portal.d.ts +3 -0
- package/dist/src/screens/{portal.js → billing-portal.js} +28 -54
- package/dist/src/screens/checkout.d.ts +2 -31
- package/dist/src/screens/checkout.js +32 -121
- package/dist/src/screens/connect-oauth.d.ts +3 -27
- package/dist/src/screens/connect-oauth.js +51 -132
- package/dist/src/screens/connect-onboarding.d.ts +3 -0
- package/dist/src/screens/{onboarding.js → connect-onboarding.js} +36 -102
- package/dist/src/screens/dashboard.d.ts +3 -0
- package/dist/src/screens/dashboard.js +117 -0
- package/dist/src/screens/shared.d.ts +27 -0
- package/dist/src/screens/shared.js +87 -0
- package/dist/src/screens/stripe-js.d.ts +3 -0
- package/dist/src/screens/stripe-js.js +135 -0
- package/dist/src/semantics/account_links.d.ts +2 -0
- package/dist/src/semantics/account_links.js +22 -0
- package/dist/src/semantics/accounts.d.ts +4 -0
- package/dist/src/semantics/accounts.js +38 -0
- package/dist/src/semantics/apps.d.ts +4 -0
- package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
- package/dist/src/semantics/around.d.ts +2 -0
- package/dist/src/semantics/around.js +16 -0
- package/dist/src/semantics/balance.d.ts +2 -11
- package/dist/src/semantics/balance.js +3 -194
- package/dist/src/semantics/balance_transactions.d.ts +2 -0
- package/dist/src/semantics/balance_transactions.js +15 -0
- package/dist/src/semantics/billing_portal.d.ts +5 -0
- package/dist/src/semantics/billing_portal.js +42 -0
- package/dist/src/semantics/charges.d.ts +3 -28
- package/dist/src/semantics/charges.js +5 -202
- package/dist/src/semantics/checkout.d.ts +3 -20
- package/dist/src/semantics/checkout.js +8 -261
- package/dist/src/semantics/clock.d.ts +2 -0
- package/dist/src/semantics/clock.js +21 -0
- package/dist/src/semantics/coupons.d.ts +2 -6
- package/dist/src/semantics/coupons.js +2 -60
- package/dist/src/semantics/customers.d.ts +6 -6
- package/dist/src/semantics/customers.js +27 -387
- package/dist/src/semantics/disputes.d.ts +2 -2
- package/dist/src/semantics/disputes.js +3 -49
- package/dist/src/semantics/doors.d.ts +23 -0
- package/dist/src/semantics/doors.js +73 -0
- package/dist/src/semantics/entitlements.d.ts +2 -2
- package/dist/src/semantics/entitlements.js +5 -50
- package/dist/src/semantics/events.d.ts +12 -0
- package/dist/src/semantics/events.js +36 -0
- package/dist/src/semantics/index.d.ts +2 -0
- package/dist/src/semantics/index.js +107 -0
- package/dist/src/semantics/invoice_payments.d.ts +2 -0
- package/dist/src/semantics/invoice_payments.js +12 -0
- package/dist/src/semantics/invoiceitems.d.ts +3 -0
- package/dist/src/semantics/invoiceitems.js +59 -0
- package/dist/src/semantics/invoices.d.ts +16 -18
- package/dist/src/semantics/invoices.js +118 -444
- package/dist/src/semantics/payment_intents.d.ts +4 -0
- package/dist/src/semantics/payment_intents.js +79 -0
- package/dist/src/semantics/payment_methods.d.ts +5 -0
- package/dist/src/semantics/payment_methods.js +39 -0
- package/dist/src/semantics/payouts.d.ts +2 -0
- package/dist/src/semantics/payouts.js +21 -0
- package/dist/src/semantics/prices.d.ts +4 -0
- package/dist/src/semantics/prices.js +37 -0
- package/dist/src/semantics/products.d.ts +6 -2
- package/dist/src/semantics/products.js +15 -130
- package/dist/src/semantics/promotion_codes.d.ts +3 -0
- package/dist/src/semantics/promotion_codes.js +35 -0
- package/dist/src/semantics/radar.d.ts +2 -2
- package/dist/src/semantics/radar.js +5 -74
- package/dist/src/semantics/refunds.d.ts +3 -9
- package/dist/src/semantics/refunds.js +6 -192
- package/dist/src/semantics/setup_intents.d.ts +3 -0
- package/dist/src/semantics/{setup-intents.js → setup_intents.js} +10 -53
- package/dist/src/semantics/shared.d.ts +822 -47
- package/dist/src/semantics/shared.js +3044 -78
- package/dist/src/semantics/states.d.ts +531 -0
- package/dist/src/semantics/states.js +852 -0
- package/dist/src/semantics/subscription_items.d.ts +5 -0
- package/dist/src/semantics/subscription_items.js +55 -0
- package/dist/src/semantics/subscription_schedules.d.ts +4 -0
- package/dist/src/semantics/subscription_schedules.js +60 -0
- package/dist/src/semantics/subscriptions.d.ts +7 -11
- package/dist/src/semantics/subscriptions.js +44 -415
- package/dist/src/semantics/test_helpers.d.ts +6 -0
- package/dist/src/semantics/{test-clocks.js → test_helpers.js} +14 -40
- package/dist/src/semantics/transfers.d.ts +2 -2
- package/dist/src/semantics/transfers.js +6 -101
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.js +7 -0
- package/generated/pack-facts.json +94 -0
- package/package.json +10 -20
- package/spec/SOURCE.md +14 -0
- package/spec/fixtures3.json.gz +0 -0
- package/spec/openapi.json.gz +0 -0
- package/spec/patches.json +34 -0
- package/spec/sources.json +378 -0
- package/src/cli.ts +12 -26
- package/src/engine/after-payment.ts +31 -0
- package/src/engine/apps-secrets.ts +4 -0
- package/src/engine/balance.ts +33 -0
- package/src/engine/billing.ts +16 -0
- package/src/engine/charges.ts +19 -0
- package/src/engine/checkout.ts +40 -0
- package/src/engine/common.ts +47 -0
- package/src/engine/connect-settings.ts +23 -0
- package/src/engine/connect.ts +184 -0
- package/src/engine/coupons.ts +5 -0
- package/src/engine/credit-notes.ts +6 -0
- package/src/engine/customers.ts +35 -0
- package/src/engine/display.ts +19 -0
- package/src/engine/disputes.ts +9 -0
- package/src/engine/entitlements.ts +5 -0
- package/src/engine/ephemeral-keys.ts +3 -0
- package/src/engine/files.ts +41 -0
- package/src/engine/front.ts +31 -0
- package/src/engine/invoices.ts +71 -0
- package/src/engine/issuing.ts +61 -0
- package/src/engine/ledger.ts +50 -0
- package/src/engine/oauth.ts +19 -0
- package/src/engine/onboarding.ts +54 -0
- package/src/{stripe-params.ts → engine/params.ts} +8 -56
- package/src/engine/payment-intents.ts +33 -0
- package/src/engine/payment-links.ts +6 -0
- package/src/engine/payment-methods.ts +25 -0
- package/src/engine/plans.ts +42 -0
- package/src/engine/platform.ts +47 -0
- package/src/engine/products.ts +3 -0
- package/src/engine/radar.ts +6 -0
- package/src/engine/refunds.ts +29 -0
- package/src/engine/renewals.ts +73 -0
- package/src/engine/setup-intents.ts +5 -0
- package/src/{stripe-twin.ts → engine/stripe.ts} +28 -323
- package/src/engine/subscription-schedules.ts +10 -0
- package/src/engine/subscriptions.ts +40 -0
- package/src/engine/tax.ts +39 -0
- package/src/engine/terminal.ts +23 -0
- package/src/engine/test-clocks.ts +11 -0
- package/src/engine/tokens.ts +22 -0
- package/src/engine/transfers.ts +23 -0
- package/src/engine/treasury.ts +47 -0
- package/src/{stripe-version.ts → engine/version.ts} +4 -3
- package/src/engine/webhook-endpoints.ts +14 -0
- package/src/engine/webhooks.ts +72 -0
- package/src/fetch.ts +27 -0
- package/src/generated/surface.gen.json +1 -1
- package/src/generated/ui.gen.json +1 -1
- package/src/index.ts +8 -116
- package/src/manifest.ts +234 -786
- package/src/screens/{portal.tsx → billing-portal.tsx} +32 -37
- package/src/screens/checkout.tsx +33 -95
- package/src/screens/connect-oauth.tsx +64 -88
- package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +38 -82
- package/src/screens/dashboard.tsx +198 -0
- package/src/screens/shared.tsx +84 -0
- package/src/screens/stripe-js.ts +170 -0
- package/src/semantics/account_links.ts +21 -0
- package/src/semantics/accounts.ts +43 -0
- package/src/semantics/{apps-secrets.ts → apps.ts} +17 -32
- package/src/semantics/around.ts +20 -0
- package/src/semantics/balance.ts +6 -207
- package/src/semantics/balance_transactions.ts +20 -0
- package/src/semantics/billing_portal.ts +51 -0
- package/src/semantics/charges.ts +12 -211
- package/src/semantics/checkout.ts +13 -268
- package/src/semantics/clock.ts +26 -0
- package/src/semantics/coupons.ts +5 -67
- package/src/semantics/customers.ts +29 -392
- package/src/semantics/disputes.ts +9 -59
- package/src/semantics/doors.ts +80 -0
- package/src/semantics/entitlements.ts +9 -56
- package/src/semantics/events.ts +44 -0
- package/src/semantics/index.ts +111 -0
- package/src/semantics/invoice_payments.ts +18 -0
- package/src/semantics/invoiceitems.ts +59 -0
- package/src/semantics/invoices.ts +109 -443
- package/src/semantics/payment_intents.ts +83 -0
- package/src/semantics/payment_methods.ts +43 -0
- package/src/semantics/payouts.ts +23 -0
- package/src/semantics/prices.ts +42 -0
- package/src/semantics/products.ts +18 -142
- package/src/semantics/promotion_codes.ts +39 -0
- package/src/semantics/radar.ts +8 -77
- package/src/semantics/refunds.ts +9 -212
- package/src/semantics/setup_intents.ts +45 -0
- package/src/semantics/shared.ts +3092 -106
- package/src/semantics/states.ts +883 -0
- package/src/semantics/subscription_items.ts +54 -0
- package/src/semantics/subscription_schedules.ts +66 -0
- package/src/semantics/subscriptions.ts +49 -432
- package/src/semantics/{test-clocks.ts → test_helpers.ts} +23 -47
- package/src/semantics/transfers.ts +11 -131
- package/src/server.ts +8 -0
- package/client/dashboard-api.ts +0 -286
- package/client/stripe-mirror.css +0 -277
- package/client/stripe-mirror.tsx +0 -1559
- package/dist/client/dashboard-api.d.ts +0 -107
- package/dist/client/dashboard-api.js +0 -238
- package/dist/client/dashboard-api.ts +0 -286
- package/dist/client/stripe-mirror.bundle.js +0 -236
- package/dist/client/stripe-mirror.css +0 -277
- package/dist/client/stripe-mirror.d.ts +0 -134
- package/dist/client/stripe-mirror.js +0 -859
- package/dist/client/stripe-mirror.tsx +0 -1559
- package/dist/src/screens/connect-settings.js +0 -103
- package/dist/src/screens/consent-skin.d.ts +0 -4
- package/dist/src/screens/consent-skin.js +0 -18
- package/dist/src/screens/financial-connections.d.ts +0 -5
- package/dist/src/screens/financial-connections.js +0 -90
- package/dist/src/screens/identity.d.ts +0 -5
- package/dist/src/screens/identity.js +0 -86
- package/dist/src/screens/onboarding.d.ts +0 -13
- package/dist/src/screens/portal.d.ts +0 -5
- package/dist/src/screens/public-details.d.ts +0 -5
- package/dist/src/screens/public-details.js +0 -90
- package/dist/src/semantics/after-payment.d.ts +0 -22
- package/dist/src/semantics/after-payment.js +0 -99
- package/dist/src/semantics/apps-secrets.d.ts +0 -2
- package/dist/src/semantics/billing.d.ts +0 -2
- package/dist/src/semantics/billing.js +0 -220
- package/dist/src/semantics/connect.d.ts +0 -5
- package/dist/src/semantics/connect.js +0 -493
- package/dist/src/semantics/credit-notes.d.ts +0 -2
- package/dist/src/semantics/credit-notes.js +0 -172
- package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
- package/dist/src/semantics/ephemeral-keys.js +0 -34
- package/dist/src/semantics/files.d.ts +0 -2
- package/dist/src/semantics/files.js +0 -125
- package/dist/src/semantics/issuing.d.ts +0 -13
- package/dist/src/semantics/issuing.js +0 -575
- package/dist/src/semantics/ledger.d.ts +0 -59
- package/dist/src/semantics/ledger.js +0 -200
- package/dist/src/semantics/payment-intents.d.ts +0 -18
- package/dist/src/semantics/payment-intents.js +0 -452
- package/dist/src/semantics/payment-links.d.ts +0 -2
- package/dist/src/semantics/payment-links.js +0 -133
- package/dist/src/semantics/payment-methods.d.ts +0 -20
- package/dist/src/semantics/payment-methods.js +0 -140
- package/dist/src/semantics/plans.d.ts +0 -5
- package/dist/src/semantics/plans.js +0 -121
- package/dist/src/semantics/platform.d.ts +0 -9
- package/dist/src/semantics/platform.js +0 -206
- package/dist/src/semantics/renewals.d.ts +0 -47
- package/dist/src/semantics/renewals.js +0 -281
- package/dist/src/semantics/setup-intents.d.ts +0 -2
- package/dist/src/semantics/subscription-schedules.d.ts +0 -2
- package/dist/src/semantics/subscription-schedules.js +0 -119
- package/dist/src/semantics/tax.d.ts +0 -2
- package/dist/src/semantics/tax.js +0 -197
- package/dist/src/semantics/terminal.d.ts +0 -5
- package/dist/src/semantics/terminal.js +0 -182
- package/dist/src/semantics/test-clocks.d.ts +0 -6
- package/dist/src/semantics/tokens.d.ts +0 -4
- package/dist/src/semantics/tokens.js +0 -44
- package/dist/src/semantics/treasury.d.ts +0 -2
- package/dist/src/semantics/treasury.js +0 -377
- package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
- package/dist/src/semantics/webhook-endpoints.js +0 -85
- package/dist/src/stripe-budget.d.ts +0 -55
- package/dist/src/stripe-budget.js +0 -155
- package/dist/src/stripe-capabilities.d.ts +0 -3
- package/dist/src/stripe-capabilities.js +0 -5836
- package/dist/src/stripe-conformance.d.ts +0 -43
- package/dist/src/stripe-conformance.js +0 -105
- package/dist/src/stripe-connector.d.ts +0 -161
- package/dist/src/stripe-connector.js +0 -414
- package/dist/src/stripe-emit.d.ts +0 -2
- package/dist/src/stripe-emit.js +0 -145
- package/dist/src/stripe-events.d.ts +0 -93
- package/dist/src/stripe-events.js +0 -392
- package/dist/src/stripe-js.d.ts +0 -4
- package/dist/src/stripe-js.js +0 -70
- package/dist/src/stripe-mirror-ui.d.ts +0 -15
- package/dist/src/stripe-mirror-ui.js +0 -87
- package/dist/src/stripe-perform-harness.d.ts +0 -9
- package/dist/src/stripe-perform-harness.js +0 -26
- package/dist/src/stripe-server.d.ts +0 -33
- package/dist/src/stripe-server.js +0 -429
- package/dist/src/stripe-shared.d.ts +0 -109
- package/dist/src/stripe-shared.js +0 -276
- package/dist/src/stripe-ui-conformance.d.ts +0 -5
- package/dist/src/stripe-ui-conformance.js +0 -79
- package/dist/src/stripe-ui-structure.d.ts +0 -3
- package/dist/src/stripe-ui-structure.js +0 -168
- package/dist/test-fixtures/stripe-known-deviations.json +0 -110
- package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
- package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
- package/dist/test-fixtures/stripe-schemas.json +0 -3813
- package/src/screens/connect-settings.tsx +0 -121
- package/src/screens/consent-skin.ts +0 -20
- package/src/screens/financial-connections.tsx +0 -101
- package/src/screens/identity.tsx +0 -96
- package/src/screens/public-details.tsx +0 -105
- package/src/semantics/after-payment.ts +0 -118
- package/src/semantics/billing.ts +0 -216
- package/src/semantics/connect.ts +0 -487
- package/src/semantics/credit-notes.ts +0 -168
- package/src/semantics/ephemeral-keys.ts +0 -34
- package/src/semantics/files.ts +0 -143
- package/src/semantics/issuing.ts +0 -590
- package/src/semantics/ledger.ts +0 -253
- package/src/semantics/payment-intents.ts +0 -463
- package/src/semantics/payment-links.ts +0 -148
- package/src/semantics/payment-methods.ts +0 -145
- package/src/semantics/plans.ts +0 -131
- package/src/semantics/platform.ts +0 -220
- package/src/semantics/renewals.ts +0 -279
- package/src/semantics/setup-intents.ts +0 -87
- package/src/semantics/subscription-schedules.ts +0 -129
- package/src/semantics/tax.ts +0 -220
- package/src/semantics/terminal.ts +0 -195
- package/src/semantics/tokens.ts +0 -52
- package/src/semantics/treasury.ts +0 -383
- package/src/semantics/webhook-endpoints.ts +0 -87
- package/src/stripe-budget.ts +0 -181
- package/src/stripe-capabilities.ts +0 -5651
- package/src/stripe-conformance.ts +0 -124
- package/src/stripe-connector.ts +0 -462
- package/src/stripe-emit.ts +0 -157
- package/src/stripe-events.ts +0 -434
- package/src/stripe-js.ts +0 -70
- package/src/stripe-mirror-ui.ts +0 -90
- package/src/stripe-perform-harness.ts +0 -29
- package/src/stripe-server.ts +0 -393
- package/src/stripe-shared.ts +0 -297
- package/src/stripe-ui-conformance.ts +0 -88
- package/src/stripe-ui-structure.ts +0 -182
- package/test-fixtures/stripe-known-deviations.json +0 -110
- package/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/test-fixtures/stripe-schemas.json +0 -3813
- /package/dist/src/{screens → engine}/industries.d.ts +0 -0
- /package/dist/src/{screens → engine}/industries.js +0 -0
- /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
- /package/dist/src/{semantics → engine}/test-cards.js +0 -0
- /package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -0
- /package/src/{screens → engine}/industries.ts +0 -0
- /package/src/{semantics → engine}/test-cards.ts +0 -0
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { declineFor, paymentMethodSubObject, TEST_TOKEN_DECLINES } from "../stripe-twin.js";
|
|
2
|
-
import { AFTER_SUCCESS_CARDS, afterSuccessOf } from "./after-payment.js";
|
|
3
|
-
import { at, created, fail } from "./shared.js";
|
|
4
|
-
const PM = 'payment_method';
|
|
5
|
-
const noBilling = { address: null, email: null, name: null, phone: null };
|
|
6
|
-
const pmMissing = (ctx, id) => fail(ctx, `No such payment_method: '${id}'`, 404, 'resource_missing');
|
|
7
|
-
// the raw card number, cvc and bank account number are never echoed: the modeled sub-object is
|
|
8
|
-
// what the PaymentMethod carries, with the decline outcome its card implies, so a later charge
|
|
9
|
-
// naming it only by id declines the same way
|
|
10
|
-
const create = async (ctx) => {
|
|
11
|
-
const params = ctx.params;
|
|
12
|
-
const pmType = typeof params.type === 'string' ? params.type : 'card';
|
|
13
|
-
const { card: _card, sepa_debit: _sepa, us_bank_account: _ach, type: _t, ...rest } = params;
|
|
14
|
-
const sub = paymentMethodSubObject(pmType, params);
|
|
15
|
-
const declineOutcome = pmType === 'card' ? (declineFor(() => undefined, params) ?? null) : null;
|
|
16
|
-
// and what Stripe does after its card succeeds (a dispute, a review), which a later charge naming it by id brings
|
|
17
|
-
const afterSuccess = pmType === 'card' ? afterSuccessOf(ctx, params.card) : undefined;
|
|
18
|
-
// the billing details the create gives are the method's (docs.stripe.com/api/payment_methods/create#create_payment_method-billing_details)
|
|
19
|
-
const given = rest.billing_details && typeof rest.billing_details === 'object' ? rest.billing_details : {};
|
|
20
|
-
return ctx.reply(await created(ctx, PM, { ...rest, type: pmType, customer: null, livemode: false, billing_details: { ...noBilling, ...given }, ...sub, _declineOutcome: declineOutcome, ...(afterSuccess ? { _afterSuccess: afterSuccess } : {}) }, {}));
|
|
21
|
-
};
|
|
22
|
-
const TEST_PM_CARDS = {
|
|
23
|
-
...AFTER_SUCCESS_CARDS,
|
|
24
|
-
pm_card_mastercard: { brand: 'mastercard', number: '5555555555554444' },
|
|
25
|
-
pm_card_amex: { brand: 'amex', number: '378282246310005' },
|
|
26
|
-
pm_card_discover: { brand: 'discover', number: '6011111111111117' },
|
|
27
|
-
};
|
|
28
|
-
/** The card a charge was paid with, as its payment_method_details reports it
|
|
29
|
-
* (docs.stripe.com/api/charges/object#charge_object-payment_method_details): a stored PaymentMethod's card, a
|
|
30
|
-
* documented test name (pm_card_* or tok_*, the same cards), or a raw card; undefined for anything else. */
|
|
31
|
-
export function paymentMethodDetails(ctx, ref) {
|
|
32
|
-
let card;
|
|
33
|
-
// a payment method of another kind (a US bank account) is described by its own block, as the charge reports it
|
|
34
|
-
const stored = typeof ref === 'string' && ref ? ctx.get(PM, ref) : undefined;
|
|
35
|
-
// Stripe's US bank account test methods (pm_us_bank_account, pm_usBankAccount_*) are its test bank's account
|
|
36
|
-
const pm = stored ?? (typeof ref === 'string' && /^pm_us_?bank_?account/i.test(ref) ? { type: 'us_bank_account', ...paymentMethodSubObject('us_bank_account', {}) } : undefined);
|
|
37
|
-
if (pm && typeof pm.type === 'string' && pm.type !== 'card') {
|
|
38
|
-
const own = pm[pm.type] ?? {};
|
|
39
|
-
const pick = ['account_holder_type', 'account_type', 'bank_name', 'fingerprint', 'last4', 'routing_number'];
|
|
40
|
-
return { type: pm.type, [pm.type]: Object.fromEntries(pick.filter((k) => own[k] !== undefined).map((k) => [k, own[k]])) };
|
|
41
|
-
}
|
|
42
|
-
if (typeof ref === 'string' && ref) {
|
|
43
|
-
const stored = ctx.get(PM, ref)?.card;
|
|
44
|
-
if (stored)
|
|
45
|
-
card = stored;
|
|
46
|
-
else
|
|
47
|
-
card = testCardOf(ref);
|
|
48
|
-
}
|
|
49
|
-
else if (ref && typeof ref === 'object')
|
|
50
|
-
card = paymentMethodSubObject('card', { card: ref }).card;
|
|
51
|
-
if (!card)
|
|
52
|
-
return undefined;
|
|
53
|
-
return {
|
|
54
|
-
type: 'card',
|
|
55
|
-
card: {
|
|
56
|
-
brand: card.brand, last4: card.last4, exp_month: card.exp_month, exp_year: card.exp_year, funding: card.funding ?? 'credit',
|
|
57
|
-
country: card.country ?? 'US', network: card.brand, fingerprint: card.fingerprint ?? null,
|
|
58
|
-
checks: card.checks ?? { address_line1_check: null, address_postal_code_check: null, cvc_check: 'pass' },
|
|
59
|
-
three_d_secure: null, wallet: null, installments: null, mandate: null,
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
// attaching needs an existing customer; a well-known test token (pm_card_visa, …) is a template:
|
|
64
|
-
// attaching it mints a new PaymentMethod on the customer carrying that card's outcome
|
|
65
|
-
/** Whether a payment method can be attached: a stored one, or a documented test name that attaching mints. */
|
|
66
|
-
export const attachable = (ctx, id) => !!ctx.get(PM, id) || (id.startsWith('pm_card_') && (id in TEST_TOKEN_DECLINES || id in AFTER_SUCCESS_CARDS));
|
|
67
|
-
/** Attach a payment method to a customer (both known to exist or be attachable): a stored one moves to the
|
|
68
|
-
* customer; a test name mints a new PaymentMethod on the customer carrying that card's outcome. */
|
|
69
|
-
/** The card a test name (pm_card_*, tok_*) stands for, never stored as a PaymentMethod (docs.stripe.com/testing#cards). */
|
|
70
|
-
function testCardOf(ref) {
|
|
71
|
-
const name = ref.replace(/^tok_/, 'pm_card_');
|
|
72
|
-
if (!name.startsWith('pm_card_'))
|
|
73
|
-
return undefined;
|
|
74
|
-
const test = TEST_PM_CARDS[name] ?? { brand: 'visa', number: '4242424242424242' };
|
|
75
|
-
return { ...paymentMethodSubObject('card', { card: { number: test.number } }).card, brand: test.brand };
|
|
76
|
-
}
|
|
77
|
-
export async function attachPaymentMethod(ctx, id, customer) {
|
|
78
|
-
if (!ctx.get(PM, id))
|
|
79
|
-
return materializeTestMethod(ctx, id, customer);
|
|
80
|
-
return ctx.write(PM, id, { customer }, 'payment_method.attach');
|
|
81
|
-
}
|
|
82
|
-
/** A documented test name (pm_card_visa, pm_card_visa_chargeDeclined, …) made a real PaymentMethod, as Stripe
|
|
83
|
-
* does when one is used: the brand and number it stands for (docs.stripe.com/testing#cards) and its outcome. */
|
|
84
|
-
export async function materializeTestMethod(ctx, id, customer) {
|
|
85
|
-
const card = TEST_PM_CARDS[id] ?? { brand: 'visa', number: '4242424242424242' };
|
|
86
|
-
const sub = paymentMethodSubObject('card', { card: { number: card.number } });
|
|
87
|
-
sub.card.brand = card.brand;
|
|
88
|
-
const afterSuccess = AFTER_SUCCESS_CARDS[id]?.outcome;
|
|
89
|
-
return created(ctx, PM, { type: 'card', customer, livemode: false, billing_details: noBilling, ...sub, _declineOutcome: TEST_TOKEN_DECLINES[id] ?? null, ...(afterSuccess ? { _afterSuccess: afterSuccess } : {}) }, {});
|
|
90
|
-
}
|
|
91
|
-
const attach = async (ctx) => {
|
|
92
|
-
const id = at(ctx, 'payment_method');
|
|
93
|
-
const customer = typeof ctx.params.customer === 'string' ? ctx.params.customer : '';
|
|
94
|
-
if (!customer)
|
|
95
|
-
return fail(ctx, 'Missing required param: customer.', 400, 'parameter_missing');
|
|
96
|
-
if (!ctx.get('customer', customer))
|
|
97
|
-
return fail(ctx, `No such customer: '${customer}'`, 400, 'resource_missing');
|
|
98
|
-
if (!attachable(ctx, id))
|
|
99
|
-
return pmMissing(ctx, id);
|
|
100
|
-
return ctx.reply(await attachPaymentMethod(ctx, id, customer));
|
|
101
|
-
};
|
|
102
|
-
const retrieve = async (ctx) => {
|
|
103
|
-
const m = ctx.get(PM, at(ctx, 'payment_method'));
|
|
104
|
-
return m ? ctx.reply(m) : pmMissing(ctx, at(ctx, 'payment_method'));
|
|
105
|
-
};
|
|
106
|
-
const detach = async (ctx) => {
|
|
107
|
-
const id = at(ctx, 'payment_method');
|
|
108
|
-
if (!ctx.get(PM, id))
|
|
109
|
-
return pmMissing(ctx, id);
|
|
110
|
-
return ctx.reply(await ctx.write(PM, id, { customer: null }, 'payment_method.detach'));
|
|
111
|
-
};
|
|
112
|
-
export const paymentMethods = {
|
|
113
|
-
PostPaymentMethods: create,
|
|
114
|
-
PostPaymentMethodsPaymentMethodAttach: attach,
|
|
115
|
-
GetPaymentMethodsPaymentMethod: retrieve,
|
|
116
|
-
PostPaymentMethodsPaymentMethodDetach: detach,
|
|
117
|
-
};
|
|
118
|
-
/** A PaymentMethod made from a confirm's `payment_method_data` ("If provided, this hash will be used to create a
|
|
119
|
-
* PaymentMethod", docs.stripe.com/api/setup_intents/confirm, docs.stripe.com/api/payment_intents/confirm), or none. */
|
|
120
|
-
export async function methodFromData(ctx, data) {
|
|
121
|
-
if (!data || typeof data !== 'object')
|
|
122
|
-
return undefined;
|
|
123
|
-
const d = data;
|
|
124
|
-
const type = typeof d.type === 'string' ? d.type : 'card';
|
|
125
|
-
const made = await created(ctx, PM, {}, {
|
|
126
|
-
type, customer: null, livemode: false, metadata: {},
|
|
127
|
-
billing_details: { ...noBilling, ...(d.billing_details ?? {}) },
|
|
128
|
-
...paymentMethodSubObject(type, d),
|
|
129
|
-
// what follows its card's success (a dispute, funds straight to available), as a PaymentMethod created directly carries
|
|
130
|
-
...(type === 'card' && afterSuccessOf(ctx, d.card) ? { _afterSuccess: afterSuccessOf(ctx, d.card) } : {}),
|
|
131
|
-
});
|
|
132
|
-
return String(made.id);
|
|
133
|
-
}
|
|
134
|
-
/** Whether an intent sets up or pays with a bank account by micro-deposits because it asks for them:
|
|
135
|
-
* payment_method_options[us_bank_account][verification_method]=microdeposits with a us_bank_account method
|
|
136
|
-
* ("Microdeposit only verification", docs.stripe.com/payments/ach-direct-debit/set-up-payment). */
|
|
137
|
-
export function microdepositsAsked(ctx, params, intent, pm) {
|
|
138
|
-
const options = (params.payment_method_options ?? intent.payment_method_options)?.us_bank_account;
|
|
139
|
-
return options?.verification_method === 'microdeposits' && !!pm && ctx.get(PM, pm)?.type === 'us_bank_account';
|
|
140
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Semantics } from '@volter/world-core';
|
|
2
|
-
import { type Row } from './shared.js';
|
|
3
|
-
/** A recurring price in the plan object's shape (the create page's example response). */
|
|
4
|
-
export declare function planOf(price: Row): Row;
|
|
5
|
-
export declare const plans: Record<string, Semantics>;
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { asBool } from "../stripe-twin.js";
|
|
2
|
-
import { at, created, fail, kept, list, newest } from "./shared.js";
|
|
3
|
-
const INTERVALS = new Set(['day', 'week', 'month', 'year']);
|
|
4
|
-
/** A recurring price in the plan object's shape (the create page's example response). */
|
|
5
|
-
export function planOf(price) {
|
|
6
|
-
const r = (price.recurring ?? {});
|
|
7
|
-
const amount = typeof price.unit_amount === 'number' ? price.unit_amount : null;
|
|
8
|
-
const decimal = typeof price.unit_amount_decimal === 'string' ? price.unit_amount_decimal : amount === null ? null : String(amount);
|
|
9
|
-
return {
|
|
10
|
-
id: price.id, object: 'plan', active: price.active ?? true, amount, amount_decimal: decimal,
|
|
11
|
-
billing_scheme: price.billing_scheme ?? 'per_unit', created: price.created, currency: price.currency, interval: r.interval ?? null,
|
|
12
|
-
interval_count: r.interval_count ?? 1, livemode: false, metadata: price.metadata ?? {}, meter: r.meter ?? null, nickname: price.nickname ?? null,
|
|
13
|
-
product: price.product, tiers_mode: price.tiers_mode ?? null, transform_usage: price.transform_quantity ?? null,
|
|
14
|
-
trial_period_days: r.trial_period_days ?? null, usage_type: r.usage_type ?? 'licensed',
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/** Metadata after an update: an empty value unsets the key, an empty `metadata` unsets them all. */
|
|
18
|
-
function metadataAfter(was, given) {
|
|
19
|
-
if (given === '' || given === null || typeof given !== 'object')
|
|
20
|
-
return {};
|
|
21
|
-
const next = { ...was };
|
|
22
|
-
for (const [k, v] of Object.entries(given))
|
|
23
|
-
if (v === '' || v === null)
|
|
24
|
-
delete next[k];
|
|
25
|
-
else
|
|
26
|
-
next[k] = v;
|
|
27
|
-
return next;
|
|
28
|
-
}
|
|
29
|
-
const planMissing = (ctx, id) => fail(ctx, `No such plan: '${id}'`, 404, 'resource_missing');
|
|
30
|
-
/** A recurring price the Plans API still answers: one whose plan was deleted is not a plan any more. */
|
|
31
|
-
const recurring = (ctx, p) => !!p && !!p.recurring && kept(ctx, 'price', p, '_plan_deleted') !== true;
|
|
32
|
-
const createPlan = async (ctx) => {
|
|
33
|
-
const p = ctx.params;
|
|
34
|
-
for (const name of ['currency', 'interval', 'product'])
|
|
35
|
-
if (p[name] === undefined || p[name] === '')
|
|
36
|
-
return fail(ctx, `Missing required param: ${name}.`, 400, 'parameter_missing');
|
|
37
|
-
if (!INTERVALS.has(String(p.interval)))
|
|
38
|
-
return fail(ctx, `Invalid interval: must be one of day, week, month, or year`, 400, 'parameter_invalid_string');
|
|
39
|
-
if (p.billing_scheme === 'tiered')
|
|
40
|
-
return fail(ctx, 'Tiered plans are not modelled by this twin; create a tiered price instead.', 400, 'parameter_invalid_string');
|
|
41
|
-
if (p.amount === undefined && p.amount_decimal === undefined)
|
|
42
|
-
return fail(ctx, 'Missing required param: amount.', 400, 'parameter_missing');
|
|
43
|
-
if (p.amount !== undefined && p.amount_decimal !== undefined)
|
|
44
|
-
return fail(ctx, 'Only one of `amount` and `amount_decimal` can be set.', 400, 'parameter_invalid');
|
|
45
|
-
const id = typeof p.id === 'string' && p.id ? p.id : ctx.mint('price').replace(/^price_/, 'plan_');
|
|
46
|
-
if (ctx.get('price', id))
|
|
47
|
-
return fail(ctx, `Plan already exists: '${id}'`, 400, 'resource_already_exists');
|
|
48
|
-
// "The product whose pricing the created plan will represent. This can either be the ID of an existing product, or a
|
|
49
|
-
// dictionary containing fields used to create a service product"
|
|
50
|
-
let product;
|
|
51
|
-
if (p.product && typeof p.product === 'object') {
|
|
52
|
-
product = String((await created(ctx, 'product', p.product, { active: true, livemode: false, images: [], marketing_features: [], metadata: {}, updated: ctx.now() })).id);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
product = String(p.product);
|
|
56
|
-
if (!ctx.get('product', product))
|
|
57
|
-
return fail(ctx, `No such product: '${product}'`, 400, 'resource_missing');
|
|
58
|
-
}
|
|
59
|
-
// the decimal is kept as given; the whole amount is its integer when it is one
|
|
60
|
-
const decimal = p.amount_decimal !== undefined ? String(p.amount_decimal) : String(Math.trunc(Number(p.amount)));
|
|
61
|
-
const unit = Number.isInteger(Number(decimal)) ? Number(decimal) : null;
|
|
62
|
-
const price = await created(ctx, 'price', {
|
|
63
|
-
id, product, currency: String(p.currency).toLowerCase(), unit_amount: unit, unit_amount_decimal: decimal,
|
|
64
|
-
recurring: { interval: p.interval, interval_count: Math.trunc(Number(p.interval_count ?? 1)), usage_type: p.usage_type ?? 'licensed', trial_period_days: p.trial_period_days !== undefined ? Math.trunc(Number(p.trial_period_days)) : null, meter: p.meter ?? null },
|
|
65
|
-
...(p.nickname !== undefined ? { nickname: p.nickname } : {}), ...(p.metadata !== undefined ? { metadata: p.metadata } : {}),
|
|
66
|
-
...(p.active !== undefined ? { active: asBool(p.active) } : {}),
|
|
67
|
-
}, { active: true, livemode: false, billing_scheme: 'per_unit', type: 'recurring', metadata: {}, lookup_key: null, nickname: null, tax_behavior: 'unspecified' }, { operation: 'plan.create' });
|
|
68
|
-
return ctx.reply(planOf(price));
|
|
69
|
-
};
|
|
70
|
-
const retrievePlan = async (ctx) => {
|
|
71
|
-
const price = ctx.get('price', at(ctx, 'plan'));
|
|
72
|
-
return recurring(ctx, price) ? ctx.reply(planOf(price)) : planMissing(ctx, at(ctx, 'plan'));
|
|
73
|
-
};
|
|
74
|
-
// "Updates the specified plan by setting the values of the parameters passed. Any parameters not provided are left
|
|
75
|
-
// unchanged. By design, you cannot change a plan's ID, amount, currency, or billing cycle." (docs.stripe.com/api/plans/update):
|
|
76
|
-
// active, metadata ("Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an
|
|
77
|
-
// empty value to `metadata`"), nickname, product, trial_period_days
|
|
78
|
-
const updatePlan = async (ctx) => {
|
|
79
|
-
const id = at(ctx, 'plan');
|
|
80
|
-
const price = ctx.get('price', id);
|
|
81
|
-
if (!recurring(ctx, price))
|
|
82
|
-
return planMissing(ctx, id);
|
|
83
|
-
const p = ctx.params;
|
|
84
|
-
if (typeof p.product === 'string' && !ctx.get('product', p.product))
|
|
85
|
-
return fail(ctx, `No such product: '${p.product}'`, 400, 'resource_missing');
|
|
86
|
-
const fields = {
|
|
87
|
-
...(p.active !== undefined ? { active: asBool(p.active) } : {}),
|
|
88
|
-
...(p.nickname !== undefined ? { nickname: p.nickname } : {}),
|
|
89
|
-
...(p.metadata !== undefined ? { metadata: metadataAfter((price.metadata ?? {}), p.metadata) } : {}),
|
|
90
|
-
...(typeof p.product === 'string' ? { product: p.product } : {}),
|
|
91
|
-
...(p.trial_period_days !== undefined ? { recurring: { ...price.recurring, trial_period_days: Math.trunc(Number(p.trial_period_days)) } } : {}),
|
|
92
|
-
};
|
|
93
|
-
const next = await ctx.write('price', id, fields, 'plan.update');
|
|
94
|
-
return ctx.reply(planOf(next));
|
|
95
|
-
};
|
|
96
|
-
const deletePlan = async (ctx) => {
|
|
97
|
-
const id = at(ctx, 'plan');
|
|
98
|
-
if (!recurring(ctx, ctx.get('price', id)))
|
|
99
|
-
return planMissing(ctx, id);
|
|
100
|
-
// existing subscribers keep it: the price stays, inactive, and only the plan is gone
|
|
101
|
-
const price = ctx.get('price', id);
|
|
102
|
-
if (price.active !== false)
|
|
103
|
-
ctx.legal('price', 'active', 'DeletePlansPlan', 'true', 'false', id);
|
|
104
|
-
await ctx.write('price', id, { active: false, _plan_deleted: true }, 'plan.delete');
|
|
105
|
-
return ctx.reply({ id, object: 'plan', deleted: true });
|
|
106
|
-
};
|
|
107
|
-
const listPlans = async (ctx) => {
|
|
108
|
-
const p = ctx.params;
|
|
109
|
-
const plans = newest(ctx, 'price').filter((x) => recurring(ctx, x))
|
|
110
|
-
.filter((x) => p.active === undefined || asBool(x.active) === asBool(p.active))
|
|
111
|
-
.filter((x) => p.product === undefined || x.product === p.product)
|
|
112
|
-
.map(planOf);
|
|
113
|
-
return list(ctx, 'price', plans);
|
|
114
|
-
};
|
|
115
|
-
export const plans = {
|
|
116
|
-
PostPlans: createPlan,
|
|
117
|
-
GetPlans: listPlans,
|
|
118
|
-
GetPlansPlan: retrievePlan,
|
|
119
|
-
PostPlansPlan: updatePlan,
|
|
120
|
-
DeletePlansPlan: deletePlan,
|
|
121
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Semantics, SemanticsContext } from '@volter/world-core';
|
|
2
|
-
/** Each pending report run completes, caught up before anything is answered: "When the run completes, Stripe updates
|
|
3
|
-
* the object, and it has a status of succeeded. It also has a nested result object, containing a URL that you can use
|
|
4
|
-
* to access the file", the guide's example a File of purpose report_run and type csv (docs.stripe.com/reports/api).
|
|
5
|
-
* "Most runs complete within a few minutes" (the same page). Where the documentation stops and the twin decides: a run
|
|
6
|
-
* completes one minute after it was created (the guide's example: created 1580832900, succeeded_at 1580832960), and
|
|
7
|
-
* its CSV holds the report type's header row alone (its size that row's bytes). */
|
|
8
|
-
export declare function finishReportRuns(ctx: SemanticsContext): Promise<void>;
|
|
9
|
-
export declare const platform: Record<string, Semantics>;
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { at, created, fail, list, newest, path, where } from "./shared.js";
|
|
2
|
-
// ── Climate: Stripe's catalog is managed and account-independent. The twin serves the catalog Stripe's reference
|
|
3
|
-
// publishes (docs.stripe.com/api/climate/product/object, /api/climate/supplier/object): Frontier's 2027 offtake
|
|
4
|
-
// portfolio at $550 a ton plus Frontier's service fees of $16.50 (3%), 18,000 tons, from Charm Industrial.
|
|
5
|
-
// Where the documentation stops and the twin decides: the catalog is that one product and supplier. ──
|
|
6
|
-
const CLIMATE_SUPPLIERS = [
|
|
7
|
-
{ id: 'climsup_charm_industrial', name: 'Charm Industrial', removal_pathway: 'biomass_carbon_removal_and_storage', info_url: 'https://frontierclimate.com/portfolio/charm-industrial', locations: [{ city: 'San Francisco', country: 'US', latitude: 37.7749, longitude: -122.4194, region: 'CA' }] },
|
|
8
|
-
];
|
|
9
|
-
const CLIMATE_PRODUCTS = [
|
|
10
|
-
{ id: 'climsku_frontier_offtake_portfolio_2027', name: "Frontier's 2027 offtake portfolio", subtotal: 55000, fees: 1650, currency: 'usd', delivery_year: 2027, metric_tons_available: '18000', created: 1881439203, suppliers: ['climsup_charm_industrial'] },
|
|
11
|
-
];
|
|
12
|
-
const supplierView = (s) => ({ id: s.id, object: 'climate.supplier', name: s.name, removal_pathway: s.removal_pathway, info_url: s.info_url, locations: s.locations, livemode: false });
|
|
13
|
-
const productView = (p) => ({
|
|
14
|
-
id: p.id, object: 'climate.product', name: p.name, livemode: false, delivery_year: p.delivery_year,
|
|
15
|
-
metric_tons_available: p.metric_tons_available, created: p.created,
|
|
16
|
-
current_prices_per_metric_ton: { [p.currency]: { amount_fees: p.fees, amount_subtotal: p.subtotal, amount_total: p.subtotal + p.fees } },
|
|
17
|
-
suppliers: p.suppliers.map((id) => supplierView(CLIMATE_SUPPLIERS.find((s) => s.id === id))),
|
|
18
|
-
});
|
|
19
|
-
const catalog = (ctx, data) => ctx.reply({ object: 'list', url: path(ctx), has_more: false, data });
|
|
20
|
-
const climateProduct = async (ctx) => {
|
|
21
|
-
const p = CLIMATE_PRODUCTS.find((x) => x.id === at(ctx, 'product'));
|
|
22
|
-
return p ? ctx.reply(productView(p)) : fail(ctx, `No such product: '${at(ctx, 'product')}'`, 404, 'resource_missing');
|
|
23
|
-
};
|
|
24
|
-
const climateSupplier = async (ctx) => {
|
|
25
|
-
const s = CLIMATE_SUPPLIERS.find((x) => x.id === at(ctx, 'supplier'));
|
|
26
|
-
return s ? ctx.reply(supplierView(s)) : fail(ctx, `No such supplier: '${at(ctx, 'supplier')}'`, 404, 'resource_missing');
|
|
27
|
-
};
|
|
28
|
-
const ORDER = 'climate.order';
|
|
29
|
-
const orderMissing = (ctx, id) => fail(ctx, `No such order: '${id}'`, 404, 'resource_missing');
|
|
30
|
-
// exactly one of amount or metric_tons; Frontier's fees are the product's per-ton share (3%: the create page's
|
|
31
|
-
// example charges 17 on a 550 subtotal, "Total amount of Frontier's service fees", the order object), rounded to the
|
|
32
|
-
// cent; the order is confirmed when made and delivers in the product's delivery year
|
|
33
|
-
const createOrder = async (ctx) => {
|
|
34
|
-
const product = typeof ctx.params.product === 'string' ? ctx.params.product : '';
|
|
35
|
-
if (!product)
|
|
36
|
-
return fail(ctx, 'Missing required param: product.', 400, 'parameter_missing');
|
|
37
|
-
const prod = CLIMATE_PRODUCTS.find((x) => x.id === product);
|
|
38
|
-
if (!prod)
|
|
39
|
-
return fail(ctx, `No such product: '${product}'`, 400, 'resource_missing');
|
|
40
|
-
const hasTons = ctx.params.metric_tons !== undefined;
|
|
41
|
-
if (hasTons === (ctx.params.amount !== undefined))
|
|
42
|
-
return fail(ctx, 'You must provide exactly one of `amount` or `metric_tons`.', 400, 'parameter_missing');
|
|
43
|
-
const metricTons = hasTons ? Number(ctx.params.metric_tons) : Number(ctx.params.amount) / prod.subtotal;
|
|
44
|
-
const amountSubtotal = Math.round(metricTons * prod.subtotal);
|
|
45
|
-
const amountFees = Math.round((amountSubtotal * prod.fees) / prod.subtotal);
|
|
46
|
-
return ctx.reply(await created(ctx, ORDER, {}, {
|
|
47
|
-
object: 'climate.order', livemode: false, status: 'confirmed', product, certificate: null,
|
|
48
|
-
amount_subtotal: amountSubtotal, amount_fees: amountFees, amount_total: amountSubtotal + amountFees,
|
|
49
|
-
currency: prod.currency, metric_tons: String(metricTons),
|
|
50
|
-
beneficiary: ctx.params.beneficiary && typeof ctx.params.beneficiary === 'object' ? ctx.params.beneficiary : { public_name: 'Stripe Climate' },
|
|
51
|
-
confirmed_at: ctx.now(), canceled_at: null, delivered_at: null, delayed_at: null,
|
|
52
|
-
product_substituted_at: null, cancellation_reason: null,
|
|
53
|
-
expected_delivery_year: prod.delivery_year,
|
|
54
|
-
delivery_details: [], metadata: ctx.params.metadata && typeof ctx.params.metadata === 'object' ? ctx.params.metadata : {},
|
|
55
|
-
}));
|
|
56
|
-
};
|
|
57
|
-
const cancelOrder = async (ctx) => {
|
|
58
|
-
const id = at(ctx, 'order');
|
|
59
|
-
const o = ctx.get(ORDER, id);
|
|
60
|
-
if (!o)
|
|
61
|
-
return orderMissing(ctx, id);
|
|
62
|
-
const refused = ctx.legal(ORDER, 'status', 'PostClimateOrdersOrderCancel', o.status, undefined, id);
|
|
63
|
-
if (refused)
|
|
64
|
-
return ctx.refuse(refused);
|
|
65
|
-
return ctx.reply(await ctx.write(ORDER, id, { status: 'canceled', canceled_at: ctx.now(), cancellation_reason: 'requested' }, 'climate_order.canceled'));
|
|
66
|
-
};
|
|
67
|
-
// only the beneficiary and metadata change
|
|
68
|
-
const updateOrder = async (ctx) => {
|
|
69
|
-
const id = at(ctx, 'order');
|
|
70
|
-
if (!ctx.get(ORDER, id))
|
|
71
|
-
return orderMissing(ctx, id);
|
|
72
|
-
const patch = {};
|
|
73
|
-
if (ctx.params.beneficiary !== undefined)
|
|
74
|
-
patch.beneficiary = ctx.params.beneficiary;
|
|
75
|
-
if (ctx.params.metadata !== undefined)
|
|
76
|
-
patch.metadata = ctx.params.metadata;
|
|
77
|
-
return ctx.reply(await ctx.write(ORDER, id, patch, 'climate_order.updated'));
|
|
78
|
-
};
|
|
79
|
-
// ── Financial Connections: a session is created for an account holder and its permissions; accounts
|
|
80
|
-
// are linked in the authentication flow Stripe.js opens (../screens/financial-connections.tsx) ──
|
|
81
|
-
const FCS = 'financial_connections.session';
|
|
82
|
-
const FCA = 'financial_connections.account';
|
|
83
|
-
const FCT = 'financial_connections.transaction';
|
|
84
|
-
const createSession = async (ctx) => {
|
|
85
|
-
const holder = ctx.params.account_holder && typeof ctx.params.account_holder === 'object' ? ctx.params.account_holder : null;
|
|
86
|
-
if (!holder)
|
|
87
|
-
return fail(ctx, 'Missing required param: account_holder.', 400, 'parameter_missing');
|
|
88
|
-
const perms = Array.isArray(ctx.params.permissions) ? ctx.params.permissions.map(String) : typeof ctx.params.permissions === 'string' ? [ctx.params.permissions] : [];
|
|
89
|
-
if (perms.length === 0)
|
|
90
|
-
return fail(ctx, 'Missing required param: permissions.', 400, 'parameter_missing');
|
|
91
|
-
const id = ctx.mint(FCS);
|
|
92
|
-
return ctx.reply(await created(ctx, FCS, { id }, {
|
|
93
|
-
object: 'financial_connections.session', livemode: false, client_secret: `fcsess_${id}_secret_twin`,
|
|
94
|
-
account_holder: holder, permissions: perms, prefetch: Array.isArray(ctx.params.prefetch) ? ctx.params.prefetch : null,
|
|
95
|
-
filters: ctx.params.filters && typeof ctx.params.filters === 'object' ? ctx.params.filters : null,
|
|
96
|
-
return_url: typeof ctx.params.return_url === 'string' ? ctx.params.return_url : null,
|
|
97
|
-
accounts: { object: 'list', has_more: false, url: `/v1/financial_connections/accounts?session=${id}`, data: [] },
|
|
98
|
-
}));
|
|
99
|
-
};
|
|
100
|
-
// a session's accounts are the ones linked to it now
|
|
101
|
-
const session = async (ctx) => {
|
|
102
|
-
const id = at(ctx, 'session');
|
|
103
|
-
const s = ctx.get(FCS, id);
|
|
104
|
-
if (!s)
|
|
105
|
-
return fail(ctx, `No such financial connections session: '${id}'`, 404, 'resource_missing');
|
|
106
|
-
return ctx.reply({ ...s, accounts: { object: 'list', has_more: false, url: `/v1/financial_connections/accounts?session=${id}`, data: newest(ctx, FCA).filter((a) => a.session === id) } });
|
|
107
|
-
};
|
|
108
|
-
const accounts = async (ctx) => list(ctx, FCA, where(ctx, newest(ctx, FCA), { session: (a, v) => a.session === v, account_holder: (a, v) => a.account_holder?.customer === v }));
|
|
109
|
-
const disconnect = async (ctx) => {
|
|
110
|
-
const id = at(ctx, 'account');
|
|
111
|
-
const a = ctx.get(FCA, id);
|
|
112
|
-
if (!a)
|
|
113
|
-
return fail(ctx, `No such account: '${id}'`, 404, 'resource_missing');
|
|
114
|
-
const refused = ctx.legal(FCA, 'status', 'PostFinancialConnectionsAccountsAccountDisconnect', a.status, undefined, id);
|
|
115
|
-
if (refused)
|
|
116
|
-
return ctx.refuse(refused);
|
|
117
|
-
return ctx.reply(await ctx.write(FCA, id, { status: 'disconnected' }, 'fc_account.disconnected'));
|
|
118
|
-
};
|
|
119
|
-
const transactions = async (ctx) => {
|
|
120
|
-
if (typeof ctx.params.account !== 'string' || !ctx.params.account)
|
|
121
|
-
return fail(ctx, 'Missing required param: account.', 400, 'parameter_missing');
|
|
122
|
-
return list(ctx, FCT, newest(ctx, FCT).filter((t) => t.account === ctx.params.account));
|
|
123
|
-
};
|
|
124
|
-
// ── forwarding: the twin answers a deterministic destination response; it makes no network call ──
|
|
125
|
-
const forward = async (ctx) => {
|
|
126
|
-
const pm = typeof ctx.params.payment_method === 'string' ? ctx.params.payment_method : '';
|
|
127
|
-
if (!pm)
|
|
128
|
-
return fail(ctx, 'Missing required param: payment_method.', 400, 'parameter_missing');
|
|
129
|
-
const url = typeof ctx.params.url === 'string' ? ctx.params.url : '';
|
|
130
|
-
if (!url)
|
|
131
|
-
return fail(ctx, 'Missing required param: url.', 400, 'parameter_missing');
|
|
132
|
-
return ctx.reply(await created(ctx, 'forwarding.request', {}, {
|
|
133
|
-
object: 'forwarding.request', livemode: false, payment_method: pm, url, replacements: Array.isArray(ctx.params.replacements) ? ctx.params.replacements.map(String) : [],
|
|
134
|
-
request_context: { destination_duration: 42, destination_ip_address: '127.0.0.1' },
|
|
135
|
-
request_details: { http_method: 'POST', url, headers: [], body: '[redacted]' },
|
|
136
|
-
response_details: { status: 200, headers: [], body: '{"approved":true}' },
|
|
137
|
-
}));
|
|
138
|
-
};
|
|
139
|
-
// ── Reporting: a representative subset of Stripe's report types; a run succeeds at once ──
|
|
140
|
-
const REPORT_TYPES = [
|
|
141
|
-
{ id: 'balance.summary.1', name: 'Balance summary' },
|
|
142
|
-
{ id: 'balance_change_from_activity.summary.1', name: 'Balance change from activity (summary)' },
|
|
143
|
-
{ id: 'payouts.summary.1', name: 'Payouts (summary)' },
|
|
144
|
-
{ id: 'payout_reconciliation.by_id.itemized.4', name: 'Payout reconciliation (itemized)' },
|
|
145
|
-
];
|
|
146
|
-
const reportTypeView = (t) => ({
|
|
147
|
-
id: t.id, object: 'reporting.report_type', name: t.name, version: 1,
|
|
148
|
-
data_available_start: 0, data_available_end: 0, default_columns: null, updated: 0, livemode: false,
|
|
149
|
-
});
|
|
150
|
-
const reportType = async (ctx) => {
|
|
151
|
-
const t = REPORT_TYPES.find((x) => x.id === at(ctx, 'report_type'));
|
|
152
|
-
return t ? ctx.reply(reportTypeView(t)) : fail(ctx, `No such report type: '${at(ctx, 'report_type')}'`, 404, 'resource_missing');
|
|
153
|
-
};
|
|
154
|
-
// report_type names the report; parameters (the interval, the columns) shape it (docs.stripe.com/api/reporting/report_run/create)
|
|
155
|
-
const runReport = async (ctx) => {
|
|
156
|
-
const p = ctx.params.parameters && typeof ctx.params.parameters === 'object' ? ctx.params.parameters : {};
|
|
157
|
-
const type = typeof ctx.params.report_type === 'string' ? ctx.params.report_type : '';
|
|
158
|
-
if (!type)
|
|
159
|
-
return fail(ctx, 'Missing required param: report_type.', 400, 'parameter_missing');
|
|
160
|
-
if (!REPORT_TYPES.some((t) => t.id === type))
|
|
161
|
-
return fail(ctx, `Invalid report type: '${type}'.`, 400, 'parameter_invalid_string_enum');
|
|
162
|
-
// a run starts pending with no result (finishReportRuns completes it)
|
|
163
|
-
return ctx.reply(await created(ctx, 'reporting.report_run', { parameters: p }, { status: 'pending', report_type: type, livemode: false, error: null, succeeded_at: null, result: null }));
|
|
164
|
-
};
|
|
165
|
-
/** Each pending report run completes, caught up before anything is answered: "When the run completes, Stripe updates
|
|
166
|
-
* the object, and it has a status of succeeded. It also has a nested result object, containing a URL that you can use
|
|
167
|
-
* to access the file", the guide's example a File of purpose report_run and type csv (docs.stripe.com/reports/api).
|
|
168
|
-
* "Most runs complete within a few minutes" (the same page). Where the documentation stops and the twin decides: a run
|
|
169
|
-
* completes one minute after it was created (the guide's example: created 1580832900, succeeded_at 1580832960), and
|
|
170
|
-
* its CSV holds the report type's header row alone (its size that row's bytes). */
|
|
171
|
-
export async function finishReportRuns(ctx) {
|
|
172
|
-
for (const run of ctx.rowsRaw('reporting.report_run')) {
|
|
173
|
-
if (run.status !== 'pending')
|
|
174
|
-
continue;
|
|
175
|
-
const done = Number(run.created) + 60;
|
|
176
|
-
if (Number(ctx.now()) < done)
|
|
177
|
-
continue;
|
|
178
|
-
const id = String(run.id);
|
|
179
|
-
const header = 'category,currency,description,net_amount\n';
|
|
180
|
-
const file = await created(ctx, 'file', { purpose: 'report_run' }, {
|
|
181
|
-
filename: `${String(run.report_type)}_${id}.csv`, size: header.length, type: 'csv', title: null, expires_at: null, url: null,
|
|
182
|
-
links: { object: 'list', data: [], has_more: false, url: '' },
|
|
183
|
-
});
|
|
184
|
-
await ctx.write('file', String(file.id), { url: `https://files.twin.local/v1/files/${String(file.id)}/contents` }, 'file.updated');
|
|
185
|
-
ctx.legal('reporting.report_run', 'status', ctx.call.operation.id, 'pending', 'succeeded', id, 'vendor');
|
|
186
|
-
await ctx.write('reporting.report_run', id, { status: 'succeeded', succeeded_at: done, result: ctx.get('file', String(file.id)) }, 'reporting.report_run.succeeded');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
export const platform = {
|
|
190
|
-
GetClimateProducts: async (ctx) => catalog(ctx, CLIMATE_PRODUCTS.map(productView)),
|
|
191
|
-
GetClimateProductsProduct: climateProduct,
|
|
192
|
-
GetClimateSuppliers: async (ctx) => catalog(ctx, CLIMATE_SUPPLIERS.map(supplierView)),
|
|
193
|
-
GetClimateSuppliersSupplier: climateSupplier,
|
|
194
|
-
PostClimateOrders: createOrder,
|
|
195
|
-
PostClimateOrdersOrderCancel: cancelOrder,
|
|
196
|
-
PostClimateOrdersOrder: updateOrder,
|
|
197
|
-
PostFinancialConnectionsSessions: createSession,
|
|
198
|
-
GetFinancialConnectionsSessionsSession: session,
|
|
199
|
-
GetFinancialConnectionsAccounts: accounts,
|
|
200
|
-
PostFinancialConnectionsAccountsAccountDisconnect: disconnect,
|
|
201
|
-
GetFinancialConnectionsTransactions: transactions,
|
|
202
|
-
PostForwardingRequests: forward,
|
|
203
|
-
GetReportingReportTypes: async (ctx) => catalog(ctx, REPORT_TYPES.map(reportTypeView)),
|
|
204
|
-
GetReportingReportTypesReportType: reportType,
|
|
205
|
-
PostReportingReportRuns: runReport,
|
|
206
|
-
};
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { type SemanticsContext } from '@volter/world-core';
|
|
2
|
-
import { type Row } from './shared.js';
|
|
3
|
-
/** A customer's now: its test clock's frozen time when it is on one (docs.stripe.com/billing/testing/test-clocks), the
|
|
4
|
-
* World's otherwise. */
|
|
5
|
-
export declare function clockNow(ctx: SemanticsContext, customer: unknown): number;
|
|
6
|
-
/** What a subscription's invoices charge: its own default payment method, else its customer's. */
|
|
7
|
-
export declare function payerOf(ctx: SemanticsContext, sub: Row): string | undefined;
|
|
8
|
-
/** An item's quantity as it bills: 1 when none is set, and 0 when 0 is (a quantity of 0 bills nothing). */
|
|
9
|
-
export declare function itemQuantity(it: Row): number;
|
|
10
|
-
/** The subscription's discounts with a `once` coupon's spent: "When a subscription uses a coupon with `duration=once`, the
|
|
11
|
-
* coupon is considered used after the invoice finalizes and is removed from the subscription's `discounts` array"
|
|
12
|
-
* (docs.stripe.com/billing/subscriptions/coupons#coupon-duration). */
|
|
13
|
-
export declare function unspentDiscounts(discounts: unknown): Row[];
|
|
14
|
-
/** A subscription whose invoice has just been finalized: the `once` coupon that invoice took is spent, and a once coupon
|
|
15
|
-
* it did not take (added after it was drafted) stays for the next (unspentDiscounts). */
|
|
16
|
-
export declare function spendOnceCoupon(ctx: SemanticsContext, invoice: Row): Promise<void>;
|
|
17
|
-
/** A subscription's discounts after `invoice` finalizes: less the `once` coupons it took. */
|
|
18
|
-
export declare function keptAfter(discounts: Row[], invoice: Row): Row[];
|
|
19
|
-
/** A draft invoice for one period of a subscription, its lines the subscription's items and any one-time lines `once`
|
|
20
|
-
* gives it (a Checkout session's one-time prices, "on the initial invoice only", docs.stripe.com/api/checkout/sessions/
|
|
21
|
-
* create#create_checkout_session-line_items), under the subscription's discount. Answers the invoice id. */
|
|
22
|
-
export declare function draftSubscriptionInvoice(ctx: SemanticsContext, sub: Row, o: {
|
|
23
|
-
start: number;
|
|
24
|
-
end: number;
|
|
25
|
-
reason: 'subscription_create' | 'subscription_cycle' | 'subscription_update';
|
|
26
|
-
trial?: boolean;
|
|
27
|
-
once?: Row[];
|
|
28
|
-
id?: string;
|
|
29
|
-
}): Promise<string>;
|
|
30
|
-
/** Finalize a subscription's draft invoice at `at` and charge what its subscription pays with. The move is time's (a
|
|
31
|
-
* renewal), the customer's (the Checkout page they paid on) or the API's (an update that ends a trial, which names the
|
|
32
|
-
* payer, may ask for no attempt, and moves the subscription itself: semantics/subscriptions.ts applyTrialEnd). Answers
|
|
33
|
-
* whether it was paid. */
|
|
34
|
-
export declare function collectSubscriptionInvoice(ctx: SemanticsContext, invoiceId: string, at: number, actor: 'time' | 'external' | 'api', opts?: {
|
|
35
|
-
payer?: string;
|
|
36
|
-
attempt?: boolean;
|
|
37
|
-
}): Promise<boolean>;
|
|
38
|
-
/** Pay a subscription's open invoice with `paymentMethod` (the customer on the portal, `external`): the charge on the
|
|
39
|
-
* invoice's PaymentIntent, the invoice paid, a past_due subscription active. Answers the decline, if the card is refused. */
|
|
40
|
-
export declare function payOpenInvoice(ctx: SemanticsContext, invoiceId: string, paymentMethod: string): Promise<{
|
|
41
|
-
code: string;
|
|
42
|
-
message: string;
|
|
43
|
-
} | undefined>;
|
|
44
|
-
/** Time's moves on subscriptions, caught up to each customer's clock in the order they fell due, each made at the
|
|
45
|
-
* moment it was due: a period that ended renews (a trial's end among them) or, set to cancel, cancels; a renewal
|
|
46
|
-
* drafted an hour or more ago is finalized and charged. */
|
|
47
|
-
export declare function advanceBilling(ctx: SemanticsContext, only?: (sub: Row) => boolean): Promise<void>;
|