@vandenberghinc/volt 1.2.6 → 1.2.8
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/.libris/config.json +82 -0
- 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/backend/old/file_watcher.ts +359 -0
- package/backend/old/request.deprc.js +626 -0
- package/backend/old/response.deprc.js +354 -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/frontend/examples/theme/theme.ts +58 -0
- package/frontend/tools/bundle_d_ts.js +71 -0
- package/frontend/tools/convert_to_jsdoc_input.txt +9452 -0
- package/frontend/tools/convert_to_jsdoc_output.txt +7626 -0
- package/frontend/tools/convert_to_jsdoc_tmp.js +345 -0
- package/frontend/tools/scan_mixed_imports.js +69 -0
- package/package.json +1 -5
|
@@ -0,0 +1,1710 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var stdin_exports = {};
|
|
29
|
+
__export(stdin_exports, {
|
|
30
|
+
Server: () => Server
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(stdin_exports);
|
|
33
|
+
var import_url = require("url");
|
|
34
|
+
var path = __toESM(require("path"));
|
|
35
|
+
var http = __toESM(require("http"));
|
|
36
|
+
var http2 = __toESM(require("http2"));
|
|
37
|
+
var crypto = __toESM(require("crypto"));
|
|
38
|
+
var import_cluster = __toESM(require("cluster"));
|
|
39
|
+
var os = __toESM(require("os"));
|
|
40
|
+
var vlib = __toESM(require("@vandenberghinc/vlib"));
|
|
41
|
+
var import_utils = require("./utils.js");
|
|
42
|
+
var import_meta2 = require("./meta.js");
|
|
43
|
+
var import_mail = require("./plugins/mail/mail.js");
|
|
44
|
+
var import_status = require("./status.js");
|
|
45
|
+
var import_endpoint = require("./endpoint.js");
|
|
46
|
+
var import_image_endpoint = require("./image_endpoint.js");
|
|
47
|
+
var import_stream = require("./stream.js");
|
|
48
|
+
var import_database = require("./database/database.js");
|
|
49
|
+
var import_users = require("./users.js");
|
|
50
|
+
var import_rate_limit = require("./rate_limit.js");
|
|
51
|
+
var import_route = require("./route.js");
|
|
52
|
+
var import_internal_external = require("./errors/internal_external.js");
|
|
53
|
+
var import_stripe = require("./payments/stripe/stripe.js");
|
|
54
|
+
var import_frontend = __toESM(require("./frontend.js"));
|
|
55
|
+
const import_meta = {};
|
|
56
|
+
const __filename = (0, import_url.fileURLToPath)(import_meta.url);
|
|
57
|
+
const __dirname = path.dirname(__filename);
|
|
58
|
+
const { debug } = vlib;
|
|
59
|
+
class Server {
|
|
60
|
+
// ---------------------------------------------------------
|
|
61
|
+
// Static attributes.
|
|
62
|
+
// ---------------------------------------------------------
|
|
63
|
+
/**
|
|
64
|
+
* A temporary directory which holds the cached endpoint data.
|
|
65
|
+
* For instance if we bundle JS then we save it to file and serve it from the file,
|
|
66
|
+
* similar for transformed image endpoints.
|
|
67
|
+
*
|
|
68
|
+
* Note that upon each server start, we should clear this cache and remove all files inside this dir.
|
|
69
|
+
*/
|
|
70
|
+
endpoint_cache_dir;
|
|
71
|
+
// ---------------------------------------------------------
|
|
72
|
+
// Attributes.
|
|
73
|
+
// ---------------------------------------------------------
|
|
74
|
+
/** The binded ip address. */
|
|
75
|
+
ip;
|
|
76
|
+
/** The binded http port. */
|
|
77
|
+
port;
|
|
78
|
+
/** The binded https port. */
|
|
79
|
+
https_port;
|
|
80
|
+
/** The raw domain. */
|
|
81
|
+
domain;
|
|
82
|
+
/** The full domain name with http/https depending if tls is enabled. */
|
|
83
|
+
full_domain;
|
|
84
|
+
/** The persistent storage source directory. */
|
|
85
|
+
source;
|
|
86
|
+
/** Is the primary thread. */
|
|
87
|
+
is_primary;
|
|
88
|
+
/** Is in production mode. */
|
|
89
|
+
production;
|
|
90
|
+
/** The company information. */
|
|
91
|
+
company;
|
|
92
|
+
/** The default meta information. */
|
|
93
|
+
meta;
|
|
94
|
+
/** Is running in offline mode. */
|
|
95
|
+
offline;
|
|
96
|
+
/** The database instance. */
|
|
97
|
+
db;
|
|
98
|
+
/** The rate limit instance. */
|
|
99
|
+
rate_limit;
|
|
100
|
+
/** The added endpoints. */
|
|
101
|
+
endpoints = /* @__PURE__ */ new Map();
|
|
102
|
+
/** The added error endpoints. */
|
|
103
|
+
err_endpoints = /* @__PURE__ */ new Map();
|
|
104
|
+
/** A record of keys used for hashing. */
|
|
105
|
+
keys = {};
|
|
106
|
+
/** Alias for the `Status` module. */
|
|
107
|
+
status;
|
|
108
|
+
/** Alias for the `RateLimits` module. */
|
|
109
|
+
rate_limits;
|
|
110
|
+
/** The file logger. */
|
|
111
|
+
log;
|
|
112
|
+
/** The users instance. */
|
|
113
|
+
users;
|
|
114
|
+
/** The payments instance. */
|
|
115
|
+
payments;
|
|
116
|
+
/** Daemon instance to manage a live daemon. */
|
|
117
|
+
daemon;
|
|
118
|
+
/** The mail instance. */
|
|
119
|
+
mail;
|
|
120
|
+
// Public for internal use:
|
|
121
|
+
csp;
|
|
122
|
+
statics_aspect_ratios;
|
|
123
|
+
google_tag;
|
|
124
|
+
rate_limit_api_key;
|
|
125
|
+
performance;
|
|
126
|
+
https_enabled;
|
|
127
|
+
/** The events map @internal */
|
|
128
|
+
events = new vlib.Events({
|
|
129
|
+
single_events: ["2fa_mail"]
|
|
130
|
+
});
|
|
131
|
+
// Private.
|
|
132
|
+
favicon;
|
|
133
|
+
statics;
|
|
134
|
+
_user_keys_opts;
|
|
135
|
+
additional_sitemap_endpoints;
|
|
136
|
+
tls;
|
|
137
|
+
default_headers;
|
|
138
|
+
http;
|
|
139
|
+
https;
|
|
140
|
+
threading;
|
|
141
|
+
// Private ollections.
|
|
142
|
+
_keys_db;
|
|
143
|
+
_sys_keys_db;
|
|
144
|
+
_website_status_db;
|
|
145
|
+
/**
|
|
146
|
+
* Construct a new server instance.
|
|
147
|
+
* @docs
|
|
148
|
+
*/
|
|
149
|
+
constructor({
|
|
150
|
+
ip = "127.0.0.1",
|
|
151
|
+
port,
|
|
152
|
+
// leave undefined for blank detection.
|
|
153
|
+
domain,
|
|
154
|
+
is_primary = true,
|
|
155
|
+
source,
|
|
156
|
+
database,
|
|
157
|
+
statics = [],
|
|
158
|
+
favicon,
|
|
159
|
+
company,
|
|
160
|
+
meta = new import_meta2.Meta(),
|
|
161
|
+
tls,
|
|
162
|
+
mail,
|
|
163
|
+
rate_limit = {
|
|
164
|
+
server: {
|
|
165
|
+
ip: void 0,
|
|
166
|
+
port: import_rate_limit.RateLimitServer.default_port,
|
|
167
|
+
https: void 0
|
|
168
|
+
},
|
|
169
|
+
client: {
|
|
170
|
+
ip: void 0,
|
|
171
|
+
port: import_rate_limit.RateLimitServer.default_port,
|
|
172
|
+
url: void 0
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
keys = [],
|
|
176
|
+
payments,
|
|
177
|
+
default_headers,
|
|
178
|
+
google_tag = void 0,
|
|
179
|
+
users,
|
|
180
|
+
production = false,
|
|
181
|
+
threading = {
|
|
182
|
+
enabled: false,
|
|
183
|
+
threads: void 0
|
|
184
|
+
},
|
|
185
|
+
offline = false,
|
|
186
|
+
additional_sitemap_endpoints = [],
|
|
187
|
+
log_level = 0,
|
|
188
|
+
daemon = false
|
|
189
|
+
// admin = {
|
|
190
|
+
// password: null,
|
|
191
|
+
// ips: [],
|
|
192
|
+
// },
|
|
193
|
+
// ts = {
|
|
194
|
+
// compiler_opts: {},
|
|
195
|
+
// output: undefined,
|
|
196
|
+
// },
|
|
197
|
+
// browser_preview = undefined,
|
|
198
|
+
}) {
|
|
199
|
+
if (production || port == null) {
|
|
200
|
+
this.port = 80;
|
|
201
|
+
this.https_port = 443;
|
|
202
|
+
} else {
|
|
203
|
+
this.port = port;
|
|
204
|
+
this.https_port = port + 1;
|
|
205
|
+
}
|
|
206
|
+
this.ip = ip ?? "127.0.0.1";
|
|
207
|
+
this.is_primary = is_primary && import_cluster.default.isPrimary;
|
|
208
|
+
this.source = new vlib.Path(source);
|
|
209
|
+
this.favicon = favicon;
|
|
210
|
+
this.google_tag = google_tag;
|
|
211
|
+
this.production = production;
|
|
212
|
+
this.company = company;
|
|
213
|
+
this.offline = offline;
|
|
214
|
+
this._user_keys_opts = keys;
|
|
215
|
+
this.additional_sitemap_endpoints = additional_sitemap_endpoints;
|
|
216
|
+
this.tls = tls;
|
|
217
|
+
this.https_enabled = tls != null;
|
|
218
|
+
if (typeof threading === "boolean") {
|
|
219
|
+
this.threading = {
|
|
220
|
+
enabled: threading,
|
|
221
|
+
threads: os.cpus().length
|
|
222
|
+
};
|
|
223
|
+
} else {
|
|
224
|
+
this.threading = {
|
|
225
|
+
enabled: threading.enabled ?? true,
|
|
226
|
+
threads: threading.threads ?? os.cpus().length
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
this.status = import_status.Status;
|
|
230
|
+
this.rate_limits = import_rate_limit.RateLimits;
|
|
231
|
+
this.performance = new vlib.Performance("Server performance");
|
|
232
|
+
const log_source = this.source.join("logs");
|
|
233
|
+
if (!log_source.exists()) {
|
|
234
|
+
log_source.mkdir_sync({ recursive: true });
|
|
235
|
+
}
|
|
236
|
+
this.log = new vlib.logging.FileLogger({
|
|
237
|
+
level: log_level,
|
|
238
|
+
log_path: log_source.join("logs").str(),
|
|
239
|
+
error_path: log_source.join("errors").str()
|
|
240
|
+
});
|
|
241
|
+
if (!this.source.exists()) {
|
|
242
|
+
throw Error(`Source directory "${this.source.str()}" does not exist.`);
|
|
243
|
+
}
|
|
244
|
+
this.source = this.source.abs();
|
|
245
|
+
this.domain = domain.replace("https://", "").replace("http://", "");
|
|
246
|
+
while (this.domain.length > 0 && this.domain.charAt(this.domain.length - 1) === "/") {
|
|
247
|
+
this.domain = this.domain.substr(0, this.domain.length - 1);
|
|
248
|
+
}
|
|
249
|
+
this.full_domain = `http${this.tls ? "s" : ""}://${this.domain}`;
|
|
250
|
+
while (this.full_domain.endsWith("/")) {
|
|
251
|
+
this.full_domain = this.full_domain.slice(0, -1);
|
|
252
|
+
}
|
|
253
|
+
this.endpoint_cache_dir = new vlib.Path("/tmp/volt_server_endpoint_cache/" + this.hash(this.domain));
|
|
254
|
+
this.statics = statics;
|
|
255
|
+
this.statics_aspect_ratios = /* @__PURE__ */ new Map();
|
|
256
|
+
this.statics.push({
|
|
257
|
+
path: import_frontend.default.assets,
|
|
258
|
+
endpoint: "/volt/assets"
|
|
259
|
+
});
|
|
260
|
+
if (!(meta instanceof import_meta2.Meta)) {
|
|
261
|
+
meta = new import_meta2.Meta(meta);
|
|
262
|
+
}
|
|
263
|
+
if (favicon != null && meta.favicon == null) {
|
|
264
|
+
meta.favicon = this.full_domain + "/favicon.ico";
|
|
265
|
+
}
|
|
266
|
+
if (favicon != null && meta.image == null) {
|
|
267
|
+
meta.image = this.full_domain + "/favicon.ico";
|
|
268
|
+
} else if (meta.image != null && !meta.image.startsWith("http")) {
|
|
269
|
+
meta.image = this.full_domain + meta.image;
|
|
270
|
+
}
|
|
271
|
+
this.meta = meta;
|
|
272
|
+
const base_default_headers = {
|
|
273
|
+
// Cache correctness for CORS/preflight:
|
|
274
|
+
"Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
|
275
|
+
// Safer default than same-origin, still keeps useful referrers:
|
|
276
|
+
"Referrer-Policy": "strict-origin-when-cross-origin",
|
|
277
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
278
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
279
|
+
// Let browsers read our rate-limit hint:
|
|
280
|
+
"Access-Control-Expose-Headers": "X-RateLimit-Reset",
|
|
281
|
+
"X-Content-Type-Options": "nosniff",
|
|
282
|
+
"X-Frame-Options": "DENY",
|
|
283
|
+
// Helpful isolation defaults (safe for most apps):
|
|
284
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
285
|
+
"Cross-Origin-Resource-Policy": "same-site",
|
|
286
|
+
// If you need SharedArrayBuffer, add COEP below (can break some embeds):
|
|
287
|
+
// "Cross-Origin-Embedder-Policy": "require-corp",
|
|
288
|
+
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
|
|
289
|
+
// Lock down powerful APIs by default.
|
|
290
|
+
// If you need one on a third-party origin, add it beside (self).
|
|
291
|
+
"Permissions-Policy": "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), hid=(), serial=(), xr-spatial-tracking=(), display-capture=(), screen-wake-lock=(), sync-xhr=(), publickey-credentials-get=(self), encrypted-media=(self), autoplay=(self 'https://www.youtube-nocookie.com') fullscreen=(self 'https://www.youtube-nocookie.com'), browsing-topics=()"
|
|
292
|
+
// Do NOT set Allow-Origin / Credentials statically; set them per-request below.
|
|
293
|
+
// "X-XSS-Protection": "1; mode=block", // deprecated
|
|
294
|
+
};
|
|
295
|
+
const default_csp = {
|
|
296
|
+
"default-src": "'self'",
|
|
297
|
+
"base-uri": "'none'",
|
|
298
|
+
"object-src": "'none'",
|
|
299
|
+
"form-action": "'self'",
|
|
300
|
+
"frame-ancestors": "'none'",
|
|
301
|
+
// Keep GA images; drop explicit http:// to avoid mixed content.
|
|
302
|
+
"img-src": "'self' data: blob: https://*.google-analytics.com",
|
|
303
|
+
"script-src": "'self' https://ajax.googleapis.com https://www.googletagmanager.com https://*.google-analytics.com",
|
|
304
|
+
// Needed for GA/GTAG beacons/fetch:
|
|
305
|
+
"connect-src": "'self' https://*.google-analytics.com",
|
|
306
|
+
"style-src": "'self'",
|
|
307
|
+
"font-src": "'self' data:",
|
|
308
|
+
// Auto-upgrade stray http URLs where possible:
|
|
309
|
+
"upgrade-insecure-requests": ""
|
|
310
|
+
};
|
|
311
|
+
if (default_headers == null) {
|
|
312
|
+
this.csp = default_csp;
|
|
313
|
+
this.default_headers = { ...base_default_headers };
|
|
314
|
+
} else {
|
|
315
|
+
if (default_headers["Content-Security-Policy"] != null && typeof default_headers["Content-Security-Policy"] !== "object") {
|
|
316
|
+
throw Error(`The Content-Security-Policy of the default headers must be an object with values for each csp key, e.g. "{'script-src': '...'}".`);
|
|
317
|
+
}
|
|
318
|
+
this.csp = default_headers["Content-Security-Policy"] != null ? default_headers["Content-Security-Policy"] : default_csp;
|
|
319
|
+
Object.keys(base_default_headers).forEach((key) => {
|
|
320
|
+
if (default_headers[key] === void 0) {
|
|
321
|
+
default_headers[key] = base_default_headers[key];
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
this.default_headers = default_headers;
|
|
325
|
+
}
|
|
326
|
+
if (!this.tls) {
|
|
327
|
+
delete this.default_headers["Strict-Transport-Security"];
|
|
328
|
+
}
|
|
329
|
+
if (payments) {
|
|
330
|
+
if (payments.type === "stripe") {
|
|
331
|
+
this.payments = new import_stripe.Stripe(this, payments);
|
|
332
|
+
} else {
|
|
333
|
+
throw Error(`Invalid payment processor type "${payments.type}", valid types are ["paddle"].`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (daemon !== false) {
|
|
337
|
+
const log_source2 = this.source.join("daemon");
|
|
338
|
+
if (!log_source2.exists()) {
|
|
339
|
+
log_source2.mkdir_sync({ recursive: true });
|
|
340
|
+
}
|
|
341
|
+
this.daemon = new vlib.Daemon({
|
|
342
|
+
name: this.domain.replaceAll(".", ""),
|
|
343
|
+
logs: daemon.logs || log_source2.join("logs").str(),
|
|
344
|
+
errors: daemon.errors || log_source2.join("errors").str(),
|
|
345
|
+
...daemon
|
|
346
|
+
// user: (daemon as Record<string, any>).user || os.userInfo().username,
|
|
347
|
+
// group: (daemon as Record<string, any>).group || null,
|
|
348
|
+
// command: "volt --service --start",
|
|
349
|
+
// cwd: this.source.str(),
|
|
350
|
+
// args: (daemon as Record<string, any>).args || [],
|
|
351
|
+
// env: (daemon as Record<string, any>).env || {},
|
|
352
|
+
// description: (daemon as Record<string, any>).description || `Service daemon for website ${this.domain}.`,
|
|
353
|
+
// auto_restart: true,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
if (typeof database === "string") {
|
|
357
|
+
this.db = new import_database.Database({ uri: database, _server: this });
|
|
358
|
+
} else {
|
|
359
|
+
this.db = new import_database.Database({ ...database, _server: this });
|
|
360
|
+
}
|
|
361
|
+
this._keys_db = this.db.collection({
|
|
362
|
+
name: "Volt.Keys",
|
|
363
|
+
indexes: ["id"]
|
|
364
|
+
});
|
|
365
|
+
this._sys_keys_db = this.db.collection({
|
|
366
|
+
name: "Volt.SystemKeys",
|
|
367
|
+
indexes: ["id"]
|
|
368
|
+
});
|
|
369
|
+
this._website_status_db = this.db.collection({
|
|
370
|
+
name: "Volt.WebsiteStatus",
|
|
371
|
+
indexes: ["id"]
|
|
372
|
+
});
|
|
373
|
+
this.users = new import_users.Users({
|
|
374
|
+
support_recipient: mail?.smtp.sender,
|
|
375
|
+
// ensure we assign the support recipient, so we dont need to define `this.mail` beforehand.
|
|
376
|
+
...users,
|
|
377
|
+
// override support recipient if provided,
|
|
378
|
+
_server: this
|
|
379
|
+
});
|
|
380
|
+
if (mail) {
|
|
381
|
+
this.mail = new import_mail.Mail(mail);
|
|
382
|
+
}
|
|
383
|
+
if (rate_limit) {
|
|
384
|
+
if (this.is_primary) {
|
|
385
|
+
this.rate_limit = new import_rate_limit.RateLimitServer({ ...rate_limit.server ?? {}, _server: this });
|
|
386
|
+
} else {
|
|
387
|
+
if (rate_limit.server?.https) {
|
|
388
|
+
rate_limit.client.https = true;
|
|
389
|
+
}
|
|
390
|
+
this.rate_limit = new import_rate_limit.RateLimitClient({ ...rate_limit.client ?? {}, _server: this });
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// ---------------------------------------------------------
|
|
395
|
+
// Utils.
|
|
396
|
+
/** Get a content type (MIME) from a file extension. */
|
|
397
|
+
/**
|
|
398
|
+
* Get a content type (MIME) from a file extension. The file extension should include the leading dot, e.g. ".html".
|
|
399
|
+
* @docs
|
|
400
|
+
*/
|
|
401
|
+
get_content_type(extension) {
|
|
402
|
+
return import_utils.Utils.mime_type(extension) ?? "application/octet-stream";
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Set the logging verbosity level.
|
|
406
|
+
* @docs
|
|
407
|
+
*/
|
|
408
|
+
set_log_level(level) {
|
|
409
|
+
this.log.level.set(level);
|
|
410
|
+
}
|
|
411
|
+
// ---------------------------------------------------------
|
|
412
|
+
// Crypto (private).
|
|
413
|
+
/**
|
|
414
|
+
* Generate a cryptographically secure random key as a hex string.
|
|
415
|
+
* @docs
|
|
416
|
+
*/
|
|
417
|
+
generate_crypto_key(length = 32) {
|
|
418
|
+
return crypto.randomBytes(length).toString("hex");
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Create an HMAC hash using the provided key and data.
|
|
422
|
+
* @docs
|
|
423
|
+
*/
|
|
424
|
+
hmac(key, data, algo = "sha256") {
|
|
425
|
+
const hmac = crypto.createHmac(algo, key);
|
|
426
|
+
hmac.update(data);
|
|
427
|
+
return hmac.digest("hex");
|
|
428
|
+
}
|
|
429
|
+
// /** Create an HMAC hash using the server's master hash key. */
|
|
430
|
+
// hmac_with_master(data: string): string {
|
|
431
|
+
// if (!this._master_hash_key) {
|
|
432
|
+
// throw new Error("Hash key not initialized");
|
|
433
|
+
// }
|
|
434
|
+
// const hmac = crypto.createHmac("sha256", this._master_hash_key);
|
|
435
|
+
// hmac.update(data);
|
|
436
|
+
// return hmac.digest("hex");
|
|
437
|
+
// }
|
|
438
|
+
/**
|
|
439
|
+
* Create a hash (no key) of the given data using the specified algorithm.
|
|
440
|
+
* @docs
|
|
441
|
+
*/
|
|
442
|
+
hash(data, algo = "sha256") {
|
|
443
|
+
if (typeof data !== "string") {
|
|
444
|
+
data = JSON.stringify(data);
|
|
445
|
+
}
|
|
446
|
+
return crypto.createHash(algo).update(data).digest("hex");
|
|
447
|
+
}
|
|
448
|
+
// ---------------------------------------------------------
|
|
449
|
+
// Headers (private).
|
|
450
|
+
// Initialize the default headers.
|
|
451
|
+
_init_default_headers() {
|
|
452
|
+
let csp = [];
|
|
453
|
+
Object.entries(this.csp).forEach(([key, value]) => {
|
|
454
|
+
csp.push(key);
|
|
455
|
+
if (typeof value === "string" && value.length > 0) {
|
|
456
|
+
csp.push(" ");
|
|
457
|
+
csp.push(value);
|
|
458
|
+
}
|
|
459
|
+
csp.push(";");
|
|
460
|
+
});
|
|
461
|
+
this.default_headers["Content-Security-Policy"] = csp.join("");
|
|
462
|
+
}
|
|
463
|
+
// Add header defaults.
|
|
464
|
+
_set_header_defaults(stream) {
|
|
465
|
+
stream.set_headers(this.default_headers);
|
|
466
|
+
const origin = stream.headers.origin;
|
|
467
|
+
if (origin) {
|
|
468
|
+
const same_http = `http://${this.domain}`;
|
|
469
|
+
const same_https = `https://${this.domain}`;
|
|
470
|
+
if (origin === same_http || origin === same_https) {
|
|
471
|
+
stream.set_header("Access-Control-Allow-Origin", origin);
|
|
472
|
+
stream.set_header("Access-Control-Allow-Credentials", "true");
|
|
473
|
+
} else {
|
|
474
|
+
stream.set_header("Access-Control-Allow-Origin", "*");
|
|
475
|
+
}
|
|
476
|
+
const req_hdrs = stream.headers["access-control-request-headers"];
|
|
477
|
+
if (req_hdrs)
|
|
478
|
+
stream.set_header("Access-Control-Allow-Headers", String(req_hdrs));
|
|
479
|
+
const req_method = stream.headers["access-control-request-method"];
|
|
480
|
+
if (req_method)
|
|
481
|
+
stream.set_header("Access-Control-Allow-Methods", String(req_method));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
// ---------------------------------------------------------
|
|
485
|
+
// Endpoints (private).
|
|
486
|
+
// Create default endpoints.
|
|
487
|
+
_create_default_endpoints() {
|
|
488
|
+
if (this.favicon != null) {
|
|
489
|
+
const favicon = new vlib.Path(this.favicon);
|
|
490
|
+
if (favicon.exists() === false) {
|
|
491
|
+
throw Error(`Specified favicon path "${favicon}" does not exist.`);
|
|
492
|
+
}
|
|
493
|
+
this.endpoint({
|
|
494
|
+
method: "GET",
|
|
495
|
+
endpoint: "/favicon.ico",
|
|
496
|
+
data: favicon.load_sync({ type: "buffer" }),
|
|
497
|
+
content_type: this.get_content_type(favicon.extension()),
|
|
498
|
+
_is_static: true,
|
|
499
|
+
server: this
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
const status_dir = this.source.join(".status");
|
|
503
|
+
if (!status_dir.exists()) {
|
|
504
|
+
status_dir.mkdir_sync({ recursive: true });
|
|
505
|
+
}
|
|
506
|
+
const status_key_path = status_dir.join("key");
|
|
507
|
+
let status_key;
|
|
508
|
+
if (!status_key_path.exists()) {
|
|
509
|
+
status_key = this.generate_crypto_key(32);
|
|
510
|
+
status_key_path.save_sync(status_key);
|
|
511
|
+
} else {
|
|
512
|
+
status_key = status_key_path.load_sync();
|
|
513
|
+
}
|
|
514
|
+
this.endpoint({
|
|
515
|
+
method: "GET",
|
|
516
|
+
endpoint: "/.status",
|
|
517
|
+
content_type: "application/json",
|
|
518
|
+
params: {
|
|
519
|
+
key: "string"
|
|
520
|
+
},
|
|
521
|
+
callback: async (stream, params) => {
|
|
522
|
+
if (params.key !== status_key) {
|
|
523
|
+
return stream.send({
|
|
524
|
+
status: 403,
|
|
525
|
+
headers: { "Content-Type": "text/plain" },
|
|
526
|
+
data: "Access Denied"
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
const status = {};
|
|
530
|
+
status.ip = this.ip;
|
|
531
|
+
if (this.http) {
|
|
532
|
+
status.http_port = this.port;
|
|
533
|
+
}
|
|
534
|
+
if (this.https) {
|
|
535
|
+
status.https_port = this.https_port;
|
|
536
|
+
}
|
|
537
|
+
const data = await this._website_status_db.load({ id: "status" }, {
|
|
538
|
+
default: {
|
|
539
|
+
id: "status",
|
|
540
|
+
running_since: void 0,
|
|
541
|
+
running_threads: 0,
|
|
542
|
+
total_threads: 0
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
Object.assign(status, data);
|
|
546
|
+
return stream.send({
|
|
547
|
+
status: 200,
|
|
548
|
+
headers: { "Content-Type": "application/json" },
|
|
549
|
+
data: status
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
// Create the sitemap endpoint.
|
|
555
|
+
async _create_sitemap() {
|
|
556
|
+
this.log(2, "Creating sitemap.");
|
|
557
|
+
let sitemap = "";
|
|
558
|
+
sitemap += '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
559
|
+
sitemap += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
|
|
560
|
+
for (const endpoint of this.endpoints.values()) {
|
|
561
|
+
if (endpoint.allow_sitemap) {
|
|
562
|
+
if (endpoint.route.is_regex)
|
|
563
|
+
continue;
|
|
564
|
+
const ep = encodeURI(endpoint.route.endpoint_str.startsWith("/") ? endpoint.route.endpoint_str : `/${endpoint.route.endpoint_str}`);
|
|
565
|
+
sitemap += `<url>
|
|
566
|
+
<loc>${this.full_domain}${ep}</loc>
|
|
567
|
+
</url>
|
|
568
|
+
`;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
this.additional_sitemap_endpoints.forEach((endpoint) => {
|
|
572
|
+
while (endpoint.length > 0 && endpoint.charAt(0) === "/") {
|
|
573
|
+
endpoint = endpoint.substr(1);
|
|
574
|
+
}
|
|
575
|
+
sitemap += `<url>
|
|
576
|
+
<loc>${this.full_domain}/${endpoint}</loc>
|
|
577
|
+
</url>
|
|
578
|
+
`;
|
|
579
|
+
});
|
|
580
|
+
sitemap += "</urlset>\n";
|
|
581
|
+
this.endpoint({
|
|
582
|
+
method: "GET",
|
|
583
|
+
endpoint: "/sitemap.xml",
|
|
584
|
+
data: sitemap,
|
|
585
|
+
content_type: "application/xml",
|
|
586
|
+
_compress: false
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
// Create the robots.txt endpoint.
|
|
590
|
+
async _create_robots_txt() {
|
|
591
|
+
this.log(2, "Creating robots.txt.");
|
|
592
|
+
let robots = "User-agent: *\n";
|
|
593
|
+
let disallowed = 0;
|
|
594
|
+
for (const endpoint of this.endpoints.values()) {
|
|
595
|
+
if (!endpoint.allow_robots) {
|
|
596
|
+
robots += `Disallow: ${endpoint.route.endpoint_str}
|
|
597
|
+
`;
|
|
598
|
+
disallowed++;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (disallowed === 0) {
|
|
602
|
+
robots += `Disallow:
|
|
603
|
+
`;
|
|
604
|
+
}
|
|
605
|
+
robots += `
|
|
606
|
+
Sitemap: ${this.full_domain}/sitemap.xml`;
|
|
607
|
+
this.endpoint({
|
|
608
|
+
method: "GET",
|
|
609
|
+
endpoint: "/robots.txt",
|
|
610
|
+
content_type: "text/plain",
|
|
611
|
+
data: robots,
|
|
612
|
+
_compress: false
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
// Create admin endpoint.
|
|
616
|
+
// @deprecated use MongoDB Atlas instead!
|
|
617
|
+
/* private _create_admin_endpoint(): void {
|
|
618
|
+
|
|
619
|
+
// Logs.
|
|
620
|
+
this.log(2, "Creating admin endpoint.");
|
|
621
|
+
|
|
622
|
+
// Add admin tokens.
|
|
623
|
+
this.admin.tokens = [];
|
|
624
|
+
|
|
625
|
+
// Verify token.
|
|
626
|
+
const verify_token = (token: string): boolean => {
|
|
627
|
+
const now = Date.now();
|
|
628
|
+
let new_tokens: Array<{token: string, expiration: number}> = [];
|
|
629
|
+
let verified = false;
|
|
630
|
+
this.admin.tokens!.forEach((i) => {
|
|
631
|
+
if (now < i.expiration) {
|
|
632
|
+
if (i.token === token) {
|
|
633
|
+
verified = true;
|
|
634
|
+
}
|
|
635
|
+
new_tokens.push(i);
|
|
636
|
+
}
|
|
637
|
+
})
|
|
638
|
+
this.admin.tokens = new_tokens;
|
|
639
|
+
return verified;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Admin data.
|
|
643
|
+
this.endpoint({
|
|
644
|
+
method: "POST",
|
|
645
|
+
endpoint: "/admin/auth",
|
|
646
|
+
content_type: "application/json",
|
|
647
|
+
rate_limit: {
|
|
648
|
+
group: "volt.admin.auth",
|
|
649
|
+
limit: 5,
|
|
650
|
+
interval: 60,
|
|
651
|
+
},
|
|
652
|
+
params: {
|
|
653
|
+
password: "string",
|
|
654
|
+
},
|
|
655
|
+
ip_whitelist: this.admin.ips,
|
|
656
|
+
callback: async (stream: Stream, params: {password: string}) => {
|
|
657
|
+
// Check key.
|
|
658
|
+
if (params.password !== this.admin.password) {
|
|
659
|
+
return stream.send({
|
|
660
|
+
status: 403,
|
|
661
|
+
headers: {"Content-Type": "text/plain"},
|
|
662
|
+
data: "Access Denied",
|
|
663
|
+
})
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Generate token.
|
|
667
|
+
const token = {
|
|
668
|
+
token: String.random(32),
|
|
669
|
+
expiration: Date.now() + 3600 * 1000,
|
|
670
|
+
};
|
|
671
|
+
this.admin.tokens!.push(token)
|
|
672
|
+
|
|
673
|
+
// Response.
|
|
674
|
+
return stream.send({
|
|
675
|
+
status: 200,
|
|
676
|
+
headers: {"Content-Type": "application/json"},
|
|
677
|
+
data: token,
|
|
678
|
+
})
|
|
679
|
+
},
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
// Admin data.
|
|
683
|
+
this.endpoint({
|
|
684
|
+
method: "GET",
|
|
685
|
+
endpoint: "/admin/data",
|
|
686
|
+
content_type: "application/json",
|
|
687
|
+
rate_limit: "global",
|
|
688
|
+
params: {
|
|
689
|
+
token: "string",
|
|
690
|
+
},
|
|
691
|
+
ip_whitelist: this.admin.ips,
|
|
692
|
+
callback: async (stream: Stream, params: {token: string}) => {
|
|
693
|
+
// Verify token.
|
|
694
|
+
if (!verify_token(params.token)) {
|
|
695
|
+
return stream.send({
|
|
696
|
+
status: 403,
|
|
697
|
+
headers: {"Content-Type": "text/plain"},
|
|
698
|
+
data: "Access Denied",
|
|
699
|
+
})
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Data.
|
|
703
|
+
const data: Record<string, any> = {};
|
|
704
|
+
|
|
705
|
+
// Parse subscriptions.
|
|
706
|
+
const subscriptions = await this.payments._get_all_active_subscriptions();
|
|
707
|
+
data.subscriptions = subscriptions.length;
|
|
708
|
+
|
|
709
|
+
// Load data.
|
|
710
|
+
const status = await this._sys_db.load("status", {
|
|
711
|
+
default: {
|
|
712
|
+
running_since: null,
|
|
713
|
+
running_threads: 0,
|
|
714
|
+
total_threads: 0,
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
Object.assign(data, status);
|
|
718
|
+
|
|
719
|
+
// System data.
|
|
720
|
+
data.cpu_usage = vlib.System.cpu_usage();
|
|
721
|
+
data.memory_usage = vlib.System.memory_usage();
|
|
722
|
+
data.network_usage = await vlib.System.network_usage();
|
|
723
|
+
|
|
724
|
+
// Users.
|
|
725
|
+
data.users = (await this.users.list()).length;
|
|
726
|
+
|
|
727
|
+
// Response.
|
|
728
|
+
return stream.send({
|
|
729
|
+
status: 200,
|
|
730
|
+
headers: {"Content-Type": "application/json"},
|
|
731
|
+
data: data,
|
|
732
|
+
})
|
|
733
|
+
},
|
|
734
|
+
})
|
|
735
|
+
|
|
736
|
+
// Admin view.
|
|
737
|
+
this.endpoint({
|
|
738
|
+
method: "GET",
|
|
739
|
+
endpoint: "/admin",
|
|
740
|
+
content_type: "application/json",
|
|
741
|
+
rate_limit: "global",
|
|
742
|
+
params: {
|
|
743
|
+
password: "string",
|
|
744
|
+
},
|
|
745
|
+
ip_whitelist: this.admin.ips,
|
|
746
|
+
sitemap: false,
|
|
747
|
+
robots: false,
|
|
748
|
+
view: {
|
|
749
|
+
templates: {
|
|
750
|
+
DOMAIN: this.domain,
|
|
751
|
+
},
|
|
752
|
+
callback: () => {
|
|
753
|
+
// Style.
|
|
754
|
+
const style = {
|
|
755
|
+
bg: "#F2F3F6",
|
|
756
|
+
sub_bg: "#FAFAFA",
|
|
757
|
+
fg: "#000000",
|
|
758
|
+
sub_fg: "#9099B4",
|
|
759
|
+
border: "#D6D6D6",
|
|
760
|
+
tint: "#64B878", //"#8EB8EB", //"#4E9CF7",
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// ... rest of the admin view implementation remains the same as it's client-side JavaScript ...
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
})
|
|
767
|
+
} */
|
|
768
|
+
// Initialize statics.
|
|
769
|
+
async _initialize_statics() {
|
|
770
|
+
this.log(2, "Initializing static directories.");
|
|
771
|
+
const static_paths = [];
|
|
772
|
+
const add_static_file = async (path2, endpoint, cache = true) => {
|
|
773
|
+
static_paths.push(path2.str());
|
|
774
|
+
if (import_image_endpoint.ImageEndpoint.supported_images.has(path2.extension())) {
|
|
775
|
+
const e = new import_image_endpoint.ImageEndpoint({
|
|
776
|
+
endpoint,
|
|
777
|
+
path: path2,
|
|
778
|
+
cache,
|
|
779
|
+
rate_limit: "global",
|
|
780
|
+
_is_static: true
|
|
781
|
+
});
|
|
782
|
+
const aspect_ratio = await e.get_aspect_ratio();
|
|
783
|
+
if (aspect_ratio != null) {
|
|
784
|
+
this.statics_aspect_ratios.set(e.route.endpoint_str, aspect_ratio);
|
|
785
|
+
}
|
|
786
|
+
this.endpoint(e);
|
|
787
|
+
} else {
|
|
788
|
+
this.endpoint(new import_endpoint.Endpoint({
|
|
789
|
+
method: "GET",
|
|
790
|
+
endpoint,
|
|
791
|
+
cache,
|
|
792
|
+
rate_limit: "global",
|
|
793
|
+
file_path: path2,
|
|
794
|
+
_is_static: true
|
|
795
|
+
}));
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const add_static = async (opts) => {
|
|
799
|
+
if (opts == null) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (typeof opts === "object") {
|
|
803
|
+
this.log(3, "Adding static directory " + opts.path);
|
|
804
|
+
vlib.schema.validate(opts, {
|
|
805
|
+
unknown: false,
|
|
806
|
+
throw: true,
|
|
807
|
+
schema: {
|
|
808
|
+
path: "string",
|
|
809
|
+
endpoint: { type: "string", default: null },
|
|
810
|
+
cache: { type: ["boolean", "number"], default: true },
|
|
811
|
+
endpoints_cache: { type: "object", default: {} },
|
|
812
|
+
exclude: { type: "array", default: [] }
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
const paths = [];
|
|
816
|
+
const source = new vlib.Path(opts.path).abs();
|
|
817
|
+
if (!source.exists()) {
|
|
818
|
+
this.log(1, `Static path "${source.str()}" does not exist; skipping.`);
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
const source_len = source.str().length;
|
|
822
|
+
const is_dir = source.is_dir();
|
|
823
|
+
const exclude = [/\.DS_Store$/, /\.cache(?:\/|$)/, /\.old(?:\/|$)/, /\.ignore$/, ...opts.exclude || []];
|
|
824
|
+
const is_excluded = (p) => {
|
|
825
|
+
const s = typeof p === "string" ? p : p.str();
|
|
826
|
+
return exclude.some((pattern) => pattern instanceof RegExp ? pattern.test(s) : s === String(pattern));
|
|
827
|
+
};
|
|
828
|
+
opts.endpoint = opts.endpoint || `/${source.full_name()}`;
|
|
829
|
+
if (opts.endpoint.charAt(0) != "/") {
|
|
830
|
+
opts.endpoint = "/" + opts.endpoint;
|
|
831
|
+
}
|
|
832
|
+
while (opts.endpoint.charAt(opts.endpoint.length - 1) == "/") {
|
|
833
|
+
opts.endpoint = opts.endpoint.slice(0, -1);
|
|
834
|
+
}
|
|
835
|
+
if (!is_dir) {
|
|
836
|
+
return await add_static_file(source, opts.endpoint, opts.cache);
|
|
837
|
+
}
|
|
838
|
+
const read_dir = async (path2) => {
|
|
839
|
+
const dir_paths = await path2.paths();
|
|
840
|
+
const promises = [];
|
|
841
|
+
for (let i = 0; i < dir_paths.length; i++) {
|
|
842
|
+
if (!is_excluded(dir_paths[i])) {
|
|
843
|
+
if (dir_paths[i].is_dir()) {
|
|
844
|
+
promises.push(read_dir(dir_paths[i]));
|
|
845
|
+
} else {
|
|
846
|
+
paths.push(dir_paths[i]);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
;
|
|
851
|
+
await Promise.all(promises);
|
|
852
|
+
};
|
|
853
|
+
if (is_dir) {
|
|
854
|
+
await read_dir(source);
|
|
855
|
+
}
|
|
856
|
+
for (const path2 of paths) {
|
|
857
|
+
const endpoint = `${opts.endpoint}${path2.str().substr(source_len)}`;
|
|
858
|
+
await add_static_file(path2, endpoint, opts.endpoints_cache === void 0 ? opts.cache : opts.endpoints_cache[endpoint] ?? opts.cache);
|
|
859
|
+
}
|
|
860
|
+
} else if (typeof opts === "string") {
|
|
861
|
+
await add_static({ path: opts });
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
for (let i = 0; i < this.statics.length; i++) {
|
|
865
|
+
if (this.statics[i] instanceof vlib.Path) {
|
|
866
|
+
this.statics[i] = this.statics[i].str();
|
|
867
|
+
}
|
|
868
|
+
await add_static(this.statics[i]);
|
|
869
|
+
}
|
|
870
|
+
return static_paths;
|
|
871
|
+
}
|
|
872
|
+
/** Initialize the system and user defined keys. */
|
|
873
|
+
async _initialize_keys() {
|
|
874
|
+
const start = Date.now();
|
|
875
|
+
await this._db_init_promise;
|
|
876
|
+
this.performance.end("_initialize_keys():await-db-init", start);
|
|
877
|
+
const sys_keys = await this._sys_keys_db.load({ id: "sys_keys" }, {
|
|
878
|
+
default: {
|
|
879
|
+
id: "sys_keys",
|
|
880
|
+
rate_limit_api_key: void 0
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
let perform_sys_keys_save = false;
|
|
884
|
+
if (sys_keys.rate_limit_api_key == null) {
|
|
885
|
+
this.rate_limit_api_key = this.generate_crypto_key(32);
|
|
886
|
+
sys_keys.rate_limit_api_key = this.rate_limit_api_key;
|
|
887
|
+
perform_sys_keys_save = true;
|
|
888
|
+
} else {
|
|
889
|
+
this.rate_limit_api_key = sys_keys.rate_limit_api_key;
|
|
890
|
+
}
|
|
891
|
+
if (perform_sys_keys_save) {
|
|
892
|
+
await this._sys_keys_db.set({ id: "sys_keys" }, sys_keys);
|
|
893
|
+
}
|
|
894
|
+
const user_keys = await this._keys_db.load({ id: "user_keys" }, {
|
|
895
|
+
default: {
|
|
896
|
+
id: "user_keys",
|
|
897
|
+
keys: {}
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
let perform_user_keys_save = false;
|
|
901
|
+
for (const key of this._user_keys_opts) {
|
|
902
|
+
const name = typeof key === "string" ? key : key.name;
|
|
903
|
+
if (user_keys[name]) {
|
|
904
|
+
this.keys[name] = user_keys[name];
|
|
905
|
+
} else {
|
|
906
|
+
perform_user_keys_save = true;
|
|
907
|
+
if (typeof key === "string") {
|
|
908
|
+
if (!key) {
|
|
909
|
+
throw Error(`Crypto key "${key}" is an invalid key name.`);
|
|
910
|
+
}
|
|
911
|
+
const generated_key = this.generate_crypto_key(32);
|
|
912
|
+
user_keys.keys[key] = generated_key;
|
|
913
|
+
this.keys[key] = generated_key;
|
|
914
|
+
} else {
|
|
915
|
+
if (!key.name) {
|
|
916
|
+
throw Error(`Crypto key "${key.name}" is an invalid key name.`);
|
|
917
|
+
}
|
|
918
|
+
if (key.length == null) {
|
|
919
|
+
throw Error(`Crypto key "${key.name}" does not contain a "length" attribute.`);
|
|
920
|
+
}
|
|
921
|
+
if (typeof key.length !== "number") {
|
|
922
|
+
throw Error(`Crypto key "${key.name}" has an invalid type for attribute "length", the valid type is "number".`);
|
|
923
|
+
}
|
|
924
|
+
const generated_key = this.generate_crypto_key(key.length);
|
|
925
|
+
user_keys.keys[key.name] = generated_key;
|
|
926
|
+
this.keys[key.name] = generated_key;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
if (perform_user_keys_save) {
|
|
931
|
+
await this._keys_db.set({ id: "user_keys" }, user_keys);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Checks if an endpoint route already exists.
|
|
936
|
+
* @param method HTTP method
|
|
937
|
+
* @param endpoint String path or RegExp
|
|
938
|
+
*/
|
|
939
|
+
_check_duplicate_route(route) {
|
|
940
|
+
const e = this.find_endpoint(route);
|
|
941
|
+
if (e) {
|
|
942
|
+
throw new Error(`Duplicate "${route.method}:${route.endpoint_str}" endpoint route, it is already defined by endpoint "${e.id}".`);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
// Serve a client.
|
|
946
|
+
// @todo implement rate limiting.
|
|
947
|
+
// @todo save internal server errors.
|
|
948
|
+
async _serve(http2_stream, headers, req, res) {
|
|
949
|
+
try {
|
|
950
|
+
const stream = new import_stream.Stream(http2_stream, headers, req, res);
|
|
951
|
+
let endpoint;
|
|
952
|
+
let method;
|
|
953
|
+
let endpoint_url;
|
|
954
|
+
const log_endpoint_result = (message, status) => {
|
|
955
|
+
let log_level = endpoint && endpoint.is_static ? 3 : 0;
|
|
956
|
+
if (status == null) {
|
|
957
|
+
status = stream.status_code;
|
|
958
|
+
}
|
|
959
|
+
this.log(log_level, `${method}:${endpoint_url}: ${message ? message : import_status.Status.get_description(status ?? "unknown")} [${status}] (${stream.ip}).`);
|
|
960
|
+
};
|
|
961
|
+
const serve_error_endpoint = async (status_code) => {
|
|
962
|
+
const is_api_endpoint = endpoint && endpoint.callback != null;
|
|
963
|
+
let default_response;
|
|
964
|
+
switch (status_code) {
|
|
965
|
+
case 400:
|
|
966
|
+
default_response = {
|
|
967
|
+
status: 400,
|
|
968
|
+
headers: { "Content-Type": is_api_endpoint ? "application/json" : "text/plain" },
|
|
969
|
+
data: is_api_endpoint ? { error: "Bad Request" } : "Bad Request"
|
|
970
|
+
};
|
|
971
|
+
break;
|
|
972
|
+
case 403:
|
|
973
|
+
default_response = {
|
|
974
|
+
status: 403,
|
|
975
|
+
headers: { "Content-Type": is_api_endpoint ? "application/json" : "text/plain" },
|
|
976
|
+
data: is_api_endpoint ? { error: "Access Denied" } : "Access Denied"
|
|
977
|
+
};
|
|
978
|
+
break;
|
|
979
|
+
case 404:
|
|
980
|
+
default_response = {
|
|
981
|
+
status: 404,
|
|
982
|
+
headers: { "Content-Type": is_api_endpoint ? "application/json" : "text/plain" },
|
|
983
|
+
data: is_api_endpoint ? { error: "Not Found" } : "Not Found"
|
|
984
|
+
};
|
|
985
|
+
break;
|
|
986
|
+
case 500:
|
|
987
|
+
default:
|
|
988
|
+
default_response = {
|
|
989
|
+
status: 500,
|
|
990
|
+
headers: { "Content-Type": is_api_endpoint ? "application/json" : "text/plain" },
|
|
991
|
+
data: is_api_endpoint ? { error: "Internal Server Error" } : "Internal Server Error"
|
|
992
|
+
};
|
|
993
|
+
break;
|
|
994
|
+
}
|
|
995
|
+
if (!this.err_endpoints.has(status_code)) {
|
|
996
|
+
stream.send(default_response);
|
|
997
|
+
} else {
|
|
998
|
+
const err_endpoint = this.err_endpoints.get(status_code);
|
|
999
|
+
try {
|
|
1000
|
+
await err_endpoint.serve({ stream, status: status_code });
|
|
1001
|
+
} catch (err) {
|
|
1002
|
+
this.log.error(`Error endpoint ${status_code}: `, err);
|
|
1003
|
+
stream.send(default_response);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
method = stream.method;
|
|
1008
|
+
endpoint_url = stream.endpoint;
|
|
1009
|
+
this.log(3, "Searching for endpoint: ", `${method}:${endpoint_url}`);
|
|
1010
|
+
endpoint = this.endpoints.get(`${method}:${endpoint_url}`);
|
|
1011
|
+
if (!endpoint) {
|
|
1012
|
+
const route = new import_route.Route(method, endpoint_url);
|
|
1013
|
+
for (const e of this.endpoints.values()) {
|
|
1014
|
+
if (e.route.is_regex) {
|
|
1015
|
+
const matched_params = e.route.match(route);
|
|
1016
|
+
if (matched_params !== false) {
|
|
1017
|
+
this.log(3, "Matched regex route: ", e.route.id);
|
|
1018
|
+
endpoint = e;
|
|
1019
|
+
Object.keys(matched_params).walk((k) => {
|
|
1020
|
+
if (stream.params[k] == null) {
|
|
1021
|
+
stream.params[k] = matched_params[k];
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
} else {
|
|
1029
|
+
this.log(3, "Matched route: ", endpoint.route.id);
|
|
1030
|
+
}
|
|
1031
|
+
if (!endpoint) {
|
|
1032
|
+
if (method === "OPTIONS") {
|
|
1033
|
+
const original_method = stream.headers["access-control-request-method"];
|
|
1034
|
+
const original_endpoint = this.find_endpoint(endpoint_url, original_method);
|
|
1035
|
+
if (original_endpoint) {
|
|
1036
|
+
this._set_header_defaults(stream);
|
|
1037
|
+
original_endpoint._set_headers(stream);
|
|
1038
|
+
stream.send({ status: import_status.Status.no_content });
|
|
1039
|
+
log_endpoint_result();
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
await serve_error_endpoint(404);
|
|
1044
|
+
log_endpoint_result();
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
this._set_header_defaults(stream);
|
|
1048
|
+
if (method === "OPTIONS") {
|
|
1049
|
+
try {
|
|
1050
|
+
await endpoint._serve_options(stream);
|
|
1051
|
+
} catch (err) {
|
|
1052
|
+
this.log.error(`${method}:${endpoint_url}: `, err);
|
|
1053
|
+
if (!stream.destroyed && !stream.finished) {
|
|
1054
|
+
await serve_error_endpoint(500);
|
|
1055
|
+
log_endpoint_result();
|
|
1056
|
+
}
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
log_endpoint_result();
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (!this.offline && this.production && this.rate_limit !== void 0 && endpoint.rate_limit_groups.length > 0) {
|
|
1063
|
+
const result = await this.rate_limit.limit(stream.ip, endpoint.rate_limit_groups);
|
|
1064
|
+
if (result != null) {
|
|
1065
|
+
stream.send({
|
|
1066
|
+
status: 429,
|
|
1067
|
+
headers: {
|
|
1068
|
+
"Content-Type": "text/plain",
|
|
1069
|
+
"X-RateLimit-Reset": result
|
|
1070
|
+
},
|
|
1071
|
+
data: `Rate limit exceeded, please try again in ${Math.floor((result - Date.now()) / 1e3)} seconds.`
|
|
1072
|
+
});
|
|
1073
|
+
log_endpoint_result();
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
try {
|
|
1078
|
+
await stream.join();
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
this.log.error(`${method}:${endpoint_url}: `, err);
|
|
1081
|
+
await serve_error_endpoint(500);
|
|
1082
|
+
log_endpoint_result();
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
try {
|
|
1086
|
+
stream._parse_params();
|
|
1087
|
+
} catch (err) {
|
|
1088
|
+
this.log.error(`${method}:${endpoint_url}: `, err);
|
|
1089
|
+
await serve_error_endpoint(400);
|
|
1090
|
+
log_endpoint_result();
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
if (!endpoint.is_static || endpoint.authenticated) {
|
|
1094
|
+
const auth_result = await this.users._authenticate(stream);
|
|
1095
|
+
if (auth_result != null && !endpoint.is_static) {
|
|
1096
|
+
this.users._reset_cookies(stream);
|
|
1097
|
+
}
|
|
1098
|
+
if (auth_result != null && !endpoint.is_static && (endpoint.view != null || endpoint.content_type === "text/html")) {
|
|
1099
|
+
stream.set_header("Location", `/signin?next=${encodeURIComponent(stream.endpoint)}`);
|
|
1100
|
+
}
|
|
1101
|
+
if (auth_result != null && endpoint.authenticated) {
|
|
1102
|
+
stream.send(auth_result);
|
|
1103
|
+
log_endpoint_result();
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
try {
|
|
1108
|
+
await endpoint.serve({ stream });
|
|
1109
|
+
} catch (err) {
|
|
1110
|
+
this.log.error(`${method}:${endpoint_url}: `, err);
|
|
1111
|
+
if (!stream.destroyed && !stream.finished) {
|
|
1112
|
+
await serve_error_endpoint(500);
|
|
1113
|
+
log_endpoint_result();
|
|
1114
|
+
}
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
if (!stream.finished) {
|
|
1118
|
+
this.log.error(`${method}:${endpoint_url}: `, "Unfinished response.");
|
|
1119
|
+
await serve_error_endpoint(500);
|
|
1120
|
+
log_endpoint_result();
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
log_endpoint_result();
|
|
1124
|
+
} catch (err) {
|
|
1125
|
+
this.log.error(err);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
// ---------------------------------------------------------
|
|
1129
|
+
// Utilities.
|
|
1130
|
+
/** The promise of database initialization and connecting. */
|
|
1131
|
+
_db_init_promise;
|
|
1132
|
+
/** Is initialized. */
|
|
1133
|
+
_initialized = false;
|
|
1134
|
+
/** Is initialized by a worker. */
|
|
1135
|
+
_initialized_by_worker = false;
|
|
1136
|
+
/**
|
|
1137
|
+
* Initialize the server.
|
|
1138
|
+
* @returns A promise that resolves when the server has been initialized.
|
|
1139
|
+
* @docs
|
|
1140
|
+
*/
|
|
1141
|
+
async initialize({ worker = false } = {}) {
|
|
1142
|
+
if (this._initialized) {
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
this._initialized = true;
|
|
1146
|
+
this._initialized_by_worker = worker;
|
|
1147
|
+
this.log(1, "Initializing server.");
|
|
1148
|
+
const initialize_start = Date.now();
|
|
1149
|
+
this.performance.start();
|
|
1150
|
+
this._db_init_promise = (async () => {
|
|
1151
|
+
let start = Date.now();
|
|
1152
|
+
await this.db.initialize();
|
|
1153
|
+
this.performance.end("init-db", start);
|
|
1154
|
+
start = Date.now();
|
|
1155
|
+
await this.db.connect();
|
|
1156
|
+
this.performance.end("connect-db", start);
|
|
1157
|
+
})();
|
|
1158
|
+
if (this.endpoint_cache_dir.exists()) {
|
|
1159
|
+
await this.endpoint_cache_dir.del({ recursive: true });
|
|
1160
|
+
}
|
|
1161
|
+
await this.endpoint_cache_dir.mkdir({ recursive: true });
|
|
1162
|
+
if (!worker) {
|
|
1163
|
+
if (this.tls) {
|
|
1164
|
+
this.https = http2.createSecureServer({
|
|
1165
|
+
key: new vlib.Path(this.tls.key).load_sync({ encoding: "utf8" }),
|
|
1166
|
+
cert: new vlib.Path(this.tls.cert).load_sync({ encoding: "utf8" }),
|
|
1167
|
+
ca: this.tls.ca == null ? void 0 : new vlib.Path(this.tls.ca).load_sync({ encoding: "utf8" }),
|
|
1168
|
+
passphrase: this.tls.passphrase,
|
|
1169
|
+
allowHTTP1: true
|
|
1170
|
+
});
|
|
1171
|
+
this.https.on("stream", (stream, headers) => {
|
|
1172
|
+
this._serve(stream, headers, void 0, void 0);
|
|
1173
|
+
});
|
|
1174
|
+
this.https.on("request", (req, res) => {
|
|
1175
|
+
if (req.httpVersionMajor === 1) {
|
|
1176
|
+
this._serve(void 0, void 0, req, res);
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
} else if (this.production && this.payments) {
|
|
1180
|
+
throw Error("Accepting payments in production mode requires HTTPS.");
|
|
1181
|
+
}
|
|
1182
|
+
this.performance.end("create-https-server");
|
|
1183
|
+
if (this.tls) {
|
|
1184
|
+
this.http = http.createServer((request, response) => {
|
|
1185
|
+
const reqUrl = typeof request.url === "string" ? request.url : "/";
|
|
1186
|
+
const location = `https://${this.domain}${reqUrl}`;
|
|
1187
|
+
response.writeHead(308, { Location: location });
|
|
1188
|
+
response.end();
|
|
1189
|
+
});
|
|
1190
|
+
} else {
|
|
1191
|
+
this.http = http.createServer((req, res) => {
|
|
1192
|
+
this._serve(void 0, void 0, req, res);
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
this.performance.end("create-http-server");
|
|
1196
|
+
this._init_default_headers();
|
|
1197
|
+
this.performance.end("init-default-headers");
|
|
1198
|
+
this._create_default_endpoints();
|
|
1199
|
+
this.performance.end("create-default-endpoints");
|
|
1200
|
+
await this._initialize_statics();
|
|
1201
|
+
this.performance.end("_initialize_statics()");
|
|
1202
|
+
}
|
|
1203
|
+
await this._initialize_keys();
|
|
1204
|
+
this.performance.end("load-keys");
|
|
1205
|
+
const promises = [];
|
|
1206
|
+
this.performance.start();
|
|
1207
|
+
promises.push(this.users._initialize({ worker }));
|
|
1208
|
+
if (this.payments !== void 0) {
|
|
1209
|
+
if (this.payments.type === "stripe") {
|
|
1210
|
+
promises.push(this.payments.initialize({ worker }));
|
|
1211
|
+
} else {
|
|
1212
|
+
this.payments.type.toString();
|
|
1213
|
+
throw Error(`Unsupported payments provider "${this.payments.type}".`);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
if (!worker) {
|
|
1217
|
+
if (this.find_endpoint("/sitemap.xml") == null) {
|
|
1218
|
+
promises.push(this._create_sitemap());
|
|
1219
|
+
}
|
|
1220
|
+
if (this.find_endpoint("/robots.txt") == null) {
|
|
1221
|
+
promises.push(this._create_robots_txt());
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
if (this.company.stroke_icon || this.company.icon) {
|
|
1225
|
+
for (const endpoint of this.endpoints.values()) {
|
|
1226
|
+
if (this.company.stroke_icon_path == null && endpoint.route.endpoint === this.company.stroke_icon) {
|
|
1227
|
+
this.company.stroke_icon_path = endpoint.file_path?.str() || void 0;
|
|
1228
|
+
}
|
|
1229
|
+
if (this.company.icon_path == null && endpoint.route.endpoint === this.company.icon) {
|
|
1230
|
+
this.company.icon_path = endpoint.file_path?.str() || void 0;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
if (this.company.stroke_icon != null && this.company.stroke_icon_path == null) {
|
|
1234
|
+
throw Error(`Unable to find the company's stroke icon endpoint "${this.company.stroke_icon}", consider defining the "company.stroke_icon_path" property.`);
|
|
1235
|
+
}
|
|
1236
|
+
if (this.company.icon != null && this.company.icon_path == null) {
|
|
1237
|
+
throw Error(`Unable to find the company's icon endpoint "${this.company.icon}", consider defining the "company.icon_path" property.`);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
await Promise.all(promises);
|
|
1241
|
+
this.performance.end("awaiting-promise-list");
|
|
1242
|
+
if (!worker) {
|
|
1243
|
+
this.performance.start();
|
|
1244
|
+
for (const endpoint of this.endpoints.values()) {
|
|
1245
|
+
endpoint._initialize(this);
|
|
1246
|
+
}
|
|
1247
|
+
for (const endpoint of this.err_endpoints.values()) {
|
|
1248
|
+
endpoint._initialize(this);
|
|
1249
|
+
}
|
|
1250
|
+
this.performance.end("initialize-endpoints");
|
|
1251
|
+
}
|
|
1252
|
+
for (const callback of this.events.get("initialize")) {
|
|
1253
|
+
await callback({ worker });
|
|
1254
|
+
}
|
|
1255
|
+
this.performance.end("on-initialize-callbacks");
|
|
1256
|
+
this.performance.end("initialize()", initialize_start);
|
|
1257
|
+
}
|
|
1258
|
+
find_endpoint(endpoint, method) {
|
|
1259
|
+
let route;
|
|
1260
|
+
if (endpoint instanceof import_route.Route) {
|
|
1261
|
+
route = endpoint;
|
|
1262
|
+
endpoint = route.endpoint_str;
|
|
1263
|
+
method = route.method;
|
|
1264
|
+
}
|
|
1265
|
+
method ??= "GET";
|
|
1266
|
+
const result = this.endpoints.get(`${method}:${endpoint}`);
|
|
1267
|
+
if (!result) {
|
|
1268
|
+
if (!route)
|
|
1269
|
+
route = new import_route.Route(method, endpoint);
|
|
1270
|
+
for (const e of this.endpoints.values()) {
|
|
1271
|
+
if (e.route.is_regex && e.route.match(route)) {
|
|
1272
|
+
return e;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
return result;
|
|
1277
|
+
}
|
|
1278
|
+
/** Assert mail is configured. */
|
|
1279
|
+
assert_mail() {
|
|
1280
|
+
if (!this.mail) {
|
|
1281
|
+
throw new import_internal_external.ExternalError({ message: "Mail is not configured." });
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
// ---------------------------------------------------------
|
|
1285
|
+
// Server.
|
|
1286
|
+
/**
|
|
1287
|
+
* Start the server.
|
|
1288
|
+
*
|
|
1289
|
+
* @example
|
|
1290
|
+
* {Start}
|
|
1291
|
+
* Start the server.
|
|
1292
|
+
* ```
|
|
1293
|
+
* const server = new volt.Server({ ... });
|
|
1294
|
+
* await server.start();
|
|
1295
|
+
* ```
|
|
1296
|
+
* @docs
|
|
1297
|
+
*/
|
|
1298
|
+
async start() {
|
|
1299
|
+
if (this._initialized_by_worker) {
|
|
1300
|
+
throw Error("Cannot start the server when it is initialized as a worker by 'Server.initialize({ worker: true })'.");
|
|
1301
|
+
}
|
|
1302
|
+
await this.initialize();
|
|
1303
|
+
if (this.production) {
|
|
1304
|
+
for (const endpoint of this.endpoints.values()) {
|
|
1305
|
+
if (endpoint.view) {
|
|
1306
|
+
await endpoint.view.production_initialize();
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
if (this.rate_limit) {
|
|
1311
|
+
this.performance.start();
|
|
1312
|
+
await this.rate_limit.start();
|
|
1313
|
+
this.performance.end("init-rate-limit");
|
|
1314
|
+
}
|
|
1315
|
+
let forked = false;
|
|
1316
|
+
if (this.production && this.threading.enabled && import_cluster.default.isPrimary && this.threading.threads > 1) {
|
|
1317
|
+
this.log(0, `Starting ${this.threading.threads} threads.`);
|
|
1318
|
+
let active_threads = 0;
|
|
1319
|
+
const thread_ids = {};
|
|
1320
|
+
const restart_limiters = {};
|
|
1321
|
+
const start_thread = (thread_id, restart = false) => {
|
|
1322
|
+
const worker = import_cluster.default.fork();
|
|
1323
|
+
this.log(restart ? 0 : 1, `Starting thread ${worker.process.pid}.`);
|
|
1324
|
+
thread_ids[worker.process.pid] = thread_id;
|
|
1325
|
+
++active_threads;
|
|
1326
|
+
};
|
|
1327
|
+
for (let i = 0; i < this.threading.threads; i++) {
|
|
1328
|
+
let thread_id;
|
|
1329
|
+
while ((thread_id = vlib.String.random(8)) && Object.values(thread_ids).includes(thread_id)) {
|
|
1330
|
+
}
|
|
1331
|
+
restart_limiters[thread_id] = new vlib.TimeLimiter({ limit: 3, duration: 60 * 1e3 });
|
|
1332
|
+
start_thread(thread_id);
|
|
1333
|
+
}
|
|
1334
|
+
await this._website_status_db.set({ id: "status" }, {
|
|
1335
|
+
running_since: Date.now(),
|
|
1336
|
+
total_threads: active_threads,
|
|
1337
|
+
running_threads: active_threads
|
|
1338
|
+
});
|
|
1339
|
+
import_cluster.default.addListener("exit", async (worker, code, signal) => {
|
|
1340
|
+
const thread_id = thread_ids[worker.process.pid];
|
|
1341
|
+
delete thread_ids[worker.process.pid];
|
|
1342
|
+
this.log.error(`Thread ${worker.process.pid} crashed.`);
|
|
1343
|
+
const limiter = restart_limiters[thread_id];
|
|
1344
|
+
if (limiter != null && limiter.limit()) {
|
|
1345
|
+
--active_threads;
|
|
1346
|
+
start_thread(thread_id, true);
|
|
1347
|
+
} else {
|
|
1348
|
+
this.log.error(`Thread ${worker.process.pid} is being shut down due to its periodic restart limit.`);
|
|
1349
|
+
--active_threads;
|
|
1350
|
+
await this._website_status_db.save({ id: "status" }, { $inc: { running_threads: -1 } });
|
|
1351
|
+
if (active_threads === 0) {
|
|
1352
|
+
this.log.error(`All threads died, stopping server.`);
|
|
1353
|
+
process.exit(0);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
await this.db.close();
|
|
1358
|
+
} else {
|
|
1359
|
+
forked = this.production && this.threading.enabled;
|
|
1360
|
+
let is_running = false;
|
|
1361
|
+
const on_running = () => {
|
|
1362
|
+
if (!is_running) {
|
|
1363
|
+
is_running = true;
|
|
1364
|
+
if (this.https !== void 0) {
|
|
1365
|
+
this.log(0, `Running on http://${this.ip}:${this.port} and https://${this.ip}:${this.https_port}.`);
|
|
1366
|
+
} else {
|
|
1367
|
+
this.log(0, `Running on http://${this.ip}:${this.port}.`);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
const on_error = (error) => {
|
|
1372
|
+
if (error.syscall !== "listen") {
|
|
1373
|
+
throw error;
|
|
1374
|
+
}
|
|
1375
|
+
switch (error.code) {
|
|
1376
|
+
case "EACCES":
|
|
1377
|
+
console.error(`Error: Address ${this.ip}:${this.port} requires elevated privileges.`);
|
|
1378
|
+
process.exit(1);
|
|
1379
|
+
break;
|
|
1380
|
+
case "EADDRINUSE":
|
|
1381
|
+
console.error(`Error: Address ${this.ip}:${this.port} is already in use.`);
|
|
1382
|
+
process.exit(1);
|
|
1383
|
+
break;
|
|
1384
|
+
default:
|
|
1385
|
+
throw error;
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
this.http.listen(this.port, this.ip === "*" ? void 0 : this.ip, on_running);
|
|
1389
|
+
this.http.on("error", on_error);
|
|
1390
|
+
if (this.https !== void 0) {
|
|
1391
|
+
this.https.listen(this.https_port, this.ip === "*" ? void 0 : this.ip, on_running);
|
|
1392
|
+
this.https.on("error", on_error);
|
|
1393
|
+
}
|
|
1394
|
+
let graceful_shutdown_shutting_down = false;
|
|
1395
|
+
const graceful_shutdown = async () => {
|
|
1396
|
+
if (graceful_shutdown_shutting_down)
|
|
1397
|
+
return;
|
|
1398
|
+
graceful_shutdown_shutting_down = true;
|
|
1399
|
+
try {
|
|
1400
|
+
await this.stop();
|
|
1401
|
+
} catch (e) {
|
|
1402
|
+
this.log.error("Shutdown error:", e);
|
|
1403
|
+
} finally {
|
|
1404
|
+
process.exit(0);
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
process.on("SIGTERM", graceful_shutdown);
|
|
1408
|
+
process.on("SIGINT", graceful_shutdown);
|
|
1409
|
+
if (process.env.VOLT_FILE_WATCHER === "1") {
|
|
1410
|
+
new vlib.Path(process.env.VOLT_STARTED_FILE).save_sync("1");
|
|
1411
|
+
}
|
|
1412
|
+
this.performance.end("listen");
|
|
1413
|
+
}
|
|
1414
|
+
this.performance.start();
|
|
1415
|
+
for (const callback of this.events.get("start")) {
|
|
1416
|
+
const res = callback({ forked });
|
|
1417
|
+
if (res instanceof Promise) {
|
|
1418
|
+
await res;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
this.performance.end("on-start-callbacks");
|
|
1422
|
+
console.log(this.performance.dump());
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Stop the server.
|
|
1426
|
+
* @note After stopping the server we can no longer restart the server.
|
|
1427
|
+
*
|
|
1428
|
+
* @example
|
|
1429
|
+
* {Stop}
|
|
1430
|
+
* Stop the server.
|
|
1431
|
+
* ```
|
|
1432
|
+
* const server = new volt.Server({ ... });
|
|
1433
|
+
* await server.start();
|
|
1434
|
+
* ...
|
|
1435
|
+
* await server.stop();
|
|
1436
|
+
* ```
|
|
1437
|
+
*
|
|
1438
|
+
* @docs
|
|
1439
|
+
*/
|
|
1440
|
+
async stop() {
|
|
1441
|
+
this.log(0, "Stopping the server...");
|
|
1442
|
+
for (const callback of this.events.get("stop")) {
|
|
1443
|
+
const res = callback();
|
|
1444
|
+
if (res instanceof Promise) {
|
|
1445
|
+
await res;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
if (this.rate_limit) {
|
|
1449
|
+
await this.rate_limit.stop();
|
|
1450
|
+
}
|
|
1451
|
+
if (this.https)
|
|
1452
|
+
this.https.close();
|
|
1453
|
+
if (this.http)
|
|
1454
|
+
this.http.close();
|
|
1455
|
+
await this.db.close();
|
|
1456
|
+
this.log.stop();
|
|
1457
|
+
this._initialized = false;
|
|
1458
|
+
}
|
|
1459
|
+
// ---------------------------------------------------------
|
|
1460
|
+
// Events.
|
|
1461
|
+
/**
|
|
1462
|
+
* Add an event callback.
|
|
1463
|
+
* See {@link Events} for more info.
|
|
1464
|
+
* @docs
|
|
1465
|
+
*/
|
|
1466
|
+
on(name, callback) {
|
|
1467
|
+
this.events.add(name, callback);
|
|
1468
|
+
return this;
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Remove an event callback.
|
|
1472
|
+
* See {@link Events} for more info.
|
|
1473
|
+
* @docs
|
|
1474
|
+
*/
|
|
1475
|
+
off(name, callback) {
|
|
1476
|
+
this.events.remove(name, callback);
|
|
1477
|
+
return this;
|
|
1478
|
+
}
|
|
1479
|
+
// ---------------------------------------------------------
|
|
1480
|
+
// Endpoints.
|
|
1481
|
+
/**
|
|
1482
|
+
* Add a single endpoint.
|
|
1483
|
+
* Only supports a single endpoint due to parameter inference.
|
|
1484
|
+
* @note An error is thrown when the endpoint route already exists.
|
|
1485
|
+
* @template Response User inputted response type that will be returned as response, optionaly typing used for consistency.
|
|
1486
|
+
* @template S system template for inferring the endpoint callback parameters.
|
|
1487
|
+
* @param endpoint The endpoint or endpoint options to add.
|
|
1488
|
+
* @returns A registered endpoint object that can for instance be used to infer the endpoint parameters.
|
|
1489
|
+
*
|
|
1490
|
+
* @docs
|
|
1491
|
+
*/
|
|
1492
|
+
endpoint(endpoint) {
|
|
1493
|
+
const e = endpoint instanceof import_endpoint.Endpoint ? endpoint : new import_endpoint.Endpoint(endpoint);
|
|
1494
|
+
this._check_duplicate_route(e.route);
|
|
1495
|
+
this.endpoints.set(e.route.id, e);
|
|
1496
|
+
return {
|
|
1497
|
+
Params: void 0,
|
|
1498
|
+
method: e.route.method,
|
|
1499
|
+
Method: e.route.method,
|
|
1500
|
+
endpoint: e.route.endpoint,
|
|
1501
|
+
Endpoint: e.route.endpoint,
|
|
1502
|
+
route: e.route
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Add an endpoint per error status code.
|
|
1507
|
+
* @param status_code
|
|
1508
|
+
* The status code of the error.
|
|
1509
|
+
*
|
|
1510
|
+
* The supported status codes are:
|
|
1511
|
+
* * `*` For all errors not specifically defined.
|
|
1512
|
+
* * `status >= 400`
|
|
1513
|
+
* @param endpoint The error endpoint or error endpoint options.
|
|
1514
|
+
*
|
|
1515
|
+
* @note
|
|
1516
|
+
* Best practice is to define a universal `/error` endpoint using `Endpoint.templates` to render the error details.
|
|
1517
|
+
* Then this endpoint can be cloned using `Endpoint.clone()` and defined with specific template values per status code.
|
|
1518
|
+
*
|
|
1519
|
+
* @docs
|
|
1520
|
+
*/
|
|
1521
|
+
error_endpoint(status_code, endpoint) {
|
|
1522
|
+
let e;
|
|
1523
|
+
if (endpoint instanceof import_endpoint.Endpoint) {
|
|
1524
|
+
e = endpoint;
|
|
1525
|
+
} else {
|
|
1526
|
+
e = new import_endpoint.Endpoint({
|
|
1527
|
+
...endpoint,
|
|
1528
|
+
method: "GET",
|
|
1529
|
+
endpoint: `/error/${status_code}`
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
if (status_code === "*") {
|
|
1533
|
+
Object.values(import_status.Status).forEach((status) => {
|
|
1534
|
+
if (typeof status === "number" && status >= 400 && !this.err_endpoints.has(status)) {
|
|
1535
|
+
this.err_endpoints.set(status, e);
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
} else {
|
|
1539
|
+
this.err_endpoints.set(status_code, e);
|
|
1540
|
+
}
|
|
1541
|
+
return this;
|
|
1542
|
+
}
|
|
1543
|
+
// ---------------------------------------------------------
|
|
1544
|
+
// Content Security Policy.
|
|
1545
|
+
/**
|
|
1546
|
+
* Add an url to the Content-Security-Policy. This function does not overwrite the existing key's value.
|
|
1547
|
+
* @warning This function no longer has any effect when `Server.start()` has been called.
|
|
1548
|
+
* @param key The Content-Security-Policy key, e.g. `script-src`.
|
|
1549
|
+
* @param value The value to add to the Content-Security-Policy key.
|
|
1550
|
+
* @example
|
|
1551
|
+
* ...
|
|
1552
|
+
* server.add_csp("script-src", "somewebsite.com");
|
|
1553
|
+
* server.add_csp("upgrade-insecure-requests");
|
|
1554
|
+
* @docs
|
|
1555
|
+
*/
|
|
1556
|
+
add_csp(key, value = null) {
|
|
1557
|
+
if (this.csp[key] === void 0) {
|
|
1558
|
+
this.csp[key] = "";
|
|
1559
|
+
}
|
|
1560
|
+
if (Array.isArray(value)) {
|
|
1561
|
+
value.forEach((v) => {
|
|
1562
|
+
if (typeof v === "string" && v.length > 0) {
|
|
1563
|
+
this.csp[key] += " " + v.trim();
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
} else if (typeof value === "string" && value.length > 0) {
|
|
1567
|
+
this.csp[key] += " " + value.trim();
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
// Remove a csp.
|
|
1571
|
+
/**
|
|
1572
|
+
* Remove an url from the Content-Security-Policy. This function does not overwrite the existing key's value.
|
|
1573
|
+
* @warning This function no longer has any effect when `Server.start()` has been called.
|
|
1574
|
+
* @param key The Content-Security-Policy key, e.g. `script-src`.
|
|
1575
|
+
* @param value The value to remove from the Content-Security-Policy key.
|
|
1576
|
+
* @example
|
|
1577
|
+
* ...
|
|
1578
|
+
* server.remove_csp("script-src", "somewebsite.com");
|
|
1579
|
+
* server.remove_csp("upgrade-insecure-requests");
|
|
1580
|
+
* @docs
|
|
1581
|
+
*/
|
|
1582
|
+
remove_csp(key, value = null) {
|
|
1583
|
+
if (this.csp[key] === void 0) {
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
if (typeof value === "string" && value.length > 0) {
|
|
1587
|
+
this.csp[key] = this.csp[key].replaceAll(value, "");
|
|
1588
|
+
} else {
|
|
1589
|
+
delete this.csp[key];
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
// Delete a csp key.
|
|
1593
|
+
/**
|
|
1594
|
+
* Delete an key from the Content-Security-Policy.
|
|
1595
|
+
* @warning This function no longer has any effect when `Server.start()` has been called.
|
|
1596
|
+
* @param key The Content-Security-Policy key, e.g. `script-src`.
|
|
1597
|
+
* @example
|
|
1598
|
+
* ...
|
|
1599
|
+
* server.del_csp("script-src");
|
|
1600
|
+
* server.del_csp("upgrade-insecure-requests");
|
|
1601
|
+
* @docs
|
|
1602
|
+
*/
|
|
1603
|
+
del_csp(key) {
|
|
1604
|
+
delete this.csp[key];
|
|
1605
|
+
}
|
|
1606
|
+
// ---------------------------------------------------------
|
|
1607
|
+
// Status.
|
|
1608
|
+
/**
|
|
1609
|
+
* This function is meant to be used when the server is in production mode, it will make an API request to your server through the defined `Server.domain` parameter.
|
|
1610
|
+
* @note This function can be called without initializing the server.
|
|
1611
|
+
* @param type The wanted output type. Either an `object` or a `string` type for CLI purposes.
|
|
1612
|
+
* @docs
|
|
1613
|
+
*/
|
|
1614
|
+
async fetch_status(type = "object") {
|
|
1615
|
+
const key_path = this.source.join(".status/key");
|
|
1616
|
+
if (!key_path.exists()) {
|
|
1617
|
+
throw new Error("No status key has been generated yet. Start your server first.");
|
|
1618
|
+
}
|
|
1619
|
+
const key = key_path.load_sync();
|
|
1620
|
+
const { body: status } = await vlib.request({
|
|
1621
|
+
host: this.domain,
|
|
1622
|
+
endpoint: "/.status",
|
|
1623
|
+
method: "GET",
|
|
1624
|
+
params: { key },
|
|
1625
|
+
query: true,
|
|
1626
|
+
json: true
|
|
1627
|
+
});
|
|
1628
|
+
if (type === "string") {
|
|
1629
|
+
if (status.running_since != null) {
|
|
1630
|
+
status.running_since = new vlib.Date(status.running_since).format("%d-%m-%y %H:%M:%S");
|
|
1631
|
+
}
|
|
1632
|
+
let str = `${this.domain}:
|
|
1633
|
+
`;
|
|
1634
|
+
Object.keys(status).forEach((key2) => {
|
|
1635
|
+
str += ` * ${key2}: ${status[key2]}
|
|
1636
|
+
`;
|
|
1637
|
+
});
|
|
1638
|
+
str = str.substr(0, str.length - 1);
|
|
1639
|
+
return str;
|
|
1640
|
+
}
|
|
1641
|
+
return status;
|
|
1642
|
+
}
|
|
1643
|
+
// ---------------------------------------------------------
|
|
1644
|
+
// TLS.
|
|
1645
|
+
/**
|
|
1646
|
+
* Generate a key and csr for tls.
|
|
1647
|
+
* @docs
|
|
1648
|
+
*/
|
|
1649
|
+
async generate_ssl_key({ output_path, ec = true }) {
|
|
1650
|
+
if (output_path == null) {
|
|
1651
|
+
throw Error('Define parameter "path".');
|
|
1652
|
+
}
|
|
1653
|
+
const key = new vlib.Path(output_path);
|
|
1654
|
+
if (key.exists()) {
|
|
1655
|
+
throw Error(`Key path "${key.str()}" already exists, remove the file manually to continue.`);
|
|
1656
|
+
}
|
|
1657
|
+
const proc = new vlib.Proc();
|
|
1658
|
+
await proc.start({
|
|
1659
|
+
command: "openssl",
|
|
1660
|
+
args: ec ? ["ecparam", "-genkey", "-name", "secp384r1", "-out", key.str()] : ["genpkey", "-algorithm", "RSA", "-pkeyopt", "rsa_keygen_bits:2048", "-out", key.str()],
|
|
1661
|
+
opts: { stdio: "inherit" }
|
|
1662
|
+
});
|
|
1663
|
+
if (proc.exit_status != 0) {
|
|
1664
|
+
throw Error(`Encountered an error while generating the private key [${proc.exit_status}]: ${proc.err}`);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Generate a csr for tls.
|
|
1669
|
+
* @docs
|
|
1670
|
+
*/
|
|
1671
|
+
async generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city }) {
|
|
1672
|
+
if (key_path == null) {
|
|
1673
|
+
throw Error('Define parameter "key_path".');
|
|
1674
|
+
}
|
|
1675
|
+
if (organization_unit == null) {
|
|
1676
|
+
throw Error('Define parameter "organization_unit".');
|
|
1677
|
+
}
|
|
1678
|
+
const key = new vlib.Path(key_path);
|
|
1679
|
+
if (!key.exists()) {
|
|
1680
|
+
throw Error(`Key path "${key.str()}" does not exist.`);
|
|
1681
|
+
}
|
|
1682
|
+
const csr = new vlib.Path(output_path);
|
|
1683
|
+
if (csr.exists()) {
|
|
1684
|
+
throw Error(`CSR path "${csr.str()}" already exists, remove the file manually to continue.`);
|
|
1685
|
+
}
|
|
1686
|
+
const proc = new vlib.Proc();
|
|
1687
|
+
await proc.start({
|
|
1688
|
+
command: "openssl",
|
|
1689
|
+
args: [
|
|
1690
|
+
"req",
|
|
1691
|
+
"-new",
|
|
1692
|
+
"-key",
|
|
1693
|
+
key.str(),
|
|
1694
|
+
"-out",
|
|
1695
|
+
csr.str(),
|
|
1696
|
+
"-subj",
|
|
1697
|
+
`/C=${country_code}/ST=${province}/L=${city}/O=${name}/OU=${organization_unit}/CN=${domain}`
|
|
1698
|
+
],
|
|
1699
|
+
opts: { stdio: "inherit" }
|
|
1700
|
+
});
|
|
1701
|
+
if (proc.exit_status != 0) {
|
|
1702
|
+
throw Error(`Encountered an error while generating the CSR [${proc.exit_status}]: ${proc.err}`);
|
|
1703
|
+
}
|
|
1704
|
+
this.log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1708
|
+
0 && (module.exports = {
|
|
1709
|
+
Server
|
|
1710
|
+
});
|