@wopr-network/platform-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/biome.json +61 -0
- package/dist/admin/admin-audit-log-repository.d.ts +33 -0
- package/dist/admin/admin-audit-log-repository.js +102 -0
- package/dist/admin/audit-log.d.ts +49 -0
- package/dist/admin/audit-log.js +63 -0
- package/dist/admin/index.d.ts +6 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/role-store.d.ts +37 -0
- package/dist/admin/role-store.js +106 -0
- package/dist/auth/api-key-repository.d.ts +11 -0
- package/dist/auth/api-key-repository.js +33 -0
- package/dist/auth/api-key-repository.test.d.ts +1 -0
- package/dist/auth/api-key-repository.test.js +46 -0
- package/dist/auth/auth.test.d.ts +1 -0
- package/dist/auth/auth.test.js +140 -0
- package/dist/auth/better-auth.d.ts +42 -0
- package/dist/auth/better-auth.js +196 -0
- package/dist/auth/index.d.ts +186 -0
- package/dist/auth/index.js +422 -0
- package/dist/auth/login-history-repository.d.ts +14 -0
- package/dist/auth/login-history-repository.js +15 -0
- package/dist/auth/login-history-repository.test.d.ts +1 -0
- package/dist/auth/login-history-repository.test.js +47 -0
- package/dist/auth/middleware.d.ts +55 -0
- package/dist/auth/middleware.js +101 -0
- package/dist/auth/middleware.test.d.ts +1 -0
- package/dist/auth/middleware.test.js +213 -0
- package/dist/auth/scoped-tokens.test.d.ts +1 -0
- package/dist/auth/scoped-tokens.test.js +306 -0
- package/dist/auth/tenant-access.test.d.ts +1 -0
- package/dist/auth/tenant-access.test.js +62 -0
- package/dist/auth/user-creator.d.ts +9 -0
- package/dist/auth/user-creator.js +47 -0
- package/dist/auth/user-creator.test.d.ts +1 -0
- package/dist/auth/user-creator.test.js +78 -0
- package/dist/auth/user-role-repository.d.ts +31 -0
- package/dist/auth/user-role-repository.js +53 -0
- package/dist/auth/user-role-repository.test.d.ts +1 -0
- package/dist/auth/user-role-repository.test.js +122 -0
- package/dist/billing/drizzle-webhook-seen-repository.d.ts +10 -0
- package/dist/billing/drizzle-webhook-seen-repository.js +28 -0
- package/dist/billing/index.d.ts +7 -0
- package/dist/billing/index.js +7 -0
- package/dist/billing/payment-processor.d.ts +127 -0
- package/dist/billing/payment-processor.js +8 -0
- package/dist/billing/payment-processor.test.d.ts +1 -0
- package/dist/billing/payment-processor.test.js +71 -0
- package/dist/billing/payram/cents-credits-boundary.test.d.ts +1 -0
- package/dist/billing/payram/cents-credits-boundary.test.js +75 -0
- package/dist/billing/payram/charge-store.d.ts +41 -0
- package/dist/billing/payram/charge-store.js +72 -0
- package/dist/billing/payram/charge-store.test.d.ts +1 -0
- package/dist/billing/payram/charge-store.test.js +64 -0
- package/dist/billing/payram/checkout.d.ts +15 -0
- package/dist/billing/payram/checkout.js +24 -0
- package/dist/billing/payram/checkout.test.d.ts +1 -0
- package/dist/billing/payram/checkout.test.js +74 -0
- package/dist/billing/payram/client.d.ts +7 -0
- package/dist/billing/payram/client.js +15 -0
- package/dist/billing/payram/client.test.d.ts +1 -0
- package/dist/billing/payram/client.test.js +52 -0
- package/dist/billing/payram/index.d.ts +8 -0
- package/dist/billing/payram/index.js +4 -0
- package/dist/billing/payram/types.d.ts +40 -0
- package/dist/billing/payram/types.js +1 -0
- package/dist/billing/payram/webhook.d.ts +19 -0
- package/dist/billing/payram/webhook.js +67 -0
- package/dist/billing/payram/webhook.test.d.ts +7 -0
- package/dist/billing/payram/webhook.test.js +248 -0
- package/dist/billing/stripe/cents-credits-boundary.test.d.ts +1 -0
- package/dist/billing/stripe/cents-credits-boundary.test.js +62 -0
- package/dist/billing/stripe/checkout.d.ts +20 -0
- package/dist/billing/stripe/checkout.js +63 -0
- package/dist/billing/stripe/checkout.test.d.ts +1 -0
- package/dist/billing/stripe/checkout.test.js +148 -0
- package/dist/billing/stripe/client.d.ts +14 -0
- package/dist/billing/stripe/client.js +33 -0
- package/dist/billing/stripe/client.test.d.ts +1 -0
- package/dist/billing/stripe/client.test.js +58 -0
- package/dist/billing/stripe/credit-prices.d.ts +63 -0
- package/dist/billing/stripe/credit-prices.js +81 -0
- package/dist/billing/stripe/credit-prices.test.d.ts +1 -0
- package/dist/billing/stripe/credit-prices.test.js +87 -0
- package/dist/billing/stripe/index.d.ts +14 -0
- package/dist/billing/stripe/index.js +8 -0
- package/dist/billing/stripe/payment-methods-detach-all.test.d.ts +1 -0
- package/dist/billing/stripe/payment-methods-detach-all.test.js +40 -0
- package/dist/billing/stripe/payment-methods.d.ts +25 -0
- package/dist/billing/stripe/payment-methods.js +53 -0
- package/dist/billing/stripe/payment-methods.test.d.ts +1 -0
- package/dist/billing/stripe/payment-methods.test.js +122 -0
- package/dist/billing/stripe/portal.d.ts +10 -0
- package/dist/billing/stripe/portal.js +16 -0
- package/dist/billing/stripe/portal.test.d.ts +1 -0
- package/dist/billing/stripe/portal.test.js +48 -0
- package/dist/billing/stripe/setup-intent.d.ts +16 -0
- package/dist/billing/stripe/setup-intent.js +22 -0
- package/dist/billing/stripe/setup-intent.test.d.ts +1 -0
- package/dist/billing/stripe/setup-intent.test.js +58 -0
- package/dist/billing/stripe/stripe-payment-processor.d.ts +49 -0
- package/dist/billing/stripe/stripe-payment-processor.js +166 -0
- package/dist/billing/stripe/stripe-payment-processor.test.d.ts +1 -0
- package/dist/billing/stripe/stripe-payment-processor.test.js +413 -0
- package/dist/billing/stripe/tenant-store.d.ts +56 -0
- package/dist/billing/stripe/tenant-store.js +119 -0
- package/dist/billing/stripe/tenant-store.test.d.ts +1 -0
- package/dist/billing/stripe/tenant-store.test.js +97 -0
- package/dist/billing/stripe/types.d.ts +49 -0
- package/dist/billing/stripe/types.js +1 -0
- package/dist/billing/webhook-seen-repository.d.ts +14 -0
- package/dist/billing/webhook-seen-repository.js +13 -0
- package/dist/config/billing-env.test.d.ts +1 -0
- package/dist/config/billing-env.test.js +48 -0
- package/dist/config/index.d.ts +46 -0
- package/dist/config/index.js +38 -0
- package/dist/config/logger.d.ts +2 -0
- package/dist/config/logger.js +11 -0
- package/dist/config/provider-endpoints.d.ts +6 -0
- package/dist/config/provider-endpoints.js +12 -0
- package/dist/credits/auto-topup-charge.d.ts +27 -0
- package/dist/credits/auto-topup-charge.js +139 -0
- package/dist/credits/auto-topup-charge.test.d.ts +1 -0
- package/dist/credits/auto-topup-charge.test.js +242 -0
- package/dist/credits/auto-topup-event-log-repository.d.ts +16 -0
- package/dist/credits/auto-topup-event-log-repository.js +18 -0
- package/dist/credits/auto-topup-event-log-repository.test.d.ts +1 -0
- package/dist/credits/auto-topup-event-log-repository.test.js +83 -0
- package/dist/credits/auto-topup-schedule.d.ts +27 -0
- package/dist/credits/auto-topup-schedule.js +66 -0
- package/dist/credits/auto-topup-schedule.test.d.ts +1 -0
- package/dist/credits/auto-topup-schedule.test.js +145 -0
- package/dist/credits/auto-topup-settings-repository.d.ts +54 -0
- package/dist/credits/auto-topup-settings-repository.js +184 -0
- package/dist/credits/auto-topup-settings-repository.test.d.ts +1 -0
- package/dist/credits/auto-topup-settings-repository.test.js +104 -0
- package/dist/credits/auto-topup-usage.d.ts +22 -0
- package/dist/credits/auto-topup-usage.js +56 -0
- package/dist/credits/auto-topup-usage.test.d.ts +1 -0
- package/dist/credits/auto-topup-usage.test.js +181 -0
- package/dist/credits/credit-expiry-cron.d.ts +19 -0
- package/dist/credits/credit-expiry-cron.js +50 -0
- package/dist/credits/credit-expiry-cron.test.d.ts +1 -0
- package/dist/credits/credit-expiry-cron.test.js +67 -0
- package/dist/credits/credit-ledger-extra.test.d.ts +1 -0
- package/dist/credits/credit-ledger-extra.test.js +40 -0
- package/dist/credits/credit-ledger.bench.d.ts +1 -0
- package/dist/credits/credit-ledger.bench.js +33 -0
- package/dist/credits/credit-ledger.d.ts +130 -0
- package/dist/credits/credit-ledger.js +293 -0
- package/dist/credits/credit-ledger.test.d.ts +4 -0
- package/dist/credits/credit-ledger.test.js +203 -0
- package/dist/credits/credit-transaction-repository.d.ts +17 -0
- package/dist/credits/credit-transaction-repository.js +35 -0
- package/dist/credits/credit-transaction-repository.test.d.ts +1 -0
- package/dist/credits/credit-transaction-repository.test.js +232 -0
- package/dist/credits/credit.d.ts +75 -0
- package/dist/credits/credit.js +139 -0
- package/dist/credits/credit.test.d.ts +1 -0
- package/dist/credits/credit.test.js +196 -0
- package/dist/credits/dividend-cron.d.ts +29 -0
- package/dist/credits/dividend-cron.js +88 -0
- package/dist/credits/dividend-cron.test.d.ts +1 -0
- package/dist/credits/dividend-cron.test.js +128 -0
- package/dist/credits/dividend-repository.d.ts +29 -0
- package/dist/credits/dividend-repository.js +126 -0
- package/dist/credits/dividend-repository.test.d.ts +1 -0
- package/dist/credits/dividend-repository.test.js +176 -0
- package/dist/credits/index.d.ts +9 -0
- package/dist/credits/index.js +5 -0
- package/dist/credits/repository-types.d.ts +29 -0
- package/dist/credits/repository-types.js +1 -0
- package/dist/credits/signup-grant.d.ts +12 -0
- package/dist/credits/signup-grant.js +35 -0
- package/dist/credits/signup-grant.test.d.ts +1 -0
- package/dist/credits/signup-grant.test.js +51 -0
- package/dist/credits/tenant-customer-repository.d.ts +30 -0
- package/dist/credits/tenant-customer-repository.js +5 -0
- package/dist/db/auth-user-repository.d.ts +46 -0
- package/dist/db/auth-user-repository.js +90 -0
- package/dist/db/credit-column.d.ts +27 -0
- package/dist/db/credit-column.js +13 -0
- package/dist/db/index.d.ts +14 -0
- package/dist/db/index.js +8 -0
- package/dist/db/schema/account-deletion-requests.d.ts +203 -0
- package/dist/db/schema/account-deletion-requests.js +36 -0
- package/dist/db/schema/account-export-requests.d.ts +148 -0
- package/dist/db/schema/account-export-requests.js +19 -0
- package/dist/db/schema/admin-audit.d.ts +194 -0
- package/dist/db/schema/admin-audit.js +21 -0
- package/dist/db/schema/admin-users.d.ts +177 -0
- package/dist/db/schema/admin-users.js +23 -0
- package/dist/db/schema/affiliate-fraud.d.ts +160 -0
- package/dist/db/schema/affiliate-fraud.js +18 -0
- package/dist/db/schema/affiliate.d.ts +277 -0
- package/dist/db/schema/affiliate.js +32 -0
- package/dist/db/schema/coupon-codes.d.ts +143 -0
- package/dist/db/schema/coupon-codes.js +17 -0
- package/dist/db/schema/credit-auto-topup-settings.d.ts +232 -0
- package/dist/db/schema/credit-auto-topup-settings.js +27 -0
- package/dist/db/schema/credit-auto-topup.d.ts +130 -0
- package/dist/db/schema/credit-auto-topup.js +21 -0
- package/dist/db/schema/credits.d.ts +283 -0
- package/dist/db/schema/credits.js +38 -0
- package/dist/db/schema/dividend-distributions.d.ts +130 -0
- package/dist/db/schema/dividend-distributions.js +19 -0
- package/dist/db/schema/email-notifications.d.ts +99 -0
- package/dist/db/schema/email-notifications.js +21 -0
- package/dist/db/schema/index.d.ts +33 -0
- package/dist/db/schema/index.js +33 -0
- package/dist/db/schema/meter-events.d.ts +599 -0
- package/dist/db/schema/meter-events.js +55 -0
- package/dist/db/schema/notification-preferences.d.ts +165 -0
- package/dist/db/schema/notification-preferences.js +18 -0
- package/dist/db/schema/notification-queue.d.ts +236 -0
- package/dist/db/schema/notification-queue.js +40 -0
- package/dist/db/schema/org-memberships.d.ts +63 -0
- package/dist/db/schema/org-memberships.js +15 -0
- package/dist/db/schema/organization-members.d.ts +235 -0
- package/dist/db/schema/organization-members.js +27 -0
- package/dist/db/schema/payram.d.ts +164 -0
- package/dist/db/schema/payram.js +21 -0
- package/dist/db/schema/platform-api-keys.d.ts +143 -0
- package/dist/db/schema/platform-api-keys.js +20 -0
- package/dist/db/schema/promotion-redemptions.d.ts +143 -0
- package/dist/db/schema/promotion-redemptions.js +18 -0
- package/dist/db/schema/promotions.d.ts +445 -0
- package/dist/db/schema/promotions.js +48 -0
- package/dist/db/schema/provider-credentials.d.ts +201 -0
- package/dist/db/schema/provider-credentials.js +36 -0
- package/dist/db/schema/rate-limit-entries.d.ts +75 -0
- package/dist/db/schema/rate-limit-entries.js +7 -0
- package/dist/db/schema/secret-audit-log.d.ts +109 -0
- package/dist/db/schema/secret-audit-log.js +15 -0
- package/dist/db/schema/session-usage.d.ts +194 -0
- package/dist/db/schema/session-usage.js +19 -0
- package/dist/db/schema/spending-limits.d.ts +92 -0
- package/dist/db/schema/spending-limits.js +8 -0
- package/dist/db/schema/tenant-addons.d.ts +58 -0
- package/dist/db/schema/tenant-addons.js +9 -0
- package/dist/db/schema/tenant-api-keys.d.ts +131 -0
- package/dist/db/schema/tenant-api-keys.js +21 -0
- package/dist/db/schema/tenant-capability-settings.d.ts +79 -0
- package/dist/db/schema/tenant-capability-settings.js +12 -0
- package/dist/db/schema/tenant-customers.d.ts +303 -0
- package/dist/db/schema/tenant-customers.js +25 -0
- package/dist/db/schema/tenants.d.ts +126 -0
- package/dist/db/schema/tenants.js +18 -0
- package/dist/db/schema/user-roles.d.ts +98 -0
- package/dist/db/schema/user-roles.js +18 -0
- package/dist/db/schema/webhook-seen-events.d.ts +58 -0
- package/dist/db/schema/webhook-seen-events.js +9 -0
- package/dist/email/billing-emails.d.ts +51 -0
- package/dist/email/billing-emails.js +163 -0
- package/dist/email/billing-emails.test.d.ts +1 -0
- package/dist/email/billing-emails.test.js +162 -0
- package/dist/email/client.d.ts +51 -0
- package/dist/email/client.js +102 -0
- package/dist/email/client.test.d.ts +1 -0
- package/dist/email/client.test.js +120 -0
- package/dist/email/drizzle-billing-email-repository.d.ts +21 -0
- package/dist/email/drizzle-billing-email-repository.js +36 -0
- package/dist/email/drizzle-billing-email-repository.test.d.ts +1 -0
- package/dist/email/drizzle-billing-email-repository.test.js +42 -0
- package/dist/email/index.d.ts +33 -0
- package/dist/email/index.js +22 -0
- package/dist/email/notification-preferences-store.d.ts +12 -0
- package/dist/email/notification-preferences-store.js +82 -0
- package/dist/email/notification-preferences-store.test.d.ts +1 -0
- package/dist/email/notification-preferences-store.test.js +86 -0
- package/dist/email/notification-queue-store.d.ts +25 -0
- package/dist/email/notification-queue-store.js +97 -0
- package/dist/email/notification-queue-store.test.d.ts +1 -0
- package/dist/email/notification-queue-store.test.js +177 -0
- package/dist/email/notification-repository-types.d.ts +70 -0
- package/dist/email/notification-repository-types.js +6 -0
- package/dist/email/notification-service.d.ts +41 -0
- package/dist/email/notification-service.js +196 -0
- package/dist/email/notification-service.test.d.ts +1 -0
- package/dist/email/notification-service.test.js +160 -0
- package/dist/email/notification-templates.d.ts +18 -0
- package/dist/email/notification-templates.js +574 -0
- package/dist/email/notification-templates.test.d.ts +1 -0
- package/dist/email/notification-templates.test.js +238 -0
- package/dist/email/notification-worker.d.ts +24 -0
- package/dist/email/notification-worker.js +109 -0
- package/dist/email/notification-worker.test.d.ts +1 -0
- package/dist/email/notification-worker.test.js +153 -0
- package/dist/email/require-verified.d.ts +25 -0
- package/dist/email/require-verified.js +52 -0
- package/dist/email/require-verified.test.d.ts +1 -0
- package/dist/email/require-verified.test.js +62 -0
- package/dist/email/resend-adapter.d.ts +47 -0
- package/dist/email/resend-adapter.js +137 -0
- package/dist/email/resend-adapter.test.d.ts +1 -0
- package/dist/email/resend-adapter.test.js +190 -0
- package/dist/email/templates.d.ts +22 -0
- package/dist/email/templates.js +359 -0
- package/dist/email/templates.test.d.ts +1 -0
- package/dist/email/templates.test.js +170 -0
- package/dist/email/verification.d.ts +42 -0
- package/dist/email/verification.js +83 -0
- package/dist/email/verification.test.d.ts +1 -0
- package/dist/email/verification.test.js +141 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +23 -0
- package/dist/metering/aggregator.d.ts +54 -0
- package/dist/metering/aggregator.js +123 -0
- package/dist/metering/aggregator.test.d.ts +1 -0
- package/dist/metering/aggregator.test.js +179 -0
- package/dist/metering/dlq.d.ts +31 -0
- package/dist/metering/dlq.js +82 -0
- package/dist/metering/dlq.test.d.ts +1 -0
- package/dist/metering/dlq.test.js +117 -0
- package/dist/metering/drizzle-usage-summary-repository.d.ts +67 -0
- package/dist/metering/drizzle-usage-summary-repository.js +98 -0
- package/dist/metering/emitter.d.ts +66 -0
- package/dist/metering/emitter.js +185 -0
- package/dist/metering/emitter.test.d.ts +1 -0
- package/dist/metering/emitter.test.js +171 -0
- package/dist/metering/index.d.ts +11 -0
- package/dist/metering/index.js +5 -0
- package/dist/metering/load-test.bench.d.ts +1 -0
- package/dist/metering/load-test.bench.js +103 -0
- package/dist/metering/meter-event-repository.d.ts +33 -0
- package/dist/metering/meter-event-repository.js +58 -0
- package/dist/metering/meter-repositories.test.d.ts +1 -0
- package/dist/metering/meter-repositories.test.js +419 -0
- package/dist/metering/metering.test.d.ts +1 -0
- package/dist/metering/metering.test.js +1046 -0
- package/dist/metering/reconciliation-cron.d.ts +37 -0
- package/dist/metering/reconciliation-cron.js +85 -0
- package/dist/metering/reconciliation-cron.test.d.ts +1 -0
- package/dist/metering/reconciliation-cron.test.js +162 -0
- package/dist/metering/reconciliation-repository.d.ts +27 -0
- package/dist/metering/reconciliation-repository.js +43 -0
- package/dist/metering/reconciliation-repository.test.d.ts +1 -0
- package/dist/metering/reconciliation-repository.test.js +160 -0
- package/dist/metering/types.d.ts +88 -0
- package/dist/metering/types.js +1 -0
- package/dist/metering/wal.d.ts +49 -0
- package/dist/metering/wal.js +124 -0
- package/dist/metering/wal.test.d.ts +1 -0
- package/dist/metering/wal.test.js +175 -0
- package/dist/middleware/csrf.d.ts +24 -0
- package/dist/middleware/csrf.js +80 -0
- package/dist/middleware/csrf.test.d.ts +1 -0
- package/dist/middleware/csrf.test.js +152 -0
- package/dist/middleware/drizzle-rate-limit-repository.d.ts +9 -0
- package/dist/middleware/drizzle-rate-limit-repository.js +52 -0
- package/dist/middleware/drizzle-rate-limit-repository.test.d.ts +1 -0
- package/dist/middleware/drizzle-rate-limit-repository.test.js +74 -0
- package/dist/middleware/get-client-ip.d.ts +22 -0
- package/dist/middleware/get-client-ip.js +51 -0
- package/dist/middleware/get-client-ip.test.d.ts +1 -0
- package/dist/middleware/get-client-ip.test.js +40 -0
- package/dist/middleware/index.d.ts +5 -0
- package/dist/middleware/index.js +4 -0
- package/dist/middleware/rate-limit-repository.d.ts +19 -0
- package/dist/middleware/rate-limit-repository.js +1 -0
- package/dist/middleware/rate-limit.d.ts +57 -0
- package/dist/middleware/rate-limit.js +109 -0
- package/dist/middleware/rate-limit.test.d.ts +1 -0
- package/dist/middleware/rate-limit.test.js +247 -0
- package/dist/security/credential-vault/audit-repository.d.ts +27 -0
- package/dist/security/credential-vault/audit-repository.js +42 -0
- package/dist/security/credential-vault/audit-repository.test.d.ts +1 -0
- package/dist/security/credential-vault/audit-repository.test.js +78 -0
- package/dist/security/credential-vault/credential-repository.d.ts +94 -0
- package/dist/security/credential-vault/credential-repository.js +145 -0
- package/dist/security/credential-vault/credential-repository.test.d.ts +1 -0
- package/dist/security/credential-vault/credential-repository.test.js +206 -0
- package/dist/security/credential-vault/index.d.ts +12 -0
- package/dist/security/credential-vault/index.js +6 -0
- package/dist/security/credential-vault/key-rotation.d.ts +18 -0
- package/dist/security/credential-vault/key-rotation.js +52 -0
- package/dist/security/credential-vault/key-rotation.test.d.ts +1 -0
- package/dist/security/credential-vault/key-rotation.test.js +95 -0
- package/dist/security/credential-vault/migrate-plaintext.d.ts +15 -0
- package/dist/security/credential-vault/migrate-plaintext.js +80 -0
- package/dist/security/credential-vault/migrate-plaintext.test.d.ts +1 -0
- package/dist/security/credential-vault/migrate-plaintext.test.js +111 -0
- package/dist/security/credential-vault/migration-check.d.ts +15 -0
- package/dist/security/credential-vault/migration-check.js +71 -0
- package/dist/security/credential-vault/migration-check.test.d.ts +1 -0
- package/dist/security/credential-vault/migration-check.test.js +457 -0
- package/dist/security/credential-vault/store.d.ts +106 -0
- package/dist/security/credential-vault/store.js +181 -0
- package/dist/security/credential-vault/store.test.d.ts +1 -0
- package/dist/security/credential-vault/store.test.js +482 -0
- package/dist/security/encryption.d.ts +22 -0
- package/dist/security/encryption.js +53 -0
- package/dist/security/encryption.test.d.ts +1 -0
- package/dist/security/encryption.test.js +95 -0
- package/dist/security/host-validation.d.ts +11 -0
- package/dist/security/host-validation.js +108 -0
- package/dist/security/host-validation.test.d.ts +1 -0
- package/dist/security/host-validation.test.js +106 -0
- package/dist/security/index.d.ts +11 -0
- package/dist/security/index.js +11 -0
- package/dist/security/key-audit.d.ts +16 -0
- package/dist/security/key-audit.js +35 -0
- package/dist/security/key-audit.test.d.ts +1 -0
- package/dist/security/key-audit.test.js +50 -0
- package/dist/security/key-injection.d.ts +28 -0
- package/dist/security/key-injection.js +57 -0
- package/dist/security/key-injection.test.d.ts +1 -0
- package/dist/security/key-injection.test.js +97 -0
- package/dist/security/key-validation.d.ts +16 -0
- package/dist/security/key-validation.js +78 -0
- package/dist/security/key-validation.test.d.ts +1 -0
- package/dist/security/key-validation.test.js +87 -0
- package/dist/security/redirect-allowlist.d.ts +6 -0
- package/dist/security/redirect-allowlist.js +36 -0
- package/dist/security/redirect-allowlist.test.d.ts +1 -0
- package/dist/security/redirect-allowlist.test.js +55 -0
- package/dist/security/tenant-keys/capability-settings-store.d.ts +22 -0
- package/dist/security/tenant-keys/capability-settings-store.js +33 -0
- package/dist/security/tenant-keys/capability-settings-store.test.d.ts +1 -0
- package/dist/security/tenant-keys/capability-settings-store.test.js +77 -0
- package/dist/security/tenant-keys/index.d.ts +10 -0
- package/dist/security/tenant-keys/index.js +5 -0
- package/dist/security/tenant-keys/key-resolution-repository.d.ts +15 -0
- package/dist/security/tenant-keys/key-resolution-repository.js +18 -0
- package/dist/security/tenant-keys/key-resolution-repository.test.d.ts +1 -0
- package/dist/security/tenant-keys/key-resolution-repository.test.js +72 -0
- package/dist/security/tenant-keys/key-resolution.d.ts +39 -0
- package/dist/security/tenant-keys/key-resolution.js +59 -0
- package/dist/security/tenant-keys/key-resolution.test.d.ts +1 -0
- package/dist/security/tenant-keys/key-resolution.test.js +97 -0
- package/dist/security/tenant-keys/org-key-resolution.d.ts +30 -0
- package/dist/security/tenant-keys/org-key-resolution.js +50 -0
- package/dist/security/tenant-keys/org-key-resolution.test.d.ts +1 -0
- package/dist/security/tenant-keys/org-key-resolution.test.js +103 -0
- package/dist/security/tenant-keys/tenant-key-repository.d.ts +36 -0
- package/dist/security/tenant-keys/tenant-key-repository.js +96 -0
- package/dist/security/tenant-keys/tenant-key-repository.test.d.ts +1 -0
- package/dist/security/tenant-keys/tenant-key-repository.test.js +114 -0
- package/dist/security/types.d.ts +35 -0
- package/dist/security/types.js +15 -0
- package/dist/tenancy/drizzle-org-repository.d.ts +40 -0
- package/dist/tenancy/drizzle-org-repository.js +126 -0
- package/dist/tenancy/index.d.ts +6 -0
- package/dist/tenancy/index.js +3 -0
- package/dist/tenancy/org-member-repository.d.ts +57 -0
- package/dist/tenancy/org-member-repository.js +99 -0
- package/dist/tenancy/org-repository.test.d.ts +1 -0
- package/dist/tenancy/org-repository.test.js +143 -0
- package/dist/tenancy/org-service.d.ts +70 -0
- package/dist/tenancy/org-service.js +223 -0
- package/dist/tenancy/org-service.test.d.ts +1 -0
- package/dist/tenancy/org-service.test.js +550 -0
- package/dist/test/db.d.ts +33 -0
- package/dist/test/db.js +65 -0
- package/dist/trpc/index.d.ts +1 -0
- package/dist/trpc/index.js +1 -0
- package/dist/trpc/init.d.ts +49 -0
- package/dist/trpc/init.js +108 -0
- package/dist/trpc/init.test.d.ts +1 -0
- package/dist/trpc/init.test.js +154 -0
- package/drizzle/migrations/0000_slippery_mandrill.sql +559 -0
- package/drizzle/migrations/meta/0000_snapshot.json +4374 -0
- package/drizzle/migrations/meta/_journal.json +13 -0
- package/drizzle.config.ts +41 -0
- package/package.json +64 -0
- package/src/admin/admin-audit-log-repository.ts +135 -0
- package/src/admin/audit-log.ts +111 -0
- package/src/admin/index.ts +6 -0
- package/src/admin/role-store.ts +134 -0
- package/src/auth/api-key-repository.test.ts +63 -0
- package/src/auth/api-key-repository.ts +46 -0
- package/src/auth/auth.test.ts +166 -0
- package/src/auth/better-auth.ts +216 -0
- package/src/auth/index.ts +520 -0
- package/src/auth/login-history-repository.test.ts +54 -0
- package/src/auth/login-history-repository.ts +28 -0
- package/src/auth/middleware.test.ts +264 -0
- package/src/auth/middleware.ts +117 -0
- package/src/auth/scoped-tokens.test.ts +362 -0
- package/src/auth/tenant-access.test.ts +69 -0
- package/src/auth/user-creator.test.ts +98 -0
- package/src/auth/user-creator.ts +54 -0
- package/src/auth/user-role-repository.test.ts +149 -0
- package/src/auth/user-role-repository.ts +67 -0
- package/src/billing/drizzle-webhook-seen-repository.ts +34 -0
- package/src/billing/index.ts +22 -0
- package/src/billing/payment-processor.test.ts +93 -0
- package/src/billing/payment-processor.ts +150 -0
- package/src/billing/payram/cents-credits-boundary.test.ts +84 -0
- package/src/billing/payram/charge-store.test.ts +84 -0
- package/src/billing/payram/charge-store.ts +109 -0
- package/src/billing/payram/checkout.test.ts +99 -0
- package/src/billing/payram/checkout.ts +40 -0
- package/src/billing/payram/client.test.ts +62 -0
- package/src/billing/payram/client.ts +21 -0
- package/src/billing/payram/index.ts +14 -0
- package/src/billing/payram/types.ts +44 -0
- package/src/billing/payram/webhook.test.ts +318 -0
- package/src/billing/payram/webhook.ts +97 -0
- package/src/billing/stripe/cents-credits-boundary.test.ts +70 -0
- package/src/billing/stripe/checkout.test.ts +186 -0
- package/src/billing/stripe/checkout.ts +82 -0
- package/src/billing/stripe/client.test.ts +64 -0
- package/src/billing/stripe/client.ts +39 -0
- package/src/billing/stripe/credit-prices.test.ts +114 -0
- package/src/billing/stripe/credit-prices.ts +113 -0
- package/src/billing/stripe/index.ts +14 -0
- package/src/billing/stripe/payment-methods-detach-all.test.ts +53 -0
- package/src/billing/stripe/payment-methods.test.ts +157 -0
- package/src/billing/stripe/payment-methods.ts +76 -0
- package/src/billing/stripe/portal.test.ts +63 -0
- package/src/billing/stripe/portal.ts +25 -0
- package/src/billing/stripe/setup-intent.test.ts +78 -0
- package/src/billing/stripe/setup-intent.ts +34 -0
- package/src/billing/stripe/stripe-payment-processor.test.ts +517 -0
- package/src/billing/stripe/stripe-payment-processor.ts +255 -0
- package/src/billing/stripe/tenant-store.test.ts +124 -0
- package/src/billing/stripe/tenant-store.ts +151 -0
- package/src/billing/stripe/types.ts +53 -0
- package/src/billing/webhook-seen-repository.ts +24 -0
- package/src/config/billing-env.test.ts +54 -0
- package/src/config/index.ts +44 -0
- package/src/config/logger.ts +12 -0
- package/src/config/provider-endpoints.ts +14 -0
- package/src/credits/auto-topup-charge.test.ts +292 -0
- package/src/credits/auto-topup-charge.ts +171 -0
- package/src/credits/auto-topup-event-log-repository.test.ts +99 -0
- package/src/credits/auto-topup-event-log-repository.ts +30 -0
- package/src/credits/auto-topup-schedule.test.ts +179 -0
- package/src/credits/auto-topup-schedule.ts +93 -0
- package/src/credits/auto-topup-settings-repository.test.ts +123 -0
- package/src/credits/auto-topup-settings-repository.ts +245 -0
- package/src/credits/auto-topup-usage.test.ts +220 -0
- package/src/credits/auto-topup-usage.ts +68 -0
- package/src/credits/credit-expiry-cron.test.ts +125 -0
- package/src/credits/credit-expiry-cron.ts +76 -0
- package/src/credits/credit-ledger-extra.test.ts +57 -0
- package/src/credits/credit-ledger.bench.ts +56 -0
- package/src/credits/credit-ledger.test.ts +276 -0
- package/src/credits/credit-ledger.ts +450 -0
- package/src/credits/credit-transaction-repository.test.ts +274 -0
- package/src/credits/credit-transaction-repository.ts +62 -0
- package/src/credits/credit.test.ts +234 -0
- package/src/credits/credit.ts +160 -0
- package/src/credits/dividend-cron.test.ts +158 -0
- package/src/credits/dividend-cron.ts +127 -0
- package/src/credits/dividend-repository.test.ts +223 -0
- package/src/credits/dividend-repository.ts +182 -0
- package/src/credits/index.ts +25 -0
- package/src/credits/repository-types.ts +33 -0
- package/src/credits/signup-grant.test.ts +63 -0
- package/src/credits/signup-grant.ts +44 -0
- package/src/credits/tenant-customer-repository.ts +28 -0
- package/src/db/auth-user-repository.ts +124 -0
- package/src/db/credit-column.ts +17 -0
- package/src/db/index.ts +21 -0
- package/src/db/schema/account-deletion-requests.ts +41 -0
- package/src/db/schema/account-export-requests.ts +24 -0
- package/src/db/schema/admin-audit.ts +26 -0
- package/src/db/schema/admin-users.ts +31 -0
- package/src/db/schema/affiliate-fraud.ts +23 -0
- package/src/db/schema/affiliate.ts +38 -0
- package/src/db/schema/coupon-codes.ts +22 -0
- package/src/db/schema/credit-auto-topup-settings.ts +32 -0
- package/src/db/schema/credit-auto-topup.ts +26 -0
- package/src/db/schema/credits.ts +44 -0
- package/src/db/schema/dividend-distributions.ts +24 -0
- package/src/db/schema/email-notifications.ts +26 -0
- package/src/db/schema/index.ts +33 -0
- package/src/db/schema/meter-events.ts +70 -0
- package/src/db/schema/notification-preferences.ts +19 -0
- package/src/db/schema/notification-queue.ts +45 -0
- package/src/db/schema/org-memberships.ts +20 -0
- package/src/db/schema/organization-members.ts +37 -0
- package/src/db/schema/payram.ts +26 -0
- package/src/db/schema/platform-api-keys.ts +25 -0
- package/src/db/schema/promotion-redemptions.ts +23 -0
- package/src/db/schema/promotions.ts +57 -0
- package/src/db/schema/provider-credentials.ts +41 -0
- package/src/db/schema/rate-limit-entries.ts +12 -0
- package/src/db/schema/secret-audit-log.ts +20 -0
- package/src/db/schema/session-usage.ts +24 -0
- package/src/db/schema/spending-limits.ts +9 -0
- package/src/db/schema/tenant-addons.ts +14 -0
- package/src/db/schema/tenant-api-keys.ts +26 -0
- package/src/db/schema/tenant-capability-settings.ts +17 -0
- package/src/db/schema/tenant-customers.ts +35 -0
- package/src/db/schema/tenants.ts +23 -0
- package/src/db/schema/user-roles.ts +23 -0
- package/src/db/schema/webhook-seen-events.ts +14 -0
- package/src/email/billing-emails.test.ts +198 -0
- package/src/email/billing-emails.ts +211 -0
- package/src/email/client.test.ts +149 -0
- package/src/email/client.ts +137 -0
- package/src/email/drizzle-billing-email-repository.test.ts +52 -0
- package/src/email/drizzle-billing-email-repository.ts +59 -0
- package/src/email/index.ts +57 -0
- package/src/email/notification-preferences-store.test.ts +102 -0
- package/src/email/notification-preferences-store.ts +90 -0
- package/src/email/notification-queue-store.test.ts +215 -0
- package/src/email/notification-queue-store.ts +127 -0
- package/src/email/notification-repository-types.ts +101 -0
- package/src/email/notification-service.test.ts +178 -0
- package/src/email/notification-service.ts +265 -0
- package/src/email/notification-templates.test.ts +261 -0
- package/src/email/notification-templates.ts +727 -0
- package/src/email/notification-worker.test.ts +189 -0
- package/src/email/notification-worker.ts +133 -0
- package/src/email/require-verified.ts +65 -0
- package/src/email/resend-adapter.test.ts +253 -0
- package/src/email/resend-adapter.ts +157 -0
- package/src/email/templates.test.ts +217 -0
- package/src/email/templates.ts +469 -0
- package/src/email/verification.test.ts +185 -0
- package/src/email/verification.ts +110 -0
- package/src/index.ts +51 -0
- package/src/metering/aggregator.test.ts +239 -0
- package/src/metering/aggregator.ts +160 -0
- package/src/metering/dlq.test.ts +134 -0
- package/src/metering/dlq.ts +102 -0
- package/src/metering/drizzle-usage-summary-repository.ts +167 -0
- package/src/metering/emitter.test.ts +202 -0
- package/src/metering/emitter.ts +227 -0
- package/src/metering/index.ts +21 -0
- package/src/metering/load-test.bench.ts +130 -0
- package/src/metering/meter-event-repository.ts +87 -0
- package/src/metering/meter-repositories.test.ts +491 -0
- package/src/metering/metering.test.ts +1317 -0
- package/src/metering/reconciliation-cron.test.ts +202 -0
- package/src/metering/reconciliation-cron.ts +134 -0
- package/src/metering/reconciliation-repository.test.ts +196 -0
- package/src/metering/reconciliation-repository.ts +83 -0
- package/src/metering/types.ts +93 -0
- package/src/metering/wal.test.ts +222 -0
- package/src/metering/wal.ts +139 -0
- package/src/middleware/csrf.test.ts +178 -0
- package/src/middleware/csrf.ts +101 -0
- package/src/middleware/drizzle-rate-limit-repository.test.ts +97 -0
- package/src/middleware/drizzle-rate-limit-repository.ts +57 -0
- package/src/middleware/get-client-ip.test.ts +49 -0
- package/src/middleware/get-client-ip.ts +62 -0
- package/src/middleware/index.ts +12 -0
- package/src/middleware/rate-limit-repository.ts +22 -0
- package/src/middleware/rate-limit.test.ts +338 -0
- package/src/middleware/rate-limit.ts +169 -0
- package/src/security/credential-vault/audit-repository.test.ts +91 -0
- package/src/security/credential-vault/audit-repository.ts +64 -0
- package/src/security/credential-vault/credential-repository.test.ts +264 -0
- package/src/security/credential-vault/credential-repository.ts +233 -0
- package/src/security/credential-vault/index.ts +26 -0
- package/src/security/credential-vault/key-rotation.test.ts +139 -0
- package/src/security/credential-vault/key-rotation.ts +70 -0
- package/src/security/credential-vault/migrate-plaintext.test.ts +138 -0
- package/src/security/credential-vault/migrate-plaintext.ts +101 -0
- package/src/security/credential-vault/migration-check.test.ts +533 -0
- package/src/security/credential-vault/migration-check.ts +88 -0
- package/src/security/credential-vault/store.test.ts +569 -0
- package/src/security/credential-vault/store.ts +284 -0
- package/src/security/encryption.test.ts +114 -0
- package/src/security/encryption.ts +65 -0
- package/src/security/host-validation.test.ts +136 -0
- package/src/security/host-validation.ts +116 -0
- package/src/security/index.ts +59 -0
- package/src/security/key-audit.test.ts +57 -0
- package/src/security/key-audit.ts +45 -0
- package/src/security/key-injection.test.ts +131 -0
- package/src/security/key-injection.ts +71 -0
- package/src/security/key-validation.test.ts +111 -0
- package/src/security/key-validation.ts +84 -0
- package/src/security/redirect-allowlist.test.ts +70 -0
- package/src/security/redirect-allowlist.ts +35 -0
- package/src/security/tenant-keys/capability-settings-store.test.ts +98 -0
- package/src/security/tenant-keys/capability-settings-store.ts +53 -0
- package/src/security/tenant-keys/index.ts +10 -0
- package/src/security/tenant-keys/key-resolution-repository.test.ts +95 -0
- package/src/security/tenant-keys/key-resolution-repository.ts +31 -0
- package/src/security/tenant-keys/key-resolution.test.ts +173 -0
- package/src/security/tenant-keys/key-resolution.ts +87 -0
- package/src/security/tenant-keys/org-key-resolution.test.ts +217 -0
- package/src/security/tenant-keys/org-key-resolution.ts +76 -0
- package/src/security/tenant-keys/tenant-key-repository.test.ts +143 -0
- package/src/security/tenant-keys/tenant-key-repository.ts +130 -0
- package/src/security/types.ts +43 -0
- package/src/tenancy/drizzle-org-repository.ts +169 -0
- package/src/tenancy/index.ts +6 -0
- package/src/tenancy/org-member-repository.ts +159 -0
- package/src/tenancy/org-repository.test.ts +172 -0
- package/src/tenancy/org-service.test.ts +634 -0
- package/src/tenancy/org-service.ts +290 -0
- package/src/test/db.ts +97 -0
- package/src/trpc/index.ts +11 -0
- package/src/trpc/init.test.ts +196 -0
- package/src/trpc/init.ts +138 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resend Email Adapter for Better Auth
|
|
3
|
+
*
|
|
4
|
+
* Provides transactional email capability for Better Auth password reset flows.
|
|
5
|
+
* Uses Resend API for email delivery.
|
|
6
|
+
*/
|
|
7
|
+
export interface EmailOptions {
|
|
8
|
+
to: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
html: string;
|
|
11
|
+
text?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Escape HTML special characters to prevent XSS.
|
|
15
|
+
*
|
|
16
|
+
* @param str - String to escape
|
|
17
|
+
* @returns Escaped string safe for HTML interpolation
|
|
18
|
+
*/
|
|
19
|
+
export declare function escapeHtml(str: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Send an email using Resend.
|
|
22
|
+
*
|
|
23
|
+
* @param options - Email configuration (to, subject, html, text)
|
|
24
|
+
* @param apiKey - Resend API key (defaults to RESEND_API_KEY env var)
|
|
25
|
+
* @param from - Sender email address (defaults to RESEND_FROM_EMAIL env var)
|
|
26
|
+
* @returns Resend response
|
|
27
|
+
*/
|
|
28
|
+
export declare function sendEmail(options: EmailOptions, apiKey?: string, from?: string): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
success: boolean;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Generate password reset email HTML template.
|
|
34
|
+
*
|
|
35
|
+
* @param resetUrl - The password reset URL with token
|
|
36
|
+
* @param email - User's email address
|
|
37
|
+
* @returns HTML email content
|
|
38
|
+
*/
|
|
39
|
+
export declare function passwordResetTemplate(resetUrl: string, email: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Generate plain text version of password reset email.
|
|
42
|
+
*
|
|
43
|
+
* @param resetUrl - The password reset URL with token
|
|
44
|
+
* @param email - User's email address
|
|
45
|
+
* @returns Plain text email content
|
|
46
|
+
*/
|
|
47
|
+
export declare function passwordResetText(resetUrl: string, email: string): string;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resend Email Adapter for Better Auth
|
|
3
|
+
*
|
|
4
|
+
* Provides transactional email capability for Better Auth password reset flows.
|
|
5
|
+
* Uses Resend API for email delivery.
|
|
6
|
+
*/
|
|
7
|
+
import { Resend } from "resend";
|
|
8
|
+
/**
|
|
9
|
+
* Escape HTML special characters to prevent XSS.
|
|
10
|
+
*
|
|
11
|
+
* @param str - String to escape
|
|
12
|
+
* @returns Escaped string safe for HTML interpolation
|
|
13
|
+
*/
|
|
14
|
+
export function escapeHtml(str) {
|
|
15
|
+
const map = {
|
|
16
|
+
"&": "&",
|
|
17
|
+
"<": "<",
|
|
18
|
+
">": ">",
|
|
19
|
+
'"': """,
|
|
20
|
+
"'": "'",
|
|
21
|
+
};
|
|
22
|
+
return str.replace(/[&<>"']/g, (char) => map[char] || char);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Send an email using Resend.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Email configuration (to, subject, html, text)
|
|
28
|
+
* @param apiKey - Resend API key (defaults to RESEND_API_KEY env var)
|
|
29
|
+
* @param from - Sender email address (defaults to RESEND_FROM_EMAIL env var)
|
|
30
|
+
* @returns Resend response
|
|
31
|
+
*/
|
|
32
|
+
export async function sendEmail(options, apiKey, from) {
|
|
33
|
+
const key = apiKey || process.env.RESEND_API_KEY;
|
|
34
|
+
if (!key) {
|
|
35
|
+
throw new Error("RESEND_API_KEY environment variable is required");
|
|
36
|
+
}
|
|
37
|
+
const fromEmail = from || process.env.RESEND_FROM_EMAIL || "noreply@wopr.bot";
|
|
38
|
+
const resend = new Resend(key);
|
|
39
|
+
const { data, error } = await resend.emails.send({
|
|
40
|
+
from: fromEmail,
|
|
41
|
+
to: options.to,
|
|
42
|
+
subject: options.subject,
|
|
43
|
+
html: options.html,
|
|
44
|
+
text: options.text,
|
|
45
|
+
});
|
|
46
|
+
if (error) {
|
|
47
|
+
throw new Error(`Failed to send email: ${error.message}`);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
id: data?.id || "",
|
|
51
|
+
success: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate password reset email HTML template.
|
|
56
|
+
*
|
|
57
|
+
* @param resetUrl - The password reset URL with token
|
|
58
|
+
* @param email - User's email address
|
|
59
|
+
* @returns HTML email content
|
|
60
|
+
*/
|
|
61
|
+
export function passwordResetTemplate(resetUrl, email) {
|
|
62
|
+
const escapedEmail = escapeHtml(email);
|
|
63
|
+
const escapedResetUrl = escapeHtml(resetUrl);
|
|
64
|
+
return `
|
|
65
|
+
<!DOCTYPE html>
|
|
66
|
+
<html>
|
|
67
|
+
<head>
|
|
68
|
+
<meta charset="utf-8">
|
|
69
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
70
|
+
<title>Reset Your Password</title>
|
|
71
|
+
</head>
|
|
72
|
+
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f4f4f4;">
|
|
73
|
+
<table role="presentation" style="width: 100%; border-collapse: collapse;">
|
|
74
|
+
<tr>
|
|
75
|
+
<td style="padding: 40px 0; text-align: center;">
|
|
76
|
+
<table role="presentation" style="width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
77
|
+
<tr>
|
|
78
|
+
<td style="padding: 40px 40px 20px 40px; text-align: center;">
|
|
79
|
+
<h1 style="margin: 0; font-size: 24px; font-weight: 600; color: #1a1a1a;">Reset Your Password</h1>
|
|
80
|
+
</td>
|
|
81
|
+
</tr>
|
|
82
|
+
<tr>
|
|
83
|
+
<td style="padding: 0 40px 20px 40px; color: #4a5568; font-size: 16px; line-height: 24px;">
|
|
84
|
+
<p>Hi there,</p>
|
|
85
|
+
<p>You requested a password reset for your WOPR account (<strong>${escapedEmail}</strong>).</p>
|
|
86
|
+
<p>Click the button below to create a new password. This link will expire in 1 hour.</p>
|
|
87
|
+
</td>
|
|
88
|
+
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td style="padding: 0 40px 30px 40px; text-align: center;">
|
|
91
|
+
<a href="${resetUrl}" style="display: inline-block; padding: 12px 32px; background-color: #2563eb; color: #ffffff; text-decoration: none; font-weight: 600; border-radius: 6px; font-size: 16px;">Reset Password</a>
|
|
92
|
+
</td>
|
|
93
|
+
</tr>
|
|
94
|
+
<tr>
|
|
95
|
+
<td style="padding: 0 40px 20px 40px; color: #718096; font-size: 14px; line-height: 20px;">
|
|
96
|
+
<p>Or copy and paste this URL into your browser:</p>
|
|
97
|
+
<p style="word-break: break-all; color: #2563eb;">${escapedResetUrl}</p>
|
|
98
|
+
</td>
|
|
99
|
+
</tr>
|
|
100
|
+
<tr>
|
|
101
|
+
<td style="padding: 0 40px 40px 40px; color: #718096; font-size: 14px; line-height: 20px; border-top: 1px solid #e2e8f0;">
|
|
102
|
+
<p style="margin-top: 20px;">If you didn't request this password reset, you can safely ignore this email.</p>
|
|
103
|
+
</td>
|
|
104
|
+
</tr>
|
|
105
|
+
</table>
|
|
106
|
+
<p style="margin-top: 20px; color: #a0aec0; font-size: 12px;">© ${new Date().getFullYear()} WOPR Network. All rights reserved.</p>
|
|
107
|
+
</td>
|
|
108
|
+
</tr>
|
|
109
|
+
</table>
|
|
110
|
+
</body>
|
|
111
|
+
</html>
|
|
112
|
+
`.trim();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Generate plain text version of password reset email.
|
|
116
|
+
*
|
|
117
|
+
* @param resetUrl - The password reset URL with token
|
|
118
|
+
* @param email - User's email address
|
|
119
|
+
* @returns Plain text email content
|
|
120
|
+
*/
|
|
121
|
+
export function passwordResetText(resetUrl, email) {
|
|
122
|
+
return `
|
|
123
|
+
Reset Your Password
|
|
124
|
+
|
|
125
|
+
Hi there,
|
|
126
|
+
|
|
127
|
+
You requested a password reset for your WOPR account (${email}).
|
|
128
|
+
|
|
129
|
+
Click the link below to create a new password. This link will expire in 1 hour.
|
|
130
|
+
|
|
131
|
+
${resetUrl}
|
|
132
|
+
|
|
133
|
+
If you didn't request this password reset, you can safely ignore this email.
|
|
134
|
+
|
|
135
|
+
© ${new Date().getFullYear()} WOPR Network. All rights reserved.
|
|
136
|
+
`.trim();
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { escapeHtml, passwordResetTemplate, passwordResetText, sendEmail, } from "./resend-adapter.js";
|
|
3
|
+
// Create a mock send function that can be controlled in tests
|
|
4
|
+
const mockSend = vi.fn();
|
|
5
|
+
// Mock the Resend module
|
|
6
|
+
vi.mock("resend", () => {
|
|
7
|
+
return {
|
|
8
|
+
Resend: class MockResend {
|
|
9
|
+
emails = {
|
|
10
|
+
send: mockSend,
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
describe("escapeHtml", () => {
|
|
16
|
+
it("should escape all dangerous HTML characters", () => {
|
|
17
|
+
expect(escapeHtml("<script>alert('XSS')</script>")).toBe("<script>alert('XSS')</script>");
|
|
18
|
+
expect(escapeHtml('Test "quotes" & <tags>')).toBe("Test "quotes" & <tags>");
|
|
19
|
+
expect(escapeHtml("user@example.com")).toBe("user@example.com");
|
|
20
|
+
});
|
|
21
|
+
it("should handle empty strings", () => {
|
|
22
|
+
expect(escapeHtml("")).toBe("");
|
|
23
|
+
});
|
|
24
|
+
it("should handle strings with no special characters", () => {
|
|
25
|
+
expect(escapeHtml("normal text 123")).toBe("normal text 123");
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("sendEmail", () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
vi.clearAllMocks();
|
|
31
|
+
delete process.env.RESEND_API_KEY;
|
|
32
|
+
delete process.env.RESEND_FROM_EMAIL;
|
|
33
|
+
// Reset mock to default success response
|
|
34
|
+
mockSend.mockResolvedValue({
|
|
35
|
+
data: { id: "test-email-id" },
|
|
36
|
+
error: null,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it("should send email with required options", async () => {
|
|
40
|
+
process.env.RESEND_API_KEY = "test-api-key";
|
|
41
|
+
const options = {
|
|
42
|
+
to: "user@example.com",
|
|
43
|
+
subject: "Test Subject",
|
|
44
|
+
html: "<p>Test HTML</p>",
|
|
45
|
+
};
|
|
46
|
+
const result = await sendEmail(options);
|
|
47
|
+
expect(result).toEqual({
|
|
48
|
+
id: "test-email-id",
|
|
49
|
+
success: true,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
it("should use custom API key when provided", async () => {
|
|
53
|
+
const options = {
|
|
54
|
+
to: "user@example.com",
|
|
55
|
+
subject: "Test Subject",
|
|
56
|
+
html: "<p>Test HTML</p>",
|
|
57
|
+
};
|
|
58
|
+
const result = await sendEmail(options, "custom-api-key");
|
|
59
|
+
expect(result.success).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
it("should use custom from address when provided", async () => {
|
|
62
|
+
process.env.RESEND_API_KEY = "test-api-key";
|
|
63
|
+
const options = {
|
|
64
|
+
to: "user@example.com",
|
|
65
|
+
subject: "Test Subject",
|
|
66
|
+
html: "<p>Test HTML</p>",
|
|
67
|
+
};
|
|
68
|
+
const result = await sendEmail(options, undefined, "custom@example.com");
|
|
69
|
+
expect(result.success).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it("should throw error when RESEND_API_KEY is missing", async () => {
|
|
72
|
+
const options = {
|
|
73
|
+
to: "user@example.com",
|
|
74
|
+
subject: "Test Subject",
|
|
75
|
+
html: "<p>Test HTML</p>",
|
|
76
|
+
};
|
|
77
|
+
await expect(sendEmail(options)).rejects.toThrow("RESEND_API_KEY environment variable is required");
|
|
78
|
+
});
|
|
79
|
+
it("should handle Resend API errors", async () => {
|
|
80
|
+
process.env.RESEND_API_KEY = "test-api-key";
|
|
81
|
+
// Mock Resend to return an error for this specific test
|
|
82
|
+
mockSend.mockResolvedValueOnce({
|
|
83
|
+
data: null,
|
|
84
|
+
error: { message: "API error" },
|
|
85
|
+
});
|
|
86
|
+
const options = {
|
|
87
|
+
to: "user@example.com",
|
|
88
|
+
subject: "Test Subject",
|
|
89
|
+
html: "<p>Test HTML</p>",
|
|
90
|
+
};
|
|
91
|
+
await expect(sendEmail(options)).rejects.toThrow("Failed to send email: API error");
|
|
92
|
+
});
|
|
93
|
+
it("should use default from email when env var is set", async () => {
|
|
94
|
+
process.env.RESEND_API_KEY = "test-api-key";
|
|
95
|
+
process.env.RESEND_FROM_EMAIL = "default@example.com";
|
|
96
|
+
const options = {
|
|
97
|
+
to: "user@example.com",
|
|
98
|
+
subject: "Test Subject",
|
|
99
|
+
html: "<p>Test HTML</p>",
|
|
100
|
+
};
|
|
101
|
+
const result = await sendEmail(options);
|
|
102
|
+
expect(result.success).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it("should include text version when provided", async () => {
|
|
105
|
+
process.env.RESEND_API_KEY = "test-api-key";
|
|
106
|
+
const options = {
|
|
107
|
+
to: "user@example.com",
|
|
108
|
+
subject: "Test Subject",
|
|
109
|
+
html: "<p>Test HTML</p>",
|
|
110
|
+
text: "Test plain text",
|
|
111
|
+
};
|
|
112
|
+
const result = await sendEmail(options);
|
|
113
|
+
expect(result.success).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe("passwordResetTemplate", () => {
|
|
117
|
+
it("should generate HTML template with reset URL", () => {
|
|
118
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
119
|
+
const email = "user@example.com";
|
|
120
|
+
const html = passwordResetTemplate(resetUrl, email);
|
|
121
|
+
expect(html).toContain(resetUrl);
|
|
122
|
+
expect(html).toContain(email);
|
|
123
|
+
expect(html).toContain("Reset Your Password");
|
|
124
|
+
expect(html).toContain("Reset Password");
|
|
125
|
+
expect(html).toContain("<!DOCTYPE html>");
|
|
126
|
+
});
|
|
127
|
+
it("should escape HTML characters in email and URL to prevent XSS", () => {
|
|
128
|
+
const resetUrl = "https://wopr.bot/reset?token=<script>alert(1)</script>";
|
|
129
|
+
const email = "<script>alert('xss')</script>@example.com";
|
|
130
|
+
const html = passwordResetTemplate(resetUrl, email);
|
|
131
|
+
// Verify email is escaped in the text where it's displayed
|
|
132
|
+
expect(html).toContain("<script>alert('xss')</script>@example.com");
|
|
133
|
+
// Verify resetUrl is escaped in the displayed text (not href)
|
|
134
|
+
expect(html).toContain("<script>alert(1)</script>");
|
|
135
|
+
// Verify the email script tag doesn't appear unescaped in body text
|
|
136
|
+
// (it may appear in href attribute, which is safe from XSS)
|
|
137
|
+
const bodyMatch = html.match(/<p>.*<\/p>/gs);
|
|
138
|
+
const bodyText = bodyMatch ? bodyMatch.join("") : "";
|
|
139
|
+
expect(bodyText).not.toContain("<script>alert('xss')</script>");
|
|
140
|
+
});
|
|
141
|
+
it("should include current year in footer", () => {
|
|
142
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
143
|
+
const email = "user@example.com";
|
|
144
|
+
const html = passwordResetTemplate(resetUrl, email);
|
|
145
|
+
const currentYear = new Date().getFullYear();
|
|
146
|
+
expect(html).toContain(`© ${currentYear} WOPR Network`);
|
|
147
|
+
});
|
|
148
|
+
it("should be valid HTML structure", () => {
|
|
149
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
150
|
+
const email = "user@example.com";
|
|
151
|
+
const html = passwordResetTemplate(resetUrl, email);
|
|
152
|
+
expect(html).toContain("<html>");
|
|
153
|
+
expect(html).toContain("</html>");
|
|
154
|
+
expect(html).toContain("<head>");
|
|
155
|
+
expect(html).toContain("</head>");
|
|
156
|
+
expect(html).toContain("<body");
|
|
157
|
+
expect(html).toContain("</body>");
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe("passwordResetText", () => {
|
|
161
|
+
it("should generate plain text with reset URL", () => {
|
|
162
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
163
|
+
const email = "user@example.com";
|
|
164
|
+
const text = passwordResetText(resetUrl, email);
|
|
165
|
+
expect(text).toContain(resetUrl);
|
|
166
|
+
expect(text).toContain(email);
|
|
167
|
+
expect(text).toContain("Reset Your Password");
|
|
168
|
+
});
|
|
169
|
+
it("should not contain HTML tags", () => {
|
|
170
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
171
|
+
const email = "user@example.com";
|
|
172
|
+
const text = passwordResetText(resetUrl, email);
|
|
173
|
+
expect(text).not.toContain("<");
|
|
174
|
+
expect(text).not.toContain(">");
|
|
175
|
+
});
|
|
176
|
+
it("should include current year in footer", () => {
|
|
177
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
178
|
+
const email = "user@example.com";
|
|
179
|
+
const text = passwordResetText(resetUrl, email);
|
|
180
|
+
const currentYear = new Date().getFullYear();
|
|
181
|
+
expect(text).toContain(`© ${currentYear} WOPR Network`);
|
|
182
|
+
});
|
|
183
|
+
it("should be readable plain text format", () => {
|
|
184
|
+
const resetUrl = "https://wopr.bot/reset?token=abc123";
|
|
185
|
+
const email = "user@example.com";
|
|
186
|
+
const text = passwordResetText(resetUrl, email);
|
|
187
|
+
// Should have line breaks and be formatted
|
|
188
|
+
expect(text.split("\n").length).toBeGreaterThan(5);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Templates — HTML and plain text templates for all transactional emails.
|
|
3
|
+
*
|
|
4
|
+
* Each template has an HTML and a plain text version. HTML uses inline styles
|
|
5
|
+
* for maximum email client compatibility. All user-supplied values are escaped
|
|
6
|
+
* to prevent XSS.
|
|
7
|
+
*/
|
|
8
|
+
export type TemplateName = "verify-email" | "welcome" | "password-reset" | "credit-purchase" | "low-balance" | "bot-suspended" | "bot-destruction" | "data-deleted";
|
|
9
|
+
export interface TemplateResult {
|
|
10
|
+
subject: string;
|
|
11
|
+
html: string;
|
|
12
|
+
text: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function verifyEmailTemplate(verifyUrl: string, email: string): TemplateResult;
|
|
15
|
+
export declare function welcomeTemplate(email: string): TemplateResult;
|
|
16
|
+
export declare function passwordResetEmailTemplate(resetUrl: string, email: string): TemplateResult;
|
|
17
|
+
export declare function creditPurchaseTemplate(email: string, amountDollars: string, newBalanceDollars?: string, creditsUrl?: string): TemplateResult;
|
|
18
|
+
export declare function lowBalanceTemplate(email: string, balanceDollars: string, estimatedDaysRemaining?: number, creditsUrl?: string): TemplateResult;
|
|
19
|
+
export declare function botSuspendedTemplate(email: string, botName: string, reason: string, creditsUrl?: string): TemplateResult;
|
|
20
|
+
export declare function botDestructionTemplate(email: string, botName: string, daysRemaining: number, creditsUrl?: string): TemplateResult;
|
|
21
|
+
export declare function dataDeletedTemplate(email: string, creditsUrl?: string): TemplateResult;
|
|
22
|
+
export declare function orgInviteEmailTemplate(inviteUrl: string, orgName: string): TemplateResult;
|