@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
|
@@ -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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { APP_CONFIG_MERGED } from "../config/index.js";
|
|
3
|
+
import { getCorsOrigins, getTrustedOrigins, isOriginAllowed, normalizeOrigin } from "../utils/cors.js";
|
|
4
|
+
import { CLIENT_REQUEST_HEADERS } from "./client-headers.js";
|
|
5
|
+
const CORS_ALLOW_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
|
|
6
|
+
const CORS_ALLOW_HEADERS = ["Content-Type", "Authorization", "X-API-Key", ...CLIENT_REQUEST_HEADERS].join(", ");
|
|
7
|
+
const APP_ONLY_PATH = /(^|\/)api\/(v1\/)?(superadmin|devtools)(\/|$)/;
|
|
8
|
+
function isAppOnlyCorsPath(pathname) {
|
|
9
|
+
let path = pathname;
|
|
10
|
+
try {
|
|
11
|
+
path = decodeURIComponent(pathname);
|
|
12
|
+
} catch {
|
|
13
|
+
}
|
|
14
|
+
return APP_ONLY_PATH.test(path.toLowerCase().replace(/\/{2,}/g, "/"));
|
|
15
|
+
}
|
|
16
|
+
function requestPathname(request) {
|
|
17
|
+
try {
|
|
18
|
+
return new URL(request.url).pathname;
|
|
19
|
+
} catch {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function appOrigins() {
|
|
24
|
+
return [process.env.NEXT_PUBLIC_APP_URL, process.env.BETTER_AUTH_URL].flatMap((url) => {
|
|
25
|
+
if (!url) return [];
|
|
26
|
+
try {
|
|
27
|
+
return [new URL(url).origin];
|
|
28
|
+
} catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function corsGrant(origin, config, env, pathname) {
|
|
34
|
+
const normalizedOrigin = normalizeOrigin(origin);
|
|
35
|
+
if (pathname !== void 0 && isAppOnlyCorsPath(pathname)) {
|
|
36
|
+
return appOrigins().includes(normalizedOrigin) ? { origin: normalizedOrigin, credentials: true } : null;
|
|
37
|
+
}
|
|
38
|
+
const listed = isOriginAllowed(normalizedOrigin, getCorsOrigins(config, env));
|
|
39
|
+
if (listed) return { origin: listed, credentials: true };
|
|
40
|
+
if (env === "development" && config.api.cors.allowAllOrigins.development) {
|
|
41
|
+
const trusted = isOriginAllowed(normalizedOrigin, getTrustedOrigins(config, normalizedOrigin, env));
|
|
42
|
+
return { origin: normalizedOrigin, credentials: trusted !== null };
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
function varyOnOrigin(headers) {
|
|
47
|
+
const vary = headers.get("vary") ?? "";
|
|
48
|
+
if (!vary.split(",").some((value) => value.trim().toLowerCase() === "origin")) headers.set("Vary", vary ? `${vary}, Origin` : "Origin");
|
|
49
|
+
}
|
|
50
|
+
function setCorsHeaders(headers, grant) {
|
|
51
|
+
if (grant) {
|
|
52
|
+
headers.set("Access-Control-Allow-Origin", grant.origin);
|
|
53
|
+
if (grant.credentials) headers.set("Access-Control-Allow-Credentials", "true");
|
|
54
|
+
}
|
|
55
|
+
varyOnOrigin(headers);
|
|
56
|
+
headers.set("Access-Control-Allow-Methods", CORS_ALLOW_METHODS);
|
|
57
|
+
headers.set("Access-Control-Allow-Headers", CORS_ALLOW_HEADERS);
|
|
58
|
+
headers.set("Access-Control-Max-Age", "86400");
|
|
59
|
+
}
|
|
60
|
+
function withCors(response, request) {
|
|
61
|
+
if (response.headers.has("access-control-allow-origin")) return response;
|
|
62
|
+
const origin = request.headers.get("origin");
|
|
63
|
+
const env = process.env.NODE_ENV || "development";
|
|
64
|
+
const grant = origin ? corsGrant(origin, APP_CONFIG_MERGED, env, requestPathname(request)) : null;
|
|
65
|
+
try {
|
|
66
|
+
setCorsHeaders(response.headers, grant);
|
|
67
|
+
return response;
|
|
68
|
+
} catch {
|
|
69
|
+
const copy = new Response(response.body, { status: response.status, statusText: response.statusText, headers: new Headers(response.headers) });
|
|
70
|
+
setCorsHeaders(copy.headers, grant);
|
|
71
|
+
return copy;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function corsPreflight(request) {
|
|
75
|
+
return withCors(new NextResponse(null, { status: 204 }), request);
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
CORS_ALLOW_HEADERS,
|
|
79
|
+
CORS_ALLOW_METHODS,
|
|
80
|
+
appOrigins,
|
|
81
|
+
corsGrant,
|
|
82
|
+
corsPreflight,
|
|
83
|
+
isAppOnlyCorsPath,
|
|
84
|
+
requestPathname,
|
|
85
|
+
setCorsHeaders,
|
|
86
|
+
varyOnOrigin,
|
|
87
|
+
withCors
|
|
88
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/lib/api/entities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/lib/api/entities.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api/entities.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getClientEntityApiPath, getClientEntityConfigs } from "../entities/client-entity-meta.js";
|
|
2
2
|
import { withBasePath, withBasePathIfInApp } from "../base-path.js";
|
|
3
|
+
import { BUILDER_SOURCE_HEADER, TEAM_ID_HEADER } from "./client-headers.js";
|
|
3
4
|
function getApiBaseUrl() {
|
|
4
5
|
if (typeof window !== "undefined") {
|
|
5
6
|
return window.location.origin;
|
|
@@ -20,7 +21,7 @@ function buildHeaders(additionalHeaders = {}) {
|
|
|
20
21
|
};
|
|
21
22
|
const teamId = getCurrentTeamId();
|
|
22
23
|
if (teamId) {
|
|
23
|
-
headers[
|
|
24
|
+
headers[TEAM_ID_HEADER] = teamId;
|
|
24
25
|
}
|
|
25
26
|
return headers;
|
|
26
27
|
}
|
|
@@ -418,7 +419,7 @@ class EntityApiClient {
|
|
|
418
419
|
delete copyData.createdAt;
|
|
419
420
|
delete copyData.updatedAt;
|
|
420
421
|
const hasBlocks = "blocks" in copyData && Array.isArray(copyData.blocks);
|
|
421
|
-
return this.create(entityType, copyData, hasBlocks ? {
|
|
422
|
+
return this.create(entityType, copyData, hasBlocks ? { [BUILDER_SOURCE_HEADER]: "true" } : {});
|
|
422
423
|
}
|
|
423
424
|
/**
|
|
424
425
|
* Detect if entity has custom override (client-side detection)
|
|
@@ -474,7 +475,7 @@ async function fetchWithTeam(url, options = {}) {
|
|
|
474
475
|
headers.set("Content-Type", "application/json");
|
|
475
476
|
}
|
|
476
477
|
if (activeTeamId) {
|
|
477
|
-
headers.set(
|
|
478
|
+
headers.set(TEAM_ID_HEADER, activeTeamId);
|
|
478
479
|
}
|
|
479
480
|
return fetch(withBasePathIfInApp(url), {
|
|
480
481
|
...options,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,GAAG,IAAI,EAC3B,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAqDf"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mutateWithRLS } from "../../db.js";
|
|
2
|
+
import { getRecordedClientIp } from "../client-ip.js";
|
|
2
3
|
async function logGenericHandlerUsage(auth, request, statusCode, responseTime) {
|
|
3
4
|
var _a;
|
|
4
5
|
const userId = (_a = auth == null ? void 0 : auth.user) == null ? void 0 : _a.id;
|
|
@@ -9,7 +10,7 @@ async function logGenericHandlerUsage(auth, request, statusCode, responseTime) {
|
|
|
9
10
|
try {
|
|
10
11
|
endpoint = request.nextUrl.pathname;
|
|
11
12
|
method = request.method;
|
|
12
|
-
const ipAddress =
|
|
13
|
+
const ipAddress = getRecordedClientIp(request.headers);
|
|
13
14
|
const userAgent = request.headers.get("user-agent");
|
|
14
15
|
await mutateWithRLS(
|
|
15
16
|
`INSERT INTO "api_audit_log"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA+wBvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEnF;AA8lBD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAErF;AAyaD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEpJ;AAoND;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AA6ZD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AAwKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtF"}
|
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import { authenticateRequest, createAuthFailureResponse, canBypassTeamContext } from "../auth/dual-auth.js";
|
|
3
3
|
import { resolveEntityFromUrl, validateEntityOperation } from "./resolver.js";
|
|
4
4
|
import { generateEntitySchemas } from "../../entities/schema-generator.js";
|
|
5
|
+
import { publicSlugIssue, otherBasePathSegments } from "../../entities/public-slug.js";
|
|
6
|
+
import { getAllEntityConfigs } from "../../entities/registry.js";
|
|
5
7
|
import { entityResponseSystemColumns, taxonomyResponseFields } from "../../entities/portable/response-shape.js";
|
|
6
8
|
import { queryWithRLS, mutateWithRLS, queryOneWithRLS } from "../../db.js";
|
|
7
9
|
import {
|
|
@@ -832,6 +834,10 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
832
834
|
return addCorsHeaders(response2, request);
|
|
833
835
|
}
|
|
834
836
|
let validatedData = validation.data;
|
|
837
|
+
const slugIssue = publicSlugIssue(entityConfig, validatedData, otherBasePathSegments(entityConfig, getAllEntityConfigs()));
|
|
838
|
+
if (slugIssue) {
|
|
839
|
+
return addCorsHeaders(createApiError(slugIssue.message, 400, [slugIssue], "VALIDATION_ERROR"), request);
|
|
840
|
+
}
|
|
835
841
|
const xssField = checkNameFieldXss(entityConfig, validatedData);
|
|
836
842
|
if (xssField) {
|
|
837
843
|
const xssResponse = createApiError(
|
|
@@ -1204,7 +1210,7 @@ async function handleGenericUpdate(request, { params }) {
|
|
|
1204
1210
|
return runWithAuditLog(request, (audit) => handleGenericUpdateImpl(request, audit, { params }));
|
|
1205
1211
|
}
|
|
1206
1212
|
async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
1207
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1213
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1208
1214
|
try {
|
|
1209
1215
|
const { id } = await params;
|
|
1210
1216
|
const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
|
|
@@ -1285,6 +1291,18 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1285
1291
|
return addCorsHeaders(response2, request);
|
|
1286
1292
|
}
|
|
1287
1293
|
let validatedData = validation.data;
|
|
1294
|
+
let slugIssue = publicSlugIssue(entityConfig, validatedData, otherBasePathSegments(entityConfig, getAllEntityConfigs()));
|
|
1295
|
+
if (slugIssue) {
|
|
1296
|
+
const current = await queryWithRLS(
|
|
1297
|
+
`SELECT "slug" FROM "${tableName}" WHERE id = $1 AND "teamId" = $2`,
|
|
1298
|
+
[id, teamId],
|
|
1299
|
+
authResult.user.id
|
|
1300
|
+
);
|
|
1301
|
+
if (((_d = current[0]) == null ? void 0 : _d.slug) === validatedData.slug) slugIssue = null;
|
|
1302
|
+
}
|
|
1303
|
+
if (slugIssue) {
|
|
1304
|
+
return addCorsHeaders(createApiError(slugIssue.message, 400, [slugIssue], "VALIDATION_ERROR"), request);
|
|
1305
|
+
}
|
|
1288
1306
|
const updateXssField = checkNameFieldXss(entityConfig, validatedData);
|
|
1289
1307
|
if (updateXssField) {
|
|
1290
1308
|
const updateXssResponse = createApiError(
|
|
@@ -1316,7 +1334,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1316
1334
|
const values = [];
|
|
1317
1335
|
let paramCount = 1;
|
|
1318
1336
|
const builderRequest = isBuilderRequest(request);
|
|
1319
|
-
const entityHasBuilder = ((
|
|
1337
|
+
const entityHasBuilder = ((_e = entityConfig.builder) == null ? void 0 : _e.enabled) === true;
|
|
1320
1338
|
if (builderRequest && entityHasBuilder && "blocks" in entityData) {
|
|
1321
1339
|
let blocksData = entityData.blocks;
|
|
1322
1340
|
blocksData = await filterOrphanedPatternReferences(blocksData, authResult.user.id);
|
|
@@ -1392,7 +1410,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1392
1410
|
whereConditions.push(`"teamId" = $${paramCount++}`);
|
|
1393
1411
|
values.push(teamId);
|
|
1394
1412
|
}
|
|
1395
|
-
if (!((
|
|
1413
|
+
if (!((_f = entityConfig.access) == null ? void 0 : _f.shared)) {
|
|
1396
1414
|
whereConditions.push(`"userId" = $${paramCount++}`);
|
|
1397
1415
|
values.push(authResult.user.id);
|
|
1398
1416
|
}
|
|
@@ -1436,7 +1454,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1436
1454
|
}
|
|
1437
1455
|
updatedItem = result[0];
|
|
1438
1456
|
}
|
|
1439
|
-
if ((
|
|
1457
|
+
if ((_g = entityConfig.taxonomies) == null ? void 0 : _g.enabled) {
|
|
1440
1458
|
await processTaxonomyRelations(entityConfig, id, body, authResult.user.id, true);
|
|
1441
1459
|
}
|
|
1442
1460
|
if (metadataWasProvided) {
|
|
@@ -1448,7 +1466,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1448
1466
|
);
|
|
1449
1467
|
}
|
|
1450
1468
|
let responseItem = updatedItem;
|
|
1451
|
-
if ((
|
|
1469
|
+
if ((_h = entityConfig.taxonomies) == null ? void 0 : _h.enabled) {
|
|
1452
1470
|
const itemsWithTaxonomies = await includeTaxonomiesInData(
|
|
1453
1471
|
entityConfig,
|
|
1454
1472
|
[updatedItem],
|
|
@@ -46,7 +46,9 @@ export declare function validateAndAuthenticateApiRequest(request: NextRequest):
|
|
|
46
46
|
rateLimitResponse?: NextResponse;
|
|
47
47
|
}>;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
49
|
+
* The API key this request was authenticated with: the one validateApiKey accepted for it (directly, or through
|
|
50
|
+
* authenticateRequest / validateAndAuthenticateRequest). Throws when no key was validated for the request.
|
|
51
|
+
* Identity never comes from request headers.
|
|
50
52
|
* @deprecated Use validateAndAuthenticateApiRequest instead
|
|
51
53
|
*/
|
|
52
54
|
export declare function getApiAuth(request: NextRequest): ApiKeyAuth;
|
|
@@ -106,6 +108,10 @@ export declare function createPaginationMeta(page: number, limit: number, total:
|
|
|
106
108
|
export declare function logApiUsage(auth: ApiKeyAuth, request: NextRequest, statusCode: number, responseTime?: number, requestBody?: unknown): Promise<void>;
|
|
107
109
|
/**
|
|
108
110
|
* Wrapper para endpoints que agrega logging automático
|
|
111
|
+
*
|
|
112
|
+
* Writes an api_audit_log row for a request authenticated with an API key, attributed to the key the handler
|
|
113
|
+
* validated (getValidatedApiKey), never to identity headers in the request. Requests without a validated key
|
|
114
|
+
* are not logged here. The request body is not stored, as in entity/audit-log.ts: payloads carry personal data.
|
|
109
115
|
*/
|
|
110
116
|
export declare function withApiLogging<T extends unknown[]>(handler: (request: NextRequest, ...args: T) => Promise<NextResponse>): (request: NextRequest, ...args: T) => Promise<NextResponse>;
|
|
111
117
|
/**
|
|
@@ -125,7 +131,7 @@ export declare function sanitizeSearchQuery(query: string): string;
|
|
|
125
131
|
export declare function parseFilters(request: NextRequest): Record<string, string>;
|
|
126
132
|
/**
|
|
127
133
|
* Agrega headers de CORS para API externa
|
|
128
|
-
* Uses unified getCorsOrigins() for single source of truth
|
|
134
|
+
* Uses unified getCorsOrigins() for single source of truth (see corsGrant)
|
|
129
135
|
*/
|
|
130
136
|
export declare function addCorsHeaders(response: NextResponse, request?: NextRequest): Promise<NextResponse>;
|
|
131
137
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api/helpers.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
-
import { validateApiKey } from "./auth.js";
|
|
2
|
+
import { getValidatedApiKey, validateApiKey } from "./auth.js";
|
|
3
3
|
import { mutateWithRLS, queryWithRLS } from "../db.js";
|
|
4
4
|
import { checkRateLimit, addRateLimitHeaders } from "./rate-limit.js";
|
|
5
|
+
import { getRecordedClientIp } from "./client-ip.js";
|
|
5
6
|
import { getApplicationConfig } from "../config/index.js";
|
|
6
7
|
import { auth } from "../auth.js";
|
|
7
8
|
import { MetaService } from "../services/meta.service.js";
|
|
8
9
|
import { ScopeService } from "../services/scope.service.js";
|
|
9
10
|
import { getChildEntities } from "../entities/queries.js";
|
|
10
|
-
import { getCorsOrigins
|
|
11
|
+
import { getCorsOrigins } from "../utils/cors.js";
|
|
12
|
+
import { corsGrant, requestPathname, setCorsHeaders, varyOnOrigin } from "./cors-response.js";
|
|
11
13
|
import { isValidUUID } from "../utils/uuid.js";
|
|
12
14
|
import {
|
|
13
15
|
describeRoute,
|
|
@@ -122,26 +124,11 @@ function applyApiKeyRateLimit(auth2) {
|
|
|
122
124
|
return { auth: auth2 };
|
|
123
125
|
}
|
|
124
126
|
function getApiAuth(request) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (!userId || !keyId || !scopesHeader) {
|
|
129
|
-
throw new Error("Missing API authentication headers");
|
|
130
|
-
}
|
|
131
|
-
let scopes = [];
|
|
132
|
-
try {
|
|
133
|
-
const parsed = JSON.parse(scopesHeader);
|
|
134
|
-
if (Array.isArray(parsed)) {
|
|
135
|
-
scopes = parsed.filter((s) => typeof s === "string");
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
console.warn("[API] Invalid scopes header format");
|
|
127
|
+
const auth2 = getValidatedApiKey(request);
|
|
128
|
+
if (!auth2) {
|
|
129
|
+
throw new Error("No validated API key for this request");
|
|
139
130
|
}
|
|
140
|
-
return
|
|
141
|
-
userId,
|
|
142
|
-
keyId,
|
|
143
|
-
scopes
|
|
144
|
-
};
|
|
131
|
+
return auth2;
|
|
145
132
|
}
|
|
146
133
|
function checkScope(auth2, requiredScope) {
|
|
147
134
|
if (!scopesSatisfy(auth2.scopes, requiredScope)) {
|
|
@@ -203,7 +190,7 @@ async function logApiUsage(auth2, request, statusCode, responseTime, requestBody
|
|
|
203
190
|
try {
|
|
204
191
|
const endpoint = request.nextUrl.pathname;
|
|
205
192
|
const method = request.method;
|
|
206
|
-
const ipAddress =
|
|
193
|
+
const ipAddress = getRecordedClientIp(request.headers);
|
|
207
194
|
const userAgent = request.headers.get("user-agent");
|
|
208
195
|
await mutateWithRLS(
|
|
209
196
|
`INSERT INTO "api_audit_log"
|
|
@@ -229,31 +216,18 @@ async function logApiUsage(auth2, request, statusCode, responseTime, requestBody
|
|
|
229
216
|
function withApiLogging(handler) {
|
|
230
217
|
return async (request, ...args) => {
|
|
231
218
|
const startTime = Date.now();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
try {
|
|
236
|
-
auth2 = getApiAuth(request);
|
|
237
|
-
} catch {
|
|
238
|
-
}
|
|
239
|
-
if (["POST", "PUT", "PATCH"].includes(request.method)) {
|
|
240
|
-
try {
|
|
241
|
-
const clonedRequest = request.clone();
|
|
242
|
-
requestBody = await clonedRequest.json();
|
|
243
|
-
} catch {
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
const response = await handler(request, ...args);
|
|
247
|
-
const responseTime = Date.now() - startTime;
|
|
219
|
+
const log = (status) => {
|
|
220
|
+
const auth2 = getValidatedApiKey(request);
|
|
248
221
|
if (auth2) {
|
|
249
|
-
logApiUsage(auth2, request,
|
|
222
|
+
logApiUsage(auth2, request, status, Date.now() - startTime).catch(console.error);
|
|
250
223
|
}
|
|
224
|
+
};
|
|
225
|
+
try {
|
|
226
|
+
const response = await handler(request, ...args);
|
|
227
|
+
log(response.status);
|
|
251
228
|
return response;
|
|
252
229
|
} catch (error) {
|
|
253
|
-
|
|
254
|
-
if (auth2) {
|
|
255
|
-
logApiUsage(auth2, request, 500, responseTime, requestBody).catch(console.error);
|
|
256
|
-
}
|
|
230
|
+
log(500);
|
|
257
231
|
throw error;
|
|
258
232
|
}
|
|
259
233
|
};
|
|
@@ -282,32 +256,15 @@ function getAllowedFiltersFromRegistry() {
|
|
|
282
256
|
async function addCorsHeaders(response, request) {
|
|
283
257
|
const env = process.env.NODE_ENV || "development";
|
|
284
258
|
const config = await getApplicationConfig();
|
|
285
|
-
|
|
286
|
-
let allowedOrigin = "null";
|
|
259
|
+
let grant = null;
|
|
287
260
|
if (request) {
|
|
288
261
|
const origin = request.headers.get("origin");
|
|
289
|
-
if (origin)
|
|
290
|
-
|
|
291
|
-
if (env === "development" && corsConfig.allowAllOrigins.development) {
|
|
292
|
-
allowedOrigin = normalizedOrigin;
|
|
293
|
-
} else {
|
|
294
|
-
const allowedOrigins = getCorsOrigins(config, env);
|
|
295
|
-
const matched = isOriginAllowed(normalizedOrigin, allowedOrigins);
|
|
296
|
-
if (matched) {
|
|
297
|
-
allowedOrigin = matched;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
} else if (env === "development" && corsConfig.allowAllOrigins.development) {
|
|
262
|
+
if (origin) grant = corsGrant(origin, config, env, requestPathname(request));
|
|
263
|
+
} else if (env === "development" && config.api.cors.allowAllOrigins.development) {
|
|
302
264
|
const allowedOrigins = getCorsOrigins(config, env);
|
|
303
|
-
|
|
265
|
+
grant = { origin: allowedOrigins[0] || "http://localhost:3000", credentials: true };
|
|
304
266
|
}
|
|
305
|
-
response.headers
|
|
306
|
-
response.headers.append("Vary", "Origin");
|
|
307
|
-
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
|
|
308
|
-
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key, x-team-id, x-builder-source");
|
|
309
|
-
response.headers.set("Access-Control-Allow-Credentials", "true");
|
|
310
|
-
response.headers.set("Access-Control-Max-Age", "86400");
|
|
267
|
+
setCorsHeaders(response.headers, grant);
|
|
311
268
|
return response;
|
|
312
269
|
}
|
|
313
270
|
async function handleCorsPreflightRequest(request) {
|
|
@@ -321,25 +278,14 @@ async function wrapAuthHandlerWithCors(handler, request) {
|
|
|
321
278
|
statusText: response.statusText,
|
|
322
279
|
headers: new Headers(response.headers)
|
|
323
280
|
});
|
|
324
|
-
const env = process.env.NODE_ENV || "development";
|
|
325
|
-
const config = await getApplicationConfig();
|
|
326
|
-
const corsConfig = config.api.cors;
|
|
327
281
|
const origin = request.headers.get("origin");
|
|
328
282
|
if (origin) {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
} else {
|
|
334
|
-
const allowedOrigins = getCorsOrigins(config, env);
|
|
335
|
-
const matched = isOriginAllowed(normalizedOrigin, allowedOrigins);
|
|
336
|
-
if (matched) {
|
|
337
|
-
allowedOrigin = matched;
|
|
338
|
-
}
|
|
283
|
+
const grant = corsGrant(origin, await getApplicationConfig(), process.env.NODE_ENV || "development", requestPathname(request));
|
|
284
|
+
if (grant) {
|
|
285
|
+
newResponse.headers.set("Access-Control-Allow-Origin", grant.origin);
|
|
286
|
+
if (grant.credentials) newResponse.headers.set("Access-Control-Allow-Credentials", "true");
|
|
339
287
|
}
|
|
340
|
-
newResponse.headers
|
|
341
|
-
newResponse.headers.set("Access-Control-Allow-Credentials", "true");
|
|
342
|
-
newResponse.headers.append("Vary", "Origin");
|
|
288
|
+
varyOnOrigin(newResponse.headers);
|
|
343
289
|
}
|
|
344
290
|
return newResponse;
|
|
345
291
|
}
|
package/dist/lib/api/keys.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export declare class ApiKeyManager {
|
|
|
35
35
|
*/
|
|
36
36
|
static suggestKeyName(scopes: string[]): string;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The API key a request presents: the token of `Authorization: Bearer <token>`,
|
|
40
|
+
* else the `x-api-key` header. validateApiKey checks this value, and the
|
|
41
|
+
* cookie-write origin check (lib/api/request-origin) reads it too.
|
|
42
|
+
*/
|
|
43
|
+
export declare function presentedApiKey(headers: Headers): string | null;
|
|
38
44
|
/**
|
|
39
45
|
* Definición de scopes disponibles para API keys
|
|
40
46
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/lib/api/keys.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,aAAa;IACxB;;;OAGG;WACU,cAAc,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAyBrF;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAM9C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAKzC;;OAEG;WACU,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQlD;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE;IAUpF;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM;CAchD;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;CAgCb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,UAAU,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGrD;AAED,oFAAoF;AACpF,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxD;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;yBAIgC,QAAQ,EAAE;;;;;yBAKV,QAAQ,EAAE;;;;;yBAKV,QAAQ,EAAE;;;;;yBAKtB,QAAQ,EAAE;;;;;yBAKQ,QAAQ,EAAE;;;;;yBAKxD,QAAQ,EAAE;;CAErB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CASd,CAAC;AAEX;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAmB9F"}
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/lib/api/keys.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,aAAa;IACxB;;;OAGG;WACU,cAAc,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAyBrF;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAM9C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAKzC;;OAEG;WACU,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQlD;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE;IAUpF;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM;CAchD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI/D;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;CAgCb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,UAAU,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGrD;AAED,oFAAoF;AACpF,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxD;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;yBAIgC,QAAQ,EAAE;;;;;yBAKV,QAAQ,EAAE;;;;;yBAKV,QAAQ,EAAE;;;;;yBAKtB,QAAQ,EAAE;;;;;yBAKQ,QAAQ,EAAE;;;;;yBAKxD,QAAQ,EAAE;;CAErB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CASd,CAAC;AAEX;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAmB9F"}
|
package/dist/lib/api/keys.js
CHANGED
|
@@ -68,6 +68,11 @@ class ApiKeyManager {
|
|
|
68
68
|
return `${categoryNames} Access Key`;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
function presentedApiKey(headers) {
|
|
72
|
+
const authorization = headers.get("authorization");
|
|
73
|
+
if (authorization == null ? void 0 : authorization.startsWith("Bearer ")) return authorization.substring(7);
|
|
74
|
+
return headers.get("x-api-key") || null;
|
|
75
|
+
}
|
|
71
76
|
const API_SCOPES = {
|
|
72
77
|
// Usuarios
|
|
73
78
|
"users:read": "Read user information",
|
|
@@ -183,5 +188,6 @@ export {
|
|
|
183
188
|
SCOPE_CATEGORIES,
|
|
184
189
|
getApiScopes,
|
|
185
190
|
getAppApiScopes,
|
|
186
|
-
getRateLimitForScopes
|
|
191
|
+
getRateLimitForScopes,
|
|
192
|
+
presentedApiKey
|
|
187
193
|
};
|
|
@@ -47,6 +47,10 @@ export declare function applyRateLimit(request: NextRequest, keyId: string, scop
|
|
|
47
47
|
export declare function addRateLimitHeaders(response: NextResponse, keyId: string, scopes: string[]): NextResponse;
|
|
48
48
|
/**
|
|
49
49
|
* Middleware helper para aplicar rate limiting automáticamente
|
|
50
|
+
*
|
|
51
|
+
* Limits per API key, with the limits of the key's scopes, when the request presents a key that validates.
|
|
52
|
+
* The key id and scopes come from that validation, never from request headers; any other request runs the
|
|
53
|
+
* handler without this limit.
|
|
50
54
|
*/
|
|
51
55
|
export declare function withRateLimit<T extends unknown[]>(handler: (request: NextRequest, ...args: T) => Promise<NextResponse>): (request: NextRequest, ...args: T) => Promise<NextResponse>;
|
|
52
56
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/lib/api/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/lib/api/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMxD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAI7B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAa,EACpB,QAAQ,GAAE,MAAc,GACvB,eAAe,CAyCjB;AAED;;;GAGG;AACH,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,aAAqB,GAC1B,OAAO,CAAC,eAAe,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CpD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,eAAe,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAwB5G;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,GACf,YAAY,GAAG,IAAI,CAkCrB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,GACf,YAAY,CASd;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,EAC/C,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,IAEtD,SAAS,WAAW,EAAE,GAAG,MAAM,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CA2BvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,IAAI,CAaP;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGlD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,KAAK,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CASD;AAED;;GAEG;AACH,wBAAgB,sBAAsB;;;;;EAErC;AA4DD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,EACnD,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,EACpE,IAAI,GAAE,aAAqB,IAkCb,SAAS,WAAW,EAAE,GAAG,MAAM,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CAIvE"}
|