@vandenberghinc/volt 1.2.6 → 1.2.7
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/backend/dist/cjs/backend/src/blacklist.d.ts +12 -0
- package/backend/dist/cjs/backend/src/blacklist.js +78 -0
- package/backend/dist/cjs/backend/src/cli.d.ts +2 -0
- package/backend/dist/cjs/backend/src/cli.js +198 -0
- package/backend/dist/cjs/backend/src/database/collection.d.ts +1765 -0
- package/backend/dist/cjs/backend/src/database/collection.js +3301 -0
- package/backend/dist/cjs/backend/src/database/database.d.ts +92 -0
- package/backend/dist/cjs/backend/src/database/database.js +170 -0
- package/backend/dist/cjs/backend/src/database/document.d.ts +1 -0
- package/backend/dist/cjs/backend/src/database/document.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/filters.d.ts +6 -0
- package/backend/dist/cjs/backend/src/database/filters/filters.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter.d.ts +223 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_test.d.ts +1 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_test.js +443 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_test_v0.d.ts +1 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_test_v0.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.d.ts +50 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v0.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.d.ts +76 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v1.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.d.ts +75 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v2.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.d.ts +219 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_filter_v3.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.d.ts +165 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_update_filter.js +15 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.d.ts +5 -0
- package/backend/dist/cjs/backend/src/database/filters/strict_update_filter_test.js +355 -0
- package/backend/dist/cjs/backend/src/database/flatten.d.ts +78 -0
- package/backend/dist/cjs/backend/src/database/flatten.js +53 -0
- package/backend/dist/cjs/backend/src/database/flatten_test.d.ts +1 -0
- package/backend/dist/cjs/backend/src/database/flatten_test.js +175 -0
- package/backend/dist/cjs/backend/src/database/quota/quoata_v2.d.ts +533 -0
- package/backend/dist/cjs/backend/src/database/quota/quoata_v2.js +1046 -0
- package/backend/dist/cjs/backend/src/database/quota/quota.d.ts +551 -0
- package/backend/dist/cjs/backend/src/database/quota/quota.js +1108 -0
- package/backend/dist/cjs/backend/src/database/quota/quota_v1.d.ts +534 -0
- package/backend/dist/cjs/backend/src/database/quota/quota_v1.js +1087 -0
- package/backend/dist/cjs/backend/src/database/quota/safe_int.d.ts +412 -0
- package/backend/dist/cjs/backend/src/database/quota/safe_int.js +745 -0
- package/backend/dist/cjs/backend/src/endpoint.d.ts +346 -0
- package/backend/dist/cjs/backend/src/endpoint.js +468 -0
- package/backend/dist/cjs/backend/src/errors/index.d.ts +7 -0
- package/backend/dist/cjs/backend/src/errors/index.js +25 -0
- package/backend/dist/cjs/backend/src/errors/internal_external.d.ts +52 -0
- package/backend/dist/cjs/backend/src/errors/internal_external.js +95 -0
- package/backend/dist/cjs/backend/src/errors/invalid_usage_error.d.ts +41 -0
- package/backend/dist/cjs/backend/src/errors/invalid_usage_error.js +47 -0
- package/backend/dist/cjs/backend/src/errors/system_error.d.ts +261 -0
- package/backend/dist/cjs/backend/src/errors/system_error.js +436 -0
- package/backend/dist/cjs/backend/src/events.d.ts +97 -0
- package/backend/dist/cjs/backend/src/events.js +15 -0
- package/backend/dist/cjs/backend/src/frontend.d.ts +13 -0
- package/backend/dist/cjs/backend/src/frontend.js +56 -0
- package/backend/dist/cjs/backend/src/image_endpoint.d.ts +44 -0
- package/backend/dist/cjs/backend/src/image_endpoint.js +185 -0
- package/backend/dist/cjs/backend/src/index.d.ts +23 -0
- package/backend/dist/cjs/backend/src/index.js +70 -0
- package/backend/dist/cjs/backend/src/logger.d.ts +5 -0
- package/backend/dist/cjs/backend/src/logger.js +15 -0
- package/backend/dist/cjs/backend/src/meta.d.ts +112 -0
- package/backend/dist/cjs/backend/src/meta.js +181 -0
- package/backend/dist/cjs/backend/src/payments/paddle.d.ts +329 -0
- package/backend/dist/cjs/backend/src/payments/paddle.js +1996 -0
- package/backend/dist/cjs/backend/src/payments/stripe/checkout.d.ts +113 -0
- package/backend/dist/cjs/backend/src/payments/stripe/checkout.js +295 -0
- package/backend/dist/cjs/backend/src/payments/stripe/customers.d.ts +17 -0
- package/backend/dist/cjs/backend/src/payments/stripe/customers.js +164 -0
- package/backend/dist/cjs/backend/src/payments/stripe/error.d.ts +74 -0
- package/backend/dist/cjs/backend/src/payments/stripe/error.js +64 -0
- package/backend/dist/cjs/backend/src/payments/stripe/events.d.ts +155 -0
- package/backend/dist/cjs/backend/src/payments/stripe/events.js +15 -0
- package/backend/dist/cjs/backend/src/payments/stripe/meters.d.ts +105 -0
- package/backend/dist/cjs/backend/src/payments/stripe/meters.js +230 -0
- package/backend/dist/cjs/backend/src/payments/stripe/payment_methods.d.ts +58 -0
- package/backend/dist/cjs/backend/src/payments/stripe/payment_methods.js +109 -0
- package/backend/dist/cjs/backend/src/payments/stripe/products.d.ts +519 -0
- package/backend/dist/cjs/backend/src/payments/stripe/products.js +650 -0
- package/backend/dist/cjs/backend/src/payments/stripe/stripe.d.ts +215 -0
- package/backend/dist/cjs/backend/src/payments/stripe/stripe.js +468 -0
- package/backend/dist/cjs/backend/src/payments/stripe/subscriptions.d.ts +172 -0
- package/backend/dist/cjs/backend/src/payments/stripe/subscriptions.js +557 -0
- package/backend/dist/cjs/backend/src/payments/stripe/utils.d.ts +63 -0
- package/backend/dist/cjs/backend/src/payments/stripe/utils.js +118 -0
- package/backend/dist/cjs/backend/src/payments/stripe/webhooks.d.ts +105 -0
- package/backend/dist/cjs/backend/src/payments/stripe/webhooks.js +627 -0
- package/backend/dist/cjs/backend/src/plugins/browser.d.ts +1 -0
- package/backend/dist/cjs/backend/src/plugins/browser.js +15 -0
- package/backend/dist/cjs/backend/src/plugins/communication.d.ts +70 -0
- package/backend/dist/cjs/backend/src/plugins/communication.js +196 -0
- package/backend/dist/cjs/backend/src/plugins/mail/mail.d.ts +255 -0
- package/backend/dist/cjs/backend/src/plugins/mail/mail.js +381 -0
- package/backend/dist/cjs/backend/src/plugins/mail/ui.d.ts +297 -0
- package/backend/dist/cjs/backend/src/plugins/mail/ui.js +1370 -0
- package/backend/dist/cjs/backend/src/plugins/pdf.d.ts +1 -0
- package/backend/dist/cjs/backend/src/plugins/pdf.js +1456 -0
- package/backend/dist/cjs/backend/src/plugins/thread_monitor.d.ts +18 -0
- package/backend/dist/cjs/backend/src/plugins/thread_monitor.js +116 -0
- package/backend/dist/cjs/backend/src/rate_limit.d.ts +148 -0
- package/backend/dist/cjs/backend/src/rate_limit.js +543 -0
- package/backend/dist/cjs/backend/src/route.d.ts +39 -0
- package/backend/dist/cjs/backend/src/route.js +172 -0
- package/backend/dist/cjs/backend/src/server.d.ts +502 -0
- package/backend/dist/cjs/backend/src/server.js +1710 -0
- package/backend/dist/cjs/backend/src/server.old.d.ts +594 -0
- package/backend/dist/cjs/backend/src/server.old.js +2058 -0
- package/backend/dist/cjs/backend/src/splash_screen.d.ts +93 -0
- package/backend/dist/cjs/backend/src/splash_screen.js +119 -0
- package/backend/dist/cjs/backend/src/status.d.ts +89 -0
- package/backend/dist/cjs/backend/src/status.js +211 -0
- package/backend/dist/cjs/backend/src/stream.d.ts +494 -0
- package/backend/dist/cjs/backend/src/stream.js +1370 -0
- package/backend/dist/cjs/backend/src/users.d.ts +926 -0
- package/backend/dist/cjs/backend/src/users.js +2223 -0
- package/backend/dist/cjs/backend/src/utils.d.ts +22 -0
- package/backend/dist/cjs/backend/src/utils.js +626 -0
- package/backend/dist/cjs/backend/src/view.d.ts +115 -0
- package/backend/dist/cjs/backend/src/view.js +519 -0
- package/backend/dist/cjs/backend/src/vinc.d.ts +6 -0
- package/backend/dist/cjs/backend/src/vinc.js +40 -0
- package/backend/dist/cjs/backend/src/volt.d.ts +24 -0
- package/backend/dist/cjs/backend/src/volt.js +72 -0
- package/backend/dist/cjs/frontend/src/modules/request.d.ts +70 -0
- package/backend/dist/cjs/frontend/src/modules/request.js +99 -0
- package/backend/dist/cjs/package.json +1 -0
- package/backend/dist/esm/backend/src/blacklist.d.ts +12 -0
- package/backend/dist/esm/backend/src/blacklist.js +52 -0
- package/backend/dist/esm/backend/src/cli.d.ts +2 -0
- package/backend/dist/esm/backend/src/cli.js +211 -0
- package/backend/dist/esm/backend/src/database/collection.d.ts +1765 -0
- package/backend/dist/esm/backend/src/database/collection.js +3779 -0
- package/backend/dist/esm/backend/src/database/database.d.ts +92 -0
- package/backend/dist/esm/backend/src/database/database.js +214 -0
- package/backend/dist/esm/backend/src/database/document.d.ts +1 -0
- package/backend/dist/esm/backend/src/database/document.js +558 -0
- package/backend/dist/esm/backend/src/database/filters/filters.d.ts +6 -0
- package/backend/dist/esm/backend/src/database/filters/filters.js +1 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter.d.ts +223 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter.js +3 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_test.d.ts +1 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_test.js +505 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.d.ts +1 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_test_v0.js +712 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.d.ts +50 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v0.js +5 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.d.ts +76 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v1.js +44 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.d.ts +75 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v2.js +5 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.d.ts +219 -0
- package/backend/dist/esm/backend/src/database/filters/strict_filter_v3.js +1 -0
- package/backend/dist/esm/backend/src/database/filters/strict_update_filter.d.ts +165 -0
- package/backend/dist/esm/backend/src/database/filters/strict_update_filter.js +5 -0
- package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.d.ts +5 -0
- package/backend/dist/esm/backend/src/database/filters/strict_update_filter_test.js +415 -0
- package/backend/dist/esm/backend/src/database/flatten.d.ts +78 -0
- package/backend/dist/esm/backend/src/database/flatten.js +22 -0
- package/backend/dist/esm/backend/src/database/flatten_test.d.ts +1 -0
- package/backend/dist/esm/backend/src/database/flatten_test.js +174 -0
- package/backend/dist/esm/backend/src/database/quota/quoata_v2.d.ts +533 -0
- package/backend/dist/esm/backend/src/database/quota/quoata_v2.js +1155 -0
- package/backend/dist/esm/backend/src/database/quota/quota.d.ts +551 -0
- package/backend/dist/esm/backend/src/database/quota/quota.js +1219 -0
- package/backend/dist/esm/backend/src/database/quota/quota_v1.d.ts +534 -0
- package/backend/dist/esm/backend/src/database/quota/quota_v1.js +1242 -0
- package/backend/dist/esm/backend/src/database/quota/safe_int.d.ts +412 -0
- package/backend/dist/esm/backend/src/database/quota/safe_int.js +810 -0
- package/backend/dist/esm/backend/src/endpoint.d.ts +346 -0
- package/backend/dist/esm/backend/src/endpoint.js +479 -0
- package/backend/dist/esm/backend/src/errors/index.d.ts +7 -0
- package/backend/dist/esm/backend/src/errors/index.js +7 -0
- package/backend/dist/esm/backend/src/errors/internal_external.d.ts +52 -0
- package/backend/dist/esm/backend/src/errors/internal_external.js +86 -0
- package/backend/dist/esm/backend/src/errors/invalid_usage_error.d.ts +41 -0
- package/backend/dist/esm/backend/src/errors/invalid_usage_error.js +33 -0
- package/backend/dist/esm/backend/src/errors/system_error.d.ts +261 -0
- package/backend/dist/esm/backend/src/errors/system_error.js +444 -0
- package/backend/dist/esm/backend/src/events.d.ts +97 -0
- package/backend/dist/esm/backend/src/events.js +5 -0
- package/backend/dist/esm/backend/src/frontend.d.ts +13 -0
- package/backend/dist/esm/backend/src/frontend.js +23 -0
- package/backend/dist/esm/backend/src/image_endpoint.d.ts +44 -0
- package/backend/dist/esm/backend/src/image_endpoint.js +196 -0
- package/backend/dist/esm/backend/src/index.d.ts +23 -0
- package/backend/dist/esm/backend/src/index.js +26 -0
- package/backend/dist/esm/backend/src/logger.d.ts +5 -0
- package/backend/dist/esm/backend/src/logger.js +8 -0
- package/backend/dist/esm/backend/src/meta.d.ts +112 -0
- package/backend/dist/esm/backend/src/meta.js +152 -0
- package/backend/dist/esm/backend/src/payments/paddle.d.ts +329 -0
- package/backend/dist/esm/backend/src/payments/paddle.js +2276 -0
- package/backend/dist/esm/backend/src/payments/stripe/checkout.d.ts +113 -0
- package/backend/dist/esm/backend/src/payments/stripe/checkout.js +356 -0
- package/backend/dist/esm/backend/src/payments/stripe/customers.d.ts +17 -0
- package/backend/dist/esm/backend/src/payments/stripe/customers.js +193 -0
- package/backend/dist/esm/backend/src/payments/stripe/error.d.ts +74 -0
- package/backend/dist/esm/backend/src/payments/stripe/error.js +51 -0
- package/backend/dist/esm/backend/src/payments/stripe/events.d.ts +155 -0
- package/backend/dist/esm/backend/src/payments/stripe/events.js +5 -0
- package/backend/dist/esm/backend/src/payments/stripe/meters.d.ts +105 -0
- package/backend/dist/esm/backend/src/payments/stripe/meters.js +318 -0
- package/backend/dist/esm/backend/src/payments/stripe/payment_methods.d.ts +58 -0
- package/backend/dist/esm/backend/src/payments/stripe/payment_methods.js +135 -0
- package/backend/dist/esm/backend/src/payments/stripe/products.d.ts +519 -0
- package/backend/dist/esm/backend/src/payments/stripe/products.js +896 -0
- package/backend/dist/esm/backend/src/payments/stripe/stripe.d.ts +215 -0
- package/backend/dist/esm/backend/src/payments/stripe/stripe.js +464 -0
- package/backend/dist/esm/backend/src/payments/stripe/subscriptions.d.ts +172 -0
- package/backend/dist/esm/backend/src/payments/stripe/subscriptions.js +754 -0
- package/backend/dist/esm/backend/src/payments/stripe/utils.d.ts +63 -0
- package/backend/dist/esm/backend/src/payments/stripe/utils.js +131 -0
- package/backend/dist/esm/backend/src/payments/stripe/webhooks.d.ts +105 -0
- package/backend/dist/esm/backend/src/payments/stripe/webhooks.js +752 -0
- package/backend/dist/esm/backend/src/plugins/browser.d.ts +1 -0
- package/backend/dist/esm/backend/src/plugins/browser.js +170 -0
- package/backend/dist/esm/backend/src/plugins/communication.d.ts +70 -0
- package/backend/dist/esm/backend/src/plugins/communication.js +169 -0
- package/backend/dist/esm/backend/src/plugins/mail/mail.d.ts +255 -0
- package/backend/dist/esm/backend/src/plugins/mail/mail.js +396 -0
- package/backend/dist/esm/backend/src/plugins/mail/ui.d.ts +297 -0
- package/backend/dist/esm/backend/src/plugins/mail/ui.js +1400 -0
- package/backend/dist/esm/backend/src/plugins/pdf.d.ts +1 -0
- package/backend/dist/esm/backend/src/plugins/pdf.js +1694 -0
- package/backend/dist/esm/backend/src/plugins/thread_monitor.d.ts +18 -0
- package/backend/dist/esm/backend/src/plugins/thread_monitor.js +120 -0
- package/backend/dist/esm/backend/src/rate_limit.d.ts +148 -0
- package/backend/dist/esm/backend/src/rate_limit.js +667 -0
- package/backend/dist/esm/backend/src/route.d.ts +39 -0
- package/backend/dist/esm/backend/src/route.js +222 -0
- package/backend/dist/esm/backend/src/server.d.ts +502 -0
- package/backend/dist/esm/backend/src/server.js +2031 -0
- package/backend/dist/esm/backend/src/server.old.d.ts +594 -0
- package/backend/dist/esm/backend/src/server.old.js +2630 -0
- package/backend/dist/esm/backend/src/splash_screen.d.ts +93 -0
- package/backend/dist/esm/backend/src/splash_screen.js +156 -0
- package/backend/dist/esm/backend/src/status.d.ts +89 -0
- package/backend/dist/esm/backend/src/status.js +213 -0
- package/backend/dist/esm/backend/src/stream.d.ts +494 -0
- package/backend/dist/esm/backend/src/stream.js +1611 -0
- package/backend/dist/esm/backend/src/users.d.ts +926 -0
- package/backend/dist/esm/backend/src/users.js +2423 -0
- package/backend/dist/esm/backend/src/utils.d.ts +22 -0
- package/backend/dist/esm/backend/src/utils.js +463 -0
- package/backend/dist/esm/backend/src/view.d.ts +115 -0
- package/backend/dist/esm/backend/src/view.js +584 -0
- package/backend/dist/esm/backend/src/vinc.d.ts +6 -0
- package/backend/dist/esm/backend/src/vinc.js +6 -0
- package/backend/dist/esm/backend/src/volt.d.ts +24 -0
- package/backend/dist/esm/backend/src/volt.js +27 -0
- package/backend/dist/esm/frontend/src/modules/request.d.ts +70 -0
- package/backend/dist/esm/frontend/src/modules/request.js +117 -0
- package/frontend/dist/backend/src/database/collection.d.ts +1765 -0
- package/frontend/dist/backend/src/database/collection.js +3779 -0
- package/frontend/dist/backend/src/database/database.d.ts +92 -0
- package/frontend/dist/backend/src/database/database.js +214 -0
- package/frontend/dist/backend/src/database/filters/filters.d.ts +6 -0
- package/frontend/dist/backend/src/database/filters/filters.js +1 -0
- package/frontend/dist/backend/src/database/filters/strict_filter.d.ts +223 -0
- package/frontend/dist/backend/src/database/filters/strict_filter.js +3 -0
- package/frontend/dist/backend/src/database/filters/strict_update_filter.d.ts +165 -0
- package/frontend/dist/backend/src/database/filters/strict_update_filter.js +5 -0
- package/frontend/dist/backend/src/database/flatten.d.ts +78 -0
- package/frontend/dist/backend/src/database/flatten.js +22 -0
- package/frontend/dist/backend/src/endpoint.d.ts +346 -0
- package/frontend/dist/backend/src/endpoint.js +479 -0
- package/frontend/dist/backend/src/errors/index.d.ts +7 -0
- package/frontend/dist/backend/src/errors/index.js +7 -0
- package/frontend/dist/backend/src/errors/internal_external.d.ts +52 -0
- package/frontend/dist/backend/src/errors/internal_external.js +86 -0
- package/frontend/dist/backend/src/errors/invalid_usage_error.d.ts +41 -0
- package/frontend/dist/backend/src/errors/invalid_usage_error.js +33 -0
- package/frontend/dist/backend/src/errors/system_error.d.ts +261 -0
- package/frontend/dist/backend/src/errors/system_error.js +444 -0
- package/frontend/dist/backend/src/events.d.ts +97 -0
- package/frontend/dist/backend/src/events.js +5 -0
- package/frontend/dist/backend/src/frontend.d.ts +13 -0
- package/frontend/dist/backend/src/frontend.js +23 -0
- package/frontend/dist/backend/src/image_endpoint.d.ts +44 -0
- package/frontend/dist/backend/src/image_endpoint.js +196 -0
- package/frontend/dist/backend/src/meta.d.ts +112 -0
- package/frontend/dist/backend/src/meta.js +152 -0
- package/frontend/dist/backend/src/payments/paddle.d.ts +329 -0
- package/frontend/dist/backend/src/payments/paddle.js +2276 -0
- package/frontend/dist/backend/src/payments/stripe/checkout.d.ts +113 -0
- package/frontend/dist/backend/src/payments/stripe/checkout.js +356 -0
- package/frontend/dist/backend/src/payments/stripe/customers.d.ts +17 -0
- package/frontend/dist/backend/src/payments/stripe/customers.js +193 -0
- package/frontend/dist/backend/src/payments/stripe/error.d.ts +74 -0
- package/frontend/dist/backend/src/payments/stripe/error.js +51 -0
- package/frontend/dist/backend/src/payments/stripe/events.d.ts +155 -0
- package/frontend/dist/backend/src/payments/stripe/events.js +5 -0
- package/frontend/dist/backend/src/payments/stripe/meters.d.ts +105 -0
- package/frontend/dist/backend/src/payments/stripe/meters.js +318 -0
- package/frontend/dist/backend/src/payments/stripe/payment_methods.d.ts +58 -0
- package/frontend/dist/backend/src/payments/stripe/payment_methods.js +135 -0
- package/frontend/dist/backend/src/payments/stripe/products.d.ts +519 -0
- package/frontend/dist/backend/src/payments/stripe/products.js +896 -0
- package/frontend/dist/backend/src/payments/stripe/stripe.d.ts +215 -0
- package/frontend/dist/backend/src/payments/stripe/stripe.js +464 -0
- package/frontend/dist/backend/src/payments/stripe/subscriptions.d.ts +172 -0
- package/frontend/dist/backend/src/payments/stripe/subscriptions.js +754 -0
- package/frontend/dist/backend/src/payments/stripe/utils.d.ts +63 -0
- package/frontend/dist/backend/src/payments/stripe/utils.js +131 -0
- package/frontend/dist/backend/src/payments/stripe/webhooks.d.ts +105 -0
- package/frontend/dist/backend/src/payments/stripe/webhooks.js +752 -0
- package/frontend/dist/backend/src/plugins/mail/mail.d.ts +255 -0
- package/frontend/dist/backend/src/plugins/mail/mail.js +396 -0
- package/frontend/dist/backend/src/plugins/mail/ui.d.ts +297 -0
- package/frontend/dist/backend/src/plugins/mail/ui.js +1400 -0
- package/frontend/dist/backend/src/rate_limit.d.ts +148 -0
- package/frontend/dist/backend/src/rate_limit.js +667 -0
- package/frontend/dist/backend/src/route.d.ts +39 -0
- package/frontend/dist/backend/src/route.js +222 -0
- package/frontend/dist/backend/src/server.d.ts +502 -0
- package/frontend/dist/backend/src/server.js +2031 -0
- package/frontend/dist/backend/src/splash_screen.d.ts +93 -0
- package/frontend/dist/backend/src/splash_screen.js +156 -0
- package/frontend/dist/backend/src/status.d.ts +89 -0
- package/frontend/dist/backend/src/status.js +213 -0
- package/frontend/dist/backend/src/stream.d.ts +494 -0
- package/frontend/dist/backend/src/stream.js +1611 -0
- package/frontend/dist/backend/src/users.d.ts +926 -0
- package/frontend/dist/backend/src/users.js +2423 -0
- package/frontend/dist/backend/src/utils.d.ts +22 -0
- package/frontend/dist/backend/src/utils.js +463 -0
- package/frontend/dist/backend/src/view.d.ts +115 -0
- package/frontend/dist/backend/src/view.js +584 -0
- package/frontend/dist/frontend/src/css/adyen.css +92 -0
- package/frontend/dist/frontend/src/css/volt.css +75 -0
- package/frontend/dist/frontend/src/elements/base.d.ts +3743 -0
- package/frontend/dist/frontend/src/elements/base.js +12151 -0
- package/frontend/dist/frontend/src/elements/module.d.ts +95 -0
- package/frontend/dist/frontend/src/elements/module.js +216 -0
- package/frontend/dist/frontend/src/elements/register_element.d.ts +3 -0
- package/frontend/dist/frontend/src/elements/register_element.js +22 -0
- package/frontend/dist/frontend/src/elements/resize_query_manager.d.ts +0 -0
- package/frontend/dist/frontend/src/elements/resize_query_manager.js +150 -0
- package/frontend/dist/frontend/src/elements/types.d.ts +52 -0
- package/frontend/dist/frontend/src/elements/types.js +5 -0
- package/frontend/dist/frontend/src/index.d.ts +21 -0
- package/frontend/dist/frontend/src/index.js +29 -0
- package/frontend/dist/frontend/src/modules/attachment.d.ts +126 -0
- package/frontend/dist/frontend/src/modules/attachment.js +306 -0
- package/frontend/dist/frontend/src/modules/auth.d.ts +44 -0
- package/frontend/dist/frontend/src/modules/auth.js +80 -0
- package/frontend/dist/frontend/src/modules/color.d.ts +160 -0
- package/frontend/dist/frontend/src/modules/color.js +316 -0
- package/frontend/dist/frontend/src/modules/compression.d.ts +39 -0
- package/frontend/dist/frontend/src/modules/compression.js +102 -0
- package/frontend/dist/frontend/src/modules/cookies.d.ts +44 -0
- package/frontend/dist/frontend/src/modules/cookies.js +143 -0
- package/frontend/dist/frontend/src/modules/events.d.ts +31 -0
- package/frontend/dist/frontend/src/modules/events.js +79 -0
- package/frontend/dist/frontend/src/modules/google.d.ts +23 -0
- package/frontend/dist/frontend/src/modules/google.js +52 -0
- package/frontend/dist/frontend/src/modules/meta.d.ts +14 -0
- package/frontend/dist/frontend/src/modules/meta.js +48 -0
- package/frontend/dist/frontend/src/modules/paddle.d.ts +1207 -0
- package/frontend/dist/frontend/src/modules/paddle.js +2594 -0
- package/frontend/dist/frontend/src/modules/request.d.ts +70 -0
- package/frontend/dist/frontend/src/modules/request.js +117 -0
- package/frontend/dist/frontend/src/modules/settings.d.ts +3 -0
- package/frontend/dist/frontend/src/modules/settings.js +5 -0
- package/frontend/dist/frontend/src/modules/statics.d.ts +21 -0
- package/frontend/dist/frontend/src/modules/statics.js +43 -0
- package/frontend/dist/frontend/src/modules/stripe/cart.d.ts +112 -0
- package/frontend/dist/frontend/src/modules/stripe/cart.js +321 -0
- package/frontend/dist/frontend/src/modules/stripe/checkout.d.ts +7 -0
- package/frontend/dist/frontend/src/modules/stripe/checkout.js +37 -0
- package/frontend/dist/frontend/src/modules/stripe/index.m.d.ts +6 -0
- package/frontend/dist/frontend/src/modules/stripe/index.m.js +6 -0
- package/frontend/dist/frontend/src/modules/stripe/payments.d.ts +58 -0
- package/frontend/dist/frontend/src/modules/stripe/payments.js +92 -0
- package/frontend/dist/frontend/src/modules/support.d.ts +30 -0
- package/frontend/dist/frontend/src/modules/support.js +53 -0
- package/frontend/dist/frontend/src/modules/theme.d.ts +133 -0
- package/frontend/dist/frontend/src/modules/theme.js +406 -0
- package/frontend/dist/frontend/src/modules/themes.d.ts +12 -0
- package/frontend/dist/frontend/src/modules/themes.js +22 -0
- package/frontend/dist/frontend/src/modules/user.d.ts +164 -0
- package/frontend/dist/frontend/src/modules/user.js +270 -0
- package/frontend/dist/frontend/src/modules/utils.d.ts +176 -0
- package/frontend/dist/frontend/src/modules/utils.js +569 -0
- package/frontend/dist/frontend/src/types/gradient.d.ts +29 -0
- package/frontend/dist/frontend/src/types/gradient.js +79 -0
- package/frontend/dist/frontend/src/ui/border_button.d.ts +94 -0
- package/frontend/dist/frontend/src/ui/border_button.js +228 -0
- package/frontend/dist/frontend/src/ui/button.d.ts +241 -0
- package/frontend/dist/frontend/src/ui/button.js +682 -0
- package/frontend/dist/frontend/src/ui/canvas.d.ts +138 -0
- package/frontend/dist/frontend/src/ui/canvas.js +444 -0
- package/frontend/dist/frontend/src/ui/checkbox.d.ts +74 -0
- package/frontend/dist/frontend/src/ui/checkbox.js +321 -0
- package/frontend/dist/frontend/src/ui/code.d.ts +235 -0
- package/frontend/dist/frontend/src/ui/code.js +1007 -0
- package/frontend/dist/frontend/src/ui/context_menu.d.ts +36 -0
- package/frontend/dist/frontend/src/ui/context_menu.js +205 -0
- package/frontend/dist/frontend/src/ui/css.d.ts +16 -0
- package/frontend/dist/frontend/src/ui/css.js +48 -0
- package/frontend/dist/frontend/src/ui/divider.d.ts +15 -0
- package/frontend/dist/frontend/src/ui/divider.js +78 -0
- package/frontend/dist/frontend/src/ui/dropdown.d.ts +176 -0
- package/frontend/dist/frontend/src/ui/dropdown.js +481 -0
- package/frontend/dist/frontend/src/ui/for_each.d.ts +37 -0
- package/frontend/dist/frontend/src/ui/for_each.js +92 -0
- package/frontend/dist/frontend/src/ui/form.d.ts +34 -0
- package/frontend/dist/frontend/src/ui/form.js +233 -0
- package/frontend/dist/frontend/src/ui/frame_modes.d.ts +37 -0
- package/frontend/dist/frontend/src/ui/frame_modes.js +108 -0
- package/frontend/dist/frontend/src/ui/google_map.d.ts +24 -0
- package/frontend/dist/frontend/src/ui/google_map.js +106 -0
- package/frontend/dist/frontend/src/ui/gradient.d.ts +25 -0
- package/frontend/dist/frontend/src/ui/gradient.js +131 -0
- package/frontend/dist/frontend/src/ui/image.d.ts +111 -0
- package/frontend/dist/frontend/src/ui/image.js +576 -0
- package/frontend/dist/frontend/src/ui/input.d.ts +392 -0
- package/frontend/dist/frontend/src/ui/input.js +1201 -0
- package/frontend/dist/frontend/src/ui/link.d.ts +25 -0
- package/frontend/dist/frontend/src/ui/link.js +140 -0
- package/frontend/dist/frontend/src/ui/list.d.ts +37 -0
- package/frontend/dist/frontend/src/ui/list.js +170 -0
- package/frontend/dist/frontend/src/ui/loader_button.d.ts +80 -0
- package/frontend/dist/frontend/src/ui/loader_button.js +193 -0
- package/frontend/dist/frontend/src/ui/loaders.d.ts +57 -0
- package/frontend/dist/frontend/src/ui/loaders.js +157 -0
- package/frontend/dist/frontend/src/ui/popup.d.ts +94 -0
- package/frontend/dist/frontend/src/ui/popup.js +510 -0
- package/frontend/dist/frontend/src/ui/pseudo.d.ts +44 -0
- package/frontend/dist/frontend/src/ui/pseudo.js +154 -0
- package/frontend/dist/frontend/src/ui/scroller.d.ts +105 -0
- package/frontend/dist/frontend/src/ui/scroller.js +1253 -0
- package/frontend/dist/frontend/src/ui/slider.d.ts +45 -0
- package/frontend/dist/frontend/src/ui/slider.js +217 -0
- package/frontend/dist/frontend/src/ui/spacer.d.ts +15 -0
- package/frontend/dist/frontend/src/ui/spacer.js +78 -0
- package/frontend/dist/frontend/src/ui/span.d.ts +15 -0
- package/frontend/dist/frontend/src/ui/span.js +73 -0
- package/frontend/dist/frontend/src/ui/stack.d.ts +66 -0
- package/frontend/dist/frontend/src/ui/stack.js +335 -0
- package/frontend/dist/frontend/src/ui/steps.d.ts +131 -0
- package/frontend/dist/frontend/src/ui/steps.js +308 -0
- package/frontend/dist/frontend/src/ui/style.d.ts +17 -0
- package/frontend/dist/frontend/src/ui/style.js +73 -0
- package/frontend/dist/frontend/src/ui/switch.d.ts +69 -0
- package/frontend/dist/frontend/src/ui/switch.js +357 -0
- package/frontend/dist/frontend/src/ui/table.d.ts +100 -0
- package/frontend/dist/frontend/src/ui/table.js +405 -0
- package/frontend/dist/frontend/src/ui/tabs.d.ts +111 -0
- package/frontend/dist/frontend/src/ui/tabs.js +424 -0
- package/frontend/dist/frontend/src/ui/text.d.ts +15 -0
- package/frontend/dist/frontend/src/ui/text.js +83 -0
- package/frontend/dist/frontend/src/ui/title.d.ts +91 -0
- package/frontend/dist/frontend/src/ui/title.js +272 -0
- package/frontend/dist/frontend/src/ui/ui.d.ts +35 -0
- package/frontend/dist/frontend/src/ui/ui.js +38 -0
- package/frontend/dist/frontend/src/ui/view.d.ts +15 -0
- package/frontend/dist/frontend/src/ui/view.js +88 -0
- package/frontend/dist/frontend/src/volt.d.ts +20 -0
- package/frontend/dist/frontend/src/volt.js +27 -0
- package/package.json +7 -2
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// meters.ts
|
|
2
|
+
/**
|
|
3
|
+
* @author Daan van den Bergh
|
|
4
|
+
* @copyright © 2026 - 2026 Daan van den Bergh. All rights reserved
|
|
5
|
+
*/
|
|
6
|
+
import { ensure_stripe_customer } from "./customers.js";
|
|
7
|
+
import { ExternalStripeError, InternalStripeError } from "./error.js";
|
|
8
|
+
import { assert, public_assert, is_non_empty_string, stripe_api_call, to_unix_seconds, stable_idempotency_key, } from "./utils.js";
|
|
9
|
+
import { MeterProduct } from "./products.js";
|
|
10
|
+
import { list_subscribed_meters } from "./subscriptions.js";
|
|
11
|
+
/**
|
|
12
|
+
* Convert a money amount in major units (e.g. USD "0.007463") into pico-cents units (10^-12 cents) as an integer string.
|
|
13
|
+
*
|
|
14
|
+
* We fix the Stripe price for money meters at:
|
|
15
|
+
* unit_amount_decimal (in cents) = "0.000000000001" => 10^-12 cents per unit
|
|
16
|
+
*
|
|
17
|
+
* Therefore:
|
|
18
|
+
* units = amount_major * 100 (cents) * 10^12 = amount_major * 10^14
|
|
19
|
+
*
|
|
20
|
+
* This function never uses float math for the actual scaling; it uses string + BigInt.
|
|
21
|
+
*/
|
|
22
|
+
function money_major_to_pico_cents_units(amount, round) {
|
|
23
|
+
const s = amount.trim();
|
|
24
|
+
assert(s.length > 0, "invalid_argument", "Property 'amount' must be a non-empty string.", { amount });
|
|
25
|
+
// Only non-negative numbers.
|
|
26
|
+
assert(/^\d+(\.\d+)?$/.test(s), "invalid_argument", "Property 'amount' must be a non-negative decimal.", { amount });
|
|
27
|
+
const [whole_raw, frac_raw = ""] = s.split(".");
|
|
28
|
+
const whole = whole_raw ?? "0";
|
|
29
|
+
const frac = frac_raw ?? "";
|
|
30
|
+
const SHIFT = MeterProduct.MONEY_METER_MAJOR_TO_PICO_CENTS_SHIFT;
|
|
31
|
+
const frac_padded = (frac + "0".repeat(SHIFT));
|
|
32
|
+
const frac_keep = frac_padded.slice(0, SHIFT);
|
|
33
|
+
const frac_rest = frac_padded.slice(SHIFT);
|
|
34
|
+
// Determine if remainder is non-zero.
|
|
35
|
+
const remainder_nonzero = /[1-9]/.test(frac_rest);
|
|
36
|
+
let increment = false;
|
|
37
|
+
if (frac.length > SHIFT || remainder_nonzero) {
|
|
38
|
+
if (round === "exact") {
|
|
39
|
+
assert(!remainder_nonzero, "invalid_argument", "Property 'amount' has more precision than supported for exact conversion.", {
|
|
40
|
+
amount,
|
|
41
|
+
max_decimals: SHIFT,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
else if (round === "floor") {
|
|
45
|
+
// do nothing
|
|
46
|
+
}
|
|
47
|
+
else if (round === "ceil") {
|
|
48
|
+
increment = remainder_nonzero;
|
|
49
|
+
}
|
|
50
|
+
else if (round === "round") {
|
|
51
|
+
increment = frac_rest.length > 0 && frac_rest[0] >= "5";
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// @ts-expect-error exhaustive
|
|
55
|
+
round.toString();
|
|
56
|
+
throw new InternalStripeError("invalid_argument", `Invalid rounding: ${round}`, { round });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const raw_int_str = (whole + frac_keep).replace(/^0+/, "") || "0";
|
|
60
|
+
let units = BigInt(raw_int_str);
|
|
61
|
+
if (increment) {
|
|
62
|
+
units += 1n;
|
|
63
|
+
}
|
|
64
|
+
return units.toString();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Normalize an amount input (string or number) to a decimal string.
|
|
68
|
+
* For numbers: use a high-precision fixed representation and trim.
|
|
69
|
+
*/
|
|
70
|
+
function normalize_amount_to_string(amount) {
|
|
71
|
+
if (typeof amount === "string") {
|
|
72
|
+
return amount;
|
|
73
|
+
}
|
|
74
|
+
assert(Number.isFinite(amount), "invalid_argument", "Property 'amount' must be a finite number.", { amount });
|
|
75
|
+
assert(Math.abs(amount) < 1e21, "invalid_argument", "Property 'amount' number is too large.", { amount });
|
|
76
|
+
// Avoid scientific notation / locale formatting.
|
|
77
|
+
// Using 20 decimals gives enough headroom; final conversion trunc/rounds to SHIFT anyway.
|
|
78
|
+
const s = amount.toFixed(20);
|
|
79
|
+
// Trim trailing zeros and optional dot.
|
|
80
|
+
return s.replace(/\.?0+$/, "");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate a meter event identifier according to Stripe constraints.
|
|
84
|
+
*/
|
|
85
|
+
function validate_meter_event_identifier(identifier) {
|
|
86
|
+
assert(identifier.length <= 100, "invalid_argument", "Meter event identifier must be <= 100 characters.", { identifier_length: identifier.length });
|
|
87
|
+
assert(identifier.trim().length > 0, "invalid_argument", "Meter event identifier must be non-empty.", {
|
|
88
|
+
identifier_length: identifier.length,
|
|
89
|
+
});
|
|
90
|
+
assert(/^[a-zA-Z0-9._-]+$/.test(identifier), "invalid_argument", "Meter event identifier contains invalid characters.", {});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Validate a meter event timestamp against Stripe constraints.
|
|
94
|
+
*
|
|
95
|
+
* Stripe requires:
|
|
96
|
+
* - within the past 35 calendar days
|
|
97
|
+
* - or up to 5 minutes in the future
|
|
98
|
+
* @see https://docs.stripe.com/api/billing/meter-event/create
|
|
99
|
+
*/
|
|
100
|
+
function validate_meter_event_timestamp(now, timestamp) {
|
|
101
|
+
const now_ms = now.getTime();
|
|
102
|
+
const ts_ms = timestamp.getTime();
|
|
103
|
+
assert(Number.isFinite(ts_ms), "invalid_argument", "Meter event timestamp is invalid.", {});
|
|
104
|
+
// 35 days is expressed as "calendar days" by Stripe; we enforce a strict 35*24h window.
|
|
105
|
+
// This is slightly stricter around DST/local offsets, but we only use UTC timestamps anyway.
|
|
106
|
+
const max_past_ms = 35 * 24 * 60 * 60 * 1000;
|
|
107
|
+
const max_future_ms = 5 * 60 * 1000;
|
|
108
|
+
assert(ts_ms >= now_ms - max_past_ms, "invalid_argument", "Meter event timestamp is too far in the past.", { now_ms, ts_ms });
|
|
109
|
+
assert(ts_ms <= now_ms + max_future_ms, "invalid_argument", "Meter event timestamp is too far in the future.", { now_ms, ts_ms });
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check whether a customer is currently entitled to record usage for a given metered price.
|
|
113
|
+
*
|
|
114
|
+
* Stripe docs:
|
|
115
|
+
* - List subscriptions: https://docs.stripe.com/api/subscriptions/list
|
|
116
|
+
* - Expand: https://docs.stripe.com/expand
|
|
117
|
+
*/
|
|
118
|
+
async function assert_customer_entitled_for_meter_price(client, server, opts) {
|
|
119
|
+
// List the subscribed meters.
|
|
120
|
+
const active_meters = await list_subscribed_meters(client, server, {
|
|
121
|
+
uid: opts.uid,
|
|
122
|
+
stripe_customer_id: opts.stripe_customer_id,
|
|
123
|
+
all_products: opts.all_products,
|
|
124
|
+
});
|
|
125
|
+
// If not entitled, this should usually be user-visible (they are not subscribed),
|
|
126
|
+
// but be careful: this function can also be called internally.
|
|
127
|
+
if (!active_meters[opts.meter_product.id]) {
|
|
128
|
+
throw new ExternalStripeError("subscription_not_active", "You must be subscribed to use this metered feature.", { uid: opts.uid, stripe_customer_id: opts.stripe_customer_id, meter_product: opts.meter_product.id });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Resolve configured payload keys for a meter product, using Stripe's defaults.
|
|
133
|
+
*
|
|
134
|
+
* These defaults must match the meter creation defaults in products.ts:
|
|
135
|
+
* - customer_mapping.event_payload_key defaults to "stripe_customer_id"
|
|
136
|
+
* - value_settings.event_payload_key defaults to "value"
|
|
137
|
+
* @see https://docs.stripe.com/api/billing/meter/create
|
|
138
|
+
*/
|
|
139
|
+
function resolve_meter_payload_keys(product) {
|
|
140
|
+
const customer_key = product.customer_mapping_event_payload_key ?? "stripe_customer_id";
|
|
141
|
+
const value_key = product.value_settings_event_payload_key ?? "value";
|
|
142
|
+
assert(customer_key.trim().length > 0, "invalid_product", "Meter customer payload key must be non-empty.", {
|
|
143
|
+
product_id: product.id,
|
|
144
|
+
customer_key,
|
|
145
|
+
});
|
|
146
|
+
assert(value_key.trim().length > 0, "invalid_product", "Meter value payload key must be non-empty.", {
|
|
147
|
+
product_id: product.id,
|
|
148
|
+
value_key,
|
|
149
|
+
});
|
|
150
|
+
// Stripe API docs specify max length 100 for these keys.
|
|
151
|
+
// @see https://docs.stripe.com/api/billing/meter/create
|
|
152
|
+
assert(customer_key.length <= 100, "invalid_product", "Meter customer payload key must be <= 100 characters.", {
|
|
153
|
+
product_id: product.id,
|
|
154
|
+
customer_key_length: customer_key.length,
|
|
155
|
+
});
|
|
156
|
+
assert(value_key.length <= 100, "invalid_product", "Meter value payload key must be <= 100 characters.", {
|
|
157
|
+
product_id: product.id,
|
|
158
|
+
value_key_length: value_key.length,
|
|
159
|
+
});
|
|
160
|
+
return { customer_key, value_key };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Record usage for a metered subscription by creating a Stripe Billing Meter Event.
|
|
164
|
+
*
|
|
165
|
+
* Security & correctness guarantees:
|
|
166
|
+
* - Requires that the user has an active-ish subscription containing the meter product's price id.
|
|
167
|
+
* - Uses the meter's configured payload keys for customer/value mapping.
|
|
168
|
+
* - Allows caller-provided `identifier` to dedupe retries.
|
|
169
|
+
*
|
|
170
|
+
* Stripe docs:
|
|
171
|
+
* - Create meter event: https://docs.stripe.com/api/billing/meter-event/create
|
|
172
|
+
* - Record usage guide: https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage-api
|
|
173
|
+
*
|
|
174
|
+
* @throws {InternalStripeError} When round mode is `exact` and the amount has more precision than supported.
|
|
175
|
+
* @throws {InternalStripeError} On internal errors.
|
|
176
|
+
* @throws {ExternalStripeError} On external errors such as the customer not being entitled to record usage for the meter product.
|
|
177
|
+
*/
|
|
178
|
+
export async function record_meter_usage(client, server, all_products, opts) {
|
|
179
|
+
// -------------------------------------------------------------------------
|
|
180
|
+
// Validate inputs.
|
|
181
|
+
public_assert(is_non_empty_string(opts.uid), "invalid_argument", "Property 'uid' must be a non-empty string.");
|
|
182
|
+
assert(opts.product.type === "meter", "invalid_argument", "Property 'product' must be a meter product.", {
|
|
183
|
+
product_type: opts.product.type,
|
|
184
|
+
});
|
|
185
|
+
// Validate event name (Stripe limit 100).
|
|
186
|
+
// @see https://docs.stripe.com/api/billing/meter-event/create
|
|
187
|
+
assert(is_non_empty_string(opts.product.meter_event_name) && opts.product.meter_event_name.length <= 100, "invalid_product", "Meter product meter_event_name is invalid.", { product_id: opts.product.id, meter_event_name: opts.product.meter_event_name });
|
|
188
|
+
// Determine the value to send to Stripe.
|
|
189
|
+
let value_str;
|
|
190
|
+
const meter_kind = opts.product.kind ?? "units";
|
|
191
|
+
if (meter_kind === "money") {
|
|
192
|
+
assert("amount" in opts, "invalid_argument", "Property 'amount' must be provided for money meters.", {
|
|
193
|
+
product_id: opts.product.id,
|
|
194
|
+
});
|
|
195
|
+
const rounding = opts.round ?? "exact";
|
|
196
|
+
const amount_str = normalize_amount_to_string(opts.amount);
|
|
197
|
+
value_str = money_major_to_pico_cents_units(amount_str, rounding);
|
|
198
|
+
// Keep legacy >=0 behavior (0 is allowed); Stripe may effectively ignore it depending on config.
|
|
199
|
+
// If you want to enforce positive-only, change this to > 0.
|
|
200
|
+
assert(BigInt(value_str) >= 0n, "invalid_argument", "Property 'amount' must be >= 0.", {
|
|
201
|
+
amount: amount_str,
|
|
202
|
+
value_str,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else if (meter_kind === "units") {
|
|
206
|
+
assert("value" in opts, "invalid_argument", "Property 'value' must be provided for unit meters.", {
|
|
207
|
+
product_id: opts.product.id,
|
|
208
|
+
});
|
|
209
|
+
// Validate value. We require a finite non-negative integer.
|
|
210
|
+
assert(Number.isFinite(opts.value), "invalid_argument", "Property 'value' must be a finite number.", { value: opts.value });
|
|
211
|
+
assert(opts.value >= 0, "invalid_argument", "Property 'value' must be >= 0.", { value: opts.value });
|
|
212
|
+
assert(Number.isInteger(opts.value), "invalid_argument", "Property 'value' must be an integer.", { value: opts.value });
|
|
213
|
+
value_str = `${opts.value}`;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// @ts-expect-error exhaustive
|
|
217
|
+
meter_kind.toString();
|
|
218
|
+
throw new InternalStripeError("invalid_product", `Invalid MeterProduct kind: ${meter_kind}`, {
|
|
219
|
+
product_id: opts.product.id,
|
|
220
|
+
meter_kind,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
// Determine identifier (dedupe) and validate.
|
|
224
|
+
const identifier = opts.identifier;
|
|
225
|
+
validate_meter_event_identifier(identifier);
|
|
226
|
+
// Timestamp validation (if provided).
|
|
227
|
+
const now = new Date();
|
|
228
|
+
const timestamp_seconds = opts.timestamp ? to_unix_seconds(opts.timestamp) : null;
|
|
229
|
+
if (opts.timestamp) {
|
|
230
|
+
validate_meter_event_timestamp(now, opts.timestamp);
|
|
231
|
+
}
|
|
232
|
+
// Resolve Stripe customer.
|
|
233
|
+
const stripe_customer_id = await ensure_stripe_customer(client, server, opts.uid);
|
|
234
|
+
// Enforce entitlement: only record usage for subscribed users.
|
|
235
|
+
await assert_customer_entitled_for_meter_price(client, server, {
|
|
236
|
+
uid: opts.uid,
|
|
237
|
+
meter_product: opts.product,
|
|
238
|
+
stripe_customer_id,
|
|
239
|
+
all_products: all_products,
|
|
240
|
+
});
|
|
241
|
+
// Resolve meter payload keys (must match the meter configuration).
|
|
242
|
+
const { customer_key, value_key } = resolve_meter_payload_keys(opts.product);
|
|
243
|
+
// -------------------------------------------------------------------------
|
|
244
|
+
// Build payload.
|
|
245
|
+
// Stripe expects payload values as strings in many examples; we send a stringified numeric value.
|
|
246
|
+
// @see https://docs.stripe.com/api/billing/meter-event/create
|
|
247
|
+
const payload = {
|
|
248
|
+
[customer_key]: stripe_customer_id,
|
|
249
|
+
[value_key]: value_str,
|
|
250
|
+
};
|
|
251
|
+
// -------------------------------------------------------------------------
|
|
252
|
+
// Create meter event.
|
|
253
|
+
// Stripe docs: https://docs.stripe.com/api/billing/meter-event/create
|
|
254
|
+
const meter_event = await stripe_api_call(() => client.billing.meterEvents.create({
|
|
255
|
+
event_name: opts.product.meter_event_name,
|
|
256
|
+
payload,
|
|
257
|
+
identifier,
|
|
258
|
+
...(timestamp_seconds !== null ? { timestamp: timestamp_seconds } : {}),
|
|
259
|
+
},
|
|
260
|
+
// Idempotency at the HTTP layer in addition to Stripe's identifier dedupe helps during transient retries.
|
|
261
|
+
{ idempotencyKey: stable_idempotency_key(`meter_event_create_${identifier}`, 255) }), {
|
|
262
|
+
operation: "billing.meterEvents.create",
|
|
263
|
+
uid: opts.uid,
|
|
264
|
+
stripe_customer_id,
|
|
265
|
+
stripe_price_id: opts.product.stripe_price_id,
|
|
266
|
+
meter_event_name: opts.product.meter_event_name,
|
|
267
|
+
identifier,
|
|
268
|
+
timestamp_seconds,
|
|
269
|
+
});
|
|
270
|
+
// We only expose minimal safe fields.
|
|
271
|
+
return {
|
|
272
|
+
meter_event_identifier: meter_event.identifier,
|
|
273
|
+
event_name: meter_event.event_name,
|
|
274
|
+
timestamp: meter_event.timestamp,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Cancel a previously recorded meter event by identifier (best-effort within 24 hours).
|
|
279
|
+
*
|
|
280
|
+
* This is useful for:
|
|
281
|
+
* - reverting accidental double-reporting
|
|
282
|
+
* - compensating failed internal workflows
|
|
283
|
+
*
|
|
284
|
+
* Stripe docs:
|
|
285
|
+
* - Create meter event adjustment: https://docs.stripe.com/api/billing/meter-event-adjustment/create
|
|
286
|
+
*/
|
|
287
|
+
export async function cancel_meter_usage_event(client, server, all_products, opts) {
|
|
288
|
+
public_assert(opts.product.type === "meter", "invalid_argument", "Property 'product' must be a meter product.", {
|
|
289
|
+
product_type: opts.product.type,
|
|
290
|
+
});
|
|
291
|
+
public_assert(is_non_empty_string(opts.uid), "invalid_argument", "Property 'uid' must be a non-empty string.");
|
|
292
|
+
public_assert(is_non_empty_string(opts.meter_event_identifier), "invalid_argument", "Property 'identifier' must be a non-empty string.");
|
|
293
|
+
validate_meter_event_identifier(opts.meter_event_identifier);
|
|
294
|
+
// Resolve Stripe customer and enforce entitlement before canceling usage.
|
|
295
|
+
const stripe_customer_id = await ensure_stripe_customer(client, server, opts.uid);
|
|
296
|
+
await assert_customer_entitled_for_meter_price(client, server, {
|
|
297
|
+
uid: opts.uid,
|
|
298
|
+
meter_product: opts.product,
|
|
299
|
+
stripe_customer_id,
|
|
300
|
+
all_products: all_products,
|
|
301
|
+
});
|
|
302
|
+
// Stripe docs: https://docs.stripe.com/api/billing/meter-event-adjustment/create
|
|
303
|
+
const adjustment = await stripe_api_call(() => client.billing.meterEventAdjustments.create({
|
|
304
|
+
event_name: opts.product.meter_event_name,
|
|
305
|
+
type: "cancel",
|
|
306
|
+
cancel: { identifier: opts.meter_event_identifier },
|
|
307
|
+
}, { idempotencyKey: stable_idempotency_key(`meter_event_cancel_${opts.meter_event_identifier}`, 255) }), {
|
|
308
|
+
operation: "billing.meterEventAdjustments.create",
|
|
309
|
+
meter_event_name: opts.product.meter_event_name,
|
|
310
|
+
identifier: opts.meter_event_identifier,
|
|
311
|
+
});
|
|
312
|
+
// The adjustment status is typically "pending" initially.
|
|
313
|
+
// We keep the response minimal and safe.
|
|
314
|
+
return {
|
|
315
|
+
meter_event_identifier: opts.meter_event_identifier,
|
|
316
|
+
status: adjustment.status,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Daan van den Bergh
|
|
3
|
+
* @copyright © 2026 - 2026 Daan van den Bergh. All rights reserved
|
|
4
|
+
*/
|
|
5
|
+
import Stripe from "stripe";
|
|
6
|
+
import { Server } from "../../server.js";
|
|
7
|
+
/**
|
|
8
|
+
* Create a Stripe SetupIntent so the client can add a payment method and prepare it for off-session billing.
|
|
9
|
+
*
|
|
10
|
+
* Client flow:
|
|
11
|
+
* - Call this endpoint to get `client_secret`.
|
|
12
|
+
* - Confirm SetupIntent on the client (e.g. Stripe.js / mobile SDK).
|
|
13
|
+
* - Call `finalize_payment_method_setup` with the returned `setup_intent_id`.
|
|
14
|
+
*
|
|
15
|
+
* Stripe docs:
|
|
16
|
+
* - SetupIntents overview: https://docs.stripe.com/payments/setup-intents
|
|
17
|
+
* - Create SetupIntent: https://docs.stripe.com/api/setup_intents/create
|
|
18
|
+
*/
|
|
19
|
+
export declare function create_payment_method_setup_intent(client: Stripe, server: Server, opts: {
|
|
20
|
+
/** The internal user id, used to resolve/ensure Stripe customer. */
|
|
21
|
+
uid: string;
|
|
22
|
+
/** An optional idempotency key. */
|
|
23
|
+
idempotency_key?: string;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
/** The SetupIntent id. */
|
|
26
|
+
id: string;
|
|
27
|
+
/** The client secret used by the client to confirm the SetupIntent. */
|
|
28
|
+
client_secret: string;
|
|
29
|
+
/** The Stripe customer id. */
|
|
30
|
+
stripe_customer_id: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Finalize a confirmed SetupIntent by setting its payment method as the customer's default for invoices/subscriptions.
|
|
34
|
+
*
|
|
35
|
+
* This ensures future subscription invoices can be charged automatically.
|
|
36
|
+
*
|
|
37
|
+
* Stripe docs:
|
|
38
|
+
* - Retrieve SetupIntent: https://docs.stripe.com/api/setup_intents/retrieve
|
|
39
|
+
* - Update customer invoice_settings.default_payment_method: https://docs.stripe.com/api/customers/update
|
|
40
|
+
*/
|
|
41
|
+
export declare function finalize_payment_method_setup(client: Stripe, server: Server, opts: {
|
|
42
|
+
/** The internal user id, used to resolve/ensure Stripe customer. */
|
|
43
|
+
uid: string;
|
|
44
|
+
/**
|
|
45
|
+
* The SetupIntent id after client confirmation.
|
|
46
|
+
* The client should send this to the backend once confirmation succeeded.
|
|
47
|
+
*/
|
|
48
|
+
setup_intent_id: string;
|
|
49
|
+
/** Optional idempotency key. */
|
|
50
|
+
idempotency_key?: string;
|
|
51
|
+
}): Promise<{
|
|
52
|
+
/** The Stripe customer id. */
|
|
53
|
+
stripe_customer_id: string;
|
|
54
|
+
/** The payment method id that is now set as default. */
|
|
55
|
+
payment_method_id: string;
|
|
56
|
+
/** The SetupIntent id used to finalize. */
|
|
57
|
+
setup_intent_id: string;
|
|
58
|
+
}>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Daan van den Bergh
|
|
3
|
+
* @copyright © 2026 - 2026 Daan van den Bergh. All rights reserved
|
|
4
|
+
*/
|
|
5
|
+
import { ensure_stripe_customer } from "./customers.js";
|
|
6
|
+
import { ExternalStripeError, InternalStripeError } from "./error.js";
|
|
7
|
+
import { assert, public_assert, stripe_api_call, is_non_empty_string, stable_idempotency_key } from "./utils.js";
|
|
8
|
+
// -------------------------------------------------------------------------------------------------
|
|
9
|
+
// Internal helpers.
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a payment method id from a SetupIntent safely.
|
|
12
|
+
*/
|
|
13
|
+
function resolve_payment_method_id_from_setup_intent(setup_intent) {
|
|
14
|
+
const payment_method = setup_intent.payment_method;
|
|
15
|
+
// SetupIntent.payment_method is string | PaymentMethod | null.
|
|
16
|
+
if (!payment_method) {
|
|
17
|
+
throw new ExternalStripeError("payment_method_missing", "No payment method was provided. Please try again.", { setup_intent_id: setup_intent.id, status: setup_intent.status });
|
|
18
|
+
}
|
|
19
|
+
if (typeof payment_method === "string") {
|
|
20
|
+
return payment_method;
|
|
21
|
+
}
|
|
22
|
+
// If expanded, it is a PaymentMethod object with an id.
|
|
23
|
+
const id = payment_method.id;
|
|
24
|
+
if (!is_non_empty_string(id)) {
|
|
25
|
+
throw new ExternalStripeError("payment_method_missing", "No payment method was provided. Please try again.", { setup_intent_id: setup_intent.id, status: setup_intent.status });
|
|
26
|
+
}
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ensure a SetupIntent belongs to the expected customer.
|
|
31
|
+
*/
|
|
32
|
+
function assert_setup_intent_belongs_to_customer(opts) {
|
|
33
|
+
const { setup_intent, expected_customer_id, uid } = opts;
|
|
34
|
+
// SetupIntent.customer is string | Customer | null.
|
|
35
|
+
const setup_intent_customer = setup_intent.customer;
|
|
36
|
+
// If missing, the intent is not usable for our flow.
|
|
37
|
+
public_assert(setup_intent_customer !== null, "invalid_argument", "Setup intent is missing a customer association.", { uid, setup_intent_id: setup_intent.id });
|
|
38
|
+
const setup_customer_id = typeof setup_intent_customer === "string" ? setup_intent_customer : setup_intent_customer.id;
|
|
39
|
+
// Security: prevent a user from finalizing an intent that belongs to someone else.
|
|
40
|
+
public_assert(setup_customer_id === expected_customer_id, "invalid_argument", "Setup intent does not belong to this customer.", { uid, setup_intent_id: setup_intent.id, expected_customer_id, setup_customer_id });
|
|
41
|
+
}
|
|
42
|
+
// -------------------------------------------------------------------------------------------------
|
|
43
|
+
// Public API.
|
|
44
|
+
/**
|
|
45
|
+
* Create a Stripe SetupIntent so the client can add a payment method and prepare it for off-session billing.
|
|
46
|
+
*
|
|
47
|
+
* Client flow:
|
|
48
|
+
* - Call this endpoint to get `client_secret`.
|
|
49
|
+
* - Confirm SetupIntent on the client (e.g. Stripe.js / mobile SDK).
|
|
50
|
+
* - Call `finalize_payment_method_setup` with the returned `setup_intent_id`.
|
|
51
|
+
*
|
|
52
|
+
* Stripe docs:
|
|
53
|
+
* - SetupIntents overview: https://docs.stripe.com/payments/setup-intents
|
|
54
|
+
* - Create SetupIntent: https://docs.stripe.com/api/setup_intents/create
|
|
55
|
+
*/
|
|
56
|
+
export async function create_payment_method_setup_intent(client, server, opts) {
|
|
57
|
+
public_assert(is_non_empty_string(opts.uid), "invalid_argument", "Property 'uid' must be a non-empty string.");
|
|
58
|
+
// Ensure a Stripe customer exists for this user.
|
|
59
|
+
const stripe_customer_id = await ensure_stripe_customer(client, server, opts.uid);
|
|
60
|
+
// Create a SetupIntent for off-session usage so the resulting payment method can be used for subscriptions/invoices.
|
|
61
|
+
// Stripe docs: https://docs.stripe.com/api/setup_intents/create
|
|
62
|
+
let setup_intent;
|
|
63
|
+
try {
|
|
64
|
+
setup_intent = await stripe_api_call(() => client.setupIntents.create({
|
|
65
|
+
customer: stripe_customer_id,
|
|
66
|
+
// off_session indicates we plan to charge when the customer is not actively in-session.
|
|
67
|
+
usage: "off_session",
|
|
68
|
+
}, {
|
|
69
|
+
idempotencyKey: opts.idempotency_key,
|
|
70
|
+
}), { operation: "setupIntents.create", uid: opts.uid, stripe_customer_id });
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw new InternalStripeError("api_error", "Failed to create a payment method setup intent.", { uid: opts.uid, stripe_customer_id }, error);
|
|
74
|
+
}
|
|
75
|
+
const client_secret = setup_intent.client_secret;
|
|
76
|
+
// SetupIntents should always return a client_secret for confirmation.
|
|
77
|
+
assert(is_non_empty_string(client_secret), "api_error", "Stripe did not return a SetupIntent client_secret.", { uid: opts.uid, stripe_customer_id, setup_intent_id: setup_intent.id });
|
|
78
|
+
return {
|
|
79
|
+
id: setup_intent.id,
|
|
80
|
+
client_secret,
|
|
81
|
+
stripe_customer_id,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Finalize a confirmed SetupIntent by setting its payment method as the customer's default for invoices/subscriptions.
|
|
86
|
+
*
|
|
87
|
+
* This ensures future subscription invoices can be charged automatically.
|
|
88
|
+
*
|
|
89
|
+
* Stripe docs:
|
|
90
|
+
* - Retrieve SetupIntent: https://docs.stripe.com/api/setup_intents/retrieve
|
|
91
|
+
* - Update customer invoice_settings.default_payment_method: https://docs.stripe.com/api/customers/update
|
|
92
|
+
*/
|
|
93
|
+
export async function finalize_payment_method_setup(client, server, opts) {
|
|
94
|
+
public_assert(is_non_empty_string(opts.uid), "invalid_argument", "Property 'uid' must be a non-empty string.");
|
|
95
|
+
public_assert(is_non_empty_string(opts.setup_intent_id), "invalid_argument", "Property 'setup_intent_id' must be a non-empty string.");
|
|
96
|
+
// Always derive the customer from uid on the server.
|
|
97
|
+
const stripe_customer_id = await ensure_stripe_customer(client, server, opts.uid);
|
|
98
|
+
// Retrieve the SetupIntent (expand payment_method to avoid extra round-trips if needed).
|
|
99
|
+
// Stripe docs: https://docs.stripe.com/api/setup_intents/retrieve
|
|
100
|
+
const setup_intent = await stripe_api_call(() => client.setupIntents.retrieve(opts.setup_intent_id, {
|
|
101
|
+
expand: ["payment_method"],
|
|
102
|
+
}), { operation: "setupIntents.retrieve", uid: opts.uid, setup_intent_id: opts.setup_intent_id });
|
|
103
|
+
// Security: ensure this SetupIntent is for the expected customer.
|
|
104
|
+
assert_setup_intent_belongs_to_customer({
|
|
105
|
+
setup_intent,
|
|
106
|
+
expected_customer_id: stripe_customer_id,
|
|
107
|
+
uid: opts.uid,
|
|
108
|
+
});
|
|
109
|
+
// The SetupIntent must be succeeded before we can safely set defaults.
|
|
110
|
+
// SetupIntent statuses: https://docs.stripe.com/api/setup_intents/object#setup_intent_object-status
|
|
111
|
+
public_assert(setup_intent.status === "succeeded", "invalid_argument", "Payment method setup is not complete. Please finish adding your payment method.", { uid: opts.uid, setup_intent_id: setup_intent.id, status: setup_intent.status });
|
|
112
|
+
// Extract the payment method id (string or expanded object).
|
|
113
|
+
const payment_method_id = resolve_payment_method_id_from_setup_intent(setup_intent);
|
|
114
|
+
// Set as default payment method for invoices/subscriptions.
|
|
115
|
+
// Stripe docs: https://docs.stripe.com/api/customers/update
|
|
116
|
+
await stripe_api_call(() => client.customers.update(stripe_customer_id, {
|
|
117
|
+
invoice_settings: {
|
|
118
|
+
default_payment_method: payment_method_id,
|
|
119
|
+
},
|
|
120
|
+
}, {
|
|
121
|
+
idempotencyKey: opts.idempotency_key ?? stable_idempotency_key(`finalize_payment_method_setup:${opts.uid}:${setup_intent.id}`),
|
|
122
|
+
}), {
|
|
123
|
+
operation: "customers.update",
|
|
124
|
+
uid: opts.uid,
|
|
125
|
+
stripe_customer_id: stripe_customer_id,
|
|
126
|
+
setup_intent_id: setup_intent.id,
|
|
127
|
+
payment_method_id,
|
|
128
|
+
action: "set_default_payment_method",
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
stripe_customer_id: stripe_customer_id,
|
|
132
|
+
payment_method_id,
|
|
133
|
+
setup_intent_id: setup_intent.id,
|
|
134
|
+
};
|
|
135
|
+
}
|