qarpeo 0.0.0-alpha.10
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/LICENSE +21 -0
- package/README.md +102 -0
- package/dist/chunks/auth-schema.mjs +219 -0
- package/dist/chunks/wrangler.mjs +783 -0
- package/dist/cli/index.mjs +1085 -0
- package/dist/dev/env.d.ts +12 -0
- package/dist/dev/wrangler.d.ts +18 -0
- package/dist/module.d.ts +16 -0
- package/dist/module.mjs +4436 -0
- package/dist/runtime/ai.d.ts +25 -0
- package/dist/runtime/ai.mjs +106 -0
- package/dist/runtime/analytics.d.ts +24 -0
- package/dist/runtime/analytics.mjs +38 -0
- package/dist/runtime/app/components/BlobImage.vue +100 -0
- package/dist/runtime/app/components/CMSBlocks.vue +93 -0
- package/dist/runtime/app/components/CMSContent.vue +23 -0
- package/dist/runtime/app/components/CMSImage.vue +49 -0
- package/dist/runtime/app/components/CMSLocaleSwitcher.vue +110 -0
- package/dist/runtime/app/components/CMSPreviewBanner.vue +79 -0
- package/dist/runtime/app/components/CMSVersionBanner.vue +49 -0
- package/dist/runtime/app/components/CMSVersionSwitcher.vue +126 -0
- package/dist/runtime/app/components/ContentRenderer.vue +80 -0
- package/dist/runtime/app/components/FileUpload.vue +196 -0
- package/dist/runtime/app/components/ImpersonationBanner.vue +57 -0
- package/dist/runtime/app/components/SignedIn.vue +13 -0
- package/dist/runtime/app/components/SignedOut.vue +13 -0
- package/dist/runtime/app/components/shiki.css +34 -0
- package/dist/runtime/app/composables/analytics.d.ts +125 -0
- package/dist/runtime/app/composables/analytics.mjs +81 -0
- package/dist/runtime/app/composables/api-tokens.d.ts +49 -0
- package/dist/runtime/app/composables/api-tokens.mjs +61 -0
- package/dist/runtime/app/composables/auth.d.ts +50 -0
- package/dist/runtime/app/composables/auth.mjs +101 -0
- package/dist/runtime/app/composables/chat.d.ts +69 -0
- package/dist/runtime/app/composables/chat.mjs +159 -0
- package/dist/runtime/app/composables/cms-preview.d.ts +33 -0
- package/dist/runtime/app/composables/cms-preview.mjs +83 -0
- package/dist/runtime/app/composables/cms.d.ts +307 -0
- package/dist/runtime/app/composables/cms.mjs +355 -0
- package/dist/runtime/app/composables/docs-version.d.ts +35 -0
- package/dist/runtime/app/composables/docs-version.mjs +70 -0
- package/dist/runtime/app/composables/impersonation.d.ts +14 -0
- package/dist/runtime/app/composables/impersonation.mjs +44 -0
- package/dist/runtime/app/composables/notifications.d.ts +35 -0
- package/dist/runtime/app/composables/notifications.mjs +139 -0
- package/dist/runtime/app/composables/organization.d.ts +127 -0
- package/dist/runtime/app/composables/organization.mjs +138 -0
- package/dist/runtime/app/composables/passkey.d.ts +6 -0
- package/dist/runtime/app/composables/passkey.mjs +105 -0
- package/dist/runtime/app/composables/passwordless.d.ts +7 -0
- package/dist/runtime/app/composables/passwordless.mjs +67 -0
- package/dist/runtime/app/composables/payments.d.ts +43 -0
- package/dist/runtime/app/composables/payments.mjs +74 -0
- package/dist/runtime/app/composables/realtime.d.ts +96 -0
- package/dist/runtime/app/composables/realtime.mjs +432 -0
- package/dist/runtime/app/composables/site.d.ts +35 -0
- package/dist/runtime/app/composables/site.mjs +36 -0
- package/dist/runtime/app/composables/storage.d.ts +60 -0
- package/dist/runtime/app/composables/storage.mjs +294 -0
- package/dist/runtime/app/composables/tenant.d.ts +82 -0
- package/dist/runtime/app/composables/tenant.mjs +120 -0
- package/dist/runtime/app/composables/turnstile.d.ts +3 -0
- package/dist/runtime/app/composables/turnstile.mjs +10 -0
- package/dist/runtime/app/composables/two-factor.d.ts +12 -0
- package/dist/runtime/app/composables/two-factor.mjs +65 -0
- package/dist/runtime/app/middleware/auth.global.d.ts +2 -0
- package/dist/runtime/app/middleware/auth.global.mjs +44 -0
- package/dist/runtime/app/pages/cms.vue +2249 -0
- package/dist/runtime/app/pages/devtools/agents.vue +717 -0
- package/dist/runtime/app/pages/devtools/analytics.vue +618 -0
- package/dist/runtime/app/pages/devtools/auth.vue +351 -0
- package/dist/runtime/app/pages/devtools/blob.vue +745 -0
- package/dist/runtime/app/pages/devtools/db.vue +546 -0
- package/dist/runtime/app/pages/devtools/domains.vue +772 -0
- package/dist/runtime/app/pages/devtools/kv.vue +829 -0
- package/dist/runtime/app/pages/devtools/logs.vue +655 -0
- package/dist/runtime/app/pages/devtools/mail.vue +389 -0
- package/dist/runtime/app/pages/devtools/overview.vue +390 -0
- package/dist/runtime/app/pages/devtools/settings.vue +560 -0
- package/dist/runtime/app/pages/devtools.vue +165 -0
- package/dist/runtime/app/plugins/seo.d.ts +2 -0
- package/dist/runtime/app/plugins/seo.mjs +105 -0
- package/dist/runtime/app/plugins/shortcuts.client.d.ts +6 -0
- package/dist/runtime/app/plugins/shortcuts.client.mjs +19 -0
- package/dist/runtime/app/public/sw-notifications.mjs +52 -0
- package/dist/runtime/auth.d.ts +25 -0
- package/dist/runtime/auth.mjs +11 -0
- package/dist/runtime/bindings.d.ts +27 -0
- package/dist/runtime/bindings.mjs +38 -0
- package/dist/runtime/blob.d.ts +26 -0
- package/dist/runtime/blob.mjs +334 -0
- package/dist/runtime/bots.d.ts +1 -0
- package/dist/runtime/bots.mjs +1 -0
- package/dist/runtime/browser.d.ts +21 -0
- package/dist/runtime/browser.mjs +64 -0
- package/dist/runtime/cache.d.ts +19 -0
- package/dist/runtime/cache.mjs +12 -0
- package/dist/runtime/cms.d.ts +2 -0
- package/dist/runtime/cms.mjs +0 -0
- package/dist/runtime/db.d.ts +21 -0
- package/dist/runtime/db.mjs +36 -0
- package/dist/runtime/drizzle.d.ts +11 -0
- package/dist/runtime/drizzle.mjs +18 -0
- package/dist/runtime/email.d.ts +51 -0
- package/dist/runtime/email.mjs +245 -0
- package/dist/runtime/hyperdrive.d.ts +21 -0
- package/dist/runtime/hyperdrive.mjs +49 -0
- package/dist/runtime/index.d.ts +23 -0
- package/dist/runtime/index.mjs +23 -0
- package/dist/runtime/kv.d.ts +16 -0
- package/dist/runtime/kv.mjs +126 -0
- package/dist/runtime/payments.d.ts +2 -0
- package/dist/runtime/payments.mjs +0 -0
- package/dist/runtime/queue.d.ts +21 -0
- package/dist/runtime/queue.mjs +41 -0
- package/dist/runtime/rag.d.ts +1 -0
- package/dist/runtime/rag.mjs +1 -0
- package/dist/runtime/ratelimit.d.ts +21 -0
- package/dist/runtime/ratelimit.mjs +38 -0
- package/dist/runtime/realtime.d.ts +6 -0
- package/dist/runtime/realtime.mjs +13 -0
- package/dist/runtime/server/db/cms-schema.d.ts +651 -0
- package/dist/runtime/server/db/cms-schema.mjs +74 -0
- package/dist/runtime/server/durable-objects/agent.d.ts +14 -0
- package/dist/runtime/server/durable-objects/agent.mjs +571 -0
- package/dist/runtime/server/durable-objects/room.d.ts +34 -0
- package/dist/runtime/server/durable-objects/room.mjs +514 -0
- package/dist/runtime/server/middleware/auth.d.ts +2 -0
- package/dist/runtime/server/middleware/auth.mjs +108 -0
- package/dist/runtime/server/middleware/devtools.d.ts +2 -0
- package/dist/runtime/server/middleware/devtools.mjs +61 -0
- package/dist/runtime/server/middleware/ratelimit.d.ts +2 -0
- package/dist/runtime/server/middleware/ratelimit.mjs +49 -0
- package/dist/runtime/server/middleware/tenancy.d.ts +6 -0
- package/dist/runtime/server/middleware/tenancy.mjs +15 -0
- package/dist/runtime/server/middleware/tracker.d.ts +7 -0
- package/dist/runtime/server/middleware/tracker.mjs +9 -0
- package/dist/runtime/server/plugins/agents.d.ts +7 -0
- package/dist/runtime/server/plugins/agents.mjs +3 -0
- package/dist/runtime/server/plugins/cms.d.ts +7 -0
- package/dist/runtime/server/plugins/cms.mjs +16 -0
- package/dist/runtime/server/plugins/dev-logs.d.ts +1 -0
- package/dist/runtime/server/plugins/dev-logs.mjs +58 -0
- package/dist/runtime/server/plugins/dev-proxy.d.ts +3 -0
- package/dist/runtime/server/plugins/dev-proxy.mjs +21 -0
- package/dist/runtime/server/plugins/env.d.ts +6 -0
- package/dist/runtime/server/plugins/env.mjs +17 -0
- package/dist/runtime/server/plugins/queue.d.ts +6 -0
- package/dist/runtime/server/plugins/queue.mjs +8 -0
- package/dist/runtime/server/routes/__qarpeo/agents/chat.post.d.ts +20 -0
- package/dist/runtime/server/routes/__qarpeo/agents/chat.post.mjs +110 -0
- package/dist/runtime/server/routes/__qarpeo/agents/clear.post.d.ts +7 -0
- package/dist/runtime/server/routes/__qarpeo/agents/clear.post.mjs +15 -0
- package/dist/runtime/server/routes/__qarpeo/agents/create.post.d.ts +17 -0
- package/dist/runtime/server/routes/__qarpeo/agents/create.post.mjs +47 -0
- package/dist/runtime/server/routes/__qarpeo/agents/history.get.d.ts +15 -0
- package/dist/runtime/server/routes/__qarpeo/agents/history.get.mjs +24 -0
- package/dist/runtime/server/routes/__qarpeo/agents/list.get.d.ts +5 -0
- package/dist/runtime/server/routes/__qarpeo/agents/list.get.mjs +63 -0
- package/dist/runtime/server/routes/__qarpeo/analytics/events.get.d.ts +64 -0
- package/dist/runtime/server/routes/__qarpeo/analytics/events.get.mjs +55 -0
- package/dist/runtime/server/routes/__qarpeo/analytics/summary.get.d.ts +30 -0
- package/dist/runtime/server/routes/__qarpeo/analytics/summary.get.mjs +73 -0
- package/dist/runtime/server/routes/__qarpeo/auth/revoke-session.post.d.ts +6 -0
- package/dist/runtime/server/routes/__qarpeo/auth/revoke-session.post.mjs +26 -0
- package/dist/runtime/server/routes/__qarpeo/auth/sessions.get.d.ts +6 -0
- package/dist/runtime/server/routes/__qarpeo/auth/sessions.get.mjs +46 -0
- package/dist/runtime/server/routes/__qarpeo/auth/users.get.d.ts +7 -0
- package/dist/runtime/server/routes/__qarpeo/auth/users.get.mjs +65 -0
- package/dist/runtime/server/routes/__qarpeo/blob/files.get.d.ts +22 -0
- package/dist/runtime/server/routes/__qarpeo/blob/files.get.mjs +36 -0
- package/dist/runtime/server/routes/__qarpeo/db/query.post.d.ts +23 -0
- package/dist/runtime/server/routes/__qarpeo/db/query.post.mjs +34 -0
- package/dist/runtime/server/routes/__qarpeo/db/tables.get.d.ts +31 -0
- package/dist/runtime/server/routes/__qarpeo/db/tables.get.mjs +81 -0
- package/dist/runtime/server/routes/__qarpeo/kv/delete.post.d.ts +11 -0
- package/dist/runtime/server/routes/__qarpeo/kv/delete.post.mjs +18 -0
- package/dist/runtime/server/routes/__qarpeo/kv/get.get.d.ts +11 -0
- package/dist/runtime/server/routes/__qarpeo/kv/get.get.mjs +20 -0
- package/dist/runtime/server/routes/__qarpeo/kv/keys.get.d.ts +8 -0
- package/dist/runtime/server/routes/__qarpeo/kv/keys.get.mjs +27 -0
- package/dist/runtime/server/routes/__qarpeo/kv/set.post.d.ts +14 -0
- package/dist/runtime/server/routes/__qarpeo/kv/set.post.mjs +24 -0
- package/dist/runtime/server/routes/__qarpeo/logs.delete.d.ts +5 -0
- package/dist/runtime/server/routes/__qarpeo/logs.delete.mjs +6 -0
- package/dist/runtime/server/routes/__qarpeo/logs.get.d.ts +5 -0
- package/dist/runtime/server/routes/__qarpeo/logs.get.mjs +26 -0
- package/dist/runtime/server/routes/__qarpeo/logs.post.d.ts +6 -0
- package/dist/runtime/server/routes/__qarpeo/logs.post.mjs +17 -0
- package/dist/runtime/server/routes/__qarpeo/mail/bounce.post.d.ts +5 -0
- package/dist/runtime/server/routes/__qarpeo/mail/bounce.post.mjs +37 -0
- package/dist/runtime/server/routes/__qarpeo/mail/clear.post.d.ts +4 -0
- package/dist/runtime/server/routes/__qarpeo/mail/clear.post.mjs +6 -0
- package/dist/runtime/server/routes/__qarpeo/mail/inbox.get.d.ts +5 -0
- package/dist/runtime/server/routes/__qarpeo/mail/inbox.get.mjs +7 -0
- package/dist/runtime/server/routes/__qarpeo/mail/send-test.post.d.ts +4 -0
- package/dist/runtime/server/routes/__qarpeo/mail/send-test.post.mjs +29 -0
- package/dist/runtime/server/routes/__qarpeo/mail/track/click/[id].get.d.ts +2 -0
- package/dist/runtime/server/routes/__qarpeo/mail/track/click/[id].get.mjs +23 -0
- package/dist/runtime/server/routes/__qarpeo/mail/track/open/[id].get.d.ts +2 -0
- package/dist/runtime/server/routes/__qarpeo/mail/track/open/[id].get.mjs +31 -0
- package/dist/runtime/server/routes/__qarpeo/overview/health.get.d.ts +8 -0
- package/dist/runtime/server/routes/__qarpeo/overview/health.get.mjs +46 -0
- package/dist/runtime/server/routes/__qarpeo/overview.get.d.ts +32 -0
- package/dist/runtime/server/routes/__qarpeo/overview.get.mjs +38 -0
- package/dist/runtime/server/routes/__qarpeo/settings/reset-dev-data.post.d.ts +11 -0
- package/dist/runtime/server/routes/__qarpeo/settings/reset-dev-data.post.mjs +84 -0
- package/dist/runtime/server/routes/__qarpeo/settings.get.d.ts +124 -0
- package/dist/runtime/server/routes/__qarpeo/settings.get.mjs +145 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/create.post.d.ts +7 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/create.post.mjs +26 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-add.post.d.ts +6 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-add.post.mjs +29 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-delete.post.d.ts +7 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-delete.post.mjs +21 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-verify.post.d.ts +9 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/domain-verify.post.mjs +21 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/list.get.d.ts +15 -0
- package/dist/runtime/server/routes/__qarpeo/tenants/list.get.mjs +22 -0
- package/dist/runtime/server/routes/agents/[agent]/chat.post.d.ts +2 -0
- package/dist/runtime/server/routes/agents/[agent]/chat.post.mjs +35 -0
- package/dist/runtime/server/routes/agents/[agent]/clear.post.d.ts +4 -0
- package/dist/runtime/server/routes/agents/[agent]/clear.post.mjs +27 -0
- package/dist/runtime/server/routes/agents/[agent]/history.get.d.ts +4 -0
- package/dist/runtime/server/routes/agents/[agent]/history.get.mjs +27 -0
- package/dist/runtime/server/routes/analytics/events.get.d.ts +3 -0
- package/dist/runtime/server/routes/analytics/events.get.mjs +17 -0
- package/dist/runtime/server/routes/analytics/pageviews.get.d.ts +3 -0
- package/dist/runtime/server/routes/analytics/pageviews.get.mjs +15 -0
- package/dist/runtime/server/routes/analytics/summary.get.d.ts +6 -0
- package/dist/runtime/server/routes/analytics/summary.get.mjs +15 -0
- package/dist/runtime/server/routes/atom.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/atom.xml.get.mjs +76 -0
- package/dist/runtime/server/routes/auth/2fa/disable.post.d.ts +4 -0
- package/dist/runtime/server/routes/auth/2fa/disable.post.mjs +44 -0
- package/dist/runtime/server/routes/auth/2fa/setup.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/2fa/setup.post.mjs +32 -0
- package/dist/runtime/server/routes/auth/2fa/verify.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/2fa/verify.post.mjs +92 -0
- package/dist/runtime/server/routes/auth/[provider]/callback.d.ts +1 -0
- package/dist/runtime/server/routes/auth/[provider]/callback.mjs +1 -0
- package/dist/runtime/server/routes/auth/[provider].d.ts +3 -0
- package/dist/runtime/server/routes/auth/[provider].mjs +95 -0
- package/dist/runtime/server/routes/auth/account.delete.d.ts +5 -0
- package/dist/runtime/server/routes/auth/account.delete.mjs +52 -0
- package/dist/runtime/server/routes/auth/impersonate/start.post.d.ts +5 -0
- package/dist/runtime/server/routes/auth/impersonate/start.post.mjs +14 -0
- package/dist/runtime/server/routes/auth/impersonate/stop.post.d.ts +5 -0
- package/dist/runtime/server/routes/auth/impersonate/stop.post.mjs +5 -0
- package/dist/runtime/server/routes/auth/logout-all.post.d.ts +4 -0
- package/dist/runtime/server/routes/auth/logout-all.post.mjs +16 -0
- package/dist/runtime/server/routes/auth/logout-others.post.d.ts +4 -0
- package/dist/runtime/server/routes/auth/logout-others.post.mjs +11 -0
- package/dist/runtime/server/routes/auth/logout.post.d.ts +4 -0
- package/dist/runtime/server/routes/auth/logout.post.mjs +17 -0
- package/dist/runtime/server/routes/auth/magic-link/send.post.d.ts +10 -0
- package/dist/runtime/server/routes/auth/magic-link/send.post.mjs +29 -0
- package/dist/runtime/server/routes/auth/magic-link/verify.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/magic-link/verify.get.mjs +81 -0
- package/dist/runtime/server/routes/auth/organization/create.post.d.ts +5 -0
- package/dist/runtime/server/routes/auth/organization/create.post.mjs +10 -0
- package/dist/runtime/server/routes/auth/organization/invite.post.d.ts +9 -0
- package/dist/runtime/server/routes/auth/organization/invite.post.mjs +27 -0
- package/dist/runtime/server/routes/auth/organization/join.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/organization/join.post.mjs +15 -0
- package/dist/runtime/server/routes/auth/organization/list.get.d.ts +5 -0
- package/dist/runtime/server/routes/auth/organization/list.get.mjs +7 -0
- package/dist/runtime/server/routes/auth/organization/members/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/auth/organization/members/[id].delete.mjs +33 -0
- package/dist/runtime/server/routes/auth/organization/members/index.get.d.ts +6 -0
- package/dist/runtime/server/routes/auth/organization/members/index.get.mjs +18 -0
- package/dist/runtime/server/routes/auth/organization/mfa.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/organization/mfa.post.mjs +33 -0
- package/dist/runtime/server/routes/auth/organization/sso/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/auth/organization/sso/[id].delete.mjs +28 -0
- package/dist/runtime/server/routes/auth/organization/sso/index.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/organization/sso/index.get.mjs +23 -0
- package/dist/runtime/server/routes/auth/organization/sso/index.post.d.ts +5 -0
- package/dist/runtime/server/routes/auth/organization/sso/index.post.mjs +84 -0
- package/dist/runtime/server/routes/auth/organization/switch.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/organization/switch.post.mjs +14 -0
- package/dist/runtime/server/routes/auth/otp/send.post.d.ts +10 -0
- package/dist/runtime/server/routes/auth/otp/send.post.mjs +29 -0
- package/dist/runtime/server/routes/auth/otp/verify.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/otp/verify.post.mjs +95 -0
- package/dist/runtime/server/routes/auth/sessions/[id].delete.d.ts +5 -0
- package/dist/runtime/server/routes/auth/sessions/[id].delete.mjs +24 -0
- package/dist/runtime/server/routes/auth/sessions.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/sessions.get.mjs +11 -0
- package/dist/runtime/server/routes/auth/sso/login.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/sso/login.get.mjs +94 -0
- package/dist/runtime/server/routes/auth/sso/oidc/callback.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/sso/oidc/callback.get.mjs +113 -0
- package/dist/runtime/server/routes/auth/sso/saml/acs.post.d.ts +2 -0
- package/dist/runtime/server/routes/auth/sso/saml/acs.post.mjs +95 -0
- package/dist/runtime/server/routes/auth/tokens/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/auth/tokens/[id].delete.mjs +13 -0
- package/dist/runtime/server/routes/auth/tokens/create.post.d.ts +9 -0
- package/dist/runtime/server/routes/auth/tokens/create.post.mjs +17 -0
- package/dist/runtime/server/routes/auth/tokens/index.get.d.ts +9 -0
- package/dist/runtime/server/routes/auth/tokens/index.get.mjs +5 -0
- package/dist/runtime/server/routes/auth/turnstile/verify.post.d.ts +2 -0
- package/dist/runtime/server/routes/auth/turnstile/verify.post.mjs +15 -0
- package/dist/runtime/server/routes/auth/user.get.d.ts +2 -0
- package/dist/runtime/server/routes/auth/user.get.mjs +6 -0
- package/dist/runtime/server/routes/auth/webauthn/login/options.post.d.ts +2 -0
- package/dist/runtime/server/routes/auth/webauthn/login/options.post.mjs +17 -0
- package/dist/runtime/server/routes/auth/webauthn/login/verify.post.d.ts +6 -0
- package/dist/runtime/server/routes/auth/webauthn/login/verify.post.mjs +127 -0
- package/dist/runtime/server/routes/auth/webauthn/register/options.post.d.ts +2 -0
- package/dist/runtime/server/routes/auth/webauthn/register/options.post.mjs +47 -0
- package/dist/runtime/server/routes/auth/webauthn/register/verify.post.d.ts +5 -0
- package/dist/runtime/server/routes/auth/webauthn/register/verify.post.mjs +88 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/preview-token.post.d.ts +8 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/preview-token.post.mjs +27 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/publish.post.d.ts +6 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/publish.post.mjs +19 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/review.post.d.ts +6 -0
- package/dist/runtime/server/routes/cms/[collection]/[id]/review.post.mjs +33 -0
- package/dist/runtime/server/routes/cms/[collection]/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/cms/[collection]/[id].delete.mjs +17 -0
- package/dist/runtime/server/routes/cms/[collection]/[id].put.d.ts +4 -0
- package/dist/runtime/server/routes/cms/[collection]/[id].put.mjs +18 -0
- package/dist/runtime/server/routes/cms/[collection]/[slug].get.d.ts +4 -0
- package/dist/runtime/server/routes/cms/[collection]/[slug].get.mjs +19 -0
- package/dist/runtime/server/routes/cms/[collection]/atom.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/cms/[collection]/atom.xml.get.mjs +69 -0
- package/dist/runtime/server/routes/cms/[collection]/by-path.get.d.ts +8 -0
- package/dist/runtime/server/routes/cms/[collection]/by-path.get.mjs +23 -0
- package/dist/runtime/server/routes/cms/[collection]/feed.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/cms/[collection]/feed.xml.get.mjs +65 -0
- package/dist/runtime/server/routes/cms/[collection]/index.get.d.ts +7 -0
- package/dist/runtime/server/routes/cms/[collection]/index.get.mjs +15 -0
- package/dist/runtime/server/routes/cms/[collection]/index.post.d.ts +4 -0
- package/dist/runtime/server/routes/cms/[collection]/index.post.mjs +23 -0
- package/dist/runtime/server/routes/cms/[collection]/references.get.d.ts +19 -0
- package/dist/runtime/server/routes/cms/[collection]/references.get.mjs +47 -0
- package/dist/runtime/server/routes/cms/[collection]/surroundings.get.d.ts +10 -0
- package/dist/runtime/server/routes/cms/[collection]/surroundings.get.mjs +12 -0
- package/dist/runtime/server/routes/cms/collections/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/cms/collections/[id].delete.mjs +10 -0
- package/dist/runtime/server/routes/cms/collections/[id].put.d.ts +4 -0
- package/dist/runtime/server/routes/cms/collections/[id].put.mjs +11 -0
- package/dist/runtime/server/routes/cms/collections/index.get.d.ts +4 -0
- package/dist/runtime/server/routes/cms/collections/index.get.mjs +6 -0
- package/dist/runtime/server/routes/cms/collections/index.post.d.ts +4 -0
- package/dist/runtime/server/routes/cms/collections/index.post.mjs +19 -0
- package/dist/runtime/server/routes/cms/components/index.get.d.ts +17 -0
- package/dist/runtime/server/routes/cms/components/index.get.mjs +16 -0
- package/dist/runtime/server/routes/cms/deploy.post.d.ts +4 -0
- package/dist/runtime/server/routes/cms/deploy.post.mjs +46 -0
- package/dist/runtime/server/routes/cms/export.post.d.ts +10 -0
- package/dist/runtime/server/routes/cms/export.post.mjs +55 -0
- package/dist/runtime/server/routes/cms/navigation.get.d.ts +8 -0
- package/dist/runtime/server/routes/cms/navigation.get.mjs +36 -0
- package/dist/runtime/server/routes/cms/preview/disable.get.d.ts +9 -0
- package/dist/runtime/server/routes/cms/preview/disable.get.mjs +9 -0
- package/dist/runtime/server/routes/cms/preview/enable.get.d.ts +14 -0
- package/dist/runtime/server/routes/cms/preview/enable.get.mjs +42 -0
- package/dist/runtime/server/routes/cms/publish-scheduled.post.d.ts +11 -0
- package/dist/runtime/server/routes/cms/publish-scheduled.post.mjs +35 -0
- package/dist/runtime/server/routes/cms/search.get.d.ts +13 -0
- package/dist/runtime/server/routes/cms/search.get.mjs +137 -0
- package/dist/runtime/server/routes/cms/sync.post.d.ts +7 -0
- package/dist/runtime/server/routes/cms/sync.post.mjs +18 -0
- package/dist/runtime/server/routes/cms/webhooks/[provider].post.d.ts +150 -0
- package/dist/runtime/server/routes/cms/webhooks/[provider].post.mjs +213 -0
- package/dist/runtime/server/routes/docs/search.get.d.ts +15 -0
- package/dist/runtime/server/routes/docs/search.get.mjs +20 -0
- package/dist/runtime/server/routes/feed.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/feed.xml.get.mjs +73 -0
- package/dist/runtime/server/routes/mail/bounce.post.d.ts +14 -0
- package/dist/runtime/server/routes/mail/bounce.post.mjs +56 -0
- package/dist/runtime/server/routes/mail/inbox/[id].get.d.ts +2 -0
- package/dist/runtime/server/routes/mail/inbox/[id].get.mjs +9 -0
- package/dist/runtime/server/routes/mail/inbox.get.d.ts +4 -0
- package/dist/runtime/server/routes/mail/inbox.get.mjs +7 -0
- package/dist/runtime/server/routes/mail/suppressions/[email].delete.d.ts +11 -0
- package/dist/runtime/server/routes/mail/suppressions/[email].delete.mjs +18 -0
- package/dist/runtime/server/routes/mail/suppressions/index.get.d.ts +12 -0
- package/dist/runtime/server/routes/mail/suppressions/index.get.mjs +23 -0
- package/dist/runtime/server/routes/mail/suppressions/index.post.d.ts +10 -0
- package/dist/runtime/server/routes/mail/suppressions/index.post.mjs +23 -0
- package/dist/runtime/server/routes/mail/unsubscribe.d.ts +13 -0
- package/dist/runtime/server/routes/mail/unsubscribe.mjs +91 -0
- package/dist/runtime/server/routes/mail/webhooks.post.d.ts +12 -0
- package/dist/runtime/server/routes/mail/webhooks.post.mjs +71 -0
- package/dist/runtime/server/routes/notifications/[id]/read.post.d.ts +4 -0
- package/dist/runtime/server/routes/notifications/[id]/read.post.mjs +13 -0
- package/dist/runtime/server/routes/notifications/[id].delete.d.ts +4 -0
- package/dist/runtime/server/routes/notifications/[id].delete.mjs +13 -0
- package/dist/runtime/server/routes/notifications/[id].get.d.ts +2 -0
- package/dist/runtime/server/routes/notifications/[id].get.mjs +15 -0
- package/dist/runtime/server/routes/notifications/index.get.d.ts +6 -0
- package/dist/runtime/server/routes/notifications/index.get.mjs +18 -0
- package/dist/runtime/server/routes/notifications/push/subscribe.post.d.ts +4 -0
- package/dist/runtime/server/routes/notifications/push/subscribe.post.mjs +20 -0
- package/dist/runtime/server/routes/notifications/push/unsubscribe.post.d.ts +4 -0
- package/dist/runtime/server/routes/notifications/push/unsubscribe.post.mjs +15 -0
- package/dist/runtime/server/routes/notifications/read-all.post.d.ts +4 -0
- package/dist/runtime/server/routes/notifications/read-all.post.mjs +11 -0
- package/dist/runtime/server/routes/payments/cancel.post.d.ts +7 -0
- package/dist/runtime/server/routes/payments/cancel.post.mjs +9 -0
- package/dist/runtime/server/routes/payments/change-plan.post.d.ts +7 -0
- package/dist/runtime/server/routes/payments/change-plan.post.mjs +12 -0
- package/dist/runtime/server/routes/payments/checkout.post.d.ts +9 -0
- package/dist/runtime/server/routes/payments/checkout.post.mjs +16 -0
- package/dist/runtime/server/routes/payments/pause.post.d.ts +7 -0
- package/dist/runtime/server/routes/payments/pause.post.mjs +9 -0
- package/dist/runtime/server/routes/payments/portal.post.d.ts +5 -0
- package/dist/runtime/server/routes/payments/portal.post.mjs +9 -0
- package/dist/runtime/server/routes/payments/subscription.get.d.ts +6 -0
- package/dist/runtime/server/routes/payments/subscription.get.mjs +9 -0
- package/dist/runtime/server/routes/payments/usage.get.d.ts +12 -0
- package/dist/runtime/server/routes/payments/usage.get.mjs +18 -0
- package/dist/runtime/server/routes/payments/usage.post.d.ts +6 -0
- package/dist/runtime/server/routes/payments/usage.post.mjs +24 -0
- package/dist/runtime/server/routes/payments/webhook.post.d.ts +14 -0
- package/dist/runtime/server/routes/payments/webhook.post.mjs +21 -0
- package/dist/runtime/server/routes/realtime/broadcast.post.d.ts +4 -0
- package/dist/runtime/server/routes/realtime/broadcast.post.mjs +26 -0
- package/dist/runtime/server/routes/realtime/history.delete.d.ts +13 -0
- package/dist/runtime/server/routes/realtime/history.delete.mjs +12 -0
- package/dist/runtime/server/routes/realtime/history.get.d.ts +16 -0
- package/dist/runtime/server/routes/realtime/history.get.mjs +15 -0
- package/dist/runtime/server/routes/realtime/presence.get.d.ts +6 -0
- package/dist/runtime/server/routes/realtime/presence.get.mjs +27 -0
- package/dist/runtime/server/routes/realtime/state.get.d.ts +5 -0
- package/dist/runtime/server/routes/realtime/state.get.mjs +26 -0
- package/dist/runtime/server/routes/realtime/state.post.d.ts +6 -0
- package/dist/runtime/server/routes/realtime/state.post.mjs +37 -0
- package/dist/runtime/server/routes/realtime/ws.get.d.ts +2 -0
- package/dist/runtime/server/routes/realtime/ws.get.mjs +73 -0
- package/dist/runtime/server/routes/robots.txt.get.d.ts +2 -0
- package/dist/runtime/server/routes/robots.txt.get.mjs +41 -0
- package/dist/runtime/server/routes/rss.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/rss.xml.get.mjs +2 -0
- package/dist/runtime/server/routes/sitemap.xml.get.d.ts +2 -0
- package/dist/runtime/server/routes/sitemap.xml.get.mjs +84 -0
- package/dist/runtime/server/routes/storage/file/[...key].delete.d.ts +4 -0
- package/dist/runtime/server/routes/storage/file/[...key].delete.mjs +23 -0
- package/dist/runtime/server/routes/storage/file/[...key].get.d.ts +2 -0
- package/dist/runtime/server/routes/storage/file/[...key].get.mjs +23 -0
- package/dist/runtime/server/routes/storage/files.get.d.ts +14 -0
- package/dist/runtime/server/routes/storage/files.get.mjs +11 -0
- package/dist/runtime/server/routes/storage/presigned.post.d.ts +8 -0
- package/dist/runtime/server/routes/storage/presigned.post.mjs +39 -0
- package/dist/runtime/server/routes/storage/sign.post.d.ts +6 -0
- package/dist/runtime/server/routes/storage/sign.post.mjs +24 -0
- package/dist/runtime/server/routes/storage/upload.post.d.ts +22 -0
- package/dist/runtime/server/routes/storage/upload.post.mjs +96 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/[domain]/index.delete.d.ts +8 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/[domain]/index.delete.mjs +39 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/[domain]/verify.post.d.ts +8 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/[domain]/verify.post.mjs +39 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/index.get.d.ts +8 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/index.get.mjs +20 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/index.post.d.ts +8 -0
- package/dist/runtime/server/routes/tenants/[tenant]/domains/index.post.mjs +44 -0
- package/dist/runtime/server/routes/tenants/current.get.d.ts +8 -0
- package/dist/runtime/server/routes/tenants/current.get.mjs +6 -0
- package/dist/runtime/server/tasks/cms/publish.d.ts +4 -0
- package/dist/runtime/server/tasks/cms/publish.mjs +18 -0
- package/dist/runtime/server/utils/agent-store.d.ts +24 -0
- package/dist/runtime/server/utils/agent-store.mjs +53 -0
- package/dist/runtime/server/utils/agents-registry-fallback.d.ts +1 -0
- package/dist/runtime/server/utils/agents-registry-fallback.mjs +1 -0
- package/dist/runtime/server/utils/ai.d.ts +119 -0
- package/dist/runtime/server/utils/ai.mjs +607 -0
- package/dist/runtime/server/utils/analytics-query.d.ts +109 -0
- package/dist/runtime/server/utils/analytics-query.mjs +234 -0
- package/dist/runtime/server/utils/auth.d.ts +60 -0
- package/dist/runtime/server/utils/auth.mjs +361 -0
- package/dist/runtime/server/utils/blob-store.d.ts +13 -0
- package/dist/runtime/server/utils/blob-store.mjs +60 -0
- package/dist/runtime/server/utils/bots.d.ts +21 -0
- package/dist/runtime/server/utils/bots.mjs +491 -0
- package/dist/runtime/server/utils/cache.d.ts +33 -0
- package/dist/runtime/server/utils/cache.mjs +128 -0
- package/dist/runtime/server/utils/cms-events.d.ts +17 -0
- package/dist/runtime/server/utils/cms-events.mjs +80 -0
- package/dist/runtime/server/utils/cms-filter.d.ts +3 -0
- package/dist/runtime/server/utils/cms-filter.mjs +34 -0
- package/dist/runtime/server/utils/cms.d.ts +278 -0
- package/dist/runtime/server/utils/cms.mjs +3268 -0
- package/dist/runtime/server/utils/config.d.ts +27 -0
- package/dist/runtime/server/utils/config.mjs +38 -0
- package/dist/runtime/server/utils/context.d.ts +13 -0
- package/dist/runtime/server/utils/context.mjs +98 -0
- package/dist/runtime/server/utils/crypto.d.ts +16 -0
- package/dist/runtime/server/utils/crypto.mjs +56 -0
- package/dist/runtime/server/utils/dev-logs.d.ts +21 -0
- package/dist/runtime/server/utils/dev-logs.mjs +41 -0
- package/dist/runtime/server/utils/dev-proxy.d.ts +1 -0
- package/dist/runtime/server/utils/dev-proxy.mjs +69 -0
- package/dist/runtime/server/utils/domains.d.ts +46 -0
- package/dist/runtime/server/utils/domains.mjs +318 -0
- package/dist/runtime/server/utils/drizzle.d.ts +10 -0
- package/dist/runtime/server/utils/drizzle.mjs +36 -0
- package/dist/runtime/server/utils/email-templates.d.ts +44 -0
- package/dist/runtime/server/utils/email-templates.mjs +373 -0
- package/dist/runtime/server/utils/feed.d.ts +42 -0
- package/dist/runtime/server/utils/feed.mjs +161 -0
- package/dist/runtime/server/utils/impersonation.d.ts +67 -0
- package/dist/runtime/server/utils/impersonation.mjs +298 -0
- package/dist/runtime/server/utils/jobs.d.ts +70 -0
- package/dist/runtime/server/utils/jobs.mjs +125 -0
- package/dist/runtime/server/utils/kv-store.d.ts +9 -0
- package/dist/runtime/server/utils/kv-store.mjs +32 -0
- package/dist/runtime/server/utils/mail-suppression.d.ts +62 -0
- package/dist/runtime/server/utils/mail-suppression.mjs +328 -0
- package/dist/runtime/server/utils/mail.d.ts +90 -0
- package/dist/runtime/server/utils/mail.mjs +366 -0
- package/dist/runtime/server/utils/notifications.d.ts +51 -0
- package/dist/runtime/server/utils/notifications.mjs +215 -0
- package/dist/runtime/server/utils/organization.d.ts +54 -0
- package/dist/runtime/server/utils/organization.mjs +354 -0
- package/dist/runtime/server/utils/passwordless.d.ts +48 -0
- package/dist/runtime/server/utils/passwordless.mjs +179 -0
- package/dist/runtime/server/utils/payments.d.ts +121 -0
- package/dist/runtime/server/utils/payments.mjs +1067 -0
- package/dist/runtime/server/utils/queue-fallback.d.ts +2 -0
- package/dist/runtime/server/utils/queue-fallback.mjs +2 -0
- package/dist/runtime/server/utils/queue.d.ts +4 -0
- package/dist/runtime/server/utils/queue.mjs +3 -0
- package/dist/runtime/server/utils/rag.d.ts +25 -0
- package/dist/runtime/server/utils/rag.mjs +333 -0
- package/dist/runtime/server/utils/ratelimit.d.ts +45 -0
- package/dist/runtime/server/utils/ratelimit.mjs +182 -0
- package/dist/runtime/server/utils/realtime.d.ts +110 -0
- package/dist/runtime/server/utils/realtime.mjs +197 -0
- package/dist/runtime/server/utils/schema-fallback.d.ts +3 -0
- package/dist/runtime/server/utils/schema-fallback.mjs +2 -0
- package/dist/runtime/server/utils/session.d.ts +72 -0
- package/dist/runtime/server/utils/session.mjs +287 -0
- package/dist/runtime/server/utils/sso.d.ts +49 -0
- package/dist/runtime/server/utils/sso.mjs +131 -0
- package/dist/runtime/server/utils/storage.d.ts +111 -0
- package/dist/runtime/server/utils/storage.mjs +654 -0
- package/dist/runtime/server/utils/tenant.d.ts +44 -0
- package/dist/runtime/server/utils/tenant.mjs +285 -0
- package/dist/runtime/server/utils/totp.d.ts +33 -0
- package/dist/runtime/server/utils/totp.mjs +112 -0
- package/dist/runtime/server/utils/tracker.d.ts +72 -0
- package/dist/runtime/server/utils/tracker.mjs +139 -0
- package/dist/runtime/server/utils/turnstile.d.ts +17 -0
- package/dist/runtime/server/utils/turnstile.mjs +68 -0
- package/dist/runtime/server/utils/vapid.d.ts +35 -0
- package/dist/runtime/server/utils/vapid.mjs +211 -0
- package/dist/runtime/storage.d.ts +1 -0
- package/dist/runtime/storage.mjs +0 -0
- package/dist/runtime/types/ai.d.ts +68 -0
- package/dist/runtime/types/ai.mjs +0 -0
- package/dist/runtime/types/analytics.d.ts +30 -0
- package/dist/runtime/types/analytics.mjs +0 -0
- package/dist/runtime/types/auth-globals.d.ts +14 -0
- package/dist/runtime/types/auth.d.ts +153 -0
- package/dist/runtime/types/auth.mjs +0 -0
- package/dist/runtime/types/browser.d.ts +29 -0
- package/dist/runtime/types/browser.mjs +0 -0
- package/dist/runtime/types/d1.d.ts +44 -0
- package/dist/runtime/types/d1.mjs +0 -0
- package/dist/runtime/types/drizzle.d.ts +13 -0
- package/dist/runtime/types/drizzle.mjs +0 -0
- package/dist/runtime/types/durable-object.d.ts +51 -0
- package/dist/runtime/types/durable-object.mjs +0 -0
- package/dist/runtime/types/email.d.ts +66 -0
- package/dist/runtime/types/email.mjs +0 -0
- package/dist/runtime/types/hyperdrive.d.ts +18 -0
- package/dist/runtime/types/hyperdrive.mjs +0 -0
- package/dist/runtime/types/imports.d.ts +58 -0
- package/dist/runtime/types/index.d.ts +156 -0
- package/dist/runtime/types/index.mjs +13 -0
- package/dist/runtime/types/queue.d.ts +67 -0
- package/dist/runtime/types/queue.mjs +0 -0
- package/dist/runtime/types/r2.d.ts +108 -0
- package/dist/runtime/types/r2.mjs +0 -0
- package/dist/runtime/types/ratelimit.d.ts +21 -0
- package/dist/runtime/types/ratelimit.mjs +0 -0
- package/dist/runtime/types/vectorize.d.ts +74 -0
- package/dist/runtime/types/vectorize.mjs +0 -0
- package/dist/runtime/vectorize.d.ts +21 -0
- package/dist/runtime/vectorize.mjs +53 -0
- package/dist/types.d.ts +2750 -0
- package/dist/types.mjs +1 -0
- package/dist/utils/agents.d.ts +8 -0
- package/dist/utils/auth-schema.d.ts +11 -0
- package/dist/utils/bindings.d.ts +16 -0
- package/dist/utils/cms-schema.d.ts +1 -0
- package/dist/utils/cms-sources.d.ts +62 -0
- package/dist/utils/drizzle.d.ts +42 -0
- package/dist/utils/jobs.d.ts +8 -0
- package/dist/utils/local-db.d.ts +28 -0
- package/dist/utils/notifications-schema.d.ts +15 -0
- package/dist/utils/payments-schema.d.ts +11 -0
- package/dist/utils/pkg.d.ts +15 -0
- package/dist/utils/queue.d.ts +8 -0
- package/dist/utils/tenants-schema.d.ts +11 -0
- package/package.json +104 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { useNitroApp } from "nitro/app";
|
|
2
|
+
import { createError, getRequestURL } from "nuxt/server";
|
|
3
|
+
import { getD1Binding } from "../../db.mjs";
|
|
4
|
+
import { sendEmail } from "../../email.mjs";
|
|
5
|
+
import { ensureAuthTables } from "./auth.mjs";
|
|
6
|
+
import { getQarpeoConfig } from "./config.mjs";
|
|
7
|
+
import { escapeHtml, sanitizeUrl } from "./email-templates.mjs";
|
|
8
|
+
import { hashSessionToken, getAuthSession, setAuthSession } from "./session.mjs";
|
|
9
|
+
export function slugify(text) {
|
|
10
|
+
return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
11
|
+
}
|
|
12
|
+
function getD1(event) {
|
|
13
|
+
const bindingName = globalThis.process?.env?.QARPEO_DEFAULT_DB_BINDING || "DB";
|
|
14
|
+
return getD1Binding(bindingName, event);
|
|
15
|
+
}
|
|
16
|
+
export async function createOrganization(event, input) {
|
|
17
|
+
const session = await getAuthSession(event);
|
|
18
|
+
const user = session?.user;
|
|
19
|
+
if (!user || !user.id) {
|
|
20
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
21
|
+
}
|
|
22
|
+
const name = input.name?.trim();
|
|
23
|
+
if (!name) {
|
|
24
|
+
throw createError({
|
|
25
|
+
statusCode: 400,
|
|
26
|
+
statusMessage: "Bad Request",
|
|
27
|
+
message: "Organization name is required"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const d1 = getD1(event);
|
|
31
|
+
await ensureAuthTables(d1);
|
|
32
|
+
const orgId = crypto.randomUUID();
|
|
33
|
+
const baseSlug = slugify(input.slug || name) || `org-${orgId.slice(0, 6)}`;
|
|
34
|
+
let finalSlug = baseSlug;
|
|
35
|
+
const existing = await d1.prepare("SELECT id FROM _qarpeo_organizations WHERE slug = ? LIMIT 1").bind(finalSlug).first();
|
|
36
|
+
if (existing) {
|
|
37
|
+
finalSlug = `${baseSlug}-${crypto.randomUUID().slice(0, 6)}`;
|
|
38
|
+
}
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const organization = {
|
|
41
|
+
id: orgId,
|
|
42
|
+
name,
|
|
43
|
+
slug: finalSlug,
|
|
44
|
+
logoUrl: input.logoUrl || null,
|
|
45
|
+
createdAt: now
|
|
46
|
+
};
|
|
47
|
+
const memberId = crypto.randomUUID();
|
|
48
|
+
const member = {
|
|
49
|
+
id: memberId,
|
|
50
|
+
organizationId: orgId,
|
|
51
|
+
userId: user.id,
|
|
52
|
+
role: "owner",
|
|
53
|
+
createdAt: now
|
|
54
|
+
};
|
|
55
|
+
await d1.batch([
|
|
56
|
+
d1.prepare(
|
|
57
|
+
"INSERT INTO _qarpeo_organizations (id, name, slug, logo_url, created_at) VALUES (?, ?, ?, ?, ?)"
|
|
58
|
+
).bind(
|
|
59
|
+
organization.id,
|
|
60
|
+
organization.name,
|
|
61
|
+
organization.slug,
|
|
62
|
+
organization.logoUrl,
|
|
63
|
+
organization.createdAt
|
|
64
|
+
),
|
|
65
|
+
d1.prepare(
|
|
66
|
+
"INSERT INTO _qarpeo_members (id, organization_id, user_id, role, created_at) VALUES (?, ?, ?, ?, ?)"
|
|
67
|
+
).bind(member.id, member.organizationId, member.userId, member.role, member.createdAt)
|
|
68
|
+
]);
|
|
69
|
+
try {
|
|
70
|
+
const nitroApp = useNitroApp();
|
|
71
|
+
await nitroApp.hooks?.callHook("qarpeo:auth:organization:create", {
|
|
72
|
+
organization,
|
|
73
|
+
owner: user
|
|
74
|
+
});
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
await setAuthSession(event, {
|
|
78
|
+
...session,
|
|
79
|
+
currentOrganizationId: organization.id,
|
|
80
|
+
currentOrganization: organization,
|
|
81
|
+
currentRole: "owner"
|
|
82
|
+
});
|
|
83
|
+
return { organization, member };
|
|
84
|
+
}
|
|
85
|
+
export async function listUserOrganizations(event, userId) {
|
|
86
|
+
const d1 = getD1(event);
|
|
87
|
+
await ensureAuthTables(d1);
|
|
88
|
+
const results = await d1.prepare(`
|
|
89
|
+
SELECT o.id, o.name, o.slug, o.logo_url as logoUrl, o.created_at as createdAt,
|
|
90
|
+
m.id as memberId, m.role
|
|
91
|
+
FROM _qarpeo_members m
|
|
92
|
+
JOIN _qarpeo_organizations o ON m.organization_id = o.id
|
|
93
|
+
WHERE m.user_id = ?
|
|
94
|
+
ORDER BY o.name ASC
|
|
95
|
+
`).bind(userId).all();
|
|
96
|
+
return results.results || [];
|
|
97
|
+
}
|
|
98
|
+
export async function switchActiveOrganization(event, organizationId) {
|
|
99
|
+
const session = await getAuthSession(event);
|
|
100
|
+
const user = session?.user;
|
|
101
|
+
if (!user || !user.id) {
|
|
102
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
103
|
+
}
|
|
104
|
+
const d1 = getD1(event);
|
|
105
|
+
await ensureAuthTables(d1);
|
|
106
|
+
const member = await d1.prepare(
|
|
107
|
+
"SELECT id, role FROM _qarpeo_members WHERE organization_id = ? AND user_id = ? LIMIT 1"
|
|
108
|
+
).bind(organizationId, user.id).first();
|
|
109
|
+
if (!member) {
|
|
110
|
+
throw createError({
|
|
111
|
+
statusCode: 403,
|
|
112
|
+
statusMessage: "Forbidden",
|
|
113
|
+
message: "You are not a member of this organization"
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const orgRecord = await d1.prepare(
|
|
117
|
+
"SELECT id, name, slug, logo_url as logoUrl, created_at as createdAt FROM _qarpeo_organizations WHERE id = ? LIMIT 1"
|
|
118
|
+
).bind(organizationId).first();
|
|
119
|
+
if (!orgRecord) {
|
|
120
|
+
throw createError({
|
|
121
|
+
statusCode: 404,
|
|
122
|
+
statusMessage: "Not Found",
|
|
123
|
+
message: "Organization not found"
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const organization = {
|
|
127
|
+
id: orgRecord.id,
|
|
128
|
+
name: orgRecord.name,
|
|
129
|
+
slug: orgRecord.slug,
|
|
130
|
+
logoUrl: orgRecord.logoUrl,
|
|
131
|
+
createdAt: orgRecord.createdAt
|
|
132
|
+
};
|
|
133
|
+
await setAuthSession(event, {
|
|
134
|
+
...session,
|
|
135
|
+
currentOrganizationId: organization.id,
|
|
136
|
+
currentOrganization: organization,
|
|
137
|
+
currentRole: member.role
|
|
138
|
+
});
|
|
139
|
+
return { success: true, organization, role: member.role };
|
|
140
|
+
}
|
|
141
|
+
export async function inviteOrganizationMember(event, input) {
|
|
142
|
+
const session = await getAuthSession(event);
|
|
143
|
+
const user = session?.user;
|
|
144
|
+
if (!user || !user.id) {
|
|
145
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
146
|
+
}
|
|
147
|
+
const email = input.email?.trim().toLowerCase();
|
|
148
|
+
if (!email || !email.includes("@")) {
|
|
149
|
+
throw createError({
|
|
150
|
+
statusCode: 400,
|
|
151
|
+
statusMessage: "Bad Request",
|
|
152
|
+
message: "Valid email address is required"
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const d1 = getD1(event);
|
|
156
|
+
await ensureAuthTables(d1);
|
|
157
|
+
const callerMember = await d1.prepare("SELECT role FROM _qarpeo_members WHERE organization_id = ? AND user_id = ? LIMIT 1").bind(input.organizationId, user.id).first();
|
|
158
|
+
if (!callerMember || !["owner", "admin"].includes(callerMember.role)) {
|
|
159
|
+
throw createError({
|
|
160
|
+
statusCode: 403,
|
|
161
|
+
statusMessage: "Forbidden",
|
|
162
|
+
message: "Only organization owners and admins can invite members"
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const org = await d1.prepare(
|
|
166
|
+
"SELECT id, name, slug, logo_url as logoUrl, created_at as createdAt FROM _qarpeo_organizations WHERE id = ? LIMIT 1"
|
|
167
|
+
).bind(input.organizationId).first();
|
|
168
|
+
if (!org) {
|
|
169
|
+
throw createError({
|
|
170
|
+
statusCode: 404,
|
|
171
|
+
statusMessage: "Not Found",
|
|
172
|
+
message: "Organization not found"
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const role = input.role && ["owner", "admin", "member"].includes(input.role) ? input.role : "member";
|
|
176
|
+
const rawToken = crypto.randomUUID().replace(/-/g, "") + crypto.randomUUID().replace(/-/g, "");
|
|
177
|
+
const tokenHash = await hashSessionToken(rawToken);
|
|
178
|
+
const invitationId = crypto.randomUUID();
|
|
179
|
+
const now = Date.now();
|
|
180
|
+
const expiresAt = now + 7 * 24 * 60 * 60 * 1e3;
|
|
181
|
+
await d1.prepare(`
|
|
182
|
+
INSERT INTO _qarpeo_invitations (id, organization_id, email, role, token_hash, expires_at, created_at)
|
|
183
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
184
|
+
`).bind(invitationId, org.id, email, role, tokenHash, expiresAt, now).run();
|
|
185
|
+
const reqUrl = getRequestURL(event);
|
|
186
|
+
const origin = `${reqUrl.protocol}//${reqUrl.host}`;
|
|
187
|
+
const authPrefix = getQarpeoConfig(event).auth?.prefix || "/api/auth";
|
|
188
|
+
const inviteUrl = `${origin}${authPrefix}/organization/join?token=${rawToken}`;
|
|
189
|
+
const invitation = {
|
|
190
|
+
id: invitationId,
|
|
191
|
+
organizationId: org.id,
|
|
192
|
+
email,
|
|
193
|
+
role,
|
|
194
|
+
tokenHash,
|
|
195
|
+
expiresAt,
|
|
196
|
+
createdAt: now
|
|
197
|
+
};
|
|
198
|
+
let hookHandled = false;
|
|
199
|
+
try {
|
|
200
|
+
const nitroApp = useNitroApp();
|
|
201
|
+
await nitroApp.hooks?.callHook("qarpeo:auth:organization:invite", {
|
|
202
|
+
organization: org,
|
|
203
|
+
invitation,
|
|
204
|
+
inviteUrl
|
|
205
|
+
});
|
|
206
|
+
hookHandled = true;
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
if (!hookHandled || globalThis.process?.env?.NODE_ENV === "development") {
|
|
210
|
+
try {
|
|
211
|
+
await sendEmail(
|
|
212
|
+
{
|
|
213
|
+
to: email,
|
|
214
|
+
subject: `You've been invited to join ${org.name}`,
|
|
215
|
+
text: `You have been invited to join ${org.name} on Qarpeo as a ${role}.
|
|
216
|
+
Accept invitation: ${inviteUrl}`,
|
|
217
|
+
html: `<p>You have been invited to join <strong>${escapeHtml(org.name)}</strong> as a <strong>${escapeHtml(role)}</strong>.</p><p><a href="${sanitizeUrl(inviteUrl)}">Accept Invitation</a></p>`
|
|
218
|
+
},
|
|
219
|
+
event
|
|
220
|
+
);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
console.error("[qarpeo:auth] Failed to send organization invite email:", err?.message || err);
|
|
223
|
+
return {
|
|
224
|
+
invitationId,
|
|
225
|
+
token: rawToken,
|
|
226
|
+
expiresAt,
|
|
227
|
+
inviteUrl,
|
|
228
|
+
sent: false,
|
|
229
|
+
error: err?.message || "Failed to send invitation email"
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return { invitationId, token: rawToken, expiresAt, inviteUrl, sent: true };
|
|
234
|
+
}
|
|
235
|
+
export async function removeOrganizationMember(event, input) {
|
|
236
|
+
const session = await getAuthSession(event);
|
|
237
|
+
const user = session?.user;
|
|
238
|
+
if (!user || !user.id) {
|
|
239
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
240
|
+
}
|
|
241
|
+
const d1 = getD1(event);
|
|
242
|
+
await ensureAuthTables(d1);
|
|
243
|
+
const callerMember = await d1.prepare(
|
|
244
|
+
"SELECT id, role FROM _qarpeo_members WHERE organization_id = ? AND user_id = ? LIMIT 1"
|
|
245
|
+
).bind(input.organizationId, user.id).first();
|
|
246
|
+
if (!callerMember) {
|
|
247
|
+
throw createError({
|
|
248
|
+
statusCode: 403,
|
|
249
|
+
statusMessage: "Forbidden",
|
|
250
|
+
message: "Not a member of this organization"
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const targetMember = await d1.prepare(
|
|
254
|
+
"SELECT id, user_id as userId, role FROM _qarpeo_members WHERE id = ? AND organization_id = ? LIMIT 1"
|
|
255
|
+
).bind(input.memberId, input.organizationId).first();
|
|
256
|
+
if (!targetMember) {
|
|
257
|
+
throw createError({
|
|
258
|
+
statusCode: 404,
|
|
259
|
+
statusMessage: "Not Found",
|
|
260
|
+
message: "Member record not found"
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const isSelf = targetMember.userId === user.id;
|
|
264
|
+
const isOwnerOrAdmin = ["owner", "admin"].includes(callerMember.role);
|
|
265
|
+
if (!isSelf && !isOwnerOrAdmin) {
|
|
266
|
+
throw createError({ statusCode: 403, statusMessage: "Forbidden", message: "Permission denied" });
|
|
267
|
+
}
|
|
268
|
+
if (targetMember.role === "owner") {
|
|
269
|
+
const ownerCount = await d1.prepare(
|
|
270
|
+
"SELECT count(*) as count FROM _qarpeo_members WHERE organization_id = ? AND role = 'owner'"
|
|
271
|
+
).bind(input.organizationId).first();
|
|
272
|
+
if ((ownerCount?.count || 0) <= 1) {
|
|
273
|
+
throw createError({
|
|
274
|
+
statusCode: 400,
|
|
275
|
+
statusMessage: "Bad Request",
|
|
276
|
+
message: "Cannot remove the only owner of an organization. Transfer ownership first."
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
await d1.prepare("DELETE FROM _qarpeo_members WHERE id = ?").bind(input.memberId).run();
|
|
281
|
+
if (isSelf && session.currentOrganizationId === input.organizationId) {
|
|
282
|
+
await setAuthSession(event, {
|
|
283
|
+
...session,
|
|
284
|
+
currentOrganizationId: null,
|
|
285
|
+
currentOrganization: null,
|
|
286
|
+
currentRole: null
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return { success: true };
|
|
290
|
+
}
|
|
291
|
+
export async function acceptOrganizationInvitation(event, token) {
|
|
292
|
+
const session = await getAuthSession(event);
|
|
293
|
+
const user = session?.user;
|
|
294
|
+
if (!user || !user.id) {
|
|
295
|
+
throw createError({
|
|
296
|
+
statusCode: 401,
|
|
297
|
+
statusMessage: "Unauthorized",
|
|
298
|
+
message: "Must be logged in to accept an invitation"
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
const tokenHash = await hashSessionToken(token);
|
|
302
|
+
const d1 = getD1(event);
|
|
303
|
+
await ensureAuthTables(d1);
|
|
304
|
+
const invitation = await d1.prepare("SELECT * FROM _qarpeo_invitations WHERE token_hash = ? LIMIT 1").bind(tokenHash).first();
|
|
305
|
+
if (!invitation) {
|
|
306
|
+
throw createError({
|
|
307
|
+
statusCode: 404,
|
|
308
|
+
statusMessage: "Not Found",
|
|
309
|
+
message: "Invalid or expired invitation"
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (Date.now() > invitation.expires_at) {
|
|
313
|
+
await d1.prepare("DELETE FROM _qarpeo_invitations WHERE id = ?").bind(invitation.id).run();
|
|
314
|
+
throw createError({ statusCode: 410, statusMessage: "Gone", message: "Invitation has expired" });
|
|
315
|
+
}
|
|
316
|
+
const memberId = crypto.randomUUID();
|
|
317
|
+
const now = Date.now();
|
|
318
|
+
await d1.batch([
|
|
319
|
+
d1.prepare(`
|
|
320
|
+
INSERT INTO _qarpeo_members (id, organization_id, user_id, role, created_at)
|
|
321
|
+
VALUES (?, ?, ?, ?, ?)
|
|
322
|
+
ON CONFLICT(organization_id, user_id) DO UPDATE SET role = excluded.role
|
|
323
|
+
`).bind(memberId, invitation.organization_id, user.id, invitation.role, now),
|
|
324
|
+
d1.prepare("DELETE FROM _qarpeo_invitations WHERE id = ?").bind(invitation.id)
|
|
325
|
+
]);
|
|
326
|
+
await switchActiveOrganization(event, invitation.organization_id);
|
|
327
|
+
return { success: true, organizationId: invitation.organization_id, role: invitation.role };
|
|
328
|
+
}
|
|
329
|
+
export async function listOrganizationMembers(event, organizationId) {
|
|
330
|
+
const session = await getAuthSession(event);
|
|
331
|
+
const user = session?.user;
|
|
332
|
+
if (!user || !user.id) {
|
|
333
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
334
|
+
}
|
|
335
|
+
const d1 = getD1(event);
|
|
336
|
+
await ensureAuthTables(d1);
|
|
337
|
+
const caller = await d1.prepare("SELECT id FROM _qarpeo_members WHERE organization_id = ? AND user_id = ? LIMIT 1").bind(organizationId, user.id).first();
|
|
338
|
+
if (!caller) {
|
|
339
|
+
throw createError({
|
|
340
|
+
statusCode: 403,
|
|
341
|
+
statusMessage: "Forbidden",
|
|
342
|
+
message: "Not a member of this organization"
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const results = await d1.prepare(`
|
|
346
|
+
SELECT m.id, m.organization_id as organizationId, m.user_id as userId, m.role, m.created_at as createdAt,
|
|
347
|
+
u.email, u.name, u.avatar_url as avatarUrl
|
|
348
|
+
FROM _qarpeo_members m
|
|
349
|
+
LEFT JOIN _qarpeo_users u ON m.user_id = u.id
|
|
350
|
+
WHERE m.organization_id = ?
|
|
351
|
+
ORDER BY m.created_at ASC
|
|
352
|
+
`).bind(organizationId).all();
|
|
353
|
+
return results.results || [];
|
|
354
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface SendOTPOptions {
|
|
2
|
+
ttl?: number;
|
|
3
|
+
}
|
|
4
|
+
export interface OTPRecord {
|
|
5
|
+
codeHash: string;
|
|
6
|
+
attempts: number;
|
|
7
|
+
expiresAt: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function sendOTPCode(event: any, email: string, options?: SendOTPOptions): Promise<{
|
|
10
|
+
sent: boolean;
|
|
11
|
+
expiresAt: number;
|
|
12
|
+
error: string;
|
|
13
|
+
} | {
|
|
14
|
+
sent: boolean;
|
|
15
|
+
expiresAt: number;
|
|
16
|
+
error?: undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function verifyOTPCode(event: any, email: string, code: string): Promise<{
|
|
19
|
+
valid: boolean;
|
|
20
|
+
reason: string;
|
|
21
|
+
attemptsRemaining?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
valid: boolean;
|
|
24
|
+
reason: string;
|
|
25
|
+
attemptsRemaining: number;
|
|
26
|
+
} | {
|
|
27
|
+
valid: boolean;
|
|
28
|
+
reason?: undefined;
|
|
29
|
+
attemptsRemaining?: undefined;
|
|
30
|
+
}>;
|
|
31
|
+
export declare function sendMagicLink(event: any, email: string, options?: {
|
|
32
|
+
ttl?: number;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
sent: boolean;
|
|
35
|
+
expiresAt: number;
|
|
36
|
+
error: string;
|
|
37
|
+
} | {
|
|
38
|
+
sent: boolean;
|
|
39
|
+
expiresAt: number;
|
|
40
|
+
error?: undefined;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function verifyMagicLinkToken(event: any, token: string): Promise<{
|
|
43
|
+
valid: boolean;
|
|
44
|
+
email?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
valid: boolean;
|
|
47
|
+
email: string;
|
|
48
|
+
}>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { useNitroApp } from "nitro/app";
|
|
2
|
+
import { getRequestURL, createError } from "nuxt/server";
|
|
3
|
+
import { getQarpeoConfig } from "./config.mjs";
|
|
4
|
+
import { sendEmail } from "../../email.mjs";
|
|
5
|
+
import { getKVBinding } from "../../kv.mjs";
|
|
6
|
+
import { escapeHtml, sanitizeUrl } from "./email-templates.mjs";
|
|
7
|
+
import { assertRateLimit } from "./ratelimit.mjs";
|
|
8
|
+
import { hashSessionToken } from "./session.mjs";
|
|
9
|
+
import { timingSafeEqualString } from "./totp.mjs";
|
|
10
|
+
export async function sendOTPCode(event, email, options = {}) {
|
|
11
|
+
const cleanEmail = email.trim().toLowerCase();
|
|
12
|
+
await assertRateLimit(event, {
|
|
13
|
+
key: `auth:otp:send:${cleanEmail}`,
|
|
14
|
+
max: 5,
|
|
15
|
+
window: "10m",
|
|
16
|
+
message: "Too many verification code requests. Please wait before requesting another."
|
|
17
|
+
}).catch((err) => {
|
|
18
|
+
if (err?.statusCode === 429) throw err;
|
|
19
|
+
});
|
|
20
|
+
const code = Math.floor(1e5 + Math.random() * 9e5).toString();
|
|
21
|
+
const codeHash = await hashSessionToken(code);
|
|
22
|
+
const authConfig = getQarpeoConfig(event).auth;
|
|
23
|
+
const otpCfg = typeof authConfig.passwordless?.otp === "object" ? authConfig.passwordless.otp : void 0;
|
|
24
|
+
const ttl = options.ttl || otpCfg?.ttl || 300;
|
|
25
|
+
const expiresAt = Date.now() + ttl * 1e3;
|
|
26
|
+
try {
|
|
27
|
+
const kv = getKVBinding("KV", event);
|
|
28
|
+
const record = {
|
|
29
|
+
codeHash,
|
|
30
|
+
attempts: 0,
|
|
31
|
+
expiresAt
|
|
32
|
+
};
|
|
33
|
+
await kv.put(`otp:${cleanEmail}`, JSON.stringify(record), {
|
|
34
|
+
expirationTtl: ttl
|
|
35
|
+
});
|
|
36
|
+
} catch (err) {
|
|
37
|
+
console.warn("[qarpeo] Failed to store OTP in KV:", err.message);
|
|
38
|
+
}
|
|
39
|
+
const nitroApp = useNitroApp();
|
|
40
|
+
let hookHandled = false;
|
|
41
|
+
try {
|
|
42
|
+
await nitroApp.hooks?.callHook("qarpeo:auth:otp:send", {
|
|
43
|
+
email: cleanEmail,
|
|
44
|
+
code,
|
|
45
|
+
type: "otp"
|
|
46
|
+
});
|
|
47
|
+
hookHandled = true;
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
if (!hookHandled || globalThis.process?.env?.NODE_ENV === "development") {
|
|
51
|
+
try {
|
|
52
|
+
await sendEmail(
|
|
53
|
+
{
|
|
54
|
+
to: cleanEmail,
|
|
55
|
+
subject: `Your Login Code: ${code}`,
|
|
56
|
+
text: `Your verification code is: ${code}
|
|
57
|
+
This code will expire in ${Math.round(ttl / 60)} minutes.`,
|
|
58
|
+
html: `<p>Your verification code is: <strong>${escapeHtml(code)}</strong></p><p>This code will expire in ${escapeHtml(String(Math.round(ttl / 60)))} minutes.</p>`
|
|
59
|
+
},
|
|
60
|
+
event
|
|
61
|
+
);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error("[qarpeo] Failed to send OTP email:", err?.message || err);
|
|
64
|
+
return { sent: false, expiresAt, error: "Failed to send verification code" };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { sent: true, expiresAt };
|
|
68
|
+
}
|
|
69
|
+
export async function verifyOTPCode(event, email, code) {
|
|
70
|
+
const cleanEmail = email.trim().toLowerCase();
|
|
71
|
+
const cleanCode = code.trim();
|
|
72
|
+
await assertRateLimit(event, {
|
|
73
|
+
key: `auth:otp:verify:${cleanEmail}`,
|
|
74
|
+
max: 10,
|
|
75
|
+
window: "10m",
|
|
76
|
+
message: "Too many verification attempts. Please request a new code."
|
|
77
|
+
}).catch((err) => {
|
|
78
|
+
if (err?.statusCode === 429) throw err;
|
|
79
|
+
});
|
|
80
|
+
let kv;
|
|
81
|
+
try {
|
|
82
|
+
kv = getKVBinding("KV", event);
|
|
83
|
+
} catch {
|
|
84
|
+
throw createError({
|
|
85
|
+
statusCode: 500,
|
|
86
|
+
statusMessage: "Internal Server Error",
|
|
87
|
+
message: "KV database binding not available"
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const raw = await kv.get(`otp:${cleanEmail}`, { type: "json" });
|
|
91
|
+
if (!raw) {
|
|
92
|
+
return { valid: false, reason: "expired" };
|
|
93
|
+
}
|
|
94
|
+
const record = raw;
|
|
95
|
+
if (record.attempts >= 5) {
|
|
96
|
+
await kv.delete(`otp:${cleanEmail}`);
|
|
97
|
+
return { valid: false, reason: "too_many_attempts" };
|
|
98
|
+
}
|
|
99
|
+
const inputHash = await hashSessionToken(cleanCode);
|
|
100
|
+
if (!timingSafeEqualString(inputHash, record.codeHash)) {
|
|
101
|
+
record.attempts += 1;
|
|
102
|
+
await kv.put(`otp:${cleanEmail}`, JSON.stringify(record), {
|
|
103
|
+
expirationTtl: 300
|
|
104
|
+
});
|
|
105
|
+
return { valid: false, reason: "invalid_code", attemptsRemaining: 5 - record.attempts };
|
|
106
|
+
}
|
|
107
|
+
await kv.delete(`otp:${cleanEmail}`);
|
|
108
|
+
return { valid: true };
|
|
109
|
+
}
|
|
110
|
+
export async function sendMagicLink(event, email, options = {}) {
|
|
111
|
+
const cleanEmail = email.trim().toLowerCase();
|
|
112
|
+
await assertRateLimit(event, {
|
|
113
|
+
key: `auth:magic:send:${cleanEmail}`,
|
|
114
|
+
max: 5,
|
|
115
|
+
window: "10m",
|
|
116
|
+
message: "Too many magic link requests. Please wait before requesting another."
|
|
117
|
+
}).catch((err) => {
|
|
118
|
+
if (err?.statusCode === 429) throw err;
|
|
119
|
+
});
|
|
120
|
+
const token = crypto.randomUUID().replace(/-/g, "") + crypto.randomUUID().replace(/-/g, "");
|
|
121
|
+
const authConfig = getQarpeoConfig(event).auth;
|
|
122
|
+
const magicCfg = typeof authConfig.passwordless?.magicLink === "object" ? authConfig.passwordless.magicLink : void 0;
|
|
123
|
+
const ttl = options.ttl || magicCfg?.ttl || 900;
|
|
124
|
+
const expiresAt = Date.now() + ttl * 1e3;
|
|
125
|
+
try {
|
|
126
|
+
const kv = getKVBinding("KV", event);
|
|
127
|
+
await kv.put(`magic:${token}`, JSON.stringify({ email: cleanEmail, expiresAt }), {
|
|
128
|
+
expirationTtl: ttl
|
|
129
|
+
});
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.warn("[qarpeo] Failed to store magic link in KV:", err.message);
|
|
132
|
+
}
|
|
133
|
+
const requestUrl = getRequestURL(event);
|
|
134
|
+
const origin = `${requestUrl.protocol}//${requestUrl.host}`;
|
|
135
|
+
const authPrefix = authConfig.prefix || "/api/auth";
|
|
136
|
+
const url = `${origin}${authPrefix}/magic-link/verify?token=${token}`;
|
|
137
|
+
const nitroApp = useNitroApp();
|
|
138
|
+
let hookHandled = false;
|
|
139
|
+
try {
|
|
140
|
+
await nitroApp.hooks?.callHook("qarpeo:auth:magic-link:send", {
|
|
141
|
+
email: cleanEmail,
|
|
142
|
+
url
|
|
143
|
+
});
|
|
144
|
+
hookHandled = true;
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
147
|
+
if (!hookHandled || globalThis.process?.env?.NODE_ENV === "development") {
|
|
148
|
+
try {
|
|
149
|
+
await sendEmail(
|
|
150
|
+
{
|
|
151
|
+
to: cleanEmail,
|
|
152
|
+
subject: "Your Magic Sign-In Link",
|
|
153
|
+
text: `Click here to sign in: ${url}
|
|
154
|
+
This link expires in ${Math.round(ttl / 60)} minutes.`,
|
|
155
|
+
html: `<p>Click the link below to sign in:</p><p><a href="${sanitizeUrl(url)}">Sign In to Your Account</a></p><p>This link expires in ${escapeHtml(String(Math.round(ttl / 60)))} minutes.</p>`
|
|
156
|
+
},
|
|
157
|
+
event
|
|
158
|
+
);
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.error("[qarpeo] Failed to send magic link email:", err?.message || err);
|
|
161
|
+
return { sent: false, expiresAt, error: "Failed to send magic link" };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { sent: true, expiresAt };
|
|
165
|
+
}
|
|
166
|
+
export async function verifyMagicLinkToken(event, token) {
|
|
167
|
+
let kv;
|
|
168
|
+
try {
|
|
169
|
+
kv = getKVBinding("KV", event);
|
|
170
|
+
} catch {
|
|
171
|
+
return { valid: false };
|
|
172
|
+
}
|
|
173
|
+
const data = await kv.get(`magic:${token}`, { type: "json" });
|
|
174
|
+
if (!data || !data.email) {
|
|
175
|
+
return { valid: false };
|
|
176
|
+
}
|
|
177
|
+
await kv.delete(`magic:${token}`);
|
|
178
|
+
return { valid: true, email: data.email };
|
|
179
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { PaymentsOptions, PaymentProvider, QarpeoSubscription, SubscriptionStatus, CreateCheckoutOptions, MeterRecordOptions, MeterUsageResult, UsageSummary } from "../../../types";
|
|
2
|
+
export declare function getPaymentsConfig(event?: any): PaymentsOptions & {
|
|
3
|
+
provider: PaymentProvider;
|
|
4
|
+
secretKey: string;
|
|
5
|
+
webhookSecret: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function ensurePaymentsTables(event?: any): Promise<void>;
|
|
8
|
+
/** Verifies Stripe webhook signature: Stripe-Signature header contains: `t=timestamp,v1=signature` */
|
|
9
|
+
export declare function verifyStripeSignature(rawBody: string, signatureHeader: string | null | undefined, secret: string, toleranceSec?: number): Promise<boolean>;
|
|
10
|
+
/** Verifies Lemon Squeezy webhook signature (X-Signature header) */
|
|
11
|
+
export declare function verifyLemonSqueezySignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
|
|
12
|
+
/** Verifies Polar webhook signature (webhook-signature header) */
|
|
13
|
+
export declare function verifyPolarSignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
|
|
14
|
+
/** Verifies Paddle Billing webhook signature (Paddle-Signature header: `ts=TIMESTAMP;h1=HMAC_HEX`) */
|
|
15
|
+
export declare function verifyPaddleSignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
|
|
16
|
+
export declare function processPaymentWebhook(event: any, rawBody: string): Promise<{
|
|
17
|
+
success: boolean;
|
|
18
|
+
eventType?: string;
|
|
19
|
+
} | {
|
|
20
|
+
received: true;
|
|
21
|
+
skipped: true;
|
|
22
|
+
reason: "duplicate";
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a Stripe checkout session via Stripe REST API. Runs 100% edge-native on Cloudflare
|
|
26
|
+
* Workers using standard `fetch`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createCheckoutSession(event: any, options: CreateCheckoutOptions): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
url: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** Creates a Customer Billing Portal session for the current user. */
|
|
33
|
+
export declare function createCustomerPortalSession(event: any, options?: {
|
|
34
|
+
returnUrl?: string;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
url: string;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Cancels a Stripe subscription at the end of the current billing period. Calls Stripe POST
|
|
40
|
+
* /v1/subscriptions/{id} with `cancel_at_period_end: true` and marks the D1 row as canceled.
|
|
41
|
+
*/
|
|
42
|
+
export declare function cancelSubscription(event: any, subscriptionId: string): Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
subscriptionId: string;
|
|
45
|
+
status: string;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Pauses collection on a Stripe subscription. Calls Stripe POST /v1/subscriptions/{id} with
|
|
49
|
+
* `pause_collection: { behavior: 'void', resumes_at: null }` and marks the D1 row as paused.
|
|
50
|
+
*/
|
|
51
|
+
export declare function pauseSubscription(event: any, subscriptionId: string): Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
subscriptionId: string;
|
|
54
|
+
status: string;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Changes a Stripe subscription to a new price/plan with proration. Fetches the current
|
|
58
|
+
* subscription item id, calls Stripe POST /v1/subscriptions/{id} to swap the item price, and
|
|
59
|
+
* updates the D1 plan_id/price_id.
|
|
60
|
+
*/
|
|
61
|
+
export declare function changePlan(event: any, subscriptionId: string, newPriceId: string): Promise<{
|
|
62
|
+
success: boolean;
|
|
63
|
+
subscriptionId: string;
|
|
64
|
+
planId: string;
|
|
65
|
+
}>;
|
|
66
|
+
/** Gets the current active subscription for a user or organization from D1. */
|
|
67
|
+
export declare function getSubscription(event: any, options?: {
|
|
68
|
+
userId?: string;
|
|
69
|
+
orgId?: string;
|
|
70
|
+
}): Promise<QarpeoSubscription | null>;
|
|
71
|
+
export interface RequireSubscriptionOptions {
|
|
72
|
+
tier?: string | string[];
|
|
73
|
+
plan?: string | string[];
|
|
74
|
+
status?: SubscriptionStatus[];
|
|
75
|
+
message?: string;
|
|
76
|
+
}
|
|
77
|
+
/** Server guard: throws 402 Payment Required if caller has no active subscription. */
|
|
78
|
+
export declare function requireSubscription(event: any, options?: RequireSubscriptionOptions): Promise<QarpeoSubscription>;
|
|
79
|
+
/**
|
|
80
|
+
* Checks whether the current user or organization's active subscription plan includes a specific
|
|
81
|
+
* feature flag.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ;```ts
|
|
85
|
+
* if (!(await hasFeature(event, "custom_domain"))) {
|
|
86
|
+
* throw createError({ statusCode: 403, message: "Custom domains require Pro plan" })
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function hasFeature(event: any, feature: string): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Checks whether a numerical usage limit defined on the active plan configuration has been
|
|
93
|
+
* exceeded.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const { allowed, limit, current } = await checkLimit(event, "max_projects", projectCount)
|
|
98
|
+
* if (!allowed) {
|
|
99
|
+
* throw createError({ statusCode: 403, message: `Project limit (${limit}) reached` })
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function checkLimit(event: any, limitKey: string, currentUsage: number): Promise<{
|
|
104
|
+
allowed: boolean;
|
|
105
|
+
limit: number;
|
|
106
|
+
current: number;
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Records a metered usage event in D1 and reports to upstream provider (e.g. Stripe Meters API).
|
|
110
|
+
*/
|
|
111
|
+
export declare function reportUsage(event: any, options: MeterRecordOptions): Promise<MeterUsageResult>;
|
|
112
|
+
/**
|
|
113
|
+
* Queries metered usage summary and records from D1 for a user or organization.
|
|
114
|
+
*/
|
|
115
|
+
export declare function getUsageSummary(event: any, options: {
|
|
116
|
+
eventName?: string;
|
|
117
|
+
userId?: string;
|
|
118
|
+
orgId?: string;
|
|
119
|
+
since?: number;
|
|
120
|
+
until?: number;
|
|
121
|
+
}): Promise<UsageSummary>;
|