@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,574 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Templates — renders all system notification emails.
|
|
3
|
+
*
|
|
4
|
+
* Separate from templates.ts (which handles billing/auth emails) to keep
|
|
5
|
+
* each file focused. Imports shared layout helpers from templates.ts.
|
|
6
|
+
*
|
|
7
|
+
* Export: renderNotificationTemplate(template, data) → TemplateResult
|
|
8
|
+
*/
|
|
9
|
+
import { escapeHtml } from "./resend-adapter.js";
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Shared layout helpers (duplicated locally so this file is self-contained)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
function wrapHtml(title, bodyContent) {
|
|
14
|
+
return `<!DOCTYPE html>
|
|
15
|
+
<html>
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="utf-8">
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
<title>${escapeHtml(title)}</title>
|
|
20
|
+
</head>
|
|
21
|
+
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f4f4f4;">
|
|
22
|
+
<table role="presentation" style="width: 100%; border-collapse: collapse;">
|
|
23
|
+
<tr>
|
|
24
|
+
<td style="padding: 40px 0; text-align: center;">
|
|
25
|
+
<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);">
|
|
26
|
+
${bodyContent}
|
|
27
|
+
</table>
|
|
28
|
+
<p style="margin-top: 20px; color: #a0aec0; font-size: 12px;">© ${new Date().getFullYear()} WOPR Network. All rights reserved.</p>
|
|
29
|
+
</td>
|
|
30
|
+
</tr>
|
|
31
|
+
</table>
|
|
32
|
+
</body>
|
|
33
|
+
</html>`;
|
|
34
|
+
}
|
|
35
|
+
function heading(text) {
|
|
36
|
+
return `<tr>
|
|
37
|
+
<td style="padding: 40px 40px 20px 40px; text-align: center;">
|
|
38
|
+
<h1 style="margin: 0; font-size: 24px; font-weight: 600; color: #1a1a1a;">${escapeHtml(text)}</h1>
|
|
39
|
+
</td>
|
|
40
|
+
</tr>`;
|
|
41
|
+
}
|
|
42
|
+
function paragraph(html) {
|
|
43
|
+
return `<tr>
|
|
44
|
+
<td style="padding: 0 40px 20px 40px; color: #4a5568; font-size: 16px; line-height: 24px;">
|
|
45
|
+
${html}
|
|
46
|
+
</td>
|
|
47
|
+
</tr>`;
|
|
48
|
+
}
|
|
49
|
+
function button(url, label, color = "#2563eb") {
|
|
50
|
+
return `<tr>
|
|
51
|
+
<td style="padding: 0 40px 30px 40px; text-align: center;">
|
|
52
|
+
<a href="${escapeHtml(url)}" style="display: inline-block; padding: 12px 32px; background-color: ${color}; color: #ffffff; text-decoration: none; font-weight: 600; border-radius: 6px; font-size: 16px;">${escapeHtml(label)}</a>
|
|
53
|
+
</td>
|
|
54
|
+
</tr>`;
|
|
55
|
+
}
|
|
56
|
+
function footer(text) {
|
|
57
|
+
return `<tr>
|
|
58
|
+
<td style="padding: 0 40px 40px 40px; color: #718096; font-size: 14px; line-height: 20px; border-top: 1px solid #e2e8f0;">
|
|
59
|
+
<p style="margin-top: 20px;">${text}</p>
|
|
60
|
+
</td>
|
|
61
|
+
</tr>`;
|
|
62
|
+
}
|
|
63
|
+
function copyright() {
|
|
64
|
+
return `\n\n(c) ${new Date().getFullYear()} WOPR Network. All rights reserved.`;
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Individual template renderers
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
function creditsDepletedTemplate(data) {
|
|
70
|
+
const creditsUrl = data.creditsUrl || "";
|
|
71
|
+
const parts = [
|
|
72
|
+
heading("Your WOPR Credits Are Depleted"),
|
|
73
|
+
paragraph("<p>Your WOPR credit balance has reached $0. All agent capabilities have been paused.</p>" +
|
|
74
|
+
"<p>Add credits now to resume service immediately.</p>"),
|
|
75
|
+
];
|
|
76
|
+
if (creditsUrl)
|
|
77
|
+
parts.push(button(creditsUrl, "Add Credits"));
|
|
78
|
+
parts.push(footer("Your data is preserved. Add credits to reactivate."));
|
|
79
|
+
return {
|
|
80
|
+
subject: "Your WOPR credits are depleted — capabilities paused",
|
|
81
|
+
html: wrapHtml("Credits Depleted", parts.join("\n")),
|
|
82
|
+
text: `Your WOPR Credits Are Depleted\n\nYour WOPR credit balance has reached $0. All agent capabilities have been paused.\n\nAdd credits now to resume service immediately.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function gracePeriodStartTemplate(data) {
|
|
86
|
+
const balanceDollars = escapeHtml(data.balanceDollars || "$0.00");
|
|
87
|
+
const graceDays = Number(data.graceDays) || 7;
|
|
88
|
+
const creditsUrl = data.creditsUrl || "";
|
|
89
|
+
const parts = [
|
|
90
|
+
heading("Action Needed: Top Up to Keep Your WOPRs Running"),
|
|
91
|
+
paragraph(`<p>Your current balance is <strong>${balanceDollars}</strong> and the monthly deduction could not be processed.</p>` +
|
|
92
|
+
`<p>You have a <strong>${graceDays}-day grace period</strong> to add credits before your account is suspended.</p>`),
|
|
93
|
+
];
|
|
94
|
+
if (creditsUrl)
|
|
95
|
+
parts.push(button(creditsUrl, "Add Credits Now"));
|
|
96
|
+
parts.push(footer("This is a critical notification about your account status."));
|
|
97
|
+
return {
|
|
98
|
+
subject: "Action needed: top up to keep your WOPRs running",
|
|
99
|
+
html: wrapHtml("Grace Period Started", parts.join("\n")),
|
|
100
|
+
text: `Action Needed: Top Up to Keep Your WOPRs Running\n\nYour current balance is ${data.balanceDollars} and the monthly deduction could not be processed.\n\nYou have a ${graceDays}-day grace period to add credits before your account is suspended.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function gracePeriodWarningTemplate(data) {
|
|
104
|
+
const creditsUrl = data.creditsUrl || "";
|
|
105
|
+
const parts = [
|
|
106
|
+
heading("Last Chance: Your WOPRs Will Be Suspended Tomorrow"),
|
|
107
|
+
paragraph("<p>Your grace period expires tomorrow. If you do not add credits, your account will be suspended.</p>" +
|
|
108
|
+
"<p>Add credits now to keep your agents running.</p>"),
|
|
109
|
+
];
|
|
110
|
+
if (creditsUrl)
|
|
111
|
+
parts.push(button(creditsUrl, "Add Credits Now", "#dc2626"));
|
|
112
|
+
parts.push(footer("This is a critical notification about your account status."));
|
|
113
|
+
return {
|
|
114
|
+
subject: "Last chance: your WOPRs will be suspended tomorrow",
|
|
115
|
+
html: wrapHtml("Grace Period Warning", parts.join("\n")),
|
|
116
|
+
text: `Last Chance: Your WOPRs Will Be Suspended Tomorrow\n\nYour grace period expires tomorrow. If you do not add credits, your account will be suspended.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function autoSuspendedTemplate(data) {
|
|
120
|
+
const reason = escapeHtml(data.reason || "Grace period expired");
|
|
121
|
+
const creditsUrl = data.creditsUrl || "";
|
|
122
|
+
const parts = [
|
|
123
|
+
heading("Your Account Has Been Suspended"),
|
|
124
|
+
paragraph(`<p>Your WOPR account has been automatically suspended.</p>` +
|
|
125
|
+
`<p><strong>Reason:</strong> ${reason}</p>` +
|
|
126
|
+
`<p>Add credits to reactivate your account immediately.</p>`),
|
|
127
|
+
];
|
|
128
|
+
if (creditsUrl)
|
|
129
|
+
parts.push(button(creditsUrl, "Add Credits to Reactivate"));
|
|
130
|
+
parts.push(footer("Your data is preserved for 30 days."));
|
|
131
|
+
return {
|
|
132
|
+
subject: "Your account has been suspended",
|
|
133
|
+
html: wrapHtml("Account Suspended", parts.join("\n")),
|
|
134
|
+
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nAdd credits to reactivate your account immediately.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function autoTopupSuccessTemplate(data) {
|
|
138
|
+
const amountDollars = escapeHtml(data.amountDollars || "$0.00");
|
|
139
|
+
const newBalanceDollars = escapeHtml(data.newBalanceDollars || "$0.00");
|
|
140
|
+
const creditsUrl = data.creditsUrl || "";
|
|
141
|
+
const parts = [
|
|
142
|
+
heading(`Auto Top-Up: ${amountDollars} Credits Added`),
|
|
143
|
+
paragraph(`<p>Your auto top-up was successful. <strong>${amountDollars}</strong> in credits has been added.</p>` +
|
|
144
|
+
`<p>Your new balance is <strong>${newBalanceDollars}</strong>.</p>`),
|
|
145
|
+
];
|
|
146
|
+
if (creditsUrl)
|
|
147
|
+
parts.push(button(creditsUrl, "View Credits"));
|
|
148
|
+
parts.push(footer("Auto top-up keeps your agents running without interruption."));
|
|
149
|
+
return {
|
|
150
|
+
subject: `Auto top-up: ${data.amountDollars} credits added`,
|
|
151
|
+
html: wrapHtml("Auto Top-Up Successful", parts.join("\n")),
|
|
152
|
+
text: `Auto Top-Up: ${data.amountDollars} Credits Added\n\nYour auto top-up was successful. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${creditsUrl ? `\nView credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function autoTopupFailedTemplate(data) {
|
|
156
|
+
const creditsUrl = data.creditsUrl || "";
|
|
157
|
+
const parts = [
|
|
158
|
+
heading("Auto Top-Up Failed"),
|
|
159
|
+
paragraph("<p>Your auto top-up failed. We were unable to charge your payment method.</p>" +
|
|
160
|
+
"<p>Please update your payment method or add credits manually to avoid service interruption.</p>"),
|
|
161
|
+
];
|
|
162
|
+
if (creditsUrl)
|
|
163
|
+
parts.push(button(creditsUrl, "Add Credits"));
|
|
164
|
+
parts.push(footer("If you need help, contact support@wopr.bot."));
|
|
165
|
+
return {
|
|
166
|
+
subject: "Auto top-up failed — update your payment method",
|
|
167
|
+
html: wrapHtml("Auto Top-Up Failed", parts.join("\n")),
|
|
168
|
+
text: `Auto Top-Up Failed\n\nYour auto top-up failed. We were unable to charge your payment method.\n\nPlease update your payment method or add credits manually to avoid service interruption.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function cryptoPaymentConfirmedTemplate(data) {
|
|
172
|
+
const amountDollars = escapeHtml(data.amountDollars || "$0.00");
|
|
173
|
+
const newBalanceDollars = escapeHtml(data.newBalanceDollars || "$0.00");
|
|
174
|
+
const parts = [
|
|
175
|
+
heading(`Crypto Payment Confirmed: ${amountDollars} Credits Added`),
|
|
176
|
+
paragraph(`<p>Your crypto payment has been confirmed. <strong>${amountDollars}</strong> in credits has been added to your account.</p>` +
|
|
177
|
+
`<p>Your new balance is <strong>${newBalanceDollars}</strong>.</p>`),
|
|
178
|
+
];
|
|
179
|
+
parts.push(footer("Thank you for supporting WOPR!"));
|
|
180
|
+
return {
|
|
181
|
+
subject: `Crypto payment confirmed: ${data.amountDollars} credits added`,
|
|
182
|
+
html: wrapHtml("Crypto Payment Confirmed", parts.join("\n")),
|
|
183
|
+
text: `Crypto Payment Confirmed: ${data.amountDollars} Credits Added\n\nYour crypto payment has been confirmed. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${copyright()}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function adminSuspendedTemplate(data) {
|
|
187
|
+
const reason = escapeHtml(data.reason || "Policy violation");
|
|
188
|
+
const parts = [
|
|
189
|
+
heading("Your Account Has Been Suspended"),
|
|
190
|
+
paragraph(`<p>Your WOPR account has been suspended by an administrator.</p>` +
|
|
191
|
+
`<p><strong>Reason:</strong> ${reason}</p>` +
|
|
192
|
+
`<p>If you believe this is an error, please contact support@wopr.bot.</p>`),
|
|
193
|
+
];
|
|
194
|
+
parts.push(footer("Contact support@wopr.bot if you have questions."));
|
|
195
|
+
return {
|
|
196
|
+
subject: "Your account has been suspended",
|
|
197
|
+
html: wrapHtml("Account Suspended", parts.join("\n")),
|
|
198
|
+
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nIf you believe this is an error, please contact support@wopr.bot.\n${copyright()}`,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function adminReactivatedTemplate(_data) {
|
|
202
|
+
const parts = [
|
|
203
|
+
heading("Your Account Has Been Reactivated"),
|
|
204
|
+
paragraph("<p>Your WOPR account has been reactivated. You now have full access to all services.</p>" +
|
|
205
|
+
"<p>Your agents and channels are ready to use.</p>"),
|
|
206
|
+
];
|
|
207
|
+
parts.push(footer("Welcome back!"));
|
|
208
|
+
return {
|
|
209
|
+
subject: "Your account has been reactivated",
|
|
210
|
+
html: wrapHtml("Account Reactivated", parts.join("\n")),
|
|
211
|
+
text: `Your Account Has Been Reactivated\n\nYour WOPR account has been reactivated. You now have full access to all services.\n${copyright()}`,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function creditsGrantedTemplate(data) {
|
|
215
|
+
const amountDollars = escapeHtml(data.amountDollars || "$0.00");
|
|
216
|
+
const reason = escapeHtml(data.reason || "");
|
|
217
|
+
const parts = [
|
|
218
|
+
heading(`You Received ${amountDollars} in Credits`),
|
|
219
|
+
paragraph(`<p><strong>${amountDollars}</strong> in credits has been added to your WOPR account.</p>` +
|
|
220
|
+
(reason ? `<p><strong>Note:</strong> ${reason}</p>` : "")),
|
|
221
|
+
];
|
|
222
|
+
parts.push(footer("Thank you for using WOPR!"));
|
|
223
|
+
return {
|
|
224
|
+
subject: `You received ${data.amountDollars} in credits`,
|
|
225
|
+
html: wrapHtml("Credits Granted", parts.join("\n")),
|
|
226
|
+
text: `You Received ${data.amountDollars} in Credits\n\n${data.amountDollars} has been added to your account.${reason ? `\n\nNote: ${data.reason}` : ""}\n${copyright()}`,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function roleChangedTemplate(data) {
|
|
230
|
+
const newRole = escapeHtml(data.newRole || "");
|
|
231
|
+
const parts = [
|
|
232
|
+
heading("Your Role Has Been Updated"),
|
|
233
|
+
paragraph(`<p>Your role on the WOPR platform has been updated to <strong>${newRole}</strong>.</p>` +
|
|
234
|
+
"<p>Your new permissions are now active.</p>"),
|
|
235
|
+
];
|
|
236
|
+
parts.push(footer("If you did not expect this change, contact support@wopr.bot."));
|
|
237
|
+
return {
|
|
238
|
+
subject: "Your role has been updated",
|
|
239
|
+
html: wrapHtml("Role Changed", parts.join("\n")),
|
|
240
|
+
text: `Your Role Has Been Updated\n\nYour role has been updated to ${data.newRole}.\n${copyright()}`,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function teamInviteTemplate(data) {
|
|
244
|
+
const tenantName = escapeHtml(data.tenantName || "a tenant");
|
|
245
|
+
const inviteUrl = data.inviteUrl || "";
|
|
246
|
+
const parts = [
|
|
247
|
+
heading(`You've Been Invited to Join ${tenantName}`),
|
|
248
|
+
paragraph(`<p>You've been invited to join <strong>${tenantName}</strong> on the WOPR platform.</p>` +
|
|
249
|
+
"<p>Click below to accept the invitation.</p>"),
|
|
250
|
+
];
|
|
251
|
+
if (inviteUrl)
|
|
252
|
+
parts.push(button(inviteUrl, "Accept Invitation"));
|
|
253
|
+
parts.push(footer("If you did not expect this invitation, you can ignore this email."));
|
|
254
|
+
return {
|
|
255
|
+
subject: `You've been invited to join ${data.tenantName}`,
|
|
256
|
+
html: wrapHtml("Team Invite", parts.join("\n")),
|
|
257
|
+
text: `You've Been Invited to Join ${data.tenantName}\n\n${inviteUrl ? `Accept: ${inviteUrl}\n` : ""}${copyright()}`,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function agentCreatedTemplate(data) {
|
|
261
|
+
const agentName = escapeHtml(data.agentName || "your agent");
|
|
262
|
+
const parts = [
|
|
263
|
+
heading(`Your WOPR ${agentName} Is Ready`),
|
|
264
|
+
paragraph(`<p>Your new agent <strong>${agentName}</strong> has been created and is ready to use.</p>` +
|
|
265
|
+
"<p>Connect it to a channel to start receiving and sending messages.</p>"),
|
|
266
|
+
];
|
|
267
|
+
parts.push(footer("Happy building!"));
|
|
268
|
+
return {
|
|
269
|
+
subject: `Your WOPR ${data.agentName} is ready`,
|
|
270
|
+
html: wrapHtml("Agent Created", parts.join("\n")),
|
|
271
|
+
text: `Your WOPR ${data.agentName} Is Ready\n\nYour new agent has been created and is ready to use.\n${copyright()}`,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function channelConnectedTemplate(data) {
|
|
275
|
+
const channelName = escapeHtml(data.channelName || "A channel");
|
|
276
|
+
const agentName = escapeHtml(data.agentName || "your agent");
|
|
277
|
+
const parts = [
|
|
278
|
+
heading(`${channelName} Connected to ${agentName}`),
|
|
279
|
+
paragraph(`<p><strong>${channelName}</strong> has been successfully connected to <strong>${agentName}</strong>.</p>` +
|
|
280
|
+
"<p>Your agent is now active on this channel.</p>"),
|
|
281
|
+
];
|
|
282
|
+
parts.push(footer("Your agent is live!"));
|
|
283
|
+
return {
|
|
284
|
+
subject: `${data.channelName} connected to ${data.agentName}`,
|
|
285
|
+
html: wrapHtml("Channel Connected", parts.join("\n")),
|
|
286
|
+
text: `${data.channelName} Connected to ${data.agentName}\n\n${data.channelName} has been successfully connected to ${data.agentName}.\n${copyright()}`,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function channelDisconnectedTemplate(data) {
|
|
290
|
+
const channelName = escapeHtml(data.channelName || "A channel");
|
|
291
|
+
const agentName = escapeHtml(data.agentName || "your agent");
|
|
292
|
+
const reason = escapeHtml(data.reason || "");
|
|
293
|
+
const parts = [
|
|
294
|
+
heading(`${channelName} Disconnected from ${agentName}`),
|
|
295
|
+
paragraph(`<p><strong>${channelName}</strong> has been disconnected from <strong>${agentName}</strong>.</p>` +
|
|
296
|
+
(reason ? `<p><strong>Reason:</strong> ${reason}</p>` : "") +
|
|
297
|
+
"<p>Reconnect the channel from your dashboard to restore service.</p>"),
|
|
298
|
+
];
|
|
299
|
+
parts.push(footer("Your agent data is preserved."));
|
|
300
|
+
return {
|
|
301
|
+
subject: `${data.channelName} disconnected from ${data.agentName}`,
|
|
302
|
+
html: wrapHtml("Channel Disconnected", parts.join("\n")),
|
|
303
|
+
text: `${data.channelName} Disconnected from ${data.agentName}\n\n${reason ? `Reason: ${data.reason}\n\n` : ""}Reconnect from your dashboard to restore service.\n${copyright()}`,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function agentSuspendedTemplate(data) {
|
|
307
|
+
const agentName = escapeHtml(data.agentName || "Your agent");
|
|
308
|
+
const reason = escapeHtml(data.reason || "");
|
|
309
|
+
const parts = [
|
|
310
|
+
heading(`${agentName} Has Been Paused`),
|
|
311
|
+
paragraph(`<p>Your agent <strong>${agentName}</strong> has been paused.</p>` +
|
|
312
|
+
(reason ? `<p><strong>Reason:</strong> ${reason}</p>` : "")),
|
|
313
|
+
];
|
|
314
|
+
parts.push(footer("Contact support@wopr.bot if you have questions."));
|
|
315
|
+
return {
|
|
316
|
+
subject: `${data.agentName} has been paused`,
|
|
317
|
+
html: wrapHtml("Agent Paused", parts.join("\n")),
|
|
318
|
+
text: `${data.agentName} Has Been Paused\n\n${reason ? `Reason: ${data.reason}\n` : ""}${copyright()}`,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function accountDeletionRequestedTemplate(data) {
|
|
322
|
+
const email = escapeHtml(data.email || "");
|
|
323
|
+
const deleteAfterDate = escapeHtml(data.deleteAfterDate || "");
|
|
324
|
+
const cancelUrl = data.cancelUrl || "";
|
|
325
|
+
const parts = [
|
|
326
|
+
heading("Account Deletion Requested"),
|
|
327
|
+
paragraph(`<p>Hi <strong>${email}</strong>,</p>` +
|
|
328
|
+
`<p>We've received your request to delete your WOPR account and all associated data.</p>` +
|
|
329
|
+
`<p>Your account will be permanently deleted on <strong>${deleteAfterDate}</strong>. Until then, you can cancel this request and keep your account.</p>` +
|
|
330
|
+
`<p>After that date, all your data will be permanently and irreversibly removed, including bots, conversation history, credit records, and plugin configurations.</p>`),
|
|
331
|
+
];
|
|
332
|
+
if (cancelUrl)
|
|
333
|
+
parts.push(button(cancelUrl, "Cancel Deletion", "#22c55e"));
|
|
334
|
+
parts.push(footer("If you did not request this, please contact support@wopr.bot immediately."));
|
|
335
|
+
return {
|
|
336
|
+
subject: "Your WOPR account deletion request",
|
|
337
|
+
html: wrapHtml("Account Deletion Requested", parts.join("\n")),
|
|
338
|
+
text: `Account Deletion Requested\n\nHi ${data.email},\n\nWe've received your request to delete your WOPR account and all associated data.\n\nYour account will be permanently deleted on ${data.deleteAfterDate}. Until then, you can cancel this request.\n\nAfter that date, all your data will be permanently and irreversibly removed.\n${cancelUrl ? `\nCancel deletion: ${cancelUrl}\n` : ""}If you did not request this, please contact support@wopr.bot immediately.${copyright()}`,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function accountDeletionCancelledTemplate(data) {
|
|
342
|
+
const email = escapeHtml(data.email || "");
|
|
343
|
+
const parts = [
|
|
344
|
+
heading("Account Deletion Cancelled"),
|
|
345
|
+
paragraph(`<p>Hi <strong>${email}</strong>,</p>` +
|
|
346
|
+
`<p>Your account deletion request has been cancelled. Your account and all data remain intact.</p>` +
|
|
347
|
+
`<p>No further action is needed.</p>`),
|
|
348
|
+
footer("If you didn't cancel this, please contact support@wopr.bot."),
|
|
349
|
+
];
|
|
350
|
+
return {
|
|
351
|
+
subject: "Your WOPR account deletion has been cancelled",
|
|
352
|
+
html: wrapHtml("Account Deletion Cancelled", parts.join("\n")),
|
|
353
|
+
text: `Account Deletion Cancelled\n\nHi ${data.email},\n\nYour account deletion request has been cancelled. Your account and all data remain intact.\n\nNo further action is needed.${copyright()}`,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function accountDeletionCompletedTemplate(data) {
|
|
357
|
+
const email = escapeHtml(data.email || "");
|
|
358
|
+
const parts = [
|
|
359
|
+
heading("Your Account Has Been Deleted"),
|
|
360
|
+
paragraph(`<p>Hi <strong>${email}</strong>,</p>` +
|
|
361
|
+
`<p>Your WOPR account and all associated data have been permanently deleted as requested.</p>` +
|
|
362
|
+
`<p>This includes all bots, conversation history, credit records, billing data, and plugin configurations.</p>` +
|
|
363
|
+
`<p>If you'd like to use WOPR again in the future, you're welcome to create a new account.</p>`),
|
|
364
|
+
footer("Thank you for using WOPR. We're sorry to see you go."),
|
|
365
|
+
];
|
|
366
|
+
return {
|
|
367
|
+
subject: "Your WOPR account has been deleted",
|
|
368
|
+
html: wrapHtml("Account Deleted", parts.join("\n")),
|
|
369
|
+
text: `Your Account Has Been Deleted\n\nHi ${data.email},\n\nYour WOPR account and all associated data have been permanently deleted as requested.\n\nThis includes all bots, conversation history, credit records, billing data, and plugin configurations.\n\nIf you'd like to use WOPR again in the future, you're welcome to create a new account.${copyright()}`,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function dividendWeeklyDigestTemplate(data) {
|
|
373
|
+
const weeklyTotal = escapeHtml(data.weeklyTotalDollars || "$0.00");
|
|
374
|
+
const lifetimeTotal = escapeHtml(data.lifetimeTotalDollars || "$0.00");
|
|
375
|
+
const distributionCount = Number(data.distributionCount) || 0;
|
|
376
|
+
const poolAvgCents = Number(data.poolAvgCents) || 0;
|
|
377
|
+
const activeUsersAvg = Number(data.activeUsersAvg) || 0;
|
|
378
|
+
const nextDividendDate = escapeHtml(data.nextDividendDate || "");
|
|
379
|
+
const weekStart = escapeHtml(data.weekStartDate || "");
|
|
380
|
+
const weekEnd = escapeHtml(data.weekEndDate || "");
|
|
381
|
+
const creditsUrl = data.creditsUrl || "";
|
|
382
|
+
const unsubscribeUrl = data.unsubscribeUrl || "";
|
|
383
|
+
const poolAvgDollars = `$${(poolAvgCents / 100).toFixed(2)}`;
|
|
384
|
+
const parts = [
|
|
385
|
+
heading(`WOPR Paid You ${weeklyTotal} This Week`),
|
|
386
|
+
paragraph(`<p>Here's your weekly dividend summary for <strong>${weekStart} – ${weekEnd}</strong>.</p>` +
|
|
387
|
+
`<table style="width: 100%; border-collapse: collapse; margin: 16px 0;">` +
|
|
388
|
+
`<tr><td style="padding: 8px 0; color: #4a5568;">This week's dividends</td><td style="padding: 8px 0; text-align: right; font-weight: 600; color: #1a1a1a;">${weeklyTotal}</td></tr>` +
|
|
389
|
+
`<tr><td style="padding: 8px 0; color: #4a5568;">Days with distributions</td><td style="padding: 8px 0; text-align: right; font-weight: 600; color: #1a1a1a;">${distributionCount} of 7</td></tr>` +
|
|
390
|
+
`<tr><td style="padding: 8px 0; color: #4a5568;">Avg. daily pool</td><td style="padding: 8px 0; text-align: right; font-weight: 600; color: #1a1a1a;">${escapeHtml(poolAvgDollars)}</td></tr>` +
|
|
391
|
+
`<tr><td style="padding: 8px 0; color: #4a5568;">Avg. active users</td><td style="padding: 8px 0; text-align: right; font-weight: 600; color: #1a1a1a;">${activeUsersAvg}</td></tr>` +
|
|
392
|
+
`<tr style="border-top: 2px solid #e2e8f0;"><td style="padding: 12px 0; color: #4a5568; font-weight: 600;">Lifetime total</td><td style="padding: 12px 0; text-align: right; font-weight: 700; color: #1a1a1a; font-size: 18px;">${lifetimeTotal}</td></tr>` +
|
|
393
|
+
`</table>` +
|
|
394
|
+
(nextDividendDate
|
|
395
|
+
? `<p style="color: #718096; font-size: 14px;">Next dividend: <strong>${nextDividendDate}</strong></p>`
|
|
396
|
+
: "")),
|
|
397
|
+
];
|
|
398
|
+
if (creditsUrl)
|
|
399
|
+
parts.push(button(creditsUrl, "View Your Credits"));
|
|
400
|
+
parts.push(footer("Community dividends are distributed daily from platform revenue. Keep your credits active to stay eligible."));
|
|
401
|
+
if (unsubscribeUrl) {
|
|
402
|
+
parts.push(`<tr><td style="padding: 0 40px 20px 40px; text-align: center; color: #a0aec0; font-size: 12px;"><a href="${escapeHtml(unsubscribeUrl)}" style="color: #a0aec0; text-decoration: underline;">Unsubscribe from dividend digests</a></td></tr>`);
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
subject: `WOPR paid you ${data.weeklyTotalDollars} this week`,
|
|
406
|
+
html: wrapHtml("Weekly Dividend Digest", parts.join("\n")),
|
|
407
|
+
text: `WOPR Paid You ${data.weeklyTotalDollars} This Week\n\n` +
|
|
408
|
+
`Weekly summary for ${data.weekStartDate} – ${data.weekEndDate}:\n\n` +
|
|
409
|
+
`This week's dividends: ${data.weeklyTotalDollars}\n` +
|
|
410
|
+
`Days with distributions: ${distributionCount} of 7\n` +
|
|
411
|
+
`Avg. daily pool: ${poolAvgDollars}\n` +
|
|
412
|
+
`Avg. active users: ${activeUsersAvg}\n` +
|
|
413
|
+
`Lifetime total: ${data.lifetimeTotalDollars}\n\n` +
|
|
414
|
+
`Next dividend: ${data.nextDividendDate}\n\n` +
|
|
415
|
+
`Community dividends are distributed daily from platform revenue.` +
|
|
416
|
+
(unsubscribeUrl ? `\n\nUnsubscribe: ${unsubscribeUrl}` : "") +
|
|
417
|
+
copyright(),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function customTemplate(data) {
|
|
421
|
+
const subject = data.subject || "Message from WOPR";
|
|
422
|
+
const rawBody = data.bodyText || "";
|
|
423
|
+
const escapedBody = escapeHtml(rawBody).replace(/\n/g, "<br>\n");
|
|
424
|
+
const parts = [heading("Message from WOPR"), paragraph(`<p>${escapedBody}</p>`)];
|
|
425
|
+
parts.push(footer("This is an administrative message from WOPR Network."));
|
|
426
|
+
return {
|
|
427
|
+
subject,
|
|
428
|
+
html: wrapHtml(escapeHtml(subject), parts.join("\n")),
|
|
429
|
+
text: `${rawBody}\n${copyright()}`,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
// ---------------------------------------------------------------------------
|
|
433
|
+
// Dispatcher
|
|
434
|
+
// ---------------------------------------------------------------------------
|
|
435
|
+
/**
|
|
436
|
+
* Render a notification template by name.
|
|
437
|
+
*
|
|
438
|
+
* All new templates are dispatched here. Legacy templates (verify-email,
|
|
439
|
+
* welcome, password-reset, etc.) are handled by templates.ts directly.
|
|
440
|
+
*/
|
|
441
|
+
export function renderNotificationTemplate(template, data) {
|
|
442
|
+
switch (template) {
|
|
443
|
+
case "credits-depleted":
|
|
444
|
+
return creditsDepletedTemplate(data);
|
|
445
|
+
case "grace-period-start":
|
|
446
|
+
return gracePeriodStartTemplate(data);
|
|
447
|
+
case "grace-period-warning":
|
|
448
|
+
return gracePeriodWarningTemplate(data);
|
|
449
|
+
case "auto-suspended":
|
|
450
|
+
return autoSuspendedTemplate(data);
|
|
451
|
+
case "auto-topup-success":
|
|
452
|
+
return autoTopupSuccessTemplate(data);
|
|
453
|
+
case "auto-topup-failed":
|
|
454
|
+
return autoTopupFailedTemplate(data);
|
|
455
|
+
case "crypto-payment-confirmed":
|
|
456
|
+
return cryptoPaymentConfirmedTemplate(data);
|
|
457
|
+
case "admin-suspended":
|
|
458
|
+
return adminSuspendedTemplate(data);
|
|
459
|
+
case "admin-reactivated":
|
|
460
|
+
return adminReactivatedTemplate(data);
|
|
461
|
+
case "credits-granted":
|
|
462
|
+
return creditsGrantedTemplate(data);
|
|
463
|
+
case "role-changed":
|
|
464
|
+
return roleChangedTemplate(data);
|
|
465
|
+
case "team-invite":
|
|
466
|
+
return teamInviteTemplate(data);
|
|
467
|
+
case "agent-created":
|
|
468
|
+
return agentCreatedTemplate(data);
|
|
469
|
+
case "channel-connected":
|
|
470
|
+
return channelConnectedTemplate(data);
|
|
471
|
+
case "channel-disconnected":
|
|
472
|
+
return channelDisconnectedTemplate(data);
|
|
473
|
+
case "agent-suspended":
|
|
474
|
+
return agentSuspendedTemplate(data);
|
|
475
|
+
case "affiliate-credit-match": {
|
|
476
|
+
const amountDollars = escapeHtml(data.amountDollars || "$0.00");
|
|
477
|
+
const creditsUrl = data.creditsUrl || "";
|
|
478
|
+
const parts = [
|
|
479
|
+
heading("You Earned Affiliate Credits!"),
|
|
480
|
+
paragraph(`<p>Great news! A user you referred just made their first purchase, and you've been credited <strong>${amountDollars}</strong>.</p>`),
|
|
481
|
+
];
|
|
482
|
+
if (creditsUrl)
|
|
483
|
+
parts.push(button(creditsUrl, "View Credit Balance"));
|
|
484
|
+
parts.push(footer("Thank you for spreading the word about WOPR!"));
|
|
485
|
+
return {
|
|
486
|
+
subject: `You earned ${data.amountDollars} in affiliate credits!`,
|
|
487
|
+
html: wrapHtml("Affiliate Credits Earned", parts.join("\n")),
|
|
488
|
+
text: `You Earned Affiliate Credits!\n\nA user you referred just made their first purchase, and you've been credited ${data.amountDollars}.\n${creditsUrl ? `\nView your balance: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
case "spend-alert": {
|
|
492
|
+
const currentSpend = escapeHtml(String(data.currentSpendDollars ?? "$0.00"));
|
|
493
|
+
const alertAt = escapeHtml(String(data.alertAtDollars ?? "$0.00"));
|
|
494
|
+
const creditsUrl = data.creditsUrl || "";
|
|
495
|
+
const parts = [
|
|
496
|
+
heading("Spending Alert: Threshold Reached"),
|
|
497
|
+
paragraph(`<p>Your monthly spend has reached <strong>${currentSpend}</strong>, ` +
|
|
498
|
+
`crossing your alert threshold of <strong>${alertAt}</strong>.</p>` +
|
|
499
|
+
`<p>Review your spending to stay within your budget.</p>`),
|
|
500
|
+
];
|
|
501
|
+
if (creditsUrl)
|
|
502
|
+
parts.push(button(creditsUrl, "Review Spending"));
|
|
503
|
+
parts.push(footer("This alert fires once per day when your spend exceeds your configured threshold."));
|
|
504
|
+
return {
|
|
505
|
+
subject: `Spending alert: you've reached your ${data.alertAtDollars} threshold`,
|
|
506
|
+
html: wrapHtml("Spending Alert", parts.join("\n")),
|
|
507
|
+
text: `Spending Alert: Threshold Reached\n\nYour monthly spend has reached ${data.currentSpendDollars}, ` +
|
|
508
|
+
`crossing your alert threshold of ${data.alertAtDollars}.\n` +
|
|
509
|
+
(creditsUrl ? `\nReview spending: ${creditsUrl}\n` : "") +
|
|
510
|
+
copyright(),
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
case "custom":
|
|
514
|
+
return customTemplate(data);
|
|
515
|
+
case "dividend-weekly-digest":
|
|
516
|
+
return dividendWeeklyDigestTemplate(data);
|
|
517
|
+
case "account-deletion-requested":
|
|
518
|
+
return accountDeletionRequestedTemplate(data);
|
|
519
|
+
case "account-deletion-cancelled":
|
|
520
|
+
return accountDeletionCancelledTemplate(data);
|
|
521
|
+
case "account-deletion-completed":
|
|
522
|
+
return accountDeletionCompletedTemplate(data);
|
|
523
|
+
case "low-balance":
|
|
524
|
+
return {
|
|
525
|
+
subject: "Your WOPR credits are running low",
|
|
526
|
+
html: wrapHtml("Low Balance", [
|
|
527
|
+
heading("Your WOPR Credits Are Running Low"),
|
|
528
|
+
paragraph(`<p>Your balance is <strong>${escapeHtml(data.balanceDollars || "$0.00")}</strong>. Top up to keep your agents running.</p>`),
|
|
529
|
+
...(data.creditsUrl ? [button(data.creditsUrl, "Buy Credits")] : []),
|
|
530
|
+
footer("This is an automated billing notification."),
|
|
531
|
+
].join("\n")),
|
|
532
|
+
text: `Your WOPR Credits Are Running Low\n\nBalance: ${data.balanceDollars}\n${data.creditsUrl ? `\nBuy credits: ${data.creditsUrl}\n` : ""}${copyright()}`,
|
|
533
|
+
};
|
|
534
|
+
case "credit-purchase-receipt":
|
|
535
|
+
return {
|
|
536
|
+
subject: "Credits added to your account",
|
|
537
|
+
html: wrapHtml("Credits Added", [
|
|
538
|
+
heading("Credits Added to Your Account"),
|
|
539
|
+
paragraph(`<p><strong>${escapeHtml(data.amountDollars || "$0.00")}</strong> in credits has been added.</p>` +
|
|
540
|
+
(data.newBalanceDollars
|
|
541
|
+
? `<p>New balance: <strong>${escapeHtml(data.newBalanceDollars)}</strong></p>`
|
|
542
|
+
: "")),
|
|
543
|
+
footer("Thank you for supporting WOPR!"),
|
|
544
|
+
].join("\n")),
|
|
545
|
+
text: `Credits Added\n\n${data.amountDollars} added.\n${copyright()}`,
|
|
546
|
+
};
|
|
547
|
+
case "welcome":
|
|
548
|
+
return {
|
|
549
|
+
subject: "Welcome to WOPR",
|
|
550
|
+
html: wrapHtml("Welcome", [
|
|
551
|
+
heading("Welcome to WOPR!"),
|
|
552
|
+
paragraph("<p>Your account is now active. Start building!</p>"),
|
|
553
|
+
footer("Happy building!"),
|
|
554
|
+
].join("\n")),
|
|
555
|
+
text: `Welcome to WOPR!\n\nYour account is now active.\n${copyright()}`,
|
|
556
|
+
};
|
|
557
|
+
case "password-reset":
|
|
558
|
+
return {
|
|
559
|
+
subject: "Reset your WOPR password",
|
|
560
|
+
html: wrapHtml("Reset Password", [
|
|
561
|
+
heading("Reset Your Password"),
|
|
562
|
+
paragraph("<p>Click below to reset your password.</p>"),
|
|
563
|
+
...(data.resetUrl ? [button(data.resetUrl, "Reset Password")] : []),
|
|
564
|
+
footer("If you did not request this, ignore this email."),
|
|
565
|
+
].join("\n")),
|
|
566
|
+
text: `Reset Your Password\n\n${data.resetUrl ? `${data.resetUrl}\n` : ""}${copyright()}`,
|
|
567
|
+
};
|
|
568
|
+
default: {
|
|
569
|
+
// Exhaustiveness check
|
|
570
|
+
const _exhaustive = template;
|
|
571
|
+
throw new Error(`Unknown notification template: ${String(_exhaustive)}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|