@nextsparkjs/core 0.1.0-beta.193 → 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/README.md +2 -2
- 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/permissions.d.ts +10 -0
- package/dist/lib/api/auth/permissions.d.ts.map +1 -1
- package/dist/lib/api/auth/permissions.js +7 -0
- 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 +17 -38
- package/dist/lib/api/request-origin.d.ts +35 -0
- package/dist/lib/api/request-origin.d.ts.map +1 -0
- package/dist/lib/api/request-origin.js +69 -0
- 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 +15 -14
- 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 +5 -5
- 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/lib/services/subscription.service.d.ts.map +1 -1
- package/dist/lib/services/subscription.service.js +3 -0
- package/dist/lib/utils/cors.d.ts +7 -0
- package/dist/lib/utils/cors.d.ts.map +1 -1
- package/dist/lib/utils/cors.js +8 -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]/meta/[key]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/meta/[key]/route.js +13 -0
- package/dist/routes/api/v1/users/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/route.js +20 -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/projects/blog/package.json +3 -3
- package/dist/templates/projects/crm/package.json +3 -3
- package/dist/templates/projects/productivity/package.json +3 -3
- package/dist/templates/proxy.ts +12 -1
- package/dist/templates/public/favicon.ico +0 -0
- package/package.json +8 -5
- package/scripts/build/auth-readiness.mjs +4 -0
- 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__/build-output.test.mjs +1 -1
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +3 -0
- package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
- 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/__tests__/write-places.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
- package/scripts/build/registry/contracts/render.mjs +3 -3
- 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 +27 -3
- package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +9 -9
- 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-mode.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-plan.test.mjs +12 -2
- package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
- package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +65 -2
- package/scripts/build/registry/host/entity-routes.mjs +9 -3
- package/scripts/build/registry/host/facade-emitter.mjs +2 -2
- package/scripts/build/registry/host/generation.mjs +54 -0
- package/scripts/build/registry/host/next-route-exports.json +2 -2
- package/scripts/build/registry/host/prepare.mjs +3 -0
- package/scripts/build/registry/host/static-imports.mjs +4 -0
- package/scripts/build/routes-manifest.mjs +13 -1
- package/scripts/db/migration-time-limit.mjs +216 -34
- package/scripts/db/run-migrations.mjs +11 -179
- package/scripts/db/ssl-config.mjs +12 -1
- package/scripts/db/verify-theme-migrations.mjs +1 -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/projects/blog/package.json +3 -3
- package/templates/projects/crm/package.json +3 -3
- package/templates/projects/productivity/package.json +3 -3
- package/templates/proxy.ts +12 -1
- package/templates/public/favicon.ico +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relation-display.d.ts","sourceRoot":"","sources":["../../../src/components/ui/relation-display.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relation-display.d.ts","sourceRoot":"","sources":["../../../src/components/ui/relation-display.tsx"],"names":[],"mappings":"AAOA,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAGD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,QAAgB,EAChB,MAAM,EACP,EAAE,oBAAoB,2CAgJtB"}
|
|
@@ -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) {
|
|
@@ -27,4 +27,14 @@ export declare function isSuperAdmin(authResult: DualAuthResult): boolean;
|
|
|
27
27
|
* @returns true si tiene permisos de admin
|
|
28
28
|
*/
|
|
29
29
|
export declare function hasAdminPermission(authResult: DualAuthResult, requiredScope?: string | string[]): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the caller may read or edit the user `target` (an id or an email, as
|
|
32
|
+
* the /users/:id routes accept both): the user themselves, or a superadmin.
|
|
33
|
+
* An API key is its owner, so it gets the same answer, but a superadmin key
|
|
34
|
+
* must also carry `requiredScope`.
|
|
35
|
+
*
|
|
36
|
+
* Application-layer check: row-level security does not cover a deployment that
|
|
37
|
+
* has not cut over to the non-owner runtime role.
|
|
38
|
+
*/
|
|
39
|
+
export declare function canAccessUser(authResult: DualAuthResult, target: string, requiredScope?: string | string[]): boolean;
|
|
30
40
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAOhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAYT"}
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/auth/permissions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAOhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAYT;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAChC,OAAO,CAOT"}
|
|
@@ -14,7 +14,14 @@ function hasAdminPermission(authResult, requiredScope) {
|
|
|
14
14
|
}
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
|
+
function canAccessUser(authResult, target, requiredScope) {
|
|
18
|
+
if (!authResult.success || !authResult.user) return false;
|
|
19
|
+
if (hasAdminPermission(authResult, requiredScope)) return true;
|
|
20
|
+
const { id, email } = authResult.user;
|
|
21
|
+
return target === id || !!email && target === email;
|
|
22
|
+
}
|
|
17
23
|
export {
|
|
24
|
+
canAccessUser,
|
|
18
25
|
hasAdminPermission,
|
|
19
26
|
isSuperAdmin
|
|
20
27
|
};
|
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
|
+
};
|