@nextsparkjs/core 0.1.0-beta.194 → 0.1.0-beta.195
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/dist/components/app/guards/DeveloperGuard.d.ts +8 -1
- package/dist/components/app/guards/DeveloperGuard.d.ts.map +1 -1
- package/dist/components/app/guards/DeveloperGuard.js +2 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts +8 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts.map +1 -1
- package/dist/components/app/guards/SuperAdminGuard.js +2 -1
- package/dist/components/dashboard/block-editor/block-picker.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/block-picker.js +2 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.js +39 -23
- package/dist/components/dashboard/block-editor/pattern-reference-preview.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/pattern-reference-preview.js +2 -1
- package/dist/components/dashboard/layouts/AuthGuard.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthGuard.js +3 -4
- package/dist/components/dashboard/layouts/AuthenticatedDashboardLayout.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthenticatedDashboardLayout.js +9 -10
- package/dist/components/dashboard/layouts/DashboardAuthLayout.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/DashboardAuthLayout.js +3 -4
- package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts +2 -2
- package/dist/components/entities/wrappers/EntityDetailWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityDetailWrapper.js +5 -2
- package/dist/components/entities/wrappers/EntityFormWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityFormWrapper.js +5 -2
- package/dist/components/entities/wrappers/EntityListWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityListWrapper.js +5 -2
- package/dist/components/ui/relation-display.d.ts.map +1 -1
- package/dist/components/ui/relation-display.js +2 -1
- package/dist/components/ui/user-display.d.ts.map +1 -1
- package/dist/components/ui/user-display.js +2 -1
- package/dist/emails/otp-verification.d.ts.map +1 -1
- package/dist/emails/otp-verification.js +5 -3
- package/dist/emails/reset-password.d.ts.map +1 -1
- package/dist/emails/reset-password.js +5 -3
- package/dist/emails/team-invitation.d.ts.map +1 -1
- package/dist/emails/team-invitation.js +3 -2
- package/dist/emails/verify-email.d.ts.map +1 -1
- package/dist/emails/verify-email.js +5 -3
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +21 -4
- package/dist/hooks/usePatternUsages.d.ts.map +1 -1
- package/dist/hooks/usePatternUsages.js +3 -2
- package/dist/lib/api/auth.d.ts +2 -0
- package/dist/lib/api/auth.d.ts.map +1 -1
- package/dist/lib/api/auth.js +10 -10
- package/dist/lib/api/client-headers.d.ts +11 -0
- package/dist/lib/api/client-headers.d.ts.map +1 -0
- package/dist/lib/api/client-headers.js +12 -0
- package/dist/lib/api/client-ip.d.ts +59 -0
- package/dist/lib/api/client-ip.d.ts.map +1 -0
- package/dist/lib/api/client-ip.js +91 -0
- package/dist/lib/api/cors-response.d.ts +54 -0
- package/dist/lib/api/cors-response.d.ts.map +1 -0
- package/dist/lib/api/cors-response.js +88 -0
- package/dist/lib/api/entities.d.ts.map +1 -1
- package/dist/lib/api/entities.js +4 -3
- package/dist/lib/api/entity/audit-log.d.ts.map +1 -1
- package/dist/lib/api/entity/audit-log.js +2 -1
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +23 -5
- package/dist/lib/api/helpers.d.ts +8 -2
- package/dist/lib/api/helpers.d.ts.map +1 -1
- package/dist/lib/api/helpers.js +27 -81
- package/dist/lib/api/keys.d.ts +6 -0
- package/dist/lib/api/keys.d.ts.map +1 -1
- package/dist/lib/api/keys.js +7 -1
- package/dist/lib/api/rate-limit.d.ts +4 -0
- package/dist/lib/api/rate-limit.d.ts.map +1 -1
- package/dist/lib/api/rate-limit.js +16 -40
- package/dist/lib/api/request-origin.d.ts +16 -7
- package/dist/lib/api/request-origin.d.ts.map +1 -1
- package/dist/lib/api/request-origin.js +43 -20
- package/dist/lib/auth/load-login-page.d.ts +10 -0
- package/dist/lib/auth/load-login-page.d.ts.map +1 -0
- package/dist/lib/auth/load-login-page.js +7 -0
- package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
- package/dist/lib/auth/runtime-readiness.js +2 -0
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts +1 -8
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts.map +1 -1
- package/dist/lib/auth/security-notifications/device-fingerprint.js +2 -12
- package/dist/lib/auth-email-callbacks.js +3 -3
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +7 -2
- package/dist/lib/config/config-client.d.ts.map +1 -1
- package/dist/lib/config/config-client.js +1 -1
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +1 -1
- package/dist/lib/config/public-config-client.d.ts +1 -0
- package/dist/lib/config/public-config-client.d.ts.map +1 -1
- package/dist/lib/config/public-config-client.js +3 -1
- package/dist/lib/config/types.d.ts +2 -0
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/constants/reserved-slugs.d.ts +17 -8
- package/dist/lib/constants/reserved-slugs.d.ts.map +1 -1
- package/dist/lib/constants/reserved-slugs.js +16 -52
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +9 -3
- package/dist/lib/entities/external-api-generator.d.ts.map +1 -1
- package/dist/lib/entities/external-api-generator.js +2 -4
- package/dist/lib/entities/public-slug.d.ts +46 -0
- package/dist/lib/entities/public-slug.d.ts.map +1 -0
- package/dist/lib/entities/public-slug.js +39 -0
- package/dist/routes/(auth)/signup/page.cc.d.ts +3 -8
- package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.cc.js +7 -1
- package/dist/routes/(auth)/verify-email/page.d.ts.map +1 -1
- package/dist/routes/(auth)/verify-email/page.js +2 -1
- package/dist/routes/(public)/page.cc.d.ts +3 -0
- package/dist/routes/(public)/page.cc.d.ts.map +1 -0
- package/dist/routes/(public)/page.cc.js +3 -0
- package/dist/routes/_internal/area-access.cc.d.ts +21 -0
- package/dist/routes/_internal/area-access.cc.d.ts.map +1 -0
- package/dist/routes/_internal/area-access.cc.js +19 -0
- package/dist/routes/_internal/auth-layout.d.ts.map +1 -1
- package/dist/routes/_internal/auth-layout.js +3 -2
- package/dist/routes/_internal/dashboard-main-shared.d.ts +7 -0
- package/dist/routes/_internal/dashboard-main-shared.d.ts.map +1 -0
- package/dist/routes/_internal/dashboard-main-shared.js +49 -0
- package/dist/routes/_internal/default-auth-layout.d.ts.map +1 -1
- package/dist/routes/_internal/default-auth-layout.js +3 -2
- package/dist/routes/_internal/devtools-layout.cc.d.ts +3 -2
- package/dist/routes/_internal/devtools-layout.cc.d.ts.map +1 -1
- package/dist/routes/_internal/devtools-layout.cc.js +1 -1
- package/dist/routes/_internal/devtools-layout.d.ts +7 -2
- package/dist/routes/_internal/devtools-layout.d.ts.map +1 -1
- package/dist/routes/_internal/devtools-layout.js +4 -4
- package/dist/routes/_internal/entity-detail-route.cc.d.ts +8 -0
- package/dist/routes/_internal/entity-detail-route.cc.d.ts.map +1 -0
- package/dist/routes/_internal/entity-detail-route.cc.js +5 -0
- package/dist/routes/_internal/entity-edit-route.cc.d.ts +8 -0
- package/dist/routes/_internal/entity-edit-route.cc.d.ts.map +1 -0
- package/dist/routes/_internal/entity-edit-route.cc.js +5 -0
- package/dist/routes/_internal/public-archive-route.d.ts +1 -1
- package/dist/routes/_internal/public-archive-route.d.ts.map +1 -1
- package/dist/routes/_internal/public-archive-route.js +8 -3
- package/dist/routes/_internal/public-item-route.cc.d.ts +5 -1
- package/dist/routes/_internal/public-item-route.cc.d.ts.map +1 -1
- package/dist/routes/_internal/public-item-route.cc.js +2 -1
- package/dist/routes/_internal/public-item-route.d.ts +7 -0
- package/dist/routes/_internal/public-item-route.d.ts.map +1 -1
- package/dist/routes/_internal/public-item-route.js +6 -1
- package/dist/routes/_internal/superadmin-layout.cc.d.ts +2 -1
- package/dist/routes/_internal/superadmin-layout.cc.d.ts.map +1 -1
- package/dist/routes/_internal/superadmin-layout.cc.js +1 -1
- package/dist/routes/_internal/superadmin-layout.d.ts +7 -2
- package/dist/routes/_internal/superadmin-layout.d.ts.map +1 -1
- package/dist/routes/_internal/superadmin-layout.js +6 -6
- package/dist/routes/_internal/suspended-route.d.ts +16 -0
- package/dist/routes/_internal/suspended-route.d.ts.map +1 -0
- package/dist/routes/_internal/suspended-route.js +7 -0
- package/dist/routes/api/auth/[...all]/route.d.ts.map +1 -1
- package/dist/routes/api/auth/[...all]/route.js +4 -12
- package/dist/routes/api/csp-report/route.d.ts.map +1 -1
- package/dist/routes/api/csp-report/route.js +2 -13
- package/dist/routes/api/devtools/config/entities/route.d.ts +2 -0
- package/dist/routes/api/devtools/config/entities/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/config/entities/route.js +2 -0
- package/dist/routes/api/devtools/config/theme/route.d.ts +2 -0
- package/dist/routes/api/devtools/config/theme/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/config/theme/route.js +2 -0
- package/dist/routes/api/devtools/tests/[...path]/route.d.ts +2 -0
- package/dist/routes/api/devtools/tests/[...path]/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/tests/[...path]/route.js +2 -0
- package/dist/routes/api/devtools/tests/route.d.ts +2 -0
- package/dist/routes/api/devtools/tests/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/tests/route.js +2 -0
- package/dist/routes/api/health/route.d.ts +2 -0
- package/dist/routes/api/health/route.d.ts.map +1 -1
- package/dist/routes/api/health/route.js +2 -0
- package/dist/routes/api/internal/user-metadata/route.d.ts +2 -0
- package/dist/routes/api/internal/user-metadata/route.d.ts.map +1 -1
- package/dist/routes/api/internal/user-metadata/route.js +2 -0
- package/dist/routes/api/mcp/route.d.ts +2 -0
- package/dist/routes/api/mcp/route.d.ts.map +1 -1
- package/dist/routes/api/mcp/route.js +2 -0
- package/dist/routes/api/superadmin/subscriptions/route.d.ts +2 -0
- package/dist/routes/api/superadmin/subscriptions/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/subscriptions/route.js +2 -0
- package/dist/routes/api/superadmin/teams/[teamId]/route.d.ts +2 -0
- package/dist/routes/api/superadmin/teams/[teamId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -0
- package/dist/routes/api/superadmin/teams/route.d.ts +2 -0
- package/dist/routes/api/superadmin/teams/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/teams/route.js +2 -0
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts +2 -0
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/[userId]/route.js +2 -0
- package/dist/routes/api/superadmin/users/route.d.ts +2 -0
- package/dist/routes/api/superadmin/users/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/route.js +2 -0
- package/dist/routes/api/user/delete-account/route.d.ts +2 -0
- package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
- package/dist/routes/api/user/delete-account/route.js +2 -0
- package/dist/routes/api/user/plan-flags/route.d.ts +2 -0
- package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
- package/dist/routes/api/user/plan-flags/route.js +2 -0
- package/dist/routes/api/user/profile/route.d.ts +2 -0
- package/dist/routes/api/user/profile/route.d.ts.map +1 -1
- package/dist/routes/api/user/profile/route.js +4 -3
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.d.ts +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.js +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.d.ts +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.js +2 -0
- package/dist/routes/api/v1/billing/cancel/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/cancel/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/cancel/route.js +2 -0
- package/dist/routes/api/v1/billing/change-plan/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/change-plan/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/change-plan/route.js +2 -0
- package/dist/routes/api/v1/billing/check-action/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/check-action/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/check-action/route.js +2 -0
- package/dist/routes/api/v1/billing/checkout/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/checkout/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/checkout/route.js +2 -0
- package/dist/routes/api/v1/billing/plans/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/plans/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/plans/route.js +2 -0
- package/dist/routes/api/v1/billing/portal/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/portal/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/portal/route.js +2 -0
- package/dist/routes/api/v1/blocks/[slug]/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/[slug]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/[slug]/route.js +2 -0
- package/dist/routes/api/v1/blocks/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/route.js +2 -0
- package/dist/routes/api/v1/blocks/validate/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/validate/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/validate/route.js +2 -0
- package/dist/routes/api/v1/devtools/blocks/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/blocks/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/blocks/route.js +2 -9
- package/dist/routes/api/v1/devtools/docs/route.d.ts +2 -0
- package/dist/routes/api/v1/devtools/docs/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/docs/route.js +2 -0
- package/dist/routes/api/v1/devtools/features/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/features/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/features/route.js +2 -9
- package/dist/routes/api/v1/devtools/flows/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/flows/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/flows/route.js +2 -9
- package/dist/routes/api/v1/devtools/scheduled-actions/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/route.js +2 -9
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.js +2 -9
- package/dist/routes/api/v1/devtools/testing/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/testing/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/testing/route.js +2 -9
- package/dist/routes/api/v1/media/[id]/route.d.ts +2 -0
- package/dist/routes/api/v1/media/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/[id]/route.js +2 -0
- package/dist/routes/api/v1/media/[id]/tags/route.d.ts +2 -0
- package/dist/routes/api/v1/media/[id]/tags/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/[id]/tags/route.js +2 -0
- package/dist/routes/api/v1/media/check-duplicates/route.d.ts +2 -0
- package/dist/routes/api/v1/media/check-duplicates/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/check-duplicates/route.js +2 -0
- package/dist/routes/api/v1/media/route.d.ts +2 -0
- package/dist/routes/api/v1/media/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/route.js +2 -0
- package/dist/routes/api/v1/media/upload/route.d.ts +2 -0
- package/dist/routes/api/v1/media/upload/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/upload/route.js +2 -0
- package/dist/routes/api/v1/media-tags/route.d.ts +2 -0
- package/dist/routes/api/v1/media-tags/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media-tags/route.js +2 -0
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts +2 -0
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/[id]/route.js +2 -0
- package/dist/routes/api/v1/post-categories/route.d.ts +2 -0
- package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/route.js +2 -0
- package/dist/routes/api/v1/teams/[teamId]/members/route.js +2 -2
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.d.ts +2 -0
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.js +2 -0
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.d.ts +2 -0
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.js +2 -0
- package/dist/routes/api/v1/users/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/route.js +3 -2
- package/dist/routes/api/v1/users/docs.md +34 -19
- package/dist/routes/api/v1/users/me/route.d.ts +6 -0
- package/dist/routes/api/v1/users/me/route.d.ts.map +1 -0
- package/dist/routes/api/v1/users/me/route.js +5 -0
- package/dist/routes/api/v1/users/presets.ts +2 -2
- package/dist/routes/dashboard/(main)/layout.cc.d.ts +4 -0
- package/dist/routes/dashboard/(main)/layout.cc.d.ts.map +1 -0
- package/dist/routes/dashboard/(main)/layout.cc.js +10 -0
- package/dist/routes/dashboard/(main)/layout.d.ts.map +1 -1
- package/dist/routes/dashboard/(main)/layout.js +3 -44
- package/dist/routes/dashboard/permission-denied/page.d.ts +1 -1
- package/dist/routes/dashboard/permission-denied/page.d.ts.map +1 -1
- package/dist/routes/dashboard/permission-denied/page.js +5 -1
- package/dist/routes/devtools/layout.cc.d.ts.map +1 -1
- package/dist/routes/devtools/layout.cc.js +5 -1
- package/dist/routes/manifest.json +10 -0
- package/dist/routes/robots.d.ts +10 -0
- package/dist/routes/robots.d.ts.map +1 -0
- package/dist/routes/robots.js +10 -0
- package/dist/routes/superadmin/layout.cc.d.ts.map +1 -1
- package/dist/routes/superadmin/layout.cc.js +5 -1
- package/dist/routes/variants.json +12 -2
- package/dist/templates/next.config.mjs +2 -29
- package/dist/templates/projects/blog/api/authors/[username]/route.ts +3 -0
- package/dist/templates/projects/blog/api/authors/route.ts +3 -0
- package/dist/templates/projects/blog/api/posts/public/route.ts +3 -0
- package/dist/templates/proxy.ts +12 -1
- package/dist/templates/public/favicon.ico +0 -0
- package/package.json +2 -2
- package/scripts/build/registry/__tests__/api-docs-colocated.test.mjs +3 -0
- package/scripts/build/registry/__tests__/billing-registry.test.mjs +50 -1
- package/scripts/build/registry/__tests__/block-registry.test.mjs +3 -0
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +3 -0
- package/scripts/build/registry/__tests__/quiet-console.mjs +17 -0
- package/scripts/build/registry/__tests__/safe-fs.test.mjs +3 -0
- package/scripts/build/registry/__tests__/team-roles.test.mjs +3 -0
- package/scripts/build/registry/discovery/permissions.test.mjs +3 -0
- package/scripts/build/registry/discovery/plugin-capabilities.mjs +2 -2
- package/scripts/build/registry/generators/billing-registry.mjs +7 -3
- package/scripts/build/registry/host/README.md +25 -1
- package/scripts/build/registry/host/__tests__/host-area-access.test.mjs +32 -0
- package/scripts/build/registry/host/__tests__/host-entities.test.mjs +32 -1
- package/scripts/build/registry/host/__tests__/host-plan.test.mjs +12 -2
- package/scripts/build/registry/host/entity-routes.mjs +9 -3
- package/scripts/build/registry/host/static-imports.mjs +4 -0
- package/scripts/build/routes-manifest.mjs +13 -1
- package/scripts/db/ssl-config.mjs +12 -1
- package/templates/next.config.mjs +2 -29
- package/templates/projects/blog/api/authors/[username]/route.ts +3 -0
- package/templates/projects/blog/api/authors/route.ts +3 -0
- package/templates/projects/blog/api/posts/public/route.ts +3 -0
- package/templates/proxy.ts +12 -1
- package/templates/public/favicon.ico +0 -0
|
@@ -3,6 +3,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { parseClientChildEntity as parseChildEntity, getClientEntityApiPath as getEntityApiPath } from "../../lib/entities/client-entity-meta.js";
|
|
5
5
|
import { withBasePath } from "../../lib/base-path.js";
|
|
6
|
+
import { TEAM_ID_HEADER } from "../../lib/api/client-headers.js";
|
|
6
7
|
function RelationDisplay({
|
|
7
8
|
value,
|
|
8
9
|
entityType,
|
|
@@ -76,7 +77,7 @@ function RelationDisplay({
|
|
|
76
77
|
method: "GET",
|
|
77
78
|
headers: {
|
|
78
79
|
"Content-Type": "application/json",
|
|
79
|
-
...teamId && {
|
|
80
|
+
...teamId && { [TEAM_ID_HEADER]: teamId }
|
|
80
81
|
},
|
|
81
82
|
credentials: "include"
|
|
82
83
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-display.d.ts","sourceRoot":"","sources":["../../../src/components/ui/user-display.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"user-display.d.ts","sourceRoot":"","sources":["../../../src/components/ui/user-display.tsx"],"names":[],"mappings":"AAUA,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAChC,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAUD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,MAAM,EAAE,UAAU,EAClB,QAAgB,EAChB,SAAiB,EACjB,SAAS,GACV,EAAE,gBAAgB,2CA0IlB"}
|
|
@@ -6,6 +6,7 @@ import { Badge } from "./badge.js";
|
|
|
6
6
|
import { cn } from "../../lib/utils/index.js";
|
|
7
7
|
import { useTeam } from "../../hooks/useTeam.js";
|
|
8
8
|
import { withBasePath } from "../../lib/base-path.js";
|
|
9
|
+
import { TEAM_ID_HEADER } from "../../lib/api/client-headers.js";
|
|
9
10
|
function UserDisplay({
|
|
10
11
|
value,
|
|
11
12
|
teamId: propTeamId,
|
|
@@ -37,7 +38,7 @@ function UserDisplay({
|
|
|
37
38
|
const response = await fetch(withBasePath(`/api/v1/teams/${effectiveTeamId}/members`), {
|
|
38
39
|
headers: {
|
|
39
40
|
"Content-Type": "application/json",
|
|
40
|
-
|
|
41
|
+
[TEAM_ID_HEADER]: effectiveTeamId
|
|
41
42
|
},
|
|
42
43
|
credentials: "include"
|
|
43
44
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp-verification.d.ts","sourceRoot":"","sources":["../../src/emails/otp-verification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"otp-verification.d.ts","sourceRoot":"","sources":["../../src/emails/otp-verification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAKjF,wBAA8B,eAAe,CAC3C,IAAI,EAAE,wBAAwB,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAyEvB"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { getTranslations } from "next-intl/server";
|
|
2
|
+
import { escapeHtml } from "../lib/auth/security-notifications/templates/shared.js";
|
|
2
3
|
import { DEFAULT_OTP_CONFIG } from "../lib/auth/otp-config.js";
|
|
3
4
|
const APP_NAME_FALLBACK = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
|
|
4
5
|
async function otpVerification(data, locale) {
|
|
5
6
|
const t = locale ? await getTranslations({ locale, namespace: "email.otpVerification" }) : await getTranslations("email.otpVerification");
|
|
6
7
|
const appName = data.appName || APP_NAME_FALLBACK;
|
|
8
|
+
const htmlAppName = escapeHtml(appName);
|
|
7
9
|
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
8
10
|
const expiresInMinutes = Math.floor((data.expiresIn ?? DEFAULT_OTP_CONFIG.expiresIn) / 60);
|
|
9
11
|
return {
|
|
@@ -23,7 +25,7 @@ async function otpVerification(data, locale) {
|
|
|
23
25
|
<!-- Header -->
|
|
24
26
|
<tr>
|
|
25
27
|
<td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px 8px 0 0;">
|
|
26
|
-
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${
|
|
28
|
+
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${htmlAppName}</h1>
|
|
27
29
|
<p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">${t("headerSubtitle")}</p>
|
|
28
30
|
</td>
|
|
29
31
|
</tr>
|
|
@@ -52,10 +54,10 @@ async function otpVerification(data, locale) {
|
|
|
52
54
|
<tr>
|
|
53
55
|
<td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
|
|
54
56
|
<p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
|
|
55
|
-
${t("copyright", { year, appName })}
|
|
57
|
+
${t("copyright", { year, appName: htmlAppName })}
|
|
56
58
|
</p>
|
|
57
59
|
<p style="color: #999999; font-size: 12px; margin: 0;">
|
|
58
|
-
${t("footerLine1", { appName })}
|
|
60
|
+
${t("footerLine1", { appName: htmlAppName })}
|
|
59
61
|
</p>
|
|
60
62
|
</td>
|
|
61
63
|
</tr>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset-password.d.ts","sourceRoot":"","sources":["../../src/emails/reset-password.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"reset-password.d.ts","sourceRoot":"","sources":["../../src/emails/reset-password.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAI/E,wBAA8B,aAAa,CACzC,IAAI,EAAE,sBAAsB,EAC5B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CA8FvB"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { getTranslations } from "next-intl/server";
|
|
2
|
+
import { escapeHtml } from "../lib/auth/security-notifications/templates/shared.js";
|
|
2
3
|
const APP_NAME_FALLBACK = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
|
|
3
4
|
async function resetPassword(data, locale) {
|
|
4
5
|
const t = locale ? await getTranslations({ locale, namespace: "email.resetPassword" }) : await getTranslations("email.resetPassword");
|
|
5
6
|
const appName = data.appName || APP_NAME_FALLBACK;
|
|
7
|
+
const htmlAppName = escapeHtml(appName);
|
|
6
8
|
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
7
9
|
const greeting = `${t("greetingPrefix")}${data.userName ? ` ${data.userName}` : ""},`;
|
|
8
10
|
const expiresIn = data.expiresIn || t("defaultExpiresIn");
|
|
@@ -23,7 +25,7 @@ async function resetPassword(data, locale) {
|
|
|
23
25
|
<!-- Header -->
|
|
24
26
|
<tr>
|
|
25
27
|
<td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 8px 8px 0 0;">
|
|
26
|
-
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${
|
|
28
|
+
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${htmlAppName}</h1>
|
|
27
29
|
<p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">${t("headerSubtitle")}</p>
|
|
28
30
|
</td>
|
|
29
31
|
</tr>
|
|
@@ -73,10 +75,10 @@ async function resetPassword(data, locale) {
|
|
|
73
75
|
<tr>
|
|
74
76
|
<td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
|
|
75
77
|
<p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
|
|
76
|
-
${t("copyright", { year, appName })}
|
|
78
|
+
${t("copyright", { year, appName: htmlAppName })}
|
|
77
79
|
</p>
|
|
78
80
|
<p style="color: #999999; font-size: 12px; margin: 0;">
|
|
79
|
-
${t("footerLine1", { appName })}
|
|
81
|
+
${t("footerLine1", { appName: htmlAppName })}
|
|
80
82
|
<br>${t("footerLine2")}
|
|
81
83
|
</p>
|
|
82
84
|
</td>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-invitation.d.ts","sourceRoot":"","sources":["../../src/emails/team-invitation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAKhF,wBAA8B,cAAc,CAC1C,IAAI,EAAE,uBAAuB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"team-invitation.d.ts","sourceRoot":"","sources":["../../src/emails/team-invitation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAKhF,wBAA8B,cAAc,CAC1C,IAAI,EAAE,uBAAuB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CA4FvB"}
|
|
@@ -4,6 +4,7 @@ const APP_NAME_FALLBACK = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
|
|
|
4
4
|
async function teamInvitation(data, locale) {
|
|
5
5
|
const t = locale ? await getTranslations({ locale, namespace: "email.teamInvitation" }) : await getTranslations("email.teamInvitation");
|
|
6
6
|
const appName = data.appName || APP_NAME_FALLBACK;
|
|
7
|
+
const htmlAppName = escapeHtml(appName);
|
|
7
8
|
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
8
9
|
return {
|
|
9
10
|
subject: t("subject", { teamName: data.teamName, appName }),
|
|
@@ -22,7 +23,7 @@ async function teamInvitation(data, locale) {
|
|
|
22
23
|
<!-- Header -->
|
|
23
24
|
<tr>
|
|
24
25
|
<td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%); border-radius: 8px 8px 0 0;">
|
|
25
|
-
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${
|
|
26
|
+
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${htmlAppName}</h1>
|
|
26
27
|
<p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">${t("headerSubtitle")}</p>
|
|
27
28
|
</td>
|
|
28
29
|
</tr>
|
|
@@ -72,7 +73,7 @@ async function teamInvitation(data, locale) {
|
|
|
72
73
|
<tr>
|
|
73
74
|
<td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
|
|
74
75
|
<p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
|
|
75
|
-
${t("copyright", { year, appName })}
|
|
76
|
+
${t("copyright", { year, appName: htmlAppName })}
|
|
76
77
|
</p>
|
|
77
78
|
<p style="color: #999999; font-size: 12px; margin: 0;">
|
|
78
79
|
${t("footerSentTo", { inviteeEmail: escapeHtml(data.inviteeEmail) })}<br>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-email.d.ts","sourceRoot":"","sources":["../../src/emails/verify-email.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"verify-email.d.ts","sourceRoot":"","sources":["../../src/emails/verify-email.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI9E,wBAA8B,WAAW,CACvC,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAmFvB"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { getTranslations } from "next-intl/server";
|
|
2
|
+
import { escapeHtml } from "../lib/auth/security-notifications/templates/shared.js";
|
|
2
3
|
const APP_NAME_FALLBACK = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
|
|
3
4
|
async function verifyEmail(data, locale) {
|
|
4
5
|
const t = locale ? await getTranslations({ locale, namespace: "email.verifyEmail" }) : await getTranslations("email.verifyEmail");
|
|
5
6
|
const appName = data.appName || APP_NAME_FALLBACK;
|
|
7
|
+
const htmlAppName = escapeHtml(appName);
|
|
6
8
|
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
7
9
|
const greeting = `${t("greetingPrefix")}${data.userName ? ` ${data.userName}` : ""},`;
|
|
8
10
|
return {
|
|
@@ -22,7 +24,7 @@ async function verifyEmail(data, locale) {
|
|
|
22
24
|
<!-- Header -->
|
|
23
25
|
<tr>
|
|
24
26
|
<td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px 8px 0 0;">
|
|
25
|
-
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${
|
|
27
|
+
<h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${htmlAppName}</h1>
|
|
26
28
|
<p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">${t("headerSubtitle")}</p>
|
|
27
29
|
</td>
|
|
28
30
|
</tr>
|
|
@@ -62,10 +64,10 @@ async function verifyEmail(data, locale) {
|
|
|
62
64
|
<tr>
|
|
63
65
|
<td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
|
|
64
66
|
<p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
|
|
65
|
-
${t("copyright", { year, appName })}
|
|
67
|
+
${t("copyright", { year, appName: htmlAppName })}
|
|
66
68
|
</p>
|
|
67
69
|
<p style="color: #999999; font-size: 12px; margin: 0;">
|
|
68
|
-
${t("footerLine1", { appName })}
|
|
70
|
+
${t("footerLine1", { appName: htmlAppName })}
|
|
69
71
|
<br>${t("footerLine2")}
|
|
70
72
|
</p>
|
|
71
73
|
</td>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/useAuth.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/useAuth.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAwE9C;;;GAGG;AACH,wBAAgB,cAAc;8CAYiC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;+DAqBvC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAmF1H,MAAM;qBAlCjB,MAAM;;;gDAgBiB;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;iBAY9F,CAAC;;;;;;;;;;;;;2BAeyB,MAAM;;;;;;;;;;;;kCA6BC,MAAM,UAAU,MAAM;;;;;;;;;;;sCAwClB,MAAM,eAAe,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA8B5B,MAAM;;;;;;;;;;;EAwC3D;AAED,8DAA8D;AAC9D,wBAAgB,OAAO;;;;;8CA/PwC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;+DAqBvC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAmF1H,MAAM;qBAlCjB,MAAM;;;gDAgBiB;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;iBAY9F,CAAC;;;;;;;;;;;;;2BAeyB,MAAM;;;;;;;;;;;;kCA6BC,MAAM,UAAU,MAAM;;;;;;;;;;;sCAwClB,MAAM,eAAe,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA8B5B,MAAM;;;;;;;;;;;UAqD5B,WAAW,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;EASjD"}
|
package/dist/hooks/useAuth.js
CHANGED
|
@@ -7,9 +7,11 @@ import { useOrigin } from "./useOrigin.js";
|
|
|
7
7
|
import { useLastAuthMethod } from "./useLastAuthMethod.js";
|
|
8
8
|
import { safeCallbackPath } from "../lib/auth/callback-url.js";
|
|
9
9
|
import { withBasePath } from "../lib/base-path.js";
|
|
10
|
+
import { loadLoginPage } from "../lib/auth/load-login-page.js";
|
|
10
11
|
import { setSessionHint } from "../lib/auth/session-hint.js";
|
|
11
12
|
import { setUserLocaleClient } from "../lib/locale-client.js";
|
|
12
13
|
import { I18N_CONFIG } from "../lib/config/i18n-config-client.js";
|
|
14
|
+
import { SIGNUP_INTENT_HEADER } from "../lib/api/client-headers.js";
|
|
13
15
|
function googleCallbackURL(redirectTo) {
|
|
14
16
|
const url = new URL(safeCallbackPath(redirectTo) ?? "/dashboard", "http://callback.invalid");
|
|
15
17
|
url.searchParams.set("auth_method", "google");
|
|
@@ -23,6 +25,20 @@ function rememberSignedIn(user) {
|
|
|
23
25
|
setUserLocaleClient(language);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
28
|
+
const SESSION_DROP_TIMEOUT_MS = 2e3;
|
|
29
|
+
async function waitForSessionToDrop() {
|
|
30
|
+
var _a, _b, _c, _d, _e, _f;
|
|
31
|
+
let timer;
|
|
32
|
+
try {
|
|
33
|
+
const refetch = (_f = (_e = (_d = (_c = (_b = (_a = authClient.$store) == null ? void 0 : _a.atoms) == null ? void 0 : _b.session) == null ? void 0 : _c.get) == null ? void 0 : _d.call(_c)) == null ? void 0 : _e.refetch) == null ? void 0 : _f.call(_e);
|
|
34
|
+
await Promise.race([refetch, new Promise((resolve) => {
|
|
35
|
+
timer = setTimeout(resolve, SESSION_DROP_TIMEOUT_MS);
|
|
36
|
+
})]);
|
|
37
|
+
} catch {
|
|
38
|
+
} finally {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
26
42
|
function useAuthActions() {
|
|
27
43
|
const router = useRouter();
|
|
28
44
|
const origin = useOrigin();
|
|
@@ -57,7 +73,7 @@ function useAuthActions() {
|
|
|
57
73
|
},
|
|
58
74
|
// Optional signup intent, sent as the `x-signup-intent` header. The signup
|
|
59
75
|
// route maps it to an initial team role (AUTH_CONFIG.signupIntent).
|
|
60
|
-
intent ? { headers: {
|
|
76
|
+
intent ? { headers: { [SIGNUP_INTENT_HEADER]: intent } } : void 0
|
|
61
77
|
);
|
|
62
78
|
if (error) {
|
|
63
79
|
throw new Error(error.message || "Failed to create account");
|
|
@@ -68,10 +84,11 @@ function useAuthActions() {
|
|
|
68
84
|
if (typeof window !== "undefined") {
|
|
69
85
|
localStorage.removeItem("activeTeamId");
|
|
70
86
|
}
|
|
71
|
-
await authClient.signOut();
|
|
87
|
+
const { error } = await authClient.signOut();
|
|
88
|
+
if (error) throw new Error(error.message || "Failed to sign out");
|
|
72
89
|
setSessionHint(false);
|
|
73
|
-
|
|
74
|
-
|
|
90
|
+
await waitForSessionToDrop();
|
|
91
|
+
loadLoginPage();
|
|
75
92
|
};
|
|
76
93
|
const handleSendOtp = async (email) => {
|
|
77
94
|
const { data, error } = await authClient.emailOtp.sendVerificationOtp({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePatternUsages.d.ts","sourceRoot":"","sources":["../../src/hooks/usePatternUsages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePatternUsages.d.ts","sourceRoot":"","sources":["../../src/hooks/usePatternUsages.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,uBAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4EtC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,iEA8BxD"}
|
|
@@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
3
3
|
import { useAuth } from "./useAuth.js";
|
|
4
4
|
import { useTeam } from "./useTeam.js";
|
|
5
5
|
import { withBasePath } from "../lib/base-path.js";
|
|
6
|
+
import { TEAM_ID_HEADER } from "../lib/api/client-headers.js";
|
|
6
7
|
function usePatternUsages(patternId, options = {}) {
|
|
7
8
|
var _a, _b, _c, _d, _e;
|
|
8
9
|
const {
|
|
@@ -37,7 +38,7 @@ function usePatternUsages(patternId, options = {}) {
|
|
|
37
38
|
"Content-Type": "application/json"
|
|
38
39
|
};
|
|
39
40
|
if (teamId) {
|
|
40
|
-
headers[
|
|
41
|
+
headers[TEAM_ID_HEADER] = teamId;
|
|
41
42
|
}
|
|
42
43
|
const response = await fetch(withBasePath(url), { headers });
|
|
43
44
|
if (!response.ok) {
|
|
@@ -81,7 +82,7 @@ function usePatternUsageCount(patternId, options = {}) {
|
|
|
81
82
|
"Content-Type": "application/json"
|
|
82
83
|
};
|
|
83
84
|
if (teamId) {
|
|
84
|
-
headers[
|
|
85
|
+
headers[TEAM_ID_HEADER] = teamId;
|
|
85
86
|
}
|
|
86
87
|
const response = await fetch(withBasePath(`/api/v1/patterns/${patternId}/usages?limit=1`), { headers });
|
|
87
88
|
if (!response.ok) {
|
package/dist/lib/api/auth.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface ApiKeyValidationResult {
|
|
|
21
21
|
auth?: ApiKeyAuth;
|
|
22
22
|
error?: string;
|
|
23
23
|
}
|
|
24
|
+
/** The API key validateApiKey accepted for this request, or null when none was validated. */
|
|
25
|
+
export declare function getValidatedApiKey(request: Request): ApiKeyAuth | null;
|
|
24
26
|
/**
|
|
25
27
|
* Valida una API Key desde el header Authorization o x-api-key
|
|
26
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/lib/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA0GrF;AA8CD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E;AAID;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAM/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAMhF;AAiBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU;QAG1C,MAAM;WACH,MAAM;eACF,MAAM,GAAG,IAAI;cACd,MAAM,GAAG,IAAI;UACjB,MAAM;GAWjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC,CAyED"}
|
package/dist/lib/api/auth.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { queryOne } from "../db.js";
|
|
2
|
-
import { ApiKeyManager } from "./keys.js";
|
|
2
|
+
import { ApiKeyManager, presentedApiKey } from "./keys.js";
|
|
3
3
|
import { apiKeyCache, getCacheKey } from "./cache.js";
|
|
4
4
|
import { TeamMemberService } from "../services/team-member.service.js";
|
|
5
5
|
import { ScopeService } from "../services/scope.service.js";
|
|
6
6
|
function hasScope(auth, requiredScope) {
|
|
7
7
|
return auth.scopes.includes(requiredScope);
|
|
8
8
|
}
|
|
9
|
+
const validatedKeys = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
function getValidatedApiKey(request) {
|
|
11
|
+
return validatedKeys.get(request) ?? null;
|
|
12
|
+
}
|
|
9
13
|
async function validateApiKey(request) {
|
|
10
14
|
const startTime = Date.now();
|
|
11
15
|
try {
|
|
12
|
-
const
|
|
13
|
-
const xApiKeyHeader = request.headers.get("x-api-key");
|
|
14
|
-
let apiKey = null;
|
|
15
|
-
if (authHeader == null ? void 0 : authHeader.startsWith("Bearer ")) {
|
|
16
|
-
apiKey = authHeader.substring(7);
|
|
17
|
-
} else if (xApiKeyHeader) {
|
|
18
|
-
apiKey = xApiKeyHeader;
|
|
19
|
-
}
|
|
16
|
+
const apiKey = presentedApiKey(request.headers);
|
|
20
17
|
if (!apiKey) {
|
|
21
18
|
await constantTimeDelay(startTime);
|
|
22
19
|
return null;
|
|
@@ -72,11 +69,13 @@ async function validateApiKey(request) {
|
|
|
72
69
|
updateLastUsed(keyData.id).catch((error) => {
|
|
73
70
|
console.error("Error updating API key last used:", error);
|
|
74
71
|
});
|
|
75
|
-
|
|
72
|
+
const validated = {
|
|
76
73
|
userId: keyData.userId,
|
|
77
74
|
keyId: keyData.id,
|
|
78
75
|
scopes: keyData.scopes || []
|
|
79
76
|
};
|
|
77
|
+
validatedKeys.set(request, validated);
|
|
78
|
+
return validated;
|
|
80
79
|
} catch (error) {
|
|
81
80
|
console.error("Error validating API key:", error);
|
|
82
81
|
await constantTimeDelay(startTime);
|
|
@@ -245,6 +244,7 @@ async function validateScopesForUser(userId, teamId, requestedScopes) {
|
|
|
245
244
|
export {
|
|
246
245
|
canCreateApiKeys,
|
|
247
246
|
getApiKeyUser,
|
|
247
|
+
getValidatedApiKey,
|
|
248
248
|
hasAllScopes,
|
|
249
249
|
hasAnyScope,
|
|
250
250
|
hasScope,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The custom request headers core's own clients send to /api. The clients set them by these names and
|
|
3
|
+
* CORS_ALLOW_HEADERS (cors-response.ts) is built from this list, so a listed origin's preflight allows
|
|
4
|
+
* every header core's clients send. Client-safe: no imports.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TEAM_ID_HEADER = "x-team-id";
|
|
7
|
+
export declare const BUILDER_SOURCE_HEADER = "x-builder-source";
|
|
8
|
+
export declare const SIGNUP_INTENT_HEADER = "x-signup-intent";
|
|
9
|
+
export declare const VERIFY_FROM_UI_HEADER = "x-verify-from-ui";
|
|
10
|
+
export declare const CLIENT_REQUEST_HEADERS: readonly ["x-team-id", "x-builder-source", "x-signup-intent", "x-verify-from-ui"];
|
|
11
|
+
//# sourceMappingURL=client-headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-headers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/client-headers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,cAAc,cAAc,CAAA;AACzC,eAAO,MAAM,qBAAqB,qBAAqB,CAAA;AACvD,eAAO,MAAM,oBAAoB,oBAAoB,CAAA;AACrD,eAAO,MAAM,qBAAqB,qBAAqB,CAAA;AAEvD,eAAO,MAAM,sBAAsB,mFAAgG,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const TEAM_ID_HEADER = "x-team-id";
|
|
2
|
+
const BUILDER_SOURCE_HEADER = "x-builder-source";
|
|
3
|
+
const SIGNUP_INTENT_HEADER = "x-signup-intent";
|
|
4
|
+
const VERIFY_FROM_UI_HEADER = "x-verify-from-ui";
|
|
5
|
+
const CLIENT_REQUEST_HEADERS = [TEAM_ID_HEADER, BUILDER_SOURCE_HEADER, SIGNUP_INTENT_HEADER, VERIFY_FROM_UI_HEADER];
|
|
6
|
+
export {
|
|
7
|
+
BUILDER_SOURCE_HEADER,
|
|
8
|
+
CLIENT_REQUEST_HEADERS,
|
|
9
|
+
SIGNUP_INTENT_HEADER,
|
|
10
|
+
TEAM_ID_HEADER,
|
|
11
|
+
VERIFY_FROM_UI_HEADER
|
|
12
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client address of a request: the one place that decides it, for rate limits, audit logs,
|
|
3
|
+
* security notifications and every other reader in core.
|
|
4
|
+
*
|
|
5
|
+
* Which header can be trusted depends on what sits in front of the app, so the deployment names it:
|
|
6
|
+
*
|
|
7
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=vercel x-vercel-forwarded-for, then x-real-ip (set by Vercel)
|
|
8
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=cloudflare cf-connecting-ip (set by Cloudflare)
|
|
9
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=header:<name> one header that your proxy sets, e.g. header:x-real-ip
|
|
10
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=xff X-Forwarded-For, counting NEXTSPARK_TRUSTED_PROXY_HOPS
|
|
11
|
+
* (default 1) trusted proxies from the right
|
|
12
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=none no client address: every request shares one bucket
|
|
13
|
+
*
|
|
14
|
+
* Unset keeps the order core always used (cf-connecting-ip, rightmost X-Forwarded-For, x-real-ip,
|
|
15
|
+
* true-client-ip), and production logs one warning saying what to set. Next.js gives route handlers
|
|
16
|
+
* no socket address, so 'none' cannot fall back to one.
|
|
17
|
+
* What to set per deployment: the upgrade note in CHANGELOG.md, and https://nextspark.dev/docs.
|
|
18
|
+
*/
|
|
19
|
+
export declare const UNKNOWN_CLIENT_IP = "unknown";
|
|
20
|
+
export type ClientIpSource = {
|
|
21
|
+
kind: 'default';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'vercel';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'cloudflare';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'header';
|
|
28
|
+
header: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'xff';
|
|
31
|
+
hops: number;
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'none';
|
|
34
|
+
};
|
|
35
|
+
type Env = Record<string, string | undefined>;
|
|
36
|
+
/** Reads the setting. Throws on a value it does not understand: a typo must not silently trust a header. */
|
|
37
|
+
export declare function getClientIpSource(env?: Env): ClientIpSource;
|
|
38
|
+
/** The client address of a request, from the source the deployment configured (getClientIpSource). */
|
|
39
|
+
export declare function getClientIp(headers: Headers, env?: Env): string;
|
|
40
|
+
/**
|
|
41
|
+
* getClientIp for readers that only record the address (audit rows, the new-device fingerprint): an invalid
|
|
42
|
+
* setting records UNKNOWN_CLIENT_IP instead of throwing, so the row is still written. Rate limits use getClientIp,
|
|
43
|
+
* which throws.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getRecordedClientIp(headers: Headers, env?: Env): string;
|
|
46
|
+
/**
|
|
47
|
+
* The headers Better Auth's own rate limiter should read (advanced.ipAddress.ipAddressHeaders), or undefined
|
|
48
|
+
* to keep its default. Better Auth trusts only a single-valued header, so 'xff' keeps its default; 'none' names no
|
|
49
|
+
* header, so Better Auth counts every request to a path in one shared bucket.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getBetterAuthIpHeaders(env?: Env): string[] | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Logs once per process when the client address source is invalid (in every environment) or, in production
|
|
54
|
+
* only, not set. Called at server start (logAuthReadinessAtStartup) and again on first use, for projects whose
|
|
55
|
+
* instrumentation does not run it; the flag lives on globalThis so both bundles share it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function warnClientIpSourceAtStartup(env?: Env): void;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=client-ip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-ip.d.ts","sourceRoot":"","sources":["../../../src/lib/api/client-ip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,iBAAiB,YAAY,CAAA;AAE1C,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpB,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAI7C,4GAA4G;AAC5G,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,GAAiB,GAAG,cAAc,CAiBxE;AAWD,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,GAAiB,GAAG,MAAM,CA2B5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,GAAiB,GAAG,MAAM,CAMpF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,GAAiB,GAAG,MAAM,EAAE,GAAG,SAAS,CAWnF;AAID;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,GAAiB,GAAG,IAAI,CAkBxE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const UNKNOWN_CLIENT_IP = "unknown";
|
|
2
|
+
const HEADER_NAME = /^[a-z0-9!#$%&'*+.^_`|~-]+$/;
|
|
3
|
+
function getClientIpSource(env = process.env) {
|
|
4
|
+
var _a, _b;
|
|
5
|
+
const raw = (_a = env.NEXTSPARK_CLIENT_IP_SOURCE) == null ? void 0 : _a.trim().toLowerCase();
|
|
6
|
+
if (!raw) return { kind: "default" };
|
|
7
|
+
if (raw === "vercel" || raw === "cloudflare" || raw === "none") return { kind: raw };
|
|
8
|
+
if (raw === "xff") {
|
|
9
|
+
const hopsRaw = ((_b = env.NEXTSPARK_TRUSTED_PROXY_HOPS) == null ? void 0 : _b.trim()) || "1";
|
|
10
|
+
const hops = Number(hopsRaw);
|
|
11
|
+
if (!/^\d+$/.test(hopsRaw) || hops < 1) {
|
|
12
|
+
throw new Error("[client-ip] NEXTSPARK_TRUSTED_PROXY_HOPS must be a whole number of 1 or more");
|
|
13
|
+
}
|
|
14
|
+
return { kind: "xff", hops };
|
|
15
|
+
}
|
|
16
|
+
if (raw.startsWith("header:")) {
|
|
17
|
+
const header = raw.slice("header:".length).trim();
|
|
18
|
+
if (HEADER_NAME.test(header)) return { kind: "header", header };
|
|
19
|
+
}
|
|
20
|
+
throw new Error("[client-ip] NEXTSPARK_CLIENT_IP_SOURCE must be vercel, cloudflare, xff, none or header:<name>");
|
|
21
|
+
}
|
|
22
|
+
function entries(value) {
|
|
23
|
+
return value ? value.split(",").map((ip) => ip.trim()).filter(Boolean) : [];
|
|
24
|
+
}
|
|
25
|
+
function lastEntry(value) {
|
|
26
|
+
return entries(value).at(-1) ?? null;
|
|
27
|
+
}
|
|
28
|
+
function getClientIp(headers, env = process.env) {
|
|
29
|
+
warnClientIpSourceAtStartup(env);
|
|
30
|
+
const source = getClientIpSource(env);
|
|
31
|
+
switch (source.kind) {
|
|
32
|
+
case "vercel":
|
|
33
|
+
return lastEntry(headers.get("x-vercel-forwarded-for")) ?? lastEntry(headers.get("x-real-ip")) ?? UNKNOWN_CLIENT_IP;
|
|
34
|
+
case "cloudflare":
|
|
35
|
+
return lastEntry(headers.get("cf-connecting-ip")) ?? UNKNOWN_CLIENT_IP;
|
|
36
|
+
case "header":
|
|
37
|
+
return lastEntry(headers.get(source.header)) ?? UNKNOWN_CLIENT_IP;
|
|
38
|
+
case "xff": {
|
|
39
|
+
const ips = entries(headers.get("x-forwarded-for"));
|
|
40
|
+
return ips.length >= source.hops ? ips[ips.length - source.hops] : UNKNOWN_CLIENT_IP;
|
|
41
|
+
}
|
|
42
|
+
case "none":
|
|
43
|
+
return UNKNOWN_CLIENT_IP;
|
|
44
|
+
default:
|
|
45
|
+
return headers.get("cf-connecting-ip") || lastEntry(headers.get("x-forwarded-for")) || headers.get("x-real-ip") || headers.get("true-client-ip") || UNKNOWN_CLIENT_IP;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function getRecordedClientIp(headers, env = process.env) {
|
|
49
|
+
try {
|
|
50
|
+
return getClientIp(headers, env);
|
|
51
|
+
} catch {
|
|
52
|
+
return UNKNOWN_CLIENT_IP;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function getBetterAuthIpHeaders(env = process.env) {
|
|
56
|
+
try {
|
|
57
|
+
const source = getClientIpSource(env);
|
|
58
|
+
if (source.kind === "vercel") return ["x-vercel-forwarded-for", "x-real-ip"];
|
|
59
|
+
if (source.kind === "cloudflare") return ["cf-connecting-ip"];
|
|
60
|
+
if (source.kind === "header") return [source.header];
|
|
61
|
+
if (source.kind === "none") return [];
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
const WARNED = /* @__PURE__ */ Symbol.for("nextspark.clientIpSourceWarned");
|
|
67
|
+
function warnClientIpSourceAtStartup(env = process.env) {
|
|
68
|
+
const state = globalThis;
|
|
69
|
+
if (state[WARNED]) return;
|
|
70
|
+
let source;
|
|
71
|
+
try {
|
|
72
|
+
source = getClientIpSource(env);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
state[WARNED] = true;
|
|
75
|
+
console.error(error.message);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (source.kind !== "default" || env.NODE_ENV !== "production") return;
|
|
79
|
+
state[WARNED] = true;
|
|
80
|
+
console.warn(
|
|
81
|
+
"[client-ip] NEXTSPARK_CLIENT_IP_SOURCE is not set, so rate limits and audit logs read the client address from request headers in a fixed order. Set it for your deployment: vercel, cloudflare, xff (with NEXTSPARK_TRUSTED_PROXY_HOPS) or header:<name>; none if nothing in front sets a client address."
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
UNKNOWN_CLIENT_IP,
|
|
86
|
+
getBetterAuthIpHeaders,
|
|
87
|
+
getClientIp,
|
|
88
|
+
getClientIpSource,
|
|
89
|
+
getRecordedClientIp,
|
|
90
|
+
warnClientIpSourceAtStartup
|
|
91
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core's CORS answer for /api responses, in one place: addCorsHeaders and wrapAuthHandlerWithCors (helpers.ts)
|
|
3
|
+
* and the common route wrapper (withRateLimitTier) all use it, so every response and preflight a route gives
|
|
4
|
+
* names the same origin, with or without credentials, for the same request.
|
|
5
|
+
*/
|
|
6
|
+
import { NextResponse } from 'next/server';
|
|
7
|
+
import type { ApplicationConfig } from '../config/config-types';
|
|
8
|
+
type CorsConfig = Pick<ApplicationConfig, 'api'>;
|
|
9
|
+
export declare const CORS_ALLOW_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
|
|
10
|
+
export declare const CORS_ALLOW_HEADERS: string;
|
|
11
|
+
/**
|
|
12
|
+
* True for a path under the admin or developer areas, which answer CORS only to the app's own origin and accept
|
|
13
|
+
* cookie-authenticated writes only from it (checkRequestOrigin).
|
|
14
|
+
*/
|
|
15
|
+
export declare function isAppOnlyCorsPath(pathname: string): boolean;
|
|
16
|
+
/** A request's path, for corsGrant (undefined when its URL does not parse). */
|
|
17
|
+
export declare function requestPathname(request: Request): string | undefined;
|
|
18
|
+
/** The app's own origins: NEXT_PUBLIC_APP_URL and BETTER_AUTH_URL. */
|
|
19
|
+
export declare function appOrigins(): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Which origin a CORS response may name, and whether credentials go with it.
|
|
22
|
+
* A listed origin (getCorsOrigins, wildcard entries allowed) is echoed with
|
|
23
|
+
* credentials. In development with allowAllOrigins.development, any other
|
|
24
|
+
* origin is echoed too, but with credentials only when the cookie-write origin
|
|
25
|
+
* check trusts it (getTrustedOrigins). Any other origin gets no grant: the
|
|
26
|
+
* response names no origin and sends no credentials header.
|
|
27
|
+
* Under the admin and developer areas (isAppOnlyCorsPath, given the request's
|
|
28
|
+
* `pathname`), only the app's own origin is granted, with credentials; no
|
|
29
|
+
* other origin, listed or not.
|
|
30
|
+
*/
|
|
31
|
+
export declare function corsGrant(origin: string, config: CorsConfig, env: string, pathname?: string): {
|
|
32
|
+
origin: string;
|
|
33
|
+
credentials: boolean;
|
|
34
|
+
} | null;
|
|
35
|
+
/** `Vary: Origin` once, however many times CORS is applied to the same response. */
|
|
36
|
+
export declare function varyOnOrigin(headers: Headers): void;
|
|
37
|
+
/** Core's CORS headers for a request's grant (corsGrant; null for none), written onto `headers`. */
|
|
38
|
+
export declare function setCorsHeaders(headers: Headers, grant: {
|
|
39
|
+
origin: string;
|
|
40
|
+
credentials: boolean;
|
|
41
|
+
} | null): void;
|
|
42
|
+
/**
|
|
43
|
+
* `response` with core's CORS for `request`. A response that already names an origin was answered by its
|
|
44
|
+
* route (addCorsHeaders, or a CORS policy of its own) and is returned as it is. A response with read-only
|
|
45
|
+
* headers is copied first.
|
|
46
|
+
*/
|
|
47
|
+
export declare function withCors<R extends Response>(response: R, request: Request): R;
|
|
48
|
+
/**
|
|
49
|
+
* A CORS preflight answered with the same grant the route's responses get. Routes export it as their
|
|
50
|
+
* `OPTIONS`: without one, Next.js answers OPTIONS itself, with no CORS headers.
|
|
51
|
+
*/
|
|
52
|
+
export declare function corsPreflight(request: Request): NextResponse;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=cors-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors-response.d.ts","sourceRoot":"","sources":["../../../src/lib/api/cors-response.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG/D,KAAK,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAA;AAEhD,eAAO,MAAM,kBAAkB,2CAA2C,CAAA;AAC1E,eAAO,MAAM,kBAAkB,QAAuF,CAAA;AAKtH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,sEAAsE;AACtE,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAKrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAYjD;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGnD;AAED,oGAAoG;AACpG,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,GACrD,IAAI,CAWN;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAa7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAE5D"}
|