@nextsparkjs/core 0.1.0-beta.189 → 0.1.0-beta.190
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/api/keys/CreateApiKeyDialog.d.ts.map +1 -1
- package/dist/components/api/keys/CreateApiKeyDialog.js +2 -1
- package/dist/components/app/layouts/PublicFooter.d.ts.map +1 -1
- package/dist/components/app/layouts/PublicFooter.js +2 -23
- package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
- package/dist/components/app/misc/ThemeToggle.js +2 -1
- package/dist/components/auth/forms/LoginForm.js +1 -1
- package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
- package/dist/components/auth/forms/SignupForm.js +2 -1
- package/dist/components/auth/pages/AuthErrorPage.d.ts.map +1 -1
- package/dist/components/auth/pages/AuthErrorPage.js +2 -1
- package/dist/components/billing/ManageBillingButton.d.ts.map +1 -1
- package/dist/components/billing/ManageBillingButton.js +2 -1
- package/dist/components/dashboard/block-editor/array-field.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/array-field.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 +3 -2
- package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/config-panel.js +3 -2
- package/dist/components/dashboard/block-editor/dynamic-form.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/dynamic-form.js +2 -1
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.js +3 -2
- 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/TopNavbar.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/TopNavbar.js +4 -3
- package/dist/components/dashboard/misc/SearchDropdown.d.ts.map +1 -1
- package/dist/components/dashboard/misc/SearchDropdown.js +2 -1
- package/dist/components/dashboard/mobile/MobileTopBar.d.ts.map +1 -1
- package/dist/components/dashboard/mobile/MobileTopBar.js +2 -1
- package/dist/components/devtools/BlockDetailViewer.d.ts.map +1 -1
- package/dist/components/devtools/BlockDetailViewer.js +2 -1
- package/dist/components/devtools/BlocksViewer.d.ts.map +1 -1
- package/dist/components/devtools/BlocksViewer.js +2 -1
- package/dist/components/devtools/ConfigViewer.d.ts.map +1 -1
- package/dist/components/devtools/ConfigViewer.js +3 -2
- package/dist/components/devtools/TestCasesViewer.d.ts.map +1 -1
- package/dist/components/devtools/TestCasesViewer.js +3 -2
- package/dist/components/devtools/TestCoverageDashboard.d.ts.map +1 -1
- package/dist/components/devtools/TestCoverageDashboard.js +2 -1
- package/dist/components/devtools/api-explorer/ApiDocsModal.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiDocsModal.js +0 -0
- package/dist/components/devtools/api-explorer/ApiExplorer.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiExplorer.js +2 -1
- package/dist/components/devtools/scheduled-actions/actions-table.d.ts.map +1 -1
- package/dist/components/devtools/scheduled-actions/actions-table.js +3 -2
- package/dist/components/docs/docs-sidebar.d.ts.map +1 -1
- package/dist/components/docs/docs-sidebar.js +3 -2
- package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
- package/dist/components/entities/EntityFieldRenderer.js +2 -1
- package/dist/components/entities/EntityList.d.ts.map +1 -1
- package/dist/components/entities/EntityList.js +2 -1
- package/dist/components/entities/EntityTable.d.ts.map +1 -1
- package/dist/components/entities/EntityTable.js +3 -2
- package/dist/components/entities/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/entities/ErrorBoundary.js +2 -1
- package/dist/components/entities/wrappers/EntityDetailWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityDetailWrapper.js +3 -2
- package/dist/components/media/MediaCard.d.ts.map +1 -1
- package/dist/components/media/MediaCard.js +2 -1
- package/dist/components/media/MediaDetailPanel.d.ts.map +1 -1
- package/dist/components/media/MediaDetailPanel.js +2 -1
- package/dist/components/media/MediaList.d.ts.map +1 -1
- package/dist/components/media/MediaList.js +2 -1
- package/dist/components/media/MediaSelector.d.ts.map +1 -1
- package/dist/components/media/MediaSelector.js +2 -1
- package/dist/components/media/MediaUploadZone.d.ts.map +1 -1
- package/dist/components/media/MediaUploadZone.js +2 -1
- package/dist/components/public/entities/PublicEntityDetail.d.ts.map +1 -1
- package/dist/components/public/entities/PublicEntityDetail.js +2 -1
- package/dist/components/teams/TeamPendingInvitations.d.ts.map +1 -1
- package/dist/components/teams/TeamPendingInvitations.js +3 -2
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/audio-upload.d.ts.map +1 -1
- package/dist/components/ui/audio-upload.js +2 -1
- package/dist/components/ui/avatar.d.ts +17 -1
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/avatar.js +29 -2
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.d.ts +13 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.js +23 -10
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/file-upload.d.ts.map +1 -1
- package/dist/components/ui/file-upload.js +2 -1
- package/dist/components/ui/image-upload.d.ts.map +1 -1
- package/dist/components/ui/image-upload.js +4 -3
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/label.js +1 -1
- package/dist/components/ui/optimized-image.d.ts.map +1 -1
- package/dist/components/ui/optimized-image.js +5 -0
- package/dist/components/ui/pagination.d.ts +1 -1
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/pagination.js +3 -0
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/relation-display.d.ts.map +1 -1
- package/dist/components/ui/relation-display.js +3 -2
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/simple-relation-select.d.ts.map +1 -1
- package/dist/components/ui/simple-relation-select.js +7 -6
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/user-display.d.ts.map +1 -1
- package/dist/components/ui/user-display.js +2 -1
- package/dist/components/ui/user-select.d.ts.map +1 -1
- package/dist/components/ui/user-select.js +2 -1
- package/dist/components/ui/video-upload.d.ts.map +1 -1
- package/dist/components/ui/video-upload.js +3 -2
- package/dist/components/users/tables/UsersTable.d.ts.map +1 -1
- package/dist/components/users/tables/UsersTable.js +3 -2
- package/dist/contexts/SubscriptionContext.d.ts.map +1 -1
- package/dist/contexts/SubscriptionContext.js +4 -3
- package/dist/contexts/TeamContext.d.ts.map +1 -1
- package/dist/contexts/TeamContext.js +3 -2
- package/dist/hooks/useAccountPreferencesSync.d.ts.map +1 -1
- package/dist/hooks/useAccountPreferencesSync.js +2 -1
- package/dist/hooks/useApiExplorerNavigation.d.ts.map +1 -1
- package/dist/hooks/useApiExplorerNavigation.js +2 -1
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +3 -2
- package/dist/hooks/useEnsureUserMetadata.d.ts.map +1 -1
- package/dist/hooks/useEnsureUserMetadata.js +3 -2
- package/dist/hooks/useEntityWithMeta.d.ts.map +1 -1
- package/dist/hooks/useEntityWithMeta.js +3 -2
- package/dist/hooks/useInvoice.d.ts.map +1 -1
- package/dist/hooks/useInvoice.js +2 -1
- package/dist/hooks/useInvoices.d.ts.map +1 -1
- package/dist/hooks/useInvoices.js +2 -1
- package/dist/hooks/useMedia.d.ts.map +1 -1
- package/dist/hooks/useMedia.js +10 -9
- package/dist/hooks/useMediaUpload.d.ts.map +1 -1
- package/dist/hooks/useMediaUpload.js +2 -1
- package/dist/hooks/useMembership.d.ts.map +1 -1
- package/dist/hooks/useMembership.js +3 -2
- package/dist/hooks/usePatternUsages.d.ts.map +1 -1
- package/dist/hooks/usePatternUsages.js +3 -2
- package/dist/hooks/usePrefetch.d.ts.map +1 -1
- package/dist/hooks/usePrefetch.js +3 -2
- package/dist/hooks/useQuota.d.ts.map +1 -1
- package/dist/hooks/useQuota.js +2 -1
- package/dist/hooks/useTeamInvitations.d.ts.map +1 -1
- package/dist/hooks/useTeamInvitations.js +4 -3
- package/dist/hooks/useTeamMembers.d.ts.map +1 -1
- package/dist/hooks/useTeamMembers.js +5 -4
- package/dist/hooks/useTeamUpdate.d.ts.map +1 -1
- package/dist/hooks/useTeamUpdate.js +2 -1
- package/dist/hooks/useUserProfile.d.ts.map +1 -1
- package/dist/hooks/useUserProfile.js +3 -2
- package/dist/hooks/useUserSettings.d.ts.map +1 -1
- package/dist/hooks/useUserSettings.js +3 -2
- package/dist/lib/actions/entity.actions.d.ts.map +1 -1
- package/dist/lib/actions/entity.actions.js +2 -1
- package/dist/lib/api/entities.d.ts.map +1 -1
- package/dist/lib/api/entities.js +4 -3
- package/dist/lib/auth/verify-email-link.d.ts +10 -0
- package/dist/lib/auth/verify-email-link.d.ts.map +1 -0
- package/dist/lib/auth/verify-email-link.js +14 -0
- package/dist/lib/auth-client.d.ts +2 -0
- package/dist/lib/auth-client.d.ts.map +1 -1
- package/dist/lib/auth-client.js +4 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +10 -2
- package/dist/lib/base-path.d.ts +85 -0
- package/dist/lib/base-path.d.ts.map +1 -0
- package/dist/lib/base-path.js +79 -0
- package/dist/lib/billing/schema.d.ts +1 -1
- package/dist/lib/billing/schema.d.ts.map +1 -1
- package/dist/lib/billing/schema.js +1 -1
- package/dist/lib/blocks/sanitize-html.d.ts.map +1 -1
- package/dist/lib/blocks/sanitize-html.js +18 -2
- package/dist/lib/cache/revalidate-tag.d.ts +14 -0
- package/dist/lib/cache/revalidate-tag.d.ts.map +1 -0
- package/dist/lib/cache/revalidate-tag.js +8 -0
- package/dist/lib/config/dashboard-schema.d.ts +1 -1
- package/dist/lib/config/dashboard-schema.d.ts.map +1 -1
- package/dist/lib/config/dashboard-schema.js +1 -1
- package/dist/lib/config/types.d.ts +36 -16
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/docs/access.d.ts +28 -0
- package/dist/lib/docs/access.d.ts.map +1 -0
- package/dist/lib/docs/access.js +16 -0
- package/dist/lib/docs/parser.d.ts.map +1 -1
- package/dist/lib/docs/parser.js +2 -1
- package/dist/lib/docs/remark-doc-links.d.ts +14 -0
- package/dist/lib/docs/remark-doc-links.d.ts.map +1 -0
- package/dist/lib/docs/remark-doc-links.js +38 -0
- package/dist/lib/entities/api-generator.d.ts +1 -1
- package/dist/lib/entities/api-generator.d.ts.map +1 -1
- package/dist/lib/entities/api-generator.js +1 -1
- package/dist/lib/entities/schema-generator.d.ts +1 -1
- package/dist/lib/entities/schema-generator.d.ts.map +1 -1
- package/dist/lib/entities/schema-generator.js +1 -1
- package/dist/lib/mcp/engine.js +1 -1
- package/dist/lib/mcp/schema-builder.d.ts +1 -1
- package/dist/lib/mcp/schema-builder.d.ts.map +1 -1
- package/dist/lib/mcp/schema-builder.js +1 -1
- package/dist/lib/mcp/tool-generator.js +1 -1
- package/dist/lib/mcp/types.d.ts +1 -1
- package/dist/lib/mcp/types.d.ts.map +1 -1
- package/dist/lib/media/schemas.d.ts +1 -1
- package/dist/lib/media/schemas.d.ts.map +1 -1
- package/dist/lib/media/schemas.js +1 -1
- package/dist/lib/middleware/index.d.ts +5 -1
- package/dist/lib/middleware/index.d.ts.map +1 -1
- package/dist/lib/middleware/index.js +3 -2
- package/dist/lib/services/meta.service.d.ts +60 -0
- package/dist/lib/services/meta.service.d.ts.map +1 -1
- package/dist/lib/services/meta.service.js +132 -12
- package/dist/lib/services/middleware.service.d.ts.map +1 -1
- package/dist/lib/services/middleware.service.js +3 -2
- package/dist/lib/teams/schema.d.ts +1 -1
- package/dist/lib/teams/schema.d.ts.map +1 -1
- package/dist/lib/teams/schema.js +1 -1
- package/dist/lib/teams/teams.api.d.ts.map +1 -1
- package/dist/lib/teams/teams.api.js +4 -3
- package/dist/lib/user-data-client.d.ts.map +1 -1
- package/dist/lib/user-data-client.js +3 -2
- package/dist/lib/validation/invoices.d.ts +1 -1
- package/dist/lib/validation/invoices.d.ts.map +1 -1
- package/dist/lib/validation/invoices.js +1 -1
- package/dist/lib/validation-schemas.d.ts +1 -1
- package/dist/lib/validation-schemas.d.ts.map +1 -1
- package/dist/lib/validation-schemas.js +1 -1
- package/dist/lib/validation.d.ts +1 -1
- package/dist/lib/validation.d.ts.map +1 -1
- package/dist/lib/validation.js +1 -1
- package/dist/messages/de/footer.json +0 -1
- package/dist/messages/de/index.d.ts +0 -1
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/en/footer.json +0 -1
- package/dist/messages/en/index.d.ts +0 -1
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/es/footer.json +0 -1
- package/dist/messages/es/index.d.ts +0 -1
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/fr/footer.json +0 -1
- package/dist/messages/fr/index.d.ts +0 -1
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/it/footer.json +0 -1
- package/dist/messages/it/index.d.ts +0 -1
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/pt/footer.json +0 -1
- package/dist/messages/pt/index.d.ts +0 -1
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/templates/app/(auth)/accept-invite/[token]/page.tsx +4 -3
- package/dist/templates/app/(auth)/verify-email/page.tsx +4 -3
- package/dist/templates/app/(public)/docs/[section]/[page]/page.tsx +11 -0
- package/dist/templates/app/api/auth/[...all]/route.ts +15 -14
- package/dist/templates/app/api/internal/user-metadata/route.ts +6 -8
- package/dist/templates/app/api/user/plan-flags/route.ts +1 -1
- package/dist/templates/app/api/user/profile/route.ts +12 -17
- package/dist/templates/app/api/v1/api-keys/route.ts +1 -1
- package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +2 -1
- package/dist/templates/app/api/v1/billing/cancel/route.ts +1 -1
- package/dist/templates/app/api/v1/billing/change-plan/route.ts +1 -1
- package/dist/templates/app/api/v1/billing/check-action/route.ts +1 -1
- package/dist/templates/app/api/v1/billing/checkout/route.ts +1 -1
- package/dist/templates/app/api/v1/blocks/validate/route.ts +1 -1
- package/dist/templates/app/api/v1/media/[id]/tags/route.ts +1 -1
- package/dist/templates/app/api/v1/post-categories/[id]/route.ts +1 -1
- package/dist/templates/app/api/v1/post-categories/route.ts +1 -1
- package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +2 -1
- package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -5
- package/dist/templates/app/api/v1/teams/docs.md +4 -9
- package/dist/templates/app/api/v1/teams/switch/route.ts +1 -1
- package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +1 -1
- package/dist/templates/app/api/v1/users/[id]/route.ts +1 -1
- package/dist/templates/app/api/v1/users/route.ts +1 -1
- package/dist/templates/app/dashboard/(main)/media/page.tsx +3 -1
- package/dist/templates/app/dashboard/settings/api-keys/page.tsx +5 -4
- package/dist/templates/app/dashboard/settings/profile/page.tsx +3 -2
- package/dist/templates/app/devtools/scheduled-actions/page.tsx +2 -1
- package/dist/templates/app/superadmin/docs/[section]/[page]/page.tsx +16 -0
- package/dist/templates/app/superadmin/subscriptions/page.tsx +3 -2
- package/dist/templates/app/superadmin/teams/[teamId]/page.tsx +5 -4
- package/dist/templates/app/superadmin/users/[userId]/page.tsx +2 -1
- package/dist/templates/app/superadmin/users/page.tsx +2 -1
- package/dist/templates/blocks/cta-section/component.tsx +3 -2
- package/dist/templates/blocks/cta-section/schema.ts +1 -1
- package/dist/templates/blocks/features-grid/component.tsx +2 -1
- package/dist/templates/blocks/features-grid/schema.ts +1 -1
- package/dist/templates/blocks/hero/component.tsx +3 -2
- package/dist/templates/blocks/hero/schema.ts +1 -1
- package/dist/templates/blocks/testimonials/component.tsx +2 -1
- package/dist/templates/blocks/testimonials/schema.ts +1 -1
- package/dist/templates/blocks/text-content/component.tsx +2 -1
- package/dist/templates/blocks/text-content/schema.ts +1 -1
- package/dist/templates/ci-workflows/README.md +1 -1
- package/dist/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/dist/templates/ci-workflows/github/cypress-smoke.yml +1 -1
- package/dist/templates/contents/plugins/starter/plugin/api/example/route.ts.template +1 -1
- package/dist/templates/contents/themes/starter/blocks/cta-section/component.tsx +3 -2
- package/dist/templates/contents/themes/starter/blocks/cta-section/schema.ts +1 -1
- package/dist/templates/contents/themes/starter/blocks/features-grid/component.tsx +2 -1
- package/dist/templates/contents/themes/starter/blocks/features-grid/schema.ts +1 -1
- package/dist/templates/contents/themes/starter/blocks/hero/component.tsx +3 -2
- package/dist/templates/contents/themes/starter/blocks/hero/schema.ts +1 -1
- package/dist/templates/contents/themes/starter/blocks/testimonials/component.tsx +3 -2
- package/dist/templates/contents/themes/starter/blocks/testimonials/schema.ts +1 -1
- package/dist/templates/contents/themes/starter/blocks/text-content/component.tsx +2 -1
- package/dist/templates/contents/themes/starter/blocks/text-content/schema.ts +1 -1
- package/dist/templates/contents/themes/starter/entities/posts/components/post-header.tsx +2 -1
- package/dist/templates/contents/themes/starter/lib/hooks/useAnalyticsData.ts +2 -1
- package/dist/templates/contents/themes/starter/lib/hooks/useTaskStats.ts +2 -1
- package/dist/templates/eslint.config.mjs +133 -9
- package/dist/templates/features/blog/blocks/post-content/component.tsx +2 -1
- package/dist/templates/features/blog/blocks/post-content/schema.ts +1 -1
- package/dist/templates/features/blog/entities/posts/components/post-header.tsx +2 -1
- package/dist/templates/features/pages/blocks/hero/component.tsx +3 -2
- package/dist/templates/features/pages/blocks/hero/schema.ts +1 -1
- package/dist/templates/next.config.mjs +50 -29
- package/dist/templates/proxy.ts +100 -21
- package/dist/templates/public/sw.js +2 -2
- package/dist/templates/scripts/cy-run-prod.cjs +5 -5
- package/dist/types/blocks.d.ts +1 -1
- package/dist/types/blocks.d.ts.map +1 -1
- package/dist/types/blocks.js +1 -1
- package/package.json +9 -5
- package/scripts/build/docs-registry.mjs +7 -7
- package/scripts/build/registry/__tests__/billing-registry.test.mjs +43 -0
- package/scripts/build/registry/__tests__/build-output.test.mjs +209 -0
- package/scripts/build/registry/__tests__/copy-race-child.mjs +14 -0
- package/scripts/build/registry/__tests__/direct-fs-writes.mjs +203 -0
- package/scripts/build/registry/__tests__/globals-css-tag.test.mjs +66 -0
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +530 -29
- package/scripts/build/registry/__tests__/page-generator.test.mjs +211 -37
- package/scripts/build/registry/__tests__/published-signatures.test.mjs +239 -0
- package/scripts/build/registry/__tests__/route-file-rule.test.mjs +170 -0
- package/scripts/build/registry/__tests__/safe-fs.test.mjs +333 -0
- package/scripts/build/registry/__tests__/template-analysis.test.mjs +142 -0
- package/scripts/build/registry/__tests__/template-registry.test.mjs +279 -9
- package/scripts/build/registry/__tests__/templates-plan.test.mjs +128 -0
- package/scripts/build/registry/__tests__/templates-tree.test.mjs +367 -0
- package/scripts/build/registry/__tests__/write-places.test.mjs +425 -0
- package/scripts/build/registry/config.mjs +6 -65
- package/scripts/build/registry/discovery/icons.mjs +498 -43
- package/scripts/build/registry/discovery/templates.mjs +1 -1
- package/scripts/build/registry/generators/billing-registry.mjs +1 -1
- package/scripts/build/registry/generators/docs-registry.mjs +3 -4
- package/scripts/build/registry/generators/feature-registry.mjs +1 -1
- package/scripts/build/registry/generators/permissions-registry.mjs +2 -2
- package/scripts/build/registry/generators/template-registry.mjs +65 -49
- package/scripts/build/registry/index.mjs +1 -2
- package/scripts/build/registry/post-build/index.mjs +1 -1
- package/scripts/build/registry/post-build/own-gitignores.mjs +220 -0
- package/scripts/build/registry/post-build/page-generator.mjs +512 -268
- package/scripts/build/registry/post-build/route-cleanup.mjs +16 -13
- package/scripts/build/registry/post-build/test-fixtures.mjs +26 -8
- package/scripts/build/registry/project-mode.mjs +76 -0
- package/scripts/build/registry/shared/typescript-compiler.mjs +77 -0
- package/scripts/build/registry/validate-env.test.mjs +12 -8
- package/scripts/build/registry/watch.mjs +3 -53
- package/scripts/build/registry/write-places.mjs +228 -0
- package/scripts/build/registry.mjs +53 -30
- package/scripts/build/safe-fs.mjs +279 -0
- package/scripts/build/templates-plan.mjs +44 -0
- package/scripts/build/theme.mjs +46 -42
- package/scripts/build/update-tsconfig.mjs +16 -15
- package/scripts/db/cluster-changes.mjs +205 -0
- package/scripts/db/connection-time-limits.mjs +53 -0
- package/scripts/db/inspect-server.mjs +108 -0
- package/scripts/db/migration-time-limit.mjs +695 -0
- package/scripts/db/run-migrations.mjs +46 -41
- package/scripts/db/ssl-config.mjs +194 -0
- package/scripts/db/theme-location.mjs +69 -0
- package/scripts/db/verify-tables.mjs +3 -8
- package/scripts/db/verify-teams.mjs +2 -6
- package/scripts/db/verify-theme-migrations.mjs +169 -0
- package/scripts/maintenance/core-updater.mjs +1003 -0
- package/scripts/maintenance/step-guard.mjs +74 -0
- package/scripts/maintenance/update-core.mjs +14 -831
- package/scripts/utils/console-guard.mjs +13 -0
- package/scripts/utils/generated-tag.mjs +66 -0
- package/scripts/utils/index.mjs +9 -1
- package/scripts/utils/logging.mjs +140 -0
- package/templates/app/(auth)/accept-invite/[token]/page.tsx +4 -3
- package/templates/app/(auth)/verify-email/page.tsx +4 -3
- package/templates/app/(public)/docs/[section]/[page]/page.tsx +11 -0
- package/templates/app/api/auth/[...all]/route.ts +15 -14
- package/templates/app/api/internal/user-metadata/route.ts +6 -8
- package/templates/app/api/user/plan-flags/route.ts +1 -1
- package/templates/app/api/user/profile/route.ts +12 -17
- package/templates/app/api/v1/api-keys/route.ts +1 -1
- package/templates/app/api/v1/auth/signup-with-invite/route.ts +2 -1
- package/templates/app/api/v1/billing/cancel/route.ts +1 -1
- package/templates/app/api/v1/billing/change-plan/route.ts +1 -1
- package/templates/app/api/v1/billing/check-action/route.ts +1 -1
- package/templates/app/api/v1/billing/checkout/route.ts +1 -1
- package/templates/app/api/v1/blocks/validate/route.ts +1 -1
- package/templates/app/api/v1/media/[id]/tags/route.ts +1 -1
- package/templates/app/api/v1/post-categories/[id]/route.ts +1 -1
- package/templates/app/api/v1/post-categories/route.ts +1 -1
- package/templates/app/api/v1/teams/[teamId]/members/route.ts +2 -1
- package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -5
- package/templates/app/api/v1/teams/docs.md +4 -9
- package/templates/app/api/v1/teams/switch/route.ts +1 -1
- package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +1 -1
- package/templates/app/api/v1/users/[id]/route.ts +1 -1
- package/templates/app/api/v1/users/route.ts +1 -1
- package/templates/app/dashboard/(main)/media/page.tsx +3 -1
- package/templates/app/dashboard/settings/api-keys/page.tsx +5 -4
- package/templates/app/dashboard/settings/profile/page.tsx +3 -2
- package/templates/app/devtools/scheduled-actions/page.tsx +2 -1
- package/templates/app/superadmin/docs/[section]/[page]/page.tsx +16 -0
- package/templates/app/superadmin/subscriptions/page.tsx +3 -2
- package/templates/app/superadmin/teams/[teamId]/page.tsx +5 -4
- package/templates/app/superadmin/users/[userId]/page.tsx +2 -1
- package/templates/app/superadmin/users/page.tsx +2 -1
- package/templates/blocks/cta-section/component.tsx +3 -2
- package/templates/blocks/cta-section/schema.ts +1 -1
- package/templates/blocks/features-grid/component.tsx +2 -1
- package/templates/blocks/features-grid/schema.ts +1 -1
- package/templates/blocks/hero/component.tsx +3 -2
- package/templates/blocks/hero/schema.ts +1 -1
- package/templates/blocks/testimonials/component.tsx +2 -1
- package/templates/blocks/testimonials/schema.ts +1 -1
- package/templates/blocks/text-content/component.tsx +2 -1
- package/templates/blocks/text-content/schema.ts +1 -1
- package/templates/ci-workflows/README.md +1 -1
- package/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/templates/ci-workflows/github/cypress-smoke.yml +1 -1
- package/templates/contents/plugins/starter/plugin/api/example/route.ts.template +1 -1
- package/templates/contents/themes/starter/blocks/cta-section/component.tsx +3 -2
- package/templates/contents/themes/starter/blocks/cta-section/schema.ts +1 -1
- package/templates/contents/themes/starter/blocks/features-grid/component.tsx +2 -1
- package/templates/contents/themes/starter/blocks/features-grid/schema.ts +1 -1
- package/templates/contents/themes/starter/blocks/hero/component.tsx +3 -2
- package/templates/contents/themes/starter/blocks/hero/schema.ts +1 -1
- package/templates/contents/themes/starter/blocks/testimonials/component.tsx +3 -2
- package/templates/contents/themes/starter/blocks/testimonials/schema.ts +1 -1
- package/templates/contents/themes/starter/blocks/text-content/component.tsx +2 -1
- package/templates/contents/themes/starter/blocks/text-content/schema.ts +1 -1
- package/templates/contents/themes/starter/entities/posts/components/post-header.tsx +2 -1
- package/templates/contents/themes/starter/lib/hooks/useAnalyticsData.ts +2 -1
- package/templates/contents/themes/starter/lib/hooks/useTaskStats.ts +2 -1
- package/templates/eslint.config.mjs +133 -9
- package/templates/features/blog/blocks/post-content/component.tsx +2 -1
- package/templates/features/blog/blocks/post-content/schema.ts +1 -1
- package/templates/features/blog/entities/posts/components/post-header.tsx +2 -1
- package/templates/features/pages/blocks/hero/component.tsx +3 -2
- package/templates/features/pages/blocks/hero/schema.ts +1 -1
- package/templates/next.config.mjs +50 -29
- package/templates/proxy.ts +100 -21
- package/templates/public/sw.js +2 -2
- package/templates/scripts/cy-run-prod.cjs +5 -5
- package/tests/jest/__mocks__/@nextsparkjs/registries/template-registry.client.ts +11 -0
- package/tests/jest/__mocks__/next-server.js +10 -0
- package/scripts/build/docs.mjs +0 -392
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards the console of the process that imports it, as `guardConsole` does.
|
|
3
|
+
* The scripts that run the registry build import it before anything else:
|
|
4
|
+
* modules print as they load - config.mjs has dotenv read the project's .env,
|
|
5
|
+
* which logs the path it read - and an import runs before the body of the
|
|
6
|
+
* module that imports it.
|
|
7
|
+
*
|
|
8
|
+
* @module core/scripts/utils/console-guard
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { guardConsole } from './logging.mjs'
|
|
12
|
+
|
|
13
|
+
guardConsole()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generated tag `nextspark sync:app` puts on the files it writes, read here
|
|
3
|
+
* for the build steps that rewrite part of such a file. The format and what it
|
|
4
|
+
* means are the CLI's (packages/cli/src/utils/generated-tag.ts):
|
|
5
|
+
*
|
|
6
|
+
* /* @nextspark-generated core@<version> path=<path> sha256=<hash of the rest> *\/
|
|
7
|
+
*
|
|
8
|
+
* The path runs up to the ` sha256=` that ends it, and is a JSON string when the
|
|
9
|
+
* CLI had to quote it. On the first line, or the second after a shebang. While the hash matches, the
|
|
10
|
+
* file is core's to update; a rewrite that leaves a stale hash makes sync treat
|
|
11
|
+
* the file as changed by the project and stop updating it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createHash } from 'node:crypto'
|
|
15
|
+
|
|
16
|
+
const TAG_LINE = /^(?:\/\/|\/\*) @nextspark-generated core@\S+(?: path=.+?)? sha256=([0-9a-f]{64})(?: \*\/)?$/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The hash a tag records: of the text below the tag, with CRLF line endings
|
|
20
|
+
* read as LF, so a checkout that converts line endings keeps its tags intact.
|
|
21
|
+
*/
|
|
22
|
+
export function generatedHash(text) {
|
|
23
|
+
return createHash('sha256').update(text.replace(/\r\n/g, '\n')).digest('hex')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A file split around its generated tag, or null when it has none.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} text
|
|
30
|
+
* @returns {{ head: string, line: string, body: string, intact: boolean } | null}
|
|
31
|
+
* `head` is the shebang line before the tag, if any; `line` the tag line with
|
|
32
|
+
* its line ending; `body` the file without the tag line; `intact` whether the
|
|
33
|
+
* body still hashes to what the tag recorded
|
|
34
|
+
*/
|
|
35
|
+
export function splitGeneratedTag(text) {
|
|
36
|
+
const shebangEnd = text.startsWith('#!') ? text.indexOf('\n') : -1
|
|
37
|
+
const head = text.slice(0, shebangEnd + 1)
|
|
38
|
+
const newline = text.indexOf('\n', head.length)
|
|
39
|
+
const lineEnd = newline === -1 ? text.length : newline + 1
|
|
40
|
+
|
|
41
|
+
const match = TAG_LINE.exec(text.slice(head.length, newline === -1 ? text.length : newline).replace(/\r$/, ''))
|
|
42
|
+
if (!match) return null
|
|
43
|
+
|
|
44
|
+
const body = head + text.slice(lineEnd)
|
|
45
|
+
return { head, line: text.slice(head.length, lineEnd), body, intact: generatedHash(body) === match[1] }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* `text` with what is below its generated tag passed through `rewrite`. A tag
|
|
50
|
+
* that matched the file before is given the hash of the rewritten content, so
|
|
51
|
+
* the file stays core's to update; a tag that no longer matched - the project
|
|
52
|
+
* changed the file - is kept as it was. A file with no tag is rewritten whole.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} text
|
|
55
|
+
* @param {(body: string) => string} rewrite - Receives and returns the file without its tag line
|
|
56
|
+
*/
|
|
57
|
+
export function rewriteBelowGeneratedTag(text, rewrite) {
|
|
58
|
+
const tag = splitGeneratedTag(text)
|
|
59
|
+
if (!tag) return rewrite(text)
|
|
60
|
+
|
|
61
|
+
const body = rewrite(tag.body)
|
|
62
|
+
let line = tag.intact ? tag.line.replace(/sha256=[0-9a-f]{64}/, `sha256=${generatedHash(body)}`) : tag.line
|
|
63
|
+
if (!line.endsWith('\n') && body.length > tag.head.length) line += '\n'
|
|
64
|
+
|
|
65
|
+
return tag.head + line + body.slice(tag.head.length)
|
|
66
|
+
}
|
package/scripts/utils/index.mjs
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @module core/scripts/utils/logging
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { format } from 'node:util'
|
|
8
|
+
|
|
7
9
|
// Verbose mode state (set via setVerboseMode)
|
|
8
10
|
let verboseMode = false
|
|
9
11
|
|
|
@@ -25,6 +27,144 @@ export function isVerbose() {
|
|
|
25
27
|
return verboseMode
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
/**
|
|
31
|
+
* What breaks a line in a terminal or a log, or reorders how it reads: C0 and C1
|
|
32
|
+
* controls - a newline, a carriage return, ESC and the sequences it starts - DEL,
|
|
33
|
+
* the line and paragraph separators, and the bidirectional marks, embeddings,
|
|
34
|
+
* overrides and isolates.
|
|
35
|
+
*/
|
|
36
|
+
const BREAKS_A_LINE = /[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Text as a line of output shows it: as it is, or, when it holds a character
|
|
40
|
+
* that breaks or reorders the line, quoted, with each such character escaped -
|
|
41
|
+
* the way `nextspark` shows one, which repeats these lines. JSON escapes the C0
|
|
42
|
+
* controls but writes the rest as they are.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} path - The text to show
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export function shownPath(path) {
|
|
48
|
+
if (!BREAKS_A_LINE.test(path)) return path
|
|
49
|
+
return JSON.stringify(path).replace(new RegExp(BREAKS_A_LINE.source, 'g'), character =>
|
|
50
|
+
`\\u${character.charCodeAt(0).toString(16).padStart(4, '0')}`
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* What one call to the console prints, as a line of output shows it. The
|
|
56
|
+
* newlines and spaces it starts with and the newlines it ends with are kept, as
|
|
57
|
+
* the blank lines around it and its indent; when what is between them holds a
|
|
58
|
+
* character that breaks or reorders a line, all of it is shown the way
|
|
59
|
+
* `shownPath` shows a path, on the one line. A
|
|
60
|
+
* newline inside a call can't be told from one in a name the call prints, so
|
|
61
|
+
* what spans lines is printed one call per line, and a call starts with its own
|
|
62
|
+
* text rather than with a name.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} text - What one call prints
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
export function shownLine(text) {
|
|
68
|
+
const [, before, body, after] = /^([\n ]*)([\s\S]*?)(\n*)$/.exec(text)
|
|
69
|
+
return `${before}${shownPath(body)}${after}`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `value` as JSON that a line of output shows as it is: JSON.stringify escapes
|
|
74
|
+
* the C0 controls but leaves the C1 controls, the separators and the
|
|
75
|
+
* bidirectional marks as they are, and those are valid JSON escaped too.
|
|
76
|
+
*
|
|
77
|
+
* @param {unknown} value - What to write as JSON
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
export function jsonLine(value) {
|
|
81
|
+
return JSON.stringify(value).replace(new RegExp(BREAKS_A_LINE.source, 'g'), character =>
|
|
82
|
+
`\\u${character.charCodeAt(0).toString(16).padStart(4, '0')}`
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const GUARDED = Symbol.for('nextspark.shownLine')
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Make each call to `target`'s log, info, warn, error and debug print what it
|
|
90
|
+
* formats the way `shownLine` shows it. Once this runs, whatever prints through
|
|
91
|
+
* the console - the build's own lines, the paths and names in them, and the
|
|
92
|
+
* libraries it loads, dotenv among them - is escaped there, where it is printed.
|
|
93
|
+
*
|
|
94
|
+
* @param {Console} [target] - The console to guard
|
|
95
|
+
*/
|
|
96
|
+
export function guardConsole(target = console) {
|
|
97
|
+
for (const method of ['log', 'info', 'warn', 'error', 'debug']) {
|
|
98
|
+
const original = target[method]
|
|
99
|
+
if (typeof original !== 'function' || original[GUARDED]) continue
|
|
100
|
+
const guarded = (...args) => original.call(target, shownLine(format(...args)))
|
|
101
|
+
guarded[GUARDED] = true
|
|
102
|
+
target[method] = guarded
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* An error whose message is `lines`, one per line. The build prints an error's
|
|
108
|
+
* message one line per call, and takes as lines of their own only the ones an
|
|
109
|
+
* error carries this way: a newline anywhere else in a message belongs to a
|
|
110
|
+
* name in it.
|
|
111
|
+
*
|
|
112
|
+
* @param {string[]} lines - The lines of the message
|
|
113
|
+
* @returns {Error}
|
|
114
|
+
*/
|
|
115
|
+
export function errorWithLines(lines) {
|
|
116
|
+
return Object.assign(new Error(lines.join('\n')), { lines })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The lines of an error's message, each printed with a call of its own: the
|
|
121
|
+
* ones `errorWithLines` gave it, or else the whole message as one.
|
|
122
|
+
*
|
|
123
|
+
* @param {unknown} error - What was thrown
|
|
124
|
+
* @returns {string[]}
|
|
125
|
+
*/
|
|
126
|
+
export function messageLines(error) {
|
|
127
|
+
if (Array.isArray(error?.lines) && error.lines.every(line => typeof line === 'string')) return error.lines
|
|
128
|
+
return [typeof error?.message === 'string' ? error.message : String(error)]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The lines of an error's stack, each printed with a call of its own: its
|
|
133
|
+
* heading with the message as `messageLines` splits it, and then each frame -
|
|
134
|
+
* split where the next ` at ` starts, since a frame names a file whose path
|
|
135
|
+
* can hold a newline of its own.
|
|
136
|
+
*
|
|
137
|
+
* @param {unknown} error - What was thrown
|
|
138
|
+
* @returns {string[]}
|
|
139
|
+
*/
|
|
140
|
+
export function stackLines(error) {
|
|
141
|
+
const stack = typeof error?.stack === 'string' ? error.stack : String(error)
|
|
142
|
+
const message = typeof error?.message === 'string' ? error.message : ''
|
|
143
|
+
const at = message ? stack.indexOf(message) : -1
|
|
144
|
+
if (at === -1) return stack.split(/\n(?= {4}at )/)
|
|
145
|
+
const [first, ...rest] = messageLines(error)
|
|
146
|
+
const frames = stack.slice(at + message.length).replace(/^\n/, '')
|
|
147
|
+
return [`${stack.slice(0, at)}${first}`, ...rest, ...(frames ? frames.split(/\n(?= {4}at )/) : [])]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Log that what `label` names failed with `error`: the first line of its
|
|
152
|
+
* message after the label, each other line of it on its own, and, with
|
|
153
|
+
* `withStack`, the stack on stderr, one line per call.
|
|
154
|
+
*
|
|
155
|
+
* @param {string} label - What failed
|
|
156
|
+
* @param {unknown} error - What was thrown
|
|
157
|
+
* @param {boolean} [withStack] - Whether to print the stack too
|
|
158
|
+
*/
|
|
159
|
+
export function logFailure(label, error, withStack = false) {
|
|
160
|
+
const [first, ...rest] = messageLines(error)
|
|
161
|
+
log(`${label}: ${first}`, 'error')
|
|
162
|
+
for (const line of rest) console.log(line)
|
|
163
|
+
if (withStack) {
|
|
164
|
+
for (const line of stackLines(error)) console.error(line)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
28
168
|
/**
|
|
29
169
|
* Log a message with an emoji prefix based on type
|
|
30
170
|
*
|
|
@@ -10,6 +10,7 @@ import { toast } from 'sonner'
|
|
|
10
10
|
import Link from 'next/link'
|
|
11
11
|
import { sel } from '@nextsparkjs/core/selectors'
|
|
12
12
|
import { getTemplateOrDefaultClient } from '@nextsparkjs/registries/template-registry.client'
|
|
13
|
+
import { withBasePath } from '@nextsparkjs/core/lib/base-path'
|
|
13
14
|
|
|
14
15
|
type InvitationStatus = 'loading' | 'valid' | 'accepting' | 'accepted' | 'error' | 'expired' | 'not_found' | 'email_mismatch' | 'already_member' | 'requires_auth'
|
|
15
16
|
|
|
@@ -38,7 +39,7 @@ function AcceptInvitePage() {
|
|
|
38
39
|
async function validateAndAccept() {
|
|
39
40
|
try {
|
|
40
41
|
// First validate the invitation
|
|
41
|
-
const response = await fetch(`/api/v1/team-invitations/${token}`)
|
|
42
|
+
const response = await fetch(withBasePath(`/api/v1/team-invitations/${token}`))
|
|
42
43
|
const data = await response.json()
|
|
43
44
|
|
|
44
45
|
if (!response.ok) {
|
|
@@ -80,7 +81,7 @@ function AcceptInvitePage() {
|
|
|
80
81
|
|
|
81
82
|
setStatus('accepting')
|
|
82
83
|
|
|
83
|
-
const acceptResponse = await fetch(`/api/v1/team-invitations/${token}/accept
|
|
84
|
+
const acceptResponse = await fetch(withBasePath(`/api/v1/team-invitations/${token}/accept`), {
|
|
84
85
|
method: 'POST',
|
|
85
86
|
credentials: 'include'
|
|
86
87
|
})
|
|
@@ -125,7 +126,7 @@ function AcceptInvitePage() {
|
|
|
125
126
|
setStatus('accepting')
|
|
126
127
|
|
|
127
128
|
try {
|
|
128
|
-
const response = await fetch(`/api/v1/team-invitations/${token}/accept
|
|
129
|
+
const response = await fetch(withBasePath(`/api/v1/team-invitations/${token}/accept`), {
|
|
129
130
|
method: 'POST',
|
|
130
131
|
credentials: 'include'
|
|
131
132
|
})
|
|
@@ -7,6 +7,7 @@ import { Button } from '@nextsparkjs/core/components/ui/button';
|
|
|
7
7
|
import { Alert, AlertDescription } from '@nextsparkjs/core/components/ui/alert';
|
|
8
8
|
import { getTemplateOrDefaultClient } from '@nextsparkjs/registries/template-registry.client'
|
|
9
9
|
import { sel } from '@nextsparkjs/core/selectors'
|
|
10
|
+
import { withBasePath } from '@nextsparkjs/core/lib/base-path'
|
|
10
11
|
|
|
11
12
|
function VerifyEmailContent() {
|
|
12
13
|
const searchParams = useSearchParams()!;
|
|
@@ -26,7 +27,7 @@ function VerifyEmailContent() {
|
|
|
26
27
|
|
|
27
28
|
try {
|
|
28
29
|
// Call the Better Auth verify endpoint with special header to avoid redirect loop
|
|
29
|
-
const response = await fetch(`/api/auth/verify-email?token=${token}
|
|
30
|
+
const response = await fetch(withBasePath(`/api/auth/verify-email?token=${token}`), {
|
|
30
31
|
method: 'GET',
|
|
31
32
|
credentials: 'include',
|
|
32
33
|
headers: {
|
|
@@ -43,7 +44,7 @@ function VerifyEmailContent() {
|
|
|
43
44
|
|
|
44
45
|
// Create default metadata after successful verification
|
|
45
46
|
try {
|
|
46
|
-
const response = await fetch('/api/auth/session', {
|
|
47
|
+
const response = await fetch(withBasePath('/api/auth/get-session'), {
|
|
47
48
|
method: 'GET',
|
|
48
49
|
credentials: 'include'
|
|
49
50
|
});
|
|
@@ -52,7 +53,7 @@ function VerifyEmailContent() {
|
|
|
52
53
|
const session = await response.json();
|
|
53
54
|
if (session?.user?.id) {
|
|
54
55
|
// Create default metadata for the newly verified user
|
|
55
|
-
await fetch('/api/internal/user-metadata', {
|
|
56
|
+
await fetch(withBasePath('/api/internal/user-metadata'), {
|
|
56
57
|
method: 'POST',
|
|
57
58
|
headers: {
|
|
58
59
|
'Content-Type': 'application/json',
|
|
@@ -15,6 +15,17 @@ interface DocsPageProps {
|
|
|
15
15
|
}>
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// generateStaticParams below lists every public doc page, and dynamicParams =
|
|
19
|
+
// false answers 404 for any other section/page pair before the page renders:
|
|
20
|
+
// in `next dev`, and in a production build that prerenders this route, which
|
|
21
|
+
// it does when the app's locale is fixed (see isLocaleFixed). An app that reads
|
|
22
|
+
// the locale from the request renders the route on demand, where Next has no
|
|
23
|
+
// prerendered list to check, and the notFound() calls below cannot set the
|
|
24
|
+
// status either: they run inside the layouts' Suspense boundaries, after the
|
|
25
|
+
// response head has gone out with a 200. For those requests the proxy answers
|
|
26
|
+
// 404 before anything renders (isMissingDocsPage in proxy.ts).
|
|
27
|
+
export const dynamicParams = false
|
|
28
|
+
|
|
18
29
|
export async function generateStaticParams() {
|
|
19
30
|
const params = []
|
|
20
31
|
|
|
@@ -10,6 +10,8 @@ import { wrapAuthHandlerWithCors, handleCorsPreflightRequest, addCorsHeaders } f
|
|
|
10
10
|
import { checkDistributedRateLimit } from "@nextsparkjs/core/lib/api/rate-limit";
|
|
11
11
|
import { withSignupContext } from "@nextsparkjs/core/lib/auth-context";
|
|
12
12
|
import { dispatchSecurityNotificationsForRequest } from "@nextsparkjs/core/lib/auth/security-notifications";
|
|
13
|
+
import { verifyEmailPageUrl } from "@nextsparkjs/core/lib/auth/verify-email-link";
|
|
14
|
+
import { withBasePathRequest } from "@nextsparkjs/core/lib/base-path";
|
|
13
15
|
|
|
14
16
|
const handlers = toNextJsHandler(auth);
|
|
15
17
|
|
|
@@ -28,16 +30,9 @@ export async function GET(req: NextRequest, context: { params: Promise<{ all: st
|
|
|
28
30
|
const isFromUI = req.headers.get('x-verify-from-ui') === 'true';
|
|
29
31
|
|
|
30
32
|
if (pathname === '/api/auth/verify-email' && !isFromUI) {
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
if (token) {
|
|
35
|
-
// This is from an email link, redirect to the UI verification page
|
|
36
|
-
const redirectUrl = new URL('/verify-email', req.url);
|
|
37
|
-
redirectUrl.searchParams.set('token', token);
|
|
38
|
-
if (callbackURL) {
|
|
39
|
-
redirectUrl.searchParams.set('callbackURL', callbackURL);
|
|
40
|
-
}
|
|
33
|
+
// This is from an email link, redirect to the UI verification page
|
|
34
|
+
const redirectUrl = verifyEmailPageUrl(req.url);
|
|
35
|
+
if (redirectUrl) {
|
|
41
36
|
return NextResponse.redirect(redirectUrl);
|
|
42
37
|
}
|
|
43
38
|
}
|
|
@@ -56,11 +51,14 @@ export async function GET(req: NextRequest, context: { params: Promise<{ all: st
|
|
|
56
51
|
? (req.cookies.get('signup-intent')?.value || undefined)
|
|
57
52
|
: undefined;
|
|
58
53
|
|
|
54
|
+
// Better Auth matches its routes with the base path in the URL
|
|
55
|
+
const authReq = withBasePathRequest(req);
|
|
56
|
+
|
|
59
57
|
// Wrap with CORS headers for cross-origin requests (mobile apps, etc.)
|
|
60
58
|
return wrapAuthHandlerWithCors(
|
|
61
59
|
signupIntent
|
|
62
|
-
? () => withSignupContext({ signupIntent }, () => handlers.GET(
|
|
63
|
-
: () => handlers.GET(
|
|
60
|
+
? () => withSignupContext({ signupIntent }, () => handlers.GET(authReq))
|
|
61
|
+
: () => handlers.GET(authReq),
|
|
64
62
|
req
|
|
65
63
|
);
|
|
66
64
|
}
|
|
@@ -188,11 +186,14 @@ export async function POST(req: NextRequest) {
|
|
|
188
186
|
// handlers.POST(req) reads req's body exactly once.
|
|
189
187
|
const securityReq = req.clone() as NextRequest;
|
|
190
188
|
|
|
189
|
+
// Better Auth matches its routes with the base path in the URL
|
|
190
|
+
const authReq = withBasePathRequest(req);
|
|
191
|
+
|
|
191
192
|
// Wrap with CORS headers for cross-origin requests (mobile apps, etc.)
|
|
192
193
|
const response = await wrapAuthHandlerWithCors(
|
|
193
194
|
signupIntent
|
|
194
|
-
? () => withSignupContext({ signupIntent }, () => handlers.POST(
|
|
195
|
-
: () => handlers.POST(
|
|
195
|
+
? () => withSignupContext({ signupIntent }, () => handlers.POST(authReq))
|
|
196
|
+
: () => handlers.POST(authReq),
|
|
196
197
|
req
|
|
197
198
|
);
|
|
198
199
|
|
|
@@ -28,16 +28,14 @@ export const POST = withRateLimitTier(async (req: NextRequest) => {
|
|
|
28
28
|
return NextResponse.json({ error: 'Metadata is required' }, { status: 400 })
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
}
|
|
31
|
+
// Defaults only fill in what is missing. The caller picks them from a read
|
|
32
|
+
// of the user's meta that may be stale by now, so a preference saved in
|
|
33
|
+
// between (a theme change, a collapsed sidebar) is kept.
|
|
34
|
+
await MetaService.mergeEntityMetaGroups('user', userId, metadata, userId, { defaults: true })
|
|
37
35
|
|
|
38
|
-
return NextResponse.json({
|
|
36
|
+
return NextResponse.json({
|
|
39
37
|
success: true,
|
|
40
|
-
message: 'Default metadata created successfully'
|
|
38
|
+
message: 'Default metadata created successfully'
|
|
41
39
|
})
|
|
42
40
|
} catch (error) {
|
|
43
41
|
// Log error for debugging but don't expose details to client
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { NextRequest, NextResponse } from 'next/server'
|
|
9
9
|
import { getTypedSession } from '@nextsparkjs/core/lib/auth'
|
|
10
10
|
import { getUserPlanAndFlags, updateUserPlan, updateUserFlags } from '@nextsparkjs/core/lib/user-data'
|
|
11
|
-
import
|
|
11
|
+
import * as z from 'zod'
|
|
12
12
|
import type { UserRole } from '@nextsparkjs/core/types/user.types'
|
|
13
13
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
14
14
|
|
|
@@ -3,7 +3,7 @@ import { auth } from '@nextsparkjs/core/lib/auth'
|
|
|
3
3
|
import { headers } from 'next/headers'
|
|
4
4
|
import { queryOneWithRLS, mutateWithRLS, queryOne } from '@nextsparkjs/core/lib/db'
|
|
5
5
|
import { profileSchema } from '@nextsparkjs/core/lib/validation'
|
|
6
|
-
import { MetaService } from '@nextsparkjs/core/lib/services/meta.service'
|
|
6
|
+
import { MetaService, MetaValueTooLargeError } from '@nextsparkjs/core/lib/services/meta.service'
|
|
7
7
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
8
8
|
|
|
9
9
|
export const GET = withRateLimitTier(async (request: NextRequest) => {
|
|
@@ -68,15 +68,12 @@ export const PATCH = withRateLimitTier(async (request: NextRequest) => {
|
|
|
68
68
|
const body = await request.json()
|
|
69
69
|
const { meta, ...profileData } = body
|
|
70
70
|
|
|
71
|
-
// Handle metadata-only updates (
|
|
71
|
+
// Handle metadata-only updates (nested format)
|
|
72
72
|
if (meta && Object.keys(profileData).length === 0) {
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
73
|
+
// Each group (uiPreferences, ...) is merged into the stored one: the
|
|
74
|
+
// theme toggle sends only `theme`, the sidebar only `sidebarCollapsed`.
|
|
75
|
+
await MetaService.mergeEntityMetaGroups('user', session.user.id, meta, session.user.id)
|
|
76
|
+
|
|
80
77
|
return NextResponse.json({
|
|
81
78
|
message: 'Settings updated successfully',
|
|
82
79
|
success: true
|
|
@@ -113,21 +110,19 @@ export const PATCH = withRateLimitTier(async (request: NextRequest) => {
|
|
|
113
110
|
}
|
|
114
111
|
}
|
|
115
112
|
|
|
116
|
-
// Handle metadata updates if provided (
|
|
113
|
+
// Handle metadata updates if provided (nested format), merged like above
|
|
117
114
|
if (meta) {
|
|
118
|
-
|
|
119
|
-
for (const [metaKey, metaValue] of Object.entries(meta)) {
|
|
120
|
-
if (metaValue && typeof metaValue === 'object') {
|
|
121
|
-
await MetaService.setEntityMeta('user', session.user.id, metaKey, metaValue, session.user.id)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
115
|
+
await MetaService.mergeEntityMetaGroups('user', session.user.id, meta, session.user.id)
|
|
124
116
|
}
|
|
125
|
-
|
|
117
|
+
|
|
126
118
|
return NextResponse.json({
|
|
127
119
|
message: 'Profile updated successfully',
|
|
128
120
|
success: true
|
|
129
121
|
})
|
|
130
122
|
} catch (error) {
|
|
123
|
+
if (error instanceof MetaValueTooLargeError) {
|
|
124
|
+
return NextResponse.json({ error: error.message }, { status: 413 })
|
|
125
|
+
}
|
|
131
126
|
console.error('Error updating user profile:', error)
|
|
132
127
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
|
133
128
|
}
|
|
@@ -11,7 +11,7 @@ import { authenticateRequest, createAuthFailureResponse, resolveTeamContext } fr
|
|
|
11
11
|
import { ApiKeyManager, API_SCOPES, API_KEY_LIMITS } from '@nextsparkjs/core/lib/api/keys';
|
|
12
12
|
import { validateScopesForUser } from '@nextsparkjs/core/lib/api/auth';
|
|
13
13
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit';
|
|
14
|
-
import
|
|
14
|
+
import * as z from 'zod';
|
|
15
15
|
|
|
16
16
|
const createApiKeySchema = z.object({
|
|
17
17
|
name: z.string().min(1, 'Name is required').max(API_KEY_LIMITS.maxKeyNameLength, 'Name too long'),
|
|
@@ -12,6 +12,7 @@ import type { TeamInvitation, TeamMember } from '@nextsparkjs/core/lib/teams/typ
|
|
|
12
12
|
import { I18N_CONFIG } from '@nextsparkjs/core/lib/config'
|
|
13
13
|
import { withSignupContext } from '@nextsparkjs/core/lib/auth-context'
|
|
14
14
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
15
|
+
import { withBasePath } from '@nextsparkjs/core/lib/base-path'
|
|
15
16
|
|
|
16
17
|
// Handle CORS preflight
|
|
17
18
|
export async function OPTIONS(request: NextRequest) {
|
|
@@ -111,7 +112,7 @@ export const POST = withRateLimitTier(withApiLogging(
|
|
|
111
112
|
// Step 2: Create user using Better Auth's internal API
|
|
112
113
|
// Wrap in signup context to skip automatic team creation
|
|
113
114
|
// (user will be added to the invited team instead)
|
|
114
|
-
const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}/api/auth/sign-up/email`, {
|
|
115
|
+
const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}${withBasePath('/api/auth/sign-up/email')}`, {
|
|
115
116
|
method: 'POST',
|
|
116
117
|
headers: {
|
|
117
118
|
'Content-Type': 'application/json',
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { NextRequest, NextResponse } from 'next/server'
|
|
11
|
-
import
|
|
11
|
+
import * as z from 'zod'
|
|
12
12
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
13
13
|
import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
14
14
|
import { getBillingGateway } from '@nextsparkjs/core/lib/billing/gateways/factory'
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { NextRequest, NextResponse } from 'next/server'
|
|
11
|
-
import
|
|
11
|
+
import * as z from 'zod'
|
|
12
12
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
13
13
|
import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
14
14
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { NextRequest, NextResponse } from 'next/server'
|
|
13
13
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
14
14
|
import { SubscriptionService } from '@nextsparkjs/core/lib/services'
|
|
15
|
-
import
|
|
15
|
+
import * as z from 'zod'
|
|
16
16
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
17
17
|
|
|
18
18
|
const checkActionSchema = z.object({
|
|
@@ -11,7 +11,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
|
11
11
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
12
|
import { getBillingGateway } from '@nextsparkjs/core/lib/billing/gateways/factory'
|
|
13
13
|
import { SubscriptionService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
14
|
-
import
|
|
14
|
+
import * as z from 'zod'
|
|
15
15
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
16
16
|
|
|
17
17
|
const checkoutSchema = z.object({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { BLOCK_REGISTRY } from '@nextsparkjs/registries/block-registry'
|
|
3
|
-
import
|
|
3
|
+
import * as z from 'zod'
|
|
4
4
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
5
5
|
|
|
6
6
|
const requestSchema = z.object({
|
|
@@ -5,7 +5,7 @@ import { API_ERROR_CODES } from '@nextsparkjs/core/lib/api/api-error'
|
|
|
5
5
|
import { checkPermission } from '@nextsparkjs/core/lib/permissions/check'
|
|
6
6
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
7
7
|
import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
|
|
8
|
-
import
|
|
8
|
+
import * as z from 'zod'
|
|
9
9
|
|
|
10
10
|
const addTagSchema = z.object({
|
|
11
11
|
tagId: z.string().min(1),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
3
3
|
import { query as dbQuery } from '@nextsparkjs/core/lib/db'
|
|
4
|
-
import
|
|
4
|
+
import * as z from 'zod'
|
|
5
5
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
6
6
|
|
|
7
7
|
const updateCategorySchema = z.object({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { authenticateRequest, createAuthFailureResponse } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
3
3
|
import { query as dbQuery } from '@nextsparkjs/core/lib/db'
|
|
4
|
-
import
|
|
4
|
+
import * as z from 'zod'
|
|
5
5
|
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
6
6
|
|
|
7
7
|
const createCategorySchema = z.object({
|
|
@@ -19,6 +19,7 @@ import type { TeamMember, TeamInvitation, TeamRole, Team } from '@nextsparkjs/co
|
|
|
19
19
|
import { EmailFactory } from '@nextsparkjs/core/lib/email/factory'
|
|
20
20
|
import { sendTeamInvitationEmail } from '@nextsparkjs/core/lib/email/send'
|
|
21
21
|
import { I18N_CONFIG } from '@nextsparkjs/core/lib/config'
|
|
22
|
+
import { withBasePath } from '@nextsparkjs/core/lib/base-path'
|
|
22
23
|
|
|
23
24
|
// Handle CORS preflight
|
|
24
25
|
export async function OPTIONS(request: NextRequest) {
|
|
@@ -294,7 +295,7 @@ export const POST = withRateLimitTier(withApiLogging(
|
|
|
294
295
|
|
|
295
296
|
// Build accept URL
|
|
296
297
|
const baseUrl = (process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:5173').replace(/\/$/, '')
|
|
297
|
-
const acceptUrl = `${baseUrl}
|
|
298
|
+
const acceptUrl = `${baseUrl}${withBasePath(`/accept-invite/${token}`)}`
|
|
298
299
|
|
|
299
300
|
// Send invitation email
|
|
300
301
|
try {
|
|
@@ -41,11 +41,9 @@ export const GET = withRateLimitTier(async function GET(request: NextRequest, pr
|
|
|
41
41
|
|
|
42
42
|
const subscription = await SubscriptionService.getActive(teamId)
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return createApiResponse({ subscription })
|
|
44
|
+
// A team can legitimately have no subscription yet. Keep that normal state
|
|
45
|
+
// in the successful response so dashboard loads do not log a 404.
|
|
46
|
+
return createApiResponse({ subscription: subscription ?? null })
|
|
49
47
|
} catch (error) {
|
|
50
48
|
console.error('[Billing API] Error fetching subscription:', error)
|
|
51
49
|
return createApiError('Failed to fetch subscription', 500)
|