@nextsparkjs/core 0.1.0-beta.194 → 0.1.0-beta.196
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/app/guards/DeveloperGuard.d.ts +8 -1
- package/dist/components/app/guards/DeveloperGuard.d.ts.map +1 -1
- package/dist/components/app/guards/DeveloperGuard.js +2 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts +8 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts.map +1 -1
- package/dist/components/app/guards/SuperAdminGuard.js +2 -1
- package/dist/components/billing/InvoicesPagination.js +2 -2
- 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/dashboard/navigation/DynamicNavigation.js +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/settings/layouts/SettingsSidebar.d.ts.map +1 -1
- package/dist/components/settings/layouts/SettingsSidebar.js +0 -1
- package/dist/components/teams/CreateTeamButton.js +2 -2
- package/dist/components/teams/CreateTeamDialog.js +1 -1
- package/dist/components/teams/InviteMemberButton.js +3 -3
- package/dist/components/teams/InviteMemberDialog.js +1 -1
- package/dist/components/teams/TeamPendingInvitations.js +2 -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/api-error.d.ts +2 -0
- package/dist/lib/api/api-error.d.ts.map +1 -1
- package/dist/lib/api/api-error.js +3 -1
- package/dist/lib/api/auth/dual-auth.d.ts +2 -1
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +22 -4
- package/dist/lib/api/auth/scope-policy.d.ts +6 -3
- package/dist/lib/api/auth/scope-policy.d.ts.map +1 -1
- 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 +55 -0
- package/dist/lib/api/cors-response.d.ts.map +1 -0
- package/dist/lib/api/cors-response.js +90 -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 -8
- 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 +32 -103
- 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/permission-middleware.d.ts.map +1 -1
- package/dist/lib/api/permission-middleware.js +0 -2
- package/dist/lib/api/rate-limit.d.ts +12 -0
- package/dist/lib/api/rate-limit.d.ts.map +1 -1
- package/dist/lib/api/rate-limit.js +50 -43
- package/dist/lib/api/request-origin.d.ts +16 -7
- package/dist/lib/api/request-origin.d.ts.map +1 -1
- package/dist/lib/api/request-origin.js +43 -20
- package/dist/lib/auth/load-login-page.d.ts +10 -0
- package/dist/lib/auth/load-login-page.d.ts.map +1 -0
- package/dist/lib/auth/load-login-page.js +7 -0
- package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
- package/dist/lib/auth/runtime-readiness.js +4 -0
- package/dist/lib/auth/sample-accounts.d.ts +17 -0
- package/dist/lib/auth/sample-accounts.d.ts.map +1 -0
- package/dist/lib/auth/sample-accounts.js +22 -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 +13 -5
- package/dist/lib/cache/public-entity-cache.d.ts +21 -0
- package/dist/lib/cache/public-entity-cache.d.ts.map +1 -0
- package/dist/lib/cache/public-entity-cache.js +25 -0
- 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/entity-hooks.d.ts.map +1 -1
- package/dist/lib/entities/entity-hooks.js +4 -0
- package/dist/lib/entities/external-api-generator.d.ts.map +1 -1
- package/dist/lib/entities/external-api-generator.js +2 -4
- package/dist/lib/entities/public-slug.d.ts +46 -0
- package/dist/lib/entities/public-slug.d.ts.map +1 -0
- package/dist/lib/entities/public-slug.js +39 -0
- package/dist/lib/mcp/errors.d.ts +2 -0
- package/dist/lib/mcp/errors.d.ts.map +1 -1
- package/dist/lib/mcp/errors.js +3 -1
- package/dist/lib/mcp/index.d.ts +1 -1
- package/dist/lib/mcp/index.d.ts.map +1 -1
- package/dist/lib/mcp/index.js +2 -1
- package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.js +2 -0
- package/dist/lib/teams/actions.d.ts.map +1 -1
- package/dist/lib/teams/actions.js +0 -1
- package/dist/messages/de/billing.json +12 -1
- package/dist/messages/de/common.json +2 -0
- package/dist/messages/de/docs.json +1 -0
- package/dist/messages/de/features.json +16 -4
- package/dist/messages/de/home.json +5 -0
- package/dist/messages/de/index.d.ts +68 -25
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/de/index.js +2 -0
- package/dist/messages/de/index.ts +2 -0
- package/dist/messages/de/settings.json +1 -0
- package/dist/messages/de/teams.json +3 -18
- package/dist/messages/en/billing.json +1 -1
- package/dist/messages/en/common.json +2 -0
- package/dist/messages/en/docs.json +1 -0
- package/dist/messages/en/features.json +16 -4
- package/dist/messages/en/home.json +5 -0
- package/dist/messages/en/index.d.ts +58 -25
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/en/index.js +2 -0
- package/dist/messages/en/index.ts +2 -0
- package/dist/messages/en/settings.json +1 -0
- package/dist/messages/en/teams.json +3 -18
- package/dist/messages/es/billing.json +1 -1
- package/dist/messages/es/common.json +2 -0
- package/dist/messages/es/docs.json +1 -0
- package/dist/messages/es/features.json +16 -4
- package/dist/messages/es/home.json +5 -0
- package/dist/messages/es/index.d.ts +41 -8
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/es/index.js +2 -0
- package/dist/messages/es/index.ts +2 -0
- package/dist/messages/es/settings.json +1 -0
- package/dist/messages/es/teams.json +3 -0
- package/dist/messages/fr/billing.json +12 -1
- package/dist/messages/fr/common.json +2 -0
- package/dist/messages/fr/docs.json +1 -0
- package/dist/messages/fr/features.json +16 -4
- package/dist/messages/fr/home.json +5 -0
- package/dist/messages/fr/index.d.ts +68 -25
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/fr/index.js +2 -0
- package/dist/messages/fr/index.ts +2 -0
- package/dist/messages/fr/settings.json +1 -0
- package/dist/messages/fr/teams.json +3 -18
- package/dist/messages/it/billing.json +12 -1
- package/dist/messages/it/common.json +2 -0
- package/dist/messages/it/docs.json +1 -0
- package/dist/messages/it/features.json +16 -4
- package/dist/messages/it/home.json +5 -0
- package/dist/messages/it/index.d.ts +68 -25
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/it/index.js +2 -0
- package/dist/messages/it/index.ts +2 -0
- package/dist/messages/it/settings.json +1 -0
- package/dist/messages/it/teams.json +3 -18
- package/dist/messages/pt/billing.json +12 -1
- package/dist/messages/pt/common.json +2 -0
- package/dist/messages/pt/docs.json +1 -0
- package/dist/messages/pt/features.json +16 -4
- package/dist/messages/pt/home.json +5 -0
- package/dist/messages/pt/index.d.ts +68 -25
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/messages/pt/index.js +2 -0
- package/dist/messages/pt/index.ts +2 -0
- package/dist/messages/pt/settings.json +1 -0
- package/dist/messages/pt/teams.json +3 -18
- package/dist/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/dist/migrations/090_sample_data.sql +10 -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/entity-permission-layout.d.ts.map +1 -1
- package/dist/routes/_internal/entity-permission-layout.js +0 -7
- 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 +9 -1
- 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 +4 -1
- package/dist/routes/api/v1/media/upload/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/upload/route.js +12 -2
- 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.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/members/route.js +14 -12
- 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/teams/switch/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/switch/route.js +4 -1
- package/dist/routes/api/v1/users/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/route.js +3 -2
- package/dist/routes/api/v1/users/docs.md +34 -19
- package/dist/routes/api/v1/users/me/route.d.ts +6 -0
- package/dist/routes/api/v1/users/me/route.d.ts.map +1 -0
- package/dist/routes/api/v1/users/me/route.js +5 -0
- package/dist/routes/api/v1/users/presets.ts +2 -2
- package/dist/routes/dashboard/(main)/layout.cc.d.ts +4 -0
- package/dist/routes/dashboard/(main)/layout.cc.d.ts.map +1 -0
- package/dist/routes/dashboard/(main)/layout.cc.js +10 -0
- package/dist/routes/dashboard/(main)/layout.d.ts.map +1 -1
- package/dist/routes/dashboard/(main)/layout.js +3 -44
- package/dist/routes/dashboard/permission-denied/page.d.ts +1 -1
- package/dist/routes/dashboard/permission-denied/page.d.ts.map +1 -1
- package/dist/routes/dashboard/permission-denied/page.js +5 -1
- package/dist/routes/dashboard/settings/password/page.d.ts.map +1 -1
- package/dist/routes/dashboard/settings/password/page.js +10 -12
- package/dist/routes/devtools/config/page.js +1 -1
- package/dist/routes/devtools/layout.cc.d.ts.map +1 -1
- package/dist/routes/devtools/layout.cc.js +5 -1
- package/dist/routes/devtools/page.js +1 -1
- package/dist/routes/devtools/scheduled-actions/page.js +1 -1
- package/dist/routes/devtools/tests/[[...path]]/page.js +1 -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/ci-workflows/github/cypress-regression.yml +1 -1
- package/dist/templates/ci-workflows/github/cypress-smoke.yml +2 -1
- 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/starter/README.md +2 -0
- package/dist/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/dist/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/dist/templates/proxy.ts +27 -9
- package/dist/templates/public/favicon.ico +0 -0
- package/dist/templates/public/uploads/README.md +5 -94
- package/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/migrations/090_sample_data.sql +10 -0
- package/package.json +2 -2
- package/scripts/build/registry/__tests__/api-docs-colocated.test.mjs +3 -0
- package/scripts/build/registry/__tests__/billing-registry.test.mjs +50 -1
- package/scripts/build/registry/__tests__/block-registry.test.mjs +3 -0
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +3 -0
- package/scripts/build/registry/__tests__/quiet-console.mjs +17 -0
- package/scripts/build/registry/__tests__/safe-fs.test.mjs +3 -0
- package/scripts/build/registry/__tests__/team-roles.test.mjs +3 -0
- package/scripts/build/registry/discovery/permissions.test.mjs +3 -0
- package/scripts/build/registry/discovery/plugin-capabilities.mjs +2 -2
- package/scripts/build/registry/generators/billing-registry.mjs +7 -3
- package/scripts/build/registry/host/README.md +25 -1
- package/scripts/build/registry/host/__tests__/host-area-access.test.mjs +32 -0
- package/scripts/build/registry/host/__tests__/host-entities.test.mjs +32 -1
- package/scripts/build/registry/host/__tests__/host-plan.test.mjs +12 -2
- package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +72 -1
- package/scripts/build/registry/host/entity-routes.mjs +9 -3
- package/scripts/build/registry/host/proxy-areas.mjs +65 -2
- package/scripts/build/registry/host/static-imports.mjs +4 -0
- package/scripts/build/routes-manifest.mjs +13 -1
- package/scripts/db/run-migrations.mjs +30 -10
- package/scripts/db/sample-data.mjs +44 -0
- package/scripts/db/ssl-config.mjs +12 -1
- package/scripts/db/verify-theme-migrations.mjs +6 -0
- package/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/templates/ci-workflows/github/cypress-smoke.yml +2 -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/starter/README.md +2 -0
- package/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/templates/proxy.ts +27 -9
- package/templates/public/favicon.ico +0 -0
- package/templates/public/uploads/README.md +5 -94
- package/tests/jest/__mocks__/@nextsparkjs/registries/api-presets-registry.ts +2 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/mcp-registry.ts +2 -0
- package/dist/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/dist/templates/public/uploads/.gitignore +0 -6
- package/dist/templates/public/uploads/temp/.gitkeep +0 -1
- package/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/templates/public/uploads/.gitignore +0 -6
- package/templates/public/uploads/temp/.gitkeep +0 -1
|
@@ -2,6 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { migrationTimeLimit, migrationClient, ignoredParametersNotice, runAndRecordMigration, migrationFailure } from './migration-time-limit.mjs';
|
|
4
4
|
import { getConfig } from '../build/registry/config.mjs';
|
|
5
|
+
import { isSampleDataMigration, sampleDataPolicy } from './sample-data.mjs';
|
|
5
6
|
|
|
6
7
|
const projectConfig = getConfig();
|
|
7
8
|
const projectRoot = projectConfig.projectRoot;
|
|
@@ -21,6 +22,8 @@ let DATABASE_URL = process.env.DATABASE_URL ?? null;
|
|
|
21
22
|
// Falls back to DATABASE_URL when unset (pre-cutover: same owner connection).
|
|
22
23
|
let MIGRATE_DATABASE_URL = process.env.MIGRATE_DATABASE_URL ?? null;
|
|
23
24
|
let MIGRATION_TIMEOUT_SECONDS = process.env.MIGRATION_TIMEOUT_SECONDS;
|
|
25
|
+
// What the .env says about NODE_ENV and the sample-data switch (see sample-data.mjs)
|
|
26
|
+
const fileEnv = {};
|
|
24
27
|
|
|
25
28
|
if (readEnvFile && fs.existsSync(envPath)) {
|
|
26
29
|
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
@@ -40,6 +43,11 @@ if (readEnvFile && fs.existsSync(envPath)) {
|
|
|
40
43
|
if (key?.trim() === 'MIGRATION_TIMEOUT_SECONDS' && valueParts.length > 0) {
|
|
41
44
|
MIGRATION_TIMEOUT_SECONDS = value;
|
|
42
45
|
}
|
|
46
|
+
// `export NODE_ENV=...` counts too; sample-data.mjs reads the value itself (case, trailing comment)
|
|
47
|
+
const name = key?.trim().replace(/^export\s+/, '');
|
|
48
|
+
if (['NODE_ENV', 'NEXTSPARK_SEED_SAMPLE_DATA'].includes(name) && valueParts.length > 0) {
|
|
49
|
+
fileEnv[name] = value;
|
|
50
|
+
}
|
|
43
51
|
}
|
|
44
52
|
});
|
|
45
53
|
}
|
|
@@ -65,12 +73,20 @@ try {
|
|
|
65
73
|
const ignoredParameters = ignoredParametersNotice(MIGRATION_URL, TIME_LIMIT);
|
|
66
74
|
if (ignoredParameters) console.log(`⚠️ ${ignoredParameters}\n`);
|
|
67
75
|
|
|
76
|
+
const SAMPLE_DATA = sampleDataPolicy({ argv: process.argv, env: process.env, fileEnv });
|
|
77
|
+
|
|
68
78
|
async function runMigrations() {
|
|
69
79
|
const client = migrationClient(MIGRATION_URL, TIME_LIMIT);
|
|
70
80
|
|
|
71
81
|
try {
|
|
72
82
|
await client.connect();
|
|
73
83
|
console.log("✅ Connected to database\n");
|
|
84
|
+
|
|
85
|
+
// 029_sample_accounts_outside_development.sql reads it: a run that applies sample data keeps the sample accounts
|
|
86
|
+
await client.query("SELECT set_config('nextspark.seed_sample_data', $1, false)", [SAMPLE_DATA.apply ? 'on' : 'off']);
|
|
87
|
+
client.on('notice', notice => {
|
|
88
|
+
if (notice.message?.startsWith('Sample accounts:')) console.log(`🔐 ${notice.message}`);
|
|
89
|
+
});
|
|
74
90
|
|
|
75
91
|
// Create migrations tracking table
|
|
76
92
|
await client.query(`
|
|
@@ -101,9 +117,14 @@ async function runMigrations() {
|
|
|
101
117
|
continue;
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
|
|
121
|
+
if (!SAMPLE_DATA.apply && isSampleDataMigration(file, sql)) {
|
|
122
|
+
console.log(`⏭️ Skipping ${file} (sample data)`);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
104
126
|
// Read and execute migration
|
|
105
127
|
console.log(`🔄 Running ${file}...`);
|
|
106
|
-
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
|
|
107
128
|
|
|
108
129
|
try {
|
|
109
130
|
// Runs the file and records it in one transaction (see runAndRecordMigration)
|
|
@@ -141,11 +162,6 @@ async function getActivePlugins() {
|
|
|
141
162
|
return projectConfig.plugins;
|
|
142
163
|
}
|
|
143
164
|
|
|
144
|
-
// Helper: Check if a filename is a sample_data migration
|
|
145
|
-
function isSampleDataMigration(filename) {
|
|
146
|
-
return filename.toLowerCase().includes('sample_data') || filename.toLowerCase().includes('sample-data');
|
|
147
|
-
}
|
|
148
|
-
|
|
149
165
|
// Helper: Collect all migration files from a directory (theme/plugin level)
|
|
150
166
|
function collectContentMigrations(migrationsPath, sourceType, sourceName) {
|
|
151
167
|
if (!fs.existsSync(migrationsPath)) return [];
|
|
@@ -160,7 +176,7 @@ function collectContentMigrations(migrationsPath, sourceType, sourceName) {
|
|
|
160
176
|
sourceName,
|
|
161
177
|
filename: file,
|
|
162
178
|
fullPath: path.join(migrationsPath, file),
|
|
163
|
-
isSampleData: isSampleDataMigration(file)
|
|
179
|
+
isSampleData: isSampleDataMigration(file, fs.readFileSync(path.join(migrationsPath, file), 'utf8'))
|
|
164
180
|
}));
|
|
165
181
|
}
|
|
166
182
|
|
|
@@ -193,7 +209,7 @@ function collectEntityMigrations(baseDir, sourceType, sourceName, depth = 0) {
|
|
|
193
209
|
entityName,
|
|
194
210
|
filename: file,
|
|
195
211
|
fullPath: path.join(migrationsPath, file),
|
|
196
|
-
isSampleData: isSampleDataMigration(file),
|
|
212
|
+
isSampleData: isSampleDataMigration(file, fs.readFileSync(path.join(migrationsPath, file), 'utf8')),
|
|
197
213
|
depth
|
|
198
214
|
});
|
|
199
215
|
}
|
|
@@ -415,15 +431,18 @@ async function runEntityMigrations() {
|
|
|
415
431
|
const sortByFilename = (a, b) => a.filename.localeCompare(b.filename);
|
|
416
432
|
|
|
417
433
|
const contentSchema = allContentMigrations.filter(m => !m.isSampleData).sort(sortByFilename);
|
|
418
|
-
const contentSampleData = allContentMigrations.filter(m => m.isSampleData).sort(sortByFilename);
|
|
434
|
+
const contentSampleData = allContentMigrations.filter(m => m.isSampleData && SAMPLE_DATA.apply).sort(sortByFilename);
|
|
419
435
|
const entitySchema = allEntityMigrations.filter(m => !m.isSampleData).sort(sortByFilename);
|
|
420
|
-
const entitySampleData = allEntityMigrations.filter(m => m.isSampleData).sort(sortByFilename);
|
|
436
|
+
const entitySampleData = allEntityMigrations.filter(m => m.isSampleData && SAMPLE_DATA.apply).sort(sortByFilename);
|
|
421
437
|
|
|
422
438
|
console.log(`📊 Migration breakdown:`);
|
|
423
439
|
console.log(` - Content schema: ${contentSchema.length}`);
|
|
424
440
|
console.log(` - Content sample_data: ${contentSampleData.length}`);
|
|
425
441
|
console.log(` - Entity schema: ${entitySchema.length}`);
|
|
426
442
|
console.log(` - Entity sample_data: ${entitySampleData.length}`);
|
|
443
|
+
for (const m of [...allContentMigrations, ...allEntityMigrations].filter(m => m.isSampleData && !SAMPLE_DATA.apply)) {
|
|
444
|
+
console.log(`⏭️ Skipping ${m.filename} (sample data, ${m.sourceName})`);
|
|
445
|
+
}
|
|
427
446
|
console.log('');
|
|
428
447
|
|
|
429
448
|
let totalContentMigrations = 0;
|
|
@@ -550,6 +569,7 @@ async function runEntityMigrations() {
|
|
|
550
569
|
// Main migration runner
|
|
551
570
|
async function runAllMigrations() {
|
|
552
571
|
console.log("🚀 Starting migration process...\n");
|
|
572
|
+
console.log(`🌱 ${SAMPLE_DATA.notice}\n`);
|
|
553
573
|
|
|
554
574
|
// First run core migrations
|
|
555
575
|
console.log("📋 PHASE 1: Core migrations");
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Which migrations are sample data, and whether a db:migrate run applies them.
|
|
2
|
+
//
|
|
3
|
+
// Sample data is applied only when the run asks for it -- `--sample-data`
|
|
4
|
+
// (what `nextspark db:seed` passes) or NEXTSPARK_SEED_SAMPLE_DATA=1, in the
|
|
5
|
+
// environment or the project .env -- and never when NODE_ENV is production in
|
|
6
|
+
// either: its accounts have a documented development password. A sample-data
|
|
7
|
+
// file that is not applied is not recorded either, so a later run that asks
|
|
8
|
+
// for it still applies it.
|
|
9
|
+
|
|
10
|
+
export const SAMPLE_DATA_FLAG = '--sample-data';
|
|
11
|
+
export const SAMPLE_DATA_VARIABLE = 'NEXTSPARK_SEED_SAMPLE_DATA';
|
|
12
|
+
/** A line that marks a migration as sample data when its name does not say so. */
|
|
13
|
+
export const SAMPLE_DATA_MARKER = '-- nextspark:sample-data';
|
|
14
|
+
|
|
15
|
+
// A value as a .env or a shell may write it: any case, quotes, a trailing comment.
|
|
16
|
+
const isProduction = value => /^\s*["']?production\b/i.test(String(value ?? ''));
|
|
17
|
+
const isOn = value => /^\s*["']?(1|true)\b/i.test(String(value ?? ''));
|
|
18
|
+
|
|
19
|
+
// Copies made before the name rule and the marker existed (the default theme's
|
|
20
|
+
// 090_demo_users_teams.sql and 091_greek_teams_billing.sql, up to 0.1.0-beta.191)
|
|
21
|
+
// are recognised by what they insert: a credential with a sample password. The
|
|
22
|
+
// salts are those of migrations/029_*.sql, which has them but inserts nothing.
|
|
23
|
+
const SAMPLE_PASSWORD_SALTS = ['22de14d5472248ed0bece911df908b2a:', '3db9e98e2b4d3caca97fdf2783791cbc:'];
|
|
24
|
+
const insertsSamplePassword = sql => /insert\s+into\s+(?:"?public"?\s*\.\s*)?"?account\b/i.test(sql) && SAMPLE_PASSWORD_SALTS.some(salt => sql.includes(salt));
|
|
25
|
+
|
|
26
|
+
export function isSampleDataMigration(filename, sql = '') {
|
|
27
|
+
const name = filename.toLowerCase();
|
|
28
|
+
return name.includes('sample_data') || name.includes('sample-data') || sql.split('\n').some(line => line.trim() === SAMPLE_DATA_MARKER) || insertsSamplePassword(sql);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `env` is the process environment, `fileEnv` what the project .env sets.
|
|
33
|
+
* Returns whether sample data is applied and the line the runner prints about it.
|
|
34
|
+
*/
|
|
35
|
+
export function sampleDataPolicy({ argv = [], env = {}, fileEnv = {} }) {
|
|
36
|
+
const requested = argv.includes(SAMPLE_DATA_FLAG) || [env[SAMPLE_DATA_VARIABLE], fileEnv[SAMPLE_DATA_VARIABLE]].some(isOn);
|
|
37
|
+
if ([env.NODE_ENV, fileEnv.NODE_ENV].some(isProduction)) {
|
|
38
|
+
return { apply: false, notice: `Sample data is not applied: NODE_ENV is production${requested ? ', which the sample-data switch does not override' : ''}.` };
|
|
39
|
+
}
|
|
40
|
+
if (requested) {
|
|
41
|
+
return { apply: true, notice: 'Sample data is applied (development). Its accounts share a documented password: use this only on a local database, and never use a database seeded this way in production (its sample accounts are kept, and later migrations do not disable them).' };
|
|
42
|
+
}
|
|
43
|
+
return { apply: false, notice: `Sample data is not applied. For a local development database, run \`pnpm db:seed\` (or pass ${SAMPLE_DATA_FLAG}, or set ${SAMPLE_DATA_VARIABLE}=1).` };
|
|
44
|
+
}
|
|
@@ -29,6 +29,17 @@ export function stripSSLParams(databaseUrl) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// On globalThis, like src/lib/db.ts: one warning per process however many copies of the module are loaded
|
|
33
|
+
const SSL_WARNED = Symbol.for('nextspark.dbSslDisabledWarned')
|
|
34
|
+
|
|
35
|
+
/** Once per process, and not for a loopback host: mirrors `warnSSLDisabledInProduction` in src/lib/db.ts. */
|
|
36
|
+
function warnSSLDisabledInProduction(url) {
|
|
37
|
+
if (globalThis[SSL_WARNED]) return
|
|
38
|
+
if (['localhost', '127.0.0.1', '[::1]'].includes(url.hostname.toLowerCase())) return
|
|
39
|
+
globalThis[SSL_WARNED] = true
|
|
40
|
+
console.warn('[DB] WARNING: SSL disabled in production environment. This is insecure!')
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
/**
|
|
33
44
|
* Parse the SSL policy used by database scripts.
|
|
34
45
|
*
|
|
@@ -47,7 +58,7 @@ export function parseSSLConfig(databaseUrl) {
|
|
|
47
58
|
if (sslmode) {
|
|
48
59
|
switch (sslmode) {
|
|
49
60
|
case 'disable':
|
|
50
|
-
if (isProduction)
|
|
61
|
+
if (isProduction) warnSSLDisabledInProduction(url)
|
|
51
62
|
return false
|
|
52
63
|
case 'require':
|
|
53
64
|
case 'prefer':
|
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
// `pnpm db:migrate` uses. Templates are first extracted into a clean temporary
|
|
29
29
|
// root-first project; apps/dev already is one. No .env is read or written.
|
|
30
30
|
//
|
|
31
|
+
// The run applies the theme's sample data (the database is empty and
|
|
32
|
+
// throwaway), so NODE_ENV is development for it whatever the shell says.
|
|
33
|
+
//
|
|
31
34
|
// MIGRATE_DATABASE_URL is removed from the child's environment because
|
|
32
35
|
// run-migrations.mjs connects to it in preference to DATABASE_URL, which
|
|
33
36
|
// would migrate a database this script never checked.
|
|
@@ -46,6 +49,7 @@ import { GLOBAL_OBJECTS, inspectCluster } from './cluster-changes.mjs';
|
|
|
46
49
|
import { inspectTarget, inspectMaintenanceDatabase } from './inspect-server.mjs';
|
|
47
50
|
import { findTheme } from './theme-location.mjs';
|
|
48
51
|
import { TIME_LIMIT_VARIABLE, migrationTimeLimit } from './migration-time-limit.mjs';
|
|
52
|
+
import { SAMPLE_DATA_VARIABLE } from './sample-data.mjs';
|
|
49
53
|
|
|
50
54
|
const __filename = fileURLToPath(import.meta.url);
|
|
51
55
|
const __dirname = path.dirname(__filename);
|
|
@@ -164,6 +168,8 @@ async function main() {
|
|
|
164
168
|
...inheritedEnv,
|
|
165
169
|
DATABASE_URL: databaseUrl,
|
|
166
170
|
[TIME_LIMIT_VARIABLE]: timeLimitSetting,
|
|
171
|
+
[SAMPLE_DATA_VARIABLE]: '1',
|
|
172
|
+
NODE_ENV: 'development',
|
|
167
173
|
},
|
|
168
174
|
});
|
|
169
175
|
if (extracted) fs.rmSync(extracted, { recursive: true, force: true });
|
|
@@ -59,7 +59,8 @@ jobs:
|
|
|
59
59
|
- name: Setup database
|
|
60
60
|
env:
|
|
61
61
|
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
|
|
62
|
-
|
|
62
|
+
# a throwaway test database: migrations plus the sample users the tests sign in as
|
|
63
|
+
run: pnpm db:seed
|
|
63
64
|
|
|
64
65
|
- name: Build application
|
|
65
66
|
run: pnpm build
|
|
@@ -260,35 +260,8 @@ const nextConfig = {
|
|
|
260
260
|
source: '/:path*',
|
|
261
261
|
headers: securityHeaders
|
|
262
262
|
},
|
|
263
|
-
// CORS headers
|
|
264
|
-
//
|
|
265
|
-
// to support multiple origins (web app, mobile app, etc.)
|
|
266
|
-
// In production, we set static CORS headers here
|
|
267
|
-
...(isProduction ? [{
|
|
268
|
-
source: '/api/:path*',
|
|
269
|
-
headers: [
|
|
270
|
-
{
|
|
271
|
-
key: 'Access-Control-Allow-Origin',
|
|
272
|
-
value: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
key: 'Access-Control-Allow-Methods',
|
|
276
|
-
value: 'GET, POST, PUT, DELETE, OPTIONS, PATCH'
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
key: 'Access-Control-Allow-Headers',
|
|
280
|
-
value: 'Content-Type, Authorization, x-api-key, x-verify-from-ui, Cookie, Set-Cookie'
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
key: 'Access-Control-Allow-Credentials',
|
|
284
|
-
value: 'true'
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
key: 'Access-Control-Expose-Headers',
|
|
288
|
-
value: 'Set-Cookie'
|
|
289
|
-
}
|
|
290
|
-
]
|
|
291
|
-
}] : [])
|
|
263
|
+
// No CORS headers here: core's API routes answer CORS per request (addCorsHeaders), so the
|
|
264
|
+
// origins in api.cors.allowedOrigins and CORS_ADDITIONAL_ORIGINS get their grant in production too
|
|
292
265
|
]
|
|
293
266
|
},
|
|
294
267
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { NextRequest, NextResponse } from 'next/server'
|
|
11
11
|
import { queryWithRLS } from '@nextsparkjs/core/lib/db'
|
|
12
12
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
13
|
+
import { corsPreflight } from '@nextsparkjs/core/lib/api/cors-response'
|
|
13
14
|
|
|
14
15
|
interface Author {
|
|
15
16
|
id: string
|
|
@@ -151,3 +152,5 @@ const getHandler = async (
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
export const GET = withRateLimitTier(getHandler, 'read')
|
|
155
|
+
|
|
156
|
+
export const OPTIONS = corsPreflight
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { NextRequest, NextResponse } from 'next/server'
|
|
11
11
|
import { queryWithRLS } from '@nextsparkjs/core/lib/db'
|
|
12
12
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
13
|
+
import { corsPreflight } from '@nextsparkjs/core/lib/api/cors-response'
|
|
13
14
|
|
|
14
15
|
interface AuthorWithCount {
|
|
15
16
|
id: string
|
|
@@ -64,3 +65,5 @@ const getHandler = async (request: NextRequest) => {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export const GET = withRateLimitTier(getHandler, 'read')
|
|
68
|
+
|
|
69
|
+
export const OPTIONS = corsPreflight
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { NextRequest, NextResponse } from 'next/server'
|
|
12
12
|
import { queryWithRLS } from '@nextsparkjs/core/lib/db'
|
|
13
13
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
14
|
+
import { corsPreflight } from '@nextsparkjs/core/lib/api/cors-response'
|
|
14
15
|
|
|
15
16
|
interface Post {
|
|
16
17
|
id: string
|
|
@@ -152,3 +153,5 @@ const getHandler = async (request: NextRequest) => {
|
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
export const GET = withRateLimitTier(getHandler, 'read')
|
|
156
|
+
|
|
157
|
+
export const OPTIONS = corsPreflight
|
|
@@ -17,6 +17,8 @@ Welcome to the Starter theme for NextSpark. This minimal theme provides everythi
|
|
|
17
17
|
3. Run migrations: `pnpm db:migrate`
|
|
18
18
|
4. Start development: `pnpm dev`
|
|
19
19
|
|
|
20
|
+
Sample users (DevKeyring, Cypress) are for local development only: `pnpm db:seed` loads them; `pnpm db:migrate` alone does not, and neither applies them when `NODE_ENV` is `production`.
|
|
21
|
+
|
|
20
22
|
## Project Structure
|
|
21
23
|
|
|
22
24
|
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextIntlClientProvider } from 'next-intl'
|
|
2
|
+
import { getMessages } from 'next-intl/server'
|
|
3
|
+
import { selectMessages } from '@nextsparkjs/core/lib/i18n/client-messages'
|
|
4
|
+
|
|
5
|
+
// TasksChart and RecentActivity are client components that read the `analytics`
|
|
6
|
+
// namespace, which the dashboard group does not carry to the browser by default.
|
|
7
|
+
export default async function AnalyticsLayout({ children }: { children: React.ReactNode }) {
|
|
8
|
+
const messages = await getMessages()
|
|
9
|
+
return (
|
|
10
|
+
<NextIntlClientProvider messages={selectMessages(messages, 'dashboard', ['analytics'])}>
|
|
11
|
+
{children}
|
|
12
|
+
</NextIntlClientProvider>
|
|
13
|
+
)
|
|
14
|
+
}
|
package/templates/proxy.ts
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* themselves and use only x-pathname from here, as a routing hint; the
|
|
21
21
|
* identity headers are still stripped and re-set for project code.
|
|
22
22
|
*/
|
|
23
|
-
import { betterFetch } from '@better-fetch/fetch'
|
|
24
23
|
import { NextRequest, NextResponse } from 'next/server'
|
|
24
|
+
import { auth } from '@nextsparkjs/core/lib/auth'
|
|
25
25
|
import {
|
|
26
26
|
hasProjectMiddleware,
|
|
27
27
|
executeProjectMiddleware,
|
|
@@ -181,14 +181,22 @@ function redirectAccessDenied(request: NextRequest): NextResponse {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
* The session the request's cookies carry,
|
|
185
|
-
*
|
|
184
|
+
* The session the request's cookies carry, read in this process the way core's
|
|
185
|
+
* server code reads it. Asking the app's own /api/auth/get-session over HTTP
|
|
186
|
+
* built the URL from the request's origin, which behind a proxy that
|
|
187
|
+
* terminates TLS (X-Forwarded-Proto: https) is https on a port that speaks
|
|
188
|
+
* plain HTTP: the fetch failed and every signed-in user was sent to /login.
|
|
189
|
+
* Nothing here leaves the process, so no forwarded scheme or host can point
|
|
190
|
+
* the check anywhere. `disableRefresh`: this response cannot carry the renewed
|
|
191
|
+
* session cookie, so the rolling renewal is left to the auth route
|
|
192
|
+
* (lib/auth/session-refresh).
|
|
186
193
|
*/
|
|
187
|
-
function getSession(request: NextRequest) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
194
|
+
async function getSession(request: NextRequest): Promise<Session | null> {
|
|
195
|
+
const session = await auth.api.getSession({
|
|
196
|
+
headers: new Headers({ cookie: request.headers.get('cookie') || '' }),
|
|
197
|
+
query: { disableRefresh: true },
|
|
191
198
|
})
|
|
199
|
+
return session as Session | null
|
|
192
200
|
}
|
|
193
201
|
|
|
194
202
|
/**
|
|
@@ -200,8 +208,19 @@ function getSession(request: NextRequest) {
|
|
|
200
208
|
* session. Gating the strip on protected prefixes is not enough: Next.js
|
|
201
209
|
* dispatches Server Actions by the `Next-Action` header, not by the URL, so an
|
|
202
210
|
* action can be POSTed to a public path with a forged `x-user-id`.
|
|
211
|
+
*
|
|
212
|
+
* The `x-api-*` names are never set here: core takes an API key's identity from
|
|
213
|
+
* validating the key, and nothing downstream may receive them from the client.
|
|
203
214
|
*/
|
|
204
|
-
const TRUSTED_IDENTITY_HEADERS = [
|
|
215
|
+
const TRUSTED_IDENTITY_HEADERS = [
|
|
216
|
+
'x-user-id',
|
|
217
|
+
'x-user-email',
|
|
218
|
+
'x-pathname',
|
|
219
|
+
'x-active-team-id',
|
|
220
|
+
'x-api-user-id',
|
|
221
|
+
'x-api-key-id',
|
|
222
|
+
'x-api-scopes',
|
|
223
|
+
] as const
|
|
205
224
|
|
|
206
225
|
/**
|
|
207
226
|
* Build the request headers forwarded to the app: inbound copy minus every
|
|
@@ -479,7 +498,6 @@ export async function proxy(request: NextRequest) {
|
|
|
479
498
|
const verifiedSession = async (): Promise<Session | null> => {
|
|
480
499
|
if (!sessionPromise) {
|
|
481
500
|
sessionPromise = getSession(request)
|
|
482
|
-
.then(({ data }) => data)
|
|
483
501
|
.catch(error => {
|
|
484
502
|
sessionError = error
|
|
485
503
|
return null
|
|
Binary file
|
|
@@ -1,97 +1,8 @@
|
|
|
1
|
-
# Media
|
|
1
|
+
# Media uploads
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
This application uses **Vercel Blob Storage** for all media uploads. Files are stored in the cloud, not on the local filesystem.
|
|
3
|
+
`POST /api/v1/media/upload` stores files in **Vercel Blob** when `BLOB_READ_WRITE_TOKEN` is set. The media library lists the Blob URLs.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
- **Development without a token:** files are written to `public/uploads/temp/` (git-ignored) so the library works offline.
|
|
6
|
+
- **Production without a token:** the upload answers `503` with code `STORAGE_NOT_CONFIGURED`. Nothing is written to disk: a file under `public/` is not served until the next restart and does not survive a redeploy.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
**POST** `/api/v1/media/upload`
|
|
10
|
-
|
|
11
|
-
### Authentication
|
|
12
|
-
Requires valid user session (Better Auth)
|
|
13
|
-
|
|
14
|
-
### Request
|
|
15
|
-
- **Content-Type**: `multipart/form-data`
|
|
16
|
-
- **Field name**: `files` (accepts multiple files)
|
|
17
|
-
|
|
18
|
-
### Supported File Types
|
|
19
|
-
- Images: JPEG, PNG, GIF, WebP
|
|
20
|
-
- Videos: MP4, MPEG, QuickTime, WebM
|
|
21
|
-
|
|
22
|
-
### File Size Limit
|
|
23
|
-
- Maximum: 10MB per file
|
|
24
|
-
|
|
25
|
-
### Response
|
|
26
|
-
```json
|
|
27
|
-
{
|
|
28
|
-
"message": "Files uploaded successfully",
|
|
29
|
-
"urls": [
|
|
30
|
-
"https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1234567890_abc123.jpg",
|
|
31
|
-
"https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1234567890_def456.png"
|
|
32
|
-
],
|
|
33
|
-
"count": 2
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## File Naming Convention
|
|
38
|
-
Files are automatically renamed using the pattern:
|
|
39
|
-
```
|
|
40
|
-
{timestamp}_{randomString}.{extension}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Example: `1704067200000_k9x2m4p.jpg`
|
|
44
|
-
|
|
45
|
-
## Storage Location
|
|
46
|
-
- **Storage Provider**: Vercel Blob (cloud object storage)
|
|
47
|
-
- **Blob Path**: `uploads/temp/{filename}` (organizational prefix, not a filesystem path)
|
|
48
|
-
- **Public URL**: `https://xxxxx.public.blob.vercel-storage.com/uploads/temp/{filename}`
|
|
49
|
-
|
|
50
|
-
### How It Works
|
|
51
|
-
|
|
52
|
-
**Local Development:**
|
|
53
|
-
- Files are uploaded directly to Vercel Blob using `BLOB_READ_WRITE_TOKEN` from `.env`
|
|
54
|
-
- No files are saved to your local filesystem
|
|
55
|
-
- URLs point to Vercel's CDN
|
|
56
|
-
|
|
57
|
-
**Production/Staging:**
|
|
58
|
-
- Same behavior - files go directly to Vercel Blob
|
|
59
|
-
- Uses environment-specific Blob token
|
|
60
|
-
- No filesystem writes (Vercel serverless is read-only)
|
|
61
|
-
|
|
62
|
-
## Usage in AI Content Generation
|
|
63
|
-
The generate-content endpoint (`/api/content-buddy/generate-content`) automatically processes images for AI analysis.
|
|
64
|
-
|
|
65
|
-
**Supported URL formats:**
|
|
66
|
-
- Vercel Blob URLs: `https://xxxxx.public.blob.vercel-storage.com/uploads/temp/image.jpg`
|
|
67
|
-
- External URLs: `https://example.com/image.jpg` (also supported)
|
|
68
|
-
|
|
69
|
-
## Configuration
|
|
70
|
-
Requires `BLOB_READ_WRITE_TOKEN` environment variable:
|
|
71
|
-
|
|
72
|
-
```env
|
|
73
|
-
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_..."
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Cleanup
|
|
77
|
-
Files are managed through Vercel Blob's retention policies.
|
|
78
|
-
|
|
79
|
-
**Manual cleanup** (if needed):
|
|
80
|
-
```typescript
|
|
81
|
-
import { del } from '@vercel/blob'
|
|
82
|
-
|
|
83
|
-
// Delete specific file
|
|
84
|
-
await del(fileUrl)
|
|
85
|
-
|
|
86
|
-
// Or list and delete old files
|
|
87
|
-
import { list } from '@vercel/blob'
|
|
88
|
-
const { blobs } = await list({ prefix: 'uploads/temp/' })
|
|
89
|
-
// Filter and delete as needed
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Security Notes
|
|
93
|
-
- All uploads require authentication
|
|
94
|
-
- File type validation prevents malicious uploads
|
|
95
|
-
- File size limits prevent DoS attacks
|
|
96
|
-
- Random filenames prevent enumeration attacks
|
|
97
|
-
- Files stored in secure Vercel Blob infrastructure
|
|
8
|
+
Self-hosting needs a storage provider: set `BLOB_READ_WRITE_TOKEN` (a Vercel Blob token, starts with `vercel_blob_`). See the media library docs.
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Keep this directory in git but ignore uploaded files
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Keep this directory in git but ignore uploaded files
|