@nextsparkjs/core 0.1.0-beta.82 → 0.1.0-beta.84
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/entities/wrappers/EntityDetailWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityDetailWrapper.js +11 -39
- package/dist/hooks/useEntityQuery.d.ts.map +1 -1
- package/dist/hooks/useEntityQuery.js +21 -3
- package/dist/lib/theme/get-default-theme-mode.d.ts +11 -0
- package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
- package/dist/lib/theme/get-default-theme-mode.js +42 -25
- package/dist/styles/classes.json +1 -1
- package/dist/types/theme.d.ts +2 -0
- package/dist/types/theme.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/templates/app/(auth)/forgot-password/page.tsx +0 -216
- package/dist/templates/app/(auth)/layout.tsx +0 -51
- package/dist/templates/app/(auth)/login/page.tsx +0 -21
- package/dist/templates/app/(auth)/reset-password/page.tsx +0 -212
- package/dist/templates/app/(auth)/signup/page.tsx +0 -21
- package/dist/templates/app/(auth)/verify-email/page.tsx +0 -190
- package/dist/templates/app/(public)/[...slug]/page.tsx +0 -378
- package/dist/templates/app/(public)/docs/[section]/[page]/page.tsx +0 -90
- package/dist/templates/app/(public)/docs/layout.tsx +0 -25
- package/dist/templates/app/(public)/docs/page.tsx +0 -81
- package/dist/templates/app/(public)/layout.tsx +0 -41
- package/dist/templates/app/(public)/page.tsx +0 -19
- package/dist/templates/app/403/page.tsx +0 -89
- package/dist/templates/app/api/auth/[...all]/route.ts +0 -78
- package/dist/templates/app/api/cron/billing/lifecycle/route.ts +0 -98
- package/dist/templates/app/api/csp-report/route.ts +0 -175
- package/dist/templates/app/api/devtools/config/entities/route.ts +0 -108
- package/dist/templates/app/api/devtools/config/theme/route.ts +0 -66
- package/dist/templates/app/api/devtools/tests/[...path]/route.ts +0 -130
- package/dist/templates/app/api/devtools/tests/route.ts +0 -134
- package/dist/templates/app/api/health/route.ts +0 -29
- package/dist/templates/app/api/internal/user-metadata/route.ts +0 -36
- package/dist/templates/app/api/superadmin/subscriptions/route.ts +0 -310
- package/dist/templates/app/api/superadmin/teams/[teamId]/route.ts +0 -286
- package/dist/templates/app/api/superadmin/teams/route.ts +0 -188
- package/dist/templates/app/api/superadmin/users/[userId]/route.ts +0 -540
- package/dist/templates/app/api/superadmin/users/route.ts +0 -323
- package/dist/templates/app/api/user/delete-account/route.ts +0 -55
- package/dist/templates/app/api/user/plan-flags/route.ts +0 -283
- package/dist/templates/app/api/user/profile/route.ts +0 -133
- package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +0 -210
- package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +0 -331
- package/dist/templates/app/api/v1/[entity]/[id]/route.ts +0 -35
- package/dist/templates/app/api/v1/[entity]/docs.md +0 -369
- package/dist/templates/app/api/v1/[entity]/presets.ts +0 -194
- package/dist/templates/app/api/v1/[entity]/route.ts +0 -31
- package/dist/templates/app/api/v1/api-keys/[id]/route.ts +0 -303
- package/dist/templates/app/api/v1/api-keys/docs.md +0 -101
- package/dist/templates/app/api/v1/api-keys/presets.ts +0 -31
- package/dist/templates/app/api/v1/api-keys/route.ts +0 -250
- package/dist/templates/app/api/v1/auth/docs.md +0 -184
- package/dist/templates/app/api/v1/auth/presets.ts +0 -44
- package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +0 -227
- package/dist/templates/app/api/v1/billing/cancel/route.ts +0 -206
- package/dist/templates/app/api/v1/billing/change-plan/route.ts +0 -97
- package/dist/templates/app/api/v1/billing/check-action/route.ts +0 -81
- package/dist/templates/app/api/v1/billing/checkout/route.ts +0 -124
- package/dist/templates/app/api/v1/billing/docs.md +0 -209
- package/dist/templates/app/api/v1/billing/plans/route.ts +0 -85
- package/dist/templates/app/api/v1/billing/portal/route.ts +0 -90
- package/dist/templates/app/api/v1/billing/presets.ts +0 -121
- package/dist/templates/app/api/v1/billing/webhooks/stripe/route.ts +0 -428
- package/dist/templates/app/api/v1/blocks/[slug]/route.ts +0 -29
- package/dist/templates/app/api/v1/blocks/docs.md +0 -173
- package/dist/templates/app/api/v1/blocks/presets.ts +0 -121
- package/dist/templates/app/api/v1/blocks/route.ts +0 -45
- package/dist/templates/app/api/v1/blocks/validate/route.ts +0 -45
- package/dist/templates/app/api/v1/cron/docs.md +0 -116
- package/dist/templates/app/api/v1/cron/presets.ts +0 -26
- package/dist/templates/app/api/v1/cron/process/route.ts +0 -108
- package/dist/templates/app/api/v1/devtools/blocks/route.ts +0 -82
- package/dist/templates/app/api/v1/devtools/docs/route.ts +0 -150
- package/dist/templates/app/api/v1/devtools/docs.md +0 -204
- package/dist/templates/app/api/v1/devtools/features/route.ts +0 -61
- package/dist/templates/app/api/v1/devtools/flows/route.ts +0 -61
- package/dist/templates/app/api/v1/devtools/presets.ts +0 -113
- package/dist/templates/app/api/v1/devtools/scheduled-actions/route.ts +0 -120
- package/dist/templates/app/api/v1/devtools/testing/route.ts +0 -82
- package/dist/templates/app/api/v1/media/docs.md +0 -117
- package/dist/templates/app/api/v1/media/presets.ts +0 -24
- package/dist/templates/app/api/v1/media/upload/route.ts +0 -150
- package/dist/templates/app/api/v1/patterns/[id]/usages/route.ts +0 -116
- package/dist/templates/app/api/v1/plugin/[...path]/route.ts +0 -373
- package/dist/templates/app/api/v1/plugin/docs.md +0 -79
- package/dist/templates/app/api/v1/plugin/presets.ts +0 -21
- package/dist/templates/app/api/v1/plugin/route.ts +0 -96
- package/dist/templates/app/api/v1/post-categories/[id]/route.ts +0 -255
- package/dist/templates/app/api/v1/post-categories/docs.md +0 -134
- package/dist/templates/app/api/v1/post-categories/presets.ts +0 -78
- package/dist/templates/app/api/v1/post-categories/route.ts +0 -119
- package/dist/templates/app/api/v1/team-invitations/[token]/accept/route.ts +0 -179
- package/dist/templates/app/api/v1/team-invitations/[token]/decline/route.ts +0 -120
- package/dist/templates/app/api/v1/team-invitations/[token]/route.ts +0 -89
- package/dist/templates/app/api/v1/team-invitations/docs.md +0 -88
- package/dist/templates/app/api/v1/team-invitations/presets.ts +0 -43
- package/dist/templates/app/api/v1/team-invitations/route.ts +0 -114
- package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +0 -171
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +0 -105
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +0 -125
- package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +0 -263
- package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +0 -358
- package/dist/templates/app/api/v1/teams/[teamId]/route.ts +0 -322
- package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +0 -50
- package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +0 -91
- package/dist/templates/app/api/v1/teams/docs.md +0 -320
- package/dist/templates/app/api/v1/teams/presets.ts +0 -178
- package/dist/templates/app/api/v1/teams/route.ts +0 -293
- package/dist/templates/app/api/v1/teams/switch/route.ts +0 -88
- package/dist/templates/app/api/v1/theme/[...path]/route.ts +0 -361
- package/dist/templates/app/api/v1/theme/docs.md +0 -74
- package/dist/templates/app/api/v1/theme/presets.ts +0 -21
- package/dist/templates/app/api/v1/theme/route.ts +0 -96
- package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +0 -363
- package/dist/templates/app/api/v1/users/[id]/route.ts +0 -302
- package/dist/templates/app/api/v1/users/docs.md +0 -93
- package/dist/templates/app/api/v1/users/presets.ts +0 -59
- package/dist/templates/app/api/v1/users/route.ts +0 -197
- package/dist/templates/app/dashboard/(main)/[entity]/[id]/edit/page.tsx +0 -117
- package/dist/templates/app/dashboard/(main)/[entity]/[id]/page.tsx +0 -103
- package/dist/templates/app/dashboard/(main)/[entity]/create/page.tsx +0 -95
- package/dist/templates/app/dashboard/(main)/[entity]/error.tsx +0 -51
- package/dist/templates/app/dashboard/(main)/[entity]/layout.tsx +0 -113
- package/dist/templates/app/dashboard/(main)/[entity]/loading.tsx +0 -61
- package/dist/templates/app/dashboard/(main)/[entity]/page.tsx +0 -90
- package/dist/templates/app/dashboard/(main)/layout.tsx +0 -98
- package/dist/templates/app/dashboard/(main)/loading.tsx +0 -5
- package/dist/templates/app/dashboard/(main)/page.tsx +0 -201
- package/dist/templates/app/dashboard/(main)/patterns/[id]/edit/page.tsx +0 -114
- package/dist/templates/app/dashboard/(main)/patterns/[id]/page.tsx +0 -20
- package/dist/templates/app/dashboard/(main)/patterns/[id]/reports/page.tsx +0 -171
- package/dist/templates/app/dashboard/(main)/patterns/create/page.tsx +0 -86
- package/dist/templates/app/dashboard/(main)/patterns/page.tsx +0 -444
- package/dist/templates/app/dashboard/features/analytics/page.tsx +0 -35
- package/dist/templates/app/dashboard/features/automation/page.tsx +0 -35
- package/dist/templates/app/dashboard/features/layout.tsx +0 -13
- package/dist/templates/app/dashboard/features/loading.tsx +0 -5
- package/dist/templates/app/dashboard/features/webhooks/page.tsx +0 -35
- package/dist/templates/app/dashboard/layout.tsx +0 -86
- package/dist/templates/app/dashboard/permission-denied/page.tsx +0 -29
- package/dist/templates/app/dashboard/settings/api-keys/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/api-keys/page.tsx +0 -513
- package/dist/templates/app/dashboard/settings/billing/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/billing/page.tsx +0 -284
- package/dist/templates/app/dashboard/settings/invoices/[invoiceNumber]/page.tsx +0 -222
- package/dist/templates/app/dashboard/settings/invoices/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/invoices/page.tsx +0 -82
- package/dist/templates/app/dashboard/settings/layout.tsx +0 -151
- package/dist/templates/app/dashboard/settings/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/notifications/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/notifications/page.tsx +0 -462
- package/dist/templates/app/dashboard/settings/page.tsx +0 -92
- package/dist/templates/app/dashboard/settings/password/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/password/page.tsx +0 -306
- package/dist/templates/app/dashboard/settings/plans/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/plans/page.tsx +0 -40
- package/dist/templates/app/dashboard/settings/profile/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/profile/page.tsx +0 -686
- package/dist/templates/app/dashboard/settings/security/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/security/page.tsx +0 -505
- package/dist/templates/app/dashboard/settings/teams/loading.tsx +0 -5
- package/dist/templates/app/dashboard/settings/teams/page.tsx +0 -272
- package/dist/templates/app/dashboard/settings/teams/permissions/page.tsx +0 -92
- package/dist/templates/app/devtools/blocks/[slug]/page.tsx +0 -39
- package/dist/templates/app/devtools/blocks/page.tsx +0 -31
- package/dist/templates/app/devtools/config/page.tsx +0 -31
- package/dist/templates/app/devtools/features/page.tsx +0 -31
- package/dist/templates/app/devtools/flows/page.tsx +0 -31
- package/dist/templates/app/devtools/layout.tsx +0 -58
- package/dist/templates/app/devtools/page.tsx +0 -121
- package/dist/templates/app/devtools/scheduled-actions/page.tsx +0 -157
- package/dist/templates/app/devtools/style/page.tsx +0 -330
- package/dist/templates/app/devtools/tags/page.tsx +0 -31
- package/dist/templates/app/devtools/tests/[[...path]]/page.tsx +0 -47
- package/dist/templates/app/favicon.ico +0 -0
- package/dist/templates/app/globals.css +0 -12
- package/dist/templates/app/layout.tsx +0 -96
- package/dist/templates/app/public/page.tsx +0 -30
- package/dist/templates/app/superadmin/docs/[section]/[page]/page.tsx +0 -92
- package/dist/templates/app/superadmin/docs/page.tsx +0 -75
- package/dist/templates/app/superadmin/layout.tsx +0 -67
- package/dist/templates/app/superadmin/page.tsx +0 -149
- package/dist/templates/app/superadmin/subscriptions/page.tsx +0 -655
- package/dist/templates/app/superadmin/team-roles/page.tsx +0 -493
- package/dist/templates/app/superadmin/teams/[teamId]/page.tsx +0 -687
- package/dist/templates/app/superadmin/teams/page.tsx +0 -302
- package/dist/templates/app/superadmin/users/[userId]/page.tsx +0 -548
- package/dist/templates/app/superadmin/users/page.tsx +0 -528
- package/templates/app/(auth)/forgot-password/page.tsx +0 -216
- package/templates/app/(auth)/layout.tsx +0 -51
- package/templates/app/(auth)/login/page.tsx +0 -21
- package/templates/app/(auth)/reset-password/page.tsx +0 -212
- package/templates/app/(auth)/signup/page.tsx +0 -21
- package/templates/app/(auth)/verify-email/page.tsx +0 -190
- package/templates/app/(public)/[...slug]/page.tsx +0 -378
- package/templates/app/(public)/docs/[section]/[page]/page.tsx +0 -90
- package/templates/app/(public)/docs/layout.tsx +0 -25
- package/templates/app/(public)/docs/page.tsx +0 -81
- package/templates/app/(public)/layout.tsx +0 -41
- package/templates/app/(public)/page.tsx +0 -19
- package/templates/app/403/page.tsx +0 -89
- package/templates/app/api/auth/[...all]/route.ts +0 -78
- package/templates/app/api/cron/billing/lifecycle/route.ts +0 -98
- package/templates/app/api/csp-report/route.ts +0 -175
- package/templates/app/api/devtools/config/entities/route.ts +0 -108
- package/templates/app/api/devtools/config/theme/route.ts +0 -66
- package/templates/app/api/devtools/tests/[...path]/route.ts +0 -130
- package/templates/app/api/devtools/tests/route.ts +0 -134
- package/templates/app/api/health/route.ts +0 -29
- package/templates/app/api/internal/user-metadata/route.ts +0 -36
- package/templates/app/api/superadmin/subscriptions/route.ts +0 -310
- package/templates/app/api/superadmin/teams/[teamId]/route.ts +0 -286
- package/templates/app/api/superadmin/teams/route.ts +0 -188
- package/templates/app/api/superadmin/users/[userId]/route.ts +0 -540
- package/templates/app/api/superadmin/users/route.ts +0 -323
- package/templates/app/api/user/delete-account/route.ts +0 -55
- package/templates/app/api/user/plan-flags/route.ts +0 -283
- package/templates/app/api/user/profile/route.ts +0 -133
- package/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +0 -210
- package/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +0 -331
- package/templates/app/api/v1/[entity]/[id]/route.ts +0 -35
- package/templates/app/api/v1/[entity]/docs.md +0 -369
- package/templates/app/api/v1/[entity]/presets.ts +0 -194
- package/templates/app/api/v1/[entity]/route.ts +0 -31
- package/templates/app/api/v1/api-keys/[id]/route.ts +0 -303
- package/templates/app/api/v1/api-keys/docs.md +0 -101
- package/templates/app/api/v1/api-keys/presets.ts +0 -31
- package/templates/app/api/v1/api-keys/route.ts +0 -250
- package/templates/app/api/v1/auth/docs.md +0 -184
- package/templates/app/api/v1/auth/presets.ts +0 -44
- package/templates/app/api/v1/auth/signup-with-invite/route.ts +0 -227
- package/templates/app/api/v1/billing/cancel/route.ts +0 -206
- package/templates/app/api/v1/billing/change-plan/route.ts +0 -97
- package/templates/app/api/v1/billing/check-action/route.ts +0 -81
- package/templates/app/api/v1/billing/checkout/route.ts +0 -124
- package/templates/app/api/v1/billing/docs.md +0 -209
- package/templates/app/api/v1/billing/plans/route.ts +0 -85
- package/templates/app/api/v1/billing/portal/route.ts +0 -90
- package/templates/app/api/v1/billing/presets.ts +0 -121
- package/templates/app/api/v1/billing/webhooks/stripe/route.ts +0 -428
- package/templates/app/api/v1/blocks/[slug]/route.ts +0 -29
- package/templates/app/api/v1/blocks/docs.md +0 -173
- package/templates/app/api/v1/blocks/presets.ts +0 -121
- package/templates/app/api/v1/blocks/route.ts +0 -45
- package/templates/app/api/v1/blocks/validate/route.ts +0 -45
- package/templates/app/api/v1/cron/docs.md +0 -116
- package/templates/app/api/v1/cron/presets.ts +0 -26
- package/templates/app/api/v1/cron/process/route.ts +0 -108
- package/templates/app/api/v1/devtools/blocks/route.ts +0 -82
- package/templates/app/api/v1/devtools/docs/route.ts +0 -150
- package/templates/app/api/v1/devtools/docs.md +0 -204
- package/templates/app/api/v1/devtools/features/route.ts +0 -61
- package/templates/app/api/v1/devtools/flows/route.ts +0 -61
- package/templates/app/api/v1/devtools/presets.ts +0 -113
- package/templates/app/api/v1/devtools/scheduled-actions/route.ts +0 -120
- package/templates/app/api/v1/devtools/testing/route.ts +0 -82
- package/templates/app/api/v1/media/docs.md +0 -117
- package/templates/app/api/v1/media/presets.ts +0 -24
- package/templates/app/api/v1/media/upload/route.ts +0 -150
- package/templates/app/api/v1/patterns/[id]/usages/route.ts +0 -116
- package/templates/app/api/v1/plugin/[...path]/route.ts +0 -373
- package/templates/app/api/v1/plugin/docs.md +0 -79
- package/templates/app/api/v1/plugin/presets.ts +0 -21
- package/templates/app/api/v1/plugin/route.ts +0 -96
- package/templates/app/api/v1/post-categories/[id]/route.ts +0 -255
- package/templates/app/api/v1/post-categories/docs.md +0 -134
- package/templates/app/api/v1/post-categories/presets.ts +0 -78
- package/templates/app/api/v1/post-categories/route.ts +0 -119
- package/templates/app/api/v1/team-invitations/[token]/accept/route.ts +0 -179
- package/templates/app/api/v1/team-invitations/[token]/decline/route.ts +0 -120
- package/templates/app/api/v1/team-invitations/[token]/route.ts +0 -89
- package/templates/app/api/v1/team-invitations/docs.md +0 -88
- package/templates/app/api/v1/team-invitations/presets.ts +0 -43
- package/templates/app/api/v1/team-invitations/route.ts +0 -114
- package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +0 -171
- package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +0 -105
- package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +0 -125
- package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +0 -263
- package/templates/app/api/v1/teams/[teamId]/members/route.ts +0 -358
- package/templates/app/api/v1/teams/[teamId]/route.ts +0 -322
- package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +0 -50
- package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +0 -91
- package/templates/app/api/v1/teams/docs.md +0 -320
- package/templates/app/api/v1/teams/presets.ts +0 -178
- package/templates/app/api/v1/teams/route.ts +0 -293
- package/templates/app/api/v1/teams/switch/route.ts +0 -88
- package/templates/app/api/v1/theme/[...path]/route.ts +0 -361
- package/templates/app/api/v1/theme/docs.md +0 -74
- package/templates/app/api/v1/theme/presets.ts +0 -21
- package/templates/app/api/v1/theme/route.ts +0 -96
- package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +0 -363
- package/templates/app/api/v1/users/[id]/route.ts +0 -302
- package/templates/app/api/v1/users/docs.md +0 -93
- package/templates/app/api/v1/users/presets.ts +0 -59
- package/templates/app/api/v1/users/route.ts +0 -197
- package/templates/app/dashboard/(main)/[entity]/[id]/edit/page.tsx +0 -117
- package/templates/app/dashboard/(main)/[entity]/[id]/page.tsx +0 -103
- package/templates/app/dashboard/(main)/[entity]/create/page.tsx +0 -95
- package/templates/app/dashboard/(main)/[entity]/error.tsx +0 -51
- package/templates/app/dashboard/(main)/[entity]/layout.tsx +0 -113
- package/templates/app/dashboard/(main)/[entity]/loading.tsx +0 -61
- package/templates/app/dashboard/(main)/[entity]/page.tsx +0 -90
- package/templates/app/dashboard/(main)/layout.tsx +0 -98
- package/templates/app/dashboard/(main)/loading.tsx +0 -5
- package/templates/app/dashboard/(main)/page.tsx +0 -201
- package/templates/app/dashboard/(main)/patterns/[id]/edit/page.tsx +0 -114
- package/templates/app/dashboard/(main)/patterns/[id]/page.tsx +0 -20
- package/templates/app/dashboard/(main)/patterns/[id]/reports/page.tsx +0 -171
- package/templates/app/dashboard/(main)/patterns/create/page.tsx +0 -86
- package/templates/app/dashboard/(main)/patterns/page.tsx +0 -444
- package/templates/app/dashboard/features/analytics/page.tsx +0 -35
- package/templates/app/dashboard/features/automation/page.tsx +0 -35
- package/templates/app/dashboard/features/layout.tsx +0 -13
- package/templates/app/dashboard/features/loading.tsx +0 -5
- package/templates/app/dashboard/features/webhooks/page.tsx +0 -35
- package/templates/app/dashboard/layout.tsx +0 -86
- package/templates/app/dashboard/permission-denied/page.tsx +0 -29
- package/templates/app/dashboard/settings/api-keys/loading.tsx +0 -5
- package/templates/app/dashboard/settings/api-keys/page.tsx +0 -513
- package/templates/app/dashboard/settings/billing/loading.tsx +0 -5
- package/templates/app/dashboard/settings/billing/page.tsx +0 -284
- package/templates/app/dashboard/settings/invoices/[invoiceNumber]/page.tsx +0 -222
- package/templates/app/dashboard/settings/invoices/loading.tsx +0 -5
- package/templates/app/dashboard/settings/invoices/page.tsx +0 -82
- package/templates/app/dashboard/settings/layout.tsx +0 -151
- package/templates/app/dashboard/settings/loading.tsx +0 -5
- package/templates/app/dashboard/settings/notifications/loading.tsx +0 -5
- package/templates/app/dashboard/settings/notifications/page.tsx +0 -462
- package/templates/app/dashboard/settings/page.tsx +0 -92
- package/templates/app/dashboard/settings/password/loading.tsx +0 -5
- package/templates/app/dashboard/settings/password/page.tsx +0 -306
- package/templates/app/dashboard/settings/plans/loading.tsx +0 -5
- package/templates/app/dashboard/settings/plans/page.tsx +0 -40
- package/templates/app/dashboard/settings/profile/loading.tsx +0 -5
- package/templates/app/dashboard/settings/profile/page.tsx +0 -686
- package/templates/app/dashboard/settings/security/loading.tsx +0 -5
- package/templates/app/dashboard/settings/security/page.tsx +0 -505
- package/templates/app/dashboard/settings/teams/loading.tsx +0 -5
- package/templates/app/dashboard/settings/teams/page.tsx +0 -272
- package/templates/app/dashboard/settings/teams/permissions/page.tsx +0 -92
- package/templates/app/devtools/blocks/[slug]/page.tsx +0 -39
- package/templates/app/devtools/blocks/page.tsx +0 -31
- package/templates/app/devtools/config/page.tsx +0 -31
- package/templates/app/devtools/features/page.tsx +0 -31
- package/templates/app/devtools/flows/page.tsx +0 -31
- package/templates/app/devtools/layout.tsx +0 -58
- package/templates/app/devtools/page.tsx +0 -121
- package/templates/app/devtools/scheduled-actions/page.tsx +0 -157
- package/templates/app/devtools/style/page.tsx +0 -330
- package/templates/app/devtools/tags/page.tsx +0 -31
- package/templates/app/devtools/tests/[[...path]]/page.tsx +0 -47
- package/templates/app/favicon.ico +0 -0
- package/templates/app/globals.css +0 -12
- package/templates/app/layout.tsx +0 -96
- package/templates/app/public/page.tsx +0 -30
- package/templates/app/superadmin/docs/[section]/[page]/page.tsx +0 -92
- package/templates/app/superadmin/docs/page.tsx +0 -75
- package/templates/app/superadmin/layout.tsx +0 -67
- package/templates/app/superadmin/page.tsx +0 -149
- package/templates/app/superadmin/subscriptions/page.tsx +0 -655
- package/templates/app/superadmin/team-roles/page.tsx +0 -493
- package/templates/app/superadmin/teams/[teamId]/page.tsx +0 -687
- package/templates/app/superadmin/teams/page.tsx +0 -302
- package/templates/app/superadmin/users/[userId]/page.tsx +0 -548
- package/templates/app/superadmin/users/page.tsx +0 -528
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server'
|
|
2
|
-
import { queryOneWithRLS, mutateWithRLS, getTransactionClient } from '@nextsparkjs/core/lib/db'
|
|
3
|
-
import {
|
|
4
|
-
createApiResponse,
|
|
5
|
-
createApiError,
|
|
6
|
-
withApiLogging,
|
|
7
|
-
handleCorsPreflightRequest,
|
|
8
|
-
addCorsHeaders,
|
|
9
|
-
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
|
-
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
-
import { checkRateLimit } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
|
-
import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
|
|
13
|
-
import type { TeamInvitation, TeamMember } from '@nextsparkjs/core/lib/teams/types'
|
|
14
|
-
|
|
15
|
-
// Handle CORS preflight
|
|
16
|
-
export async function OPTIONS() {
|
|
17
|
-
return handleCorsPreflightRequest()
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// POST /api/v1/team-invitations/:token/accept - Accept invitation and become member
|
|
21
|
-
export const POST = withApiLogging(
|
|
22
|
-
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
23
|
-
try {
|
|
24
|
-
// Authenticate using dual auth
|
|
25
|
-
const authResult = await authenticateRequest(req)
|
|
26
|
-
|
|
27
|
-
if (!authResult.success) {
|
|
28
|
-
return NextResponse.json(
|
|
29
|
-
{ success: false, error: 'Authentication required', code: 'AUTHENTICATION_FAILED' },
|
|
30
|
-
{ status: 401 }
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (authResult.rateLimitResponse) {
|
|
35
|
-
return authResult.rateLimitResponse as NextResponse
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Apply specific rate limit for invitation responses (50 req/min)
|
|
39
|
-
const rateLimitConfig = RATE_LIMITS['teams:invite:respond']
|
|
40
|
-
const rateLimitKey = `invite:respond:${authResult.user!.id}`
|
|
41
|
-
const rateLimit = checkRateLimit(rateLimitKey, rateLimitConfig.requests, rateLimitConfig.windowMs)
|
|
42
|
-
|
|
43
|
-
if (!rateLimit.allowed) {
|
|
44
|
-
const response = createApiError(
|
|
45
|
-
'Rate limit exceeded. Please try again later.',
|
|
46
|
-
429,
|
|
47
|
-
{ retryAfter: Math.ceil((rateLimit.resetTime - Date.now()) / 1000) },
|
|
48
|
-
'RATE_LIMIT_EXCEEDED'
|
|
49
|
-
)
|
|
50
|
-
return addCorsHeaders(response)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const { token } = await params
|
|
54
|
-
|
|
55
|
-
// Validate that token is not empty
|
|
56
|
-
if (!token || token.trim() === '') {
|
|
57
|
-
const response = createApiError('Invitation token is required', 400, null, 'MISSING_TOKEN')
|
|
58
|
-
return addCorsHeaders(response)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Get invitation by token
|
|
62
|
-
const invitation = await queryOneWithRLS<TeamInvitation>(
|
|
63
|
-
'SELECT * FROM "team_invitations" WHERE token = $1',
|
|
64
|
-
[token],
|
|
65
|
-
authResult.user!.id
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
if (!invitation) {
|
|
69
|
-
const response = createApiError('Invitation not found', 404, null, 'INVITATION_NOT_FOUND')
|
|
70
|
-
return addCorsHeaders(response)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Verify invitation is for the current user's email
|
|
74
|
-
if (invitation.email.toLowerCase() !== authResult.user!.email.toLowerCase()) {
|
|
75
|
-
const response = createApiError(
|
|
76
|
-
'This invitation is for a different email address',
|
|
77
|
-
403,
|
|
78
|
-
null,
|
|
79
|
-
'EMAIL_MISMATCH'
|
|
80
|
-
)
|
|
81
|
-
return addCorsHeaders(response)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Check if invitation is pending
|
|
85
|
-
if (invitation.status !== 'pending') {
|
|
86
|
-
const response = createApiError(
|
|
87
|
-
`Invitation has already been ${invitation.status}`,
|
|
88
|
-
409,
|
|
89
|
-
null,
|
|
90
|
-
'INVITATION_NOT_PENDING'
|
|
91
|
-
)
|
|
92
|
-
return addCorsHeaders(response)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Check if invitation has expired
|
|
96
|
-
const expiresAt = new Date(invitation.expiresAt)
|
|
97
|
-
if (expiresAt < new Date()) {
|
|
98
|
-
// Mark as expired
|
|
99
|
-
await mutateWithRLS(
|
|
100
|
-
'UPDATE "team_invitations" SET status = \'expired\', "updatedAt" = CURRENT_TIMESTAMP WHERE id = $1',
|
|
101
|
-
[invitation.id],
|
|
102
|
-
authResult.user!.id
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
const response = createApiError('Invitation has expired', 410, null, 'INVITATION_EXPIRED')
|
|
106
|
-
return addCorsHeaders(response)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check if user is already a member
|
|
110
|
-
const existingMember = await queryOneWithRLS<TeamMember>(
|
|
111
|
-
'SELECT * FROM "team_members" WHERE "teamId" = $1 AND "userId" = $2',
|
|
112
|
-
[invitation.teamId, authResult.user!.id],
|
|
113
|
-
authResult.user!.id
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
if (existingMember) {
|
|
117
|
-
const response = createApiError('You are already a member of this team', 409, null, 'ALREADY_MEMBER')
|
|
118
|
-
return addCorsHeaders(response)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Use transaction to ensure atomicity
|
|
122
|
-
const tx = await getTransactionClient(authResult.user!.id)
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
// Add user as team member
|
|
126
|
-
const [member] = await tx.query<TeamMember>(
|
|
127
|
-
`INSERT INTO "team_members" ("teamId", "userId", role, "invitedBy", "joinedAt")
|
|
128
|
-
VALUES ($1, $2, $3, $4, NOW())
|
|
129
|
-
RETURNING *`,
|
|
130
|
-
[invitation.teamId, authResult.user!.id, invitation.role, invitation.invitedBy]
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
if (!member) {
|
|
134
|
-
throw new Error('Failed to create team member')
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Update invitation status
|
|
138
|
-
await tx.query(
|
|
139
|
-
`UPDATE "team_invitations"
|
|
140
|
-
SET status = 'accepted', "acceptedAt" = NOW(), "updatedAt" = CURRENT_TIMESTAMP
|
|
141
|
-
WHERE id = $1`,
|
|
142
|
-
[invitation.id]
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
await tx.commit()
|
|
146
|
-
|
|
147
|
-
// Fetch member with user details
|
|
148
|
-
const memberWithUser = await queryOneWithRLS<
|
|
149
|
-
TeamMember & {
|
|
150
|
-
userName: string | null
|
|
151
|
-
userEmail: string
|
|
152
|
-
userImage: string | null
|
|
153
|
-
}
|
|
154
|
-
>(
|
|
155
|
-
`SELECT
|
|
156
|
-
tm.*,
|
|
157
|
-
u.name as "userName",
|
|
158
|
-
u.email as "userEmail",
|
|
159
|
-
u.image as "userImage"
|
|
160
|
-
FROM "team_members" tm
|
|
161
|
-
INNER JOIN "users" u ON tm."userId" = u.id
|
|
162
|
-
WHERE tm.id = $1`,
|
|
163
|
-
[member.id],
|
|
164
|
-
authResult.user!.id
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
const response = createApiResponse(memberWithUser, { created: true }, 201)
|
|
168
|
-
return addCorsHeaders(response)
|
|
169
|
-
} catch (error) {
|
|
170
|
-
await tx.rollback()
|
|
171
|
-
throw error
|
|
172
|
-
}
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error('Error accepting invitation:', error)
|
|
175
|
-
const response = createApiError('Internal server error', 500)
|
|
176
|
-
return addCorsHeaders(response)
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
)
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server'
|
|
2
|
-
import { queryOneWithRLS, mutateWithRLS } from '@nextsparkjs/core/lib/db'
|
|
3
|
-
import {
|
|
4
|
-
createApiResponse,
|
|
5
|
-
createApiError,
|
|
6
|
-
withApiLogging,
|
|
7
|
-
handleCorsPreflightRequest,
|
|
8
|
-
addCorsHeaders,
|
|
9
|
-
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
|
-
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
-
import { checkRateLimit } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
|
-
import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
|
|
13
|
-
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
14
|
-
|
|
15
|
-
// Handle CORS preflight
|
|
16
|
-
export async function OPTIONS() {
|
|
17
|
-
return handleCorsPreflightRequest()
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// POST /api/v1/team-invitations/:token/decline - Decline invitation
|
|
21
|
-
export const POST = withApiLogging(
|
|
22
|
-
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
23
|
-
try {
|
|
24
|
-
// Authenticate using dual auth
|
|
25
|
-
const authResult = await authenticateRequest(req)
|
|
26
|
-
|
|
27
|
-
if (!authResult.success) {
|
|
28
|
-
return NextResponse.json(
|
|
29
|
-
{ success: false, error: 'Authentication required', code: 'AUTHENTICATION_FAILED' },
|
|
30
|
-
{ status: 401 }
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (authResult.rateLimitResponse) {
|
|
35
|
-
return authResult.rateLimitResponse as NextResponse
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Apply specific rate limit for invitation responses (50 req/min)
|
|
39
|
-
const rateLimitConfig = RATE_LIMITS['teams:invite:respond']
|
|
40
|
-
const rateLimitKey = `invite:respond:${authResult.user!.id}`
|
|
41
|
-
const rateLimit = checkRateLimit(rateLimitKey, rateLimitConfig.requests, rateLimitConfig.windowMs)
|
|
42
|
-
|
|
43
|
-
if (!rateLimit.allowed) {
|
|
44
|
-
const response = createApiError(
|
|
45
|
-
'Rate limit exceeded. Please try again later.',
|
|
46
|
-
429,
|
|
47
|
-
{ retryAfter: Math.ceil((rateLimit.resetTime - Date.now()) / 1000) },
|
|
48
|
-
'RATE_LIMIT_EXCEEDED'
|
|
49
|
-
)
|
|
50
|
-
return addCorsHeaders(response)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const { token } = await params
|
|
54
|
-
|
|
55
|
-
// Validate that token is not empty
|
|
56
|
-
if (!token || token.trim() === '') {
|
|
57
|
-
const response = createApiError('Invitation token is required', 400, null, 'MISSING_TOKEN')
|
|
58
|
-
return addCorsHeaders(response)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Get invitation by token
|
|
62
|
-
const invitation = await queryOneWithRLS<TeamInvitation>(
|
|
63
|
-
'SELECT * FROM "team_invitations" WHERE token = $1',
|
|
64
|
-
[token],
|
|
65
|
-
authResult.user!.id
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
if (!invitation) {
|
|
69
|
-
const response = createApiError('Invitation not found', 404, null, 'INVITATION_NOT_FOUND')
|
|
70
|
-
return addCorsHeaders(response)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Verify invitation is for the current user's email
|
|
74
|
-
if (invitation.email.toLowerCase() !== authResult.user!.email.toLowerCase()) {
|
|
75
|
-
const response = createApiError(
|
|
76
|
-
'This invitation is for a different email address',
|
|
77
|
-
403,
|
|
78
|
-
null,
|
|
79
|
-
'EMAIL_MISMATCH'
|
|
80
|
-
)
|
|
81
|
-
return addCorsHeaders(response)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Check if invitation is pending
|
|
85
|
-
if (invitation.status !== 'pending') {
|
|
86
|
-
const response = createApiError(
|
|
87
|
-
`Invitation has already been ${invitation.status}`,
|
|
88
|
-
409,
|
|
89
|
-
null,
|
|
90
|
-
'INVITATION_NOT_PENDING'
|
|
91
|
-
)
|
|
92
|
-
return addCorsHeaders(response)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Update invitation status to declined
|
|
96
|
-
const result = await mutateWithRLS(
|
|
97
|
-
`UPDATE "team_invitations"
|
|
98
|
-
SET status = 'declined', "declinedAt" = NOW(), "updatedAt" = CURRENT_TIMESTAMP
|
|
99
|
-
WHERE id = $1
|
|
100
|
-
RETURNING *`,
|
|
101
|
-
[invitation.id],
|
|
102
|
-
authResult.user!.id
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
if (result.rows.length === 0) {
|
|
106
|
-
const response = createApiError('Invitation not found', 404, null, 'INVITATION_NOT_FOUND')
|
|
107
|
-
return addCorsHeaders(response)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const declinedInvitation = result.rows[0]
|
|
111
|
-
|
|
112
|
-
const response = createApiResponse(declinedInvitation)
|
|
113
|
-
return addCorsHeaders(response)
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error('Error declining invitation:', error)
|
|
116
|
-
const response = createApiError('Internal server error', 500)
|
|
117
|
-
return addCorsHeaders(response)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
)
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server'
|
|
2
|
-
import { queryOne } from '@nextsparkjs/core/lib/db'
|
|
3
|
-
import {
|
|
4
|
-
createApiResponse,
|
|
5
|
-
createApiError,
|
|
6
|
-
withApiLogging,
|
|
7
|
-
handleCorsPreflightRequest,
|
|
8
|
-
addCorsHeaders,
|
|
9
|
-
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
|
-
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
11
|
-
|
|
12
|
-
// Handle CORS preflight
|
|
13
|
-
export async function OPTIONS() {
|
|
14
|
-
return handleCorsPreflightRequest()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// GET /api/v1/team-invitations/:token - Get invitation details (public endpoint for preview)
|
|
18
|
-
export const GET = withApiLogging(
|
|
19
|
-
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
20
|
-
try {
|
|
21
|
-
const { token } = await params
|
|
22
|
-
|
|
23
|
-
// Validate that token is not empty
|
|
24
|
-
if (!token || token.trim() === '') {
|
|
25
|
-
const response = createApiError('Invitation token is required', 400, null, 'MISSING_TOKEN')
|
|
26
|
-
return addCorsHeaders(response)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Get invitation by token with team and inviter details
|
|
30
|
-
const invitation = await queryOne<
|
|
31
|
-
TeamInvitation & {
|
|
32
|
-
teamName: string
|
|
33
|
-
inviterName: string | null
|
|
34
|
-
inviterEmail: string
|
|
35
|
-
}
|
|
36
|
-
>(
|
|
37
|
-
`SELECT
|
|
38
|
-
ti.*,
|
|
39
|
-
t.name as "teamName",
|
|
40
|
-
u.name as "inviterName",
|
|
41
|
-
u.email as "inviterEmail"
|
|
42
|
-
FROM "team_invitations" ti
|
|
43
|
-
INNER JOIN "teams" t ON ti."teamId" = t.id
|
|
44
|
-
INNER JOIN "users" u ON ti."invitedBy" = u.id
|
|
45
|
-
WHERE ti.token = $1`,
|
|
46
|
-
[token]
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
if (!invitation) {
|
|
50
|
-
const response = createApiError('Invitation not found', 404, null, 'INVITATION_NOT_FOUND')
|
|
51
|
-
return addCorsHeaders(response)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Check if invitation has expired
|
|
55
|
-
const expiresAt = new Date(invitation.expiresAt)
|
|
56
|
-
if (expiresAt < new Date()) {
|
|
57
|
-
const response = createApiError('Invitation has expired', 410, null, 'INVITATION_EXPIRED')
|
|
58
|
-
return addCorsHeaders(response)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Check if invitation is still pending
|
|
62
|
-
if (invitation.status !== 'pending') {
|
|
63
|
-
const response = createApiError(
|
|
64
|
-
`Invitation has already been ${invitation.status}`,
|
|
65
|
-
409,
|
|
66
|
-
null,
|
|
67
|
-
`INVITATION_${invitation.status.toUpperCase()}`
|
|
68
|
-
)
|
|
69
|
-
return addCorsHeaders(response)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Return public invitation details (don't expose sensitive data)
|
|
73
|
-
const publicDetails = {
|
|
74
|
-
teamName: invitation.teamName,
|
|
75
|
-
inviterName: invitation.inviterName || invitation.inviterEmail,
|
|
76
|
-
role: invitation.role,
|
|
77
|
-
email: invitation.email,
|
|
78
|
-
expiresAt: invitation.expiresAt
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const response = createApiResponse(publicDetails)
|
|
82
|
-
return addCorsHeaders(response)
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error('Error fetching invitation:', error)
|
|
85
|
-
const response = createApiError('Internal server error', 500)
|
|
86
|
-
return addCorsHeaders(response)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
)
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# Team Invitations API
|
|
2
|
-
|
|
3
|
-
Manage team invitations for adding new members to teams.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The Team Invitations API allows you to create, list, and manage pending invitations to join a team. Invitations are sent via email and can be accepted by the recipient.
|
|
8
|
-
|
|
9
|
-
## Authentication
|
|
10
|
-
|
|
11
|
-
All endpoints require authentication via:
|
|
12
|
-
- **Session cookie** (for browser-based requests)
|
|
13
|
-
- **API Key** header (for server-to-server requests)
|
|
14
|
-
|
|
15
|
-
## Endpoints
|
|
16
|
-
|
|
17
|
-
### List Invitations
|
|
18
|
-
`GET /api/v1/team-invitations`
|
|
19
|
-
|
|
20
|
-
Returns all pending invitations for the current team.
|
|
21
|
-
|
|
22
|
-
**Example Response:**
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"data": [
|
|
26
|
-
{
|
|
27
|
-
"id": "inv_123",
|
|
28
|
-
"email": "newuser@example.com",
|
|
29
|
-
"role": "member",
|
|
30
|
-
"status": "pending",
|
|
31
|
-
"expiresAt": "2024-02-15T10:30:00Z",
|
|
32
|
-
"createdAt": "2024-01-15T10:30:00Z"
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Create Invitation
|
|
39
|
-
`POST /api/v1/team-invitations`
|
|
40
|
-
|
|
41
|
-
Send a new invitation to join the team.
|
|
42
|
-
|
|
43
|
-
**Request Body:**
|
|
44
|
-
```json
|
|
45
|
-
{
|
|
46
|
-
"email": "newuser@example.com",
|
|
47
|
-
"role": "member"
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**Roles:**
|
|
52
|
-
- `member` - Basic team member
|
|
53
|
-
- `admin` - Can manage team settings and members
|
|
54
|
-
- `owner` - Full control (only one per team)
|
|
55
|
-
|
|
56
|
-
### Cancel Invitation
|
|
57
|
-
`DELETE /api/v1/team-invitations/[id]`
|
|
58
|
-
|
|
59
|
-
Cancel a pending invitation.
|
|
60
|
-
|
|
61
|
-
**Path Parameters:**
|
|
62
|
-
- `id` (string, required): Invitation ID
|
|
63
|
-
|
|
64
|
-
### Resend Invitation
|
|
65
|
-
`POST /api/v1/team-invitations/[id]/resend`
|
|
66
|
-
|
|
67
|
-
Resend the invitation email.
|
|
68
|
-
|
|
69
|
-
**Path Parameters:**
|
|
70
|
-
- `id` (string, required): Invitation ID
|
|
71
|
-
|
|
72
|
-
## Invitation Flow
|
|
73
|
-
|
|
74
|
-
1. Admin creates invitation with email and role
|
|
75
|
-
2. System sends invitation email with unique link
|
|
76
|
-
3. Recipient clicks link and signs up/signs in
|
|
77
|
-
4. User is automatically added to the team
|
|
78
|
-
|
|
79
|
-
## Error Responses
|
|
80
|
-
|
|
81
|
-
| Status | Description |
|
|
82
|
-
|--------|-------------|
|
|
83
|
-
| 400 | Bad Request - Invalid parameters |
|
|
84
|
-
| 401 | Unauthorized - Missing or invalid auth |
|
|
85
|
-
| 403 | Forbidden - Insufficient permissions |
|
|
86
|
-
| 404 | Not Found - Invitation doesn't exist |
|
|
87
|
-
| 409 | Conflict - User already in team or invitation pending |
|
|
88
|
-
| 422 | Validation Error - Invalid email |
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API Presets for Team Invitations
|
|
3
|
-
*
|
|
4
|
-
* These presets appear in the DevTools API Explorer's "Presets" tab.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { defineApiEndpoint } from '@nextsparkjs/core/types/api-presets'
|
|
8
|
-
|
|
9
|
-
export default defineApiEndpoint({
|
|
10
|
-
endpoint: '/api/v1/team-invitations',
|
|
11
|
-
summary: 'Manage team invitations for new members',
|
|
12
|
-
presets: [
|
|
13
|
-
{
|
|
14
|
-
id: 'list-pending',
|
|
15
|
-
title: 'List Pending Invitations',
|
|
16
|
-
description: 'Fetch all pending invitations for the team',
|
|
17
|
-
method: 'GET',
|
|
18
|
-
tags: ['read', 'list']
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
id: 'invite-member',
|
|
22
|
-
title: 'Invite as Member',
|
|
23
|
-
description: 'Send invitation with member role',
|
|
24
|
-
method: 'POST',
|
|
25
|
-
payload: {
|
|
26
|
-
email: 'newuser@example.com',
|
|
27
|
-
role: 'member'
|
|
28
|
-
},
|
|
29
|
-
tags: ['write', 'create', 'invite']
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: 'invite-admin',
|
|
33
|
-
title: 'Invite as Admin',
|
|
34
|
-
description: 'Send invitation with admin role',
|
|
35
|
-
method: 'POST',
|
|
36
|
-
payload: {
|
|
37
|
-
email: 'admin@example.com',
|
|
38
|
-
role: 'admin'
|
|
39
|
-
},
|
|
40
|
-
tags: ['write', 'create', 'invite', 'admin']
|
|
41
|
-
}
|
|
42
|
-
]
|
|
43
|
-
})
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from 'next/server'
|
|
2
|
-
import { queryWithRLS } from '@nextsparkjs/core/lib/db'
|
|
3
|
-
import {
|
|
4
|
-
createApiResponse,
|
|
5
|
-
createApiError,
|
|
6
|
-
createPaginationMeta,
|
|
7
|
-
withApiLogging,
|
|
8
|
-
handleCorsPreflightRequest,
|
|
9
|
-
addCorsHeaders,
|
|
10
|
-
} from '@nextsparkjs/core/lib/api/helpers'
|
|
11
|
-
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
|
-
import { invitationListQuerySchema } from '@nextsparkjs/core/lib/teams/schema'
|
|
13
|
-
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
14
|
-
|
|
15
|
-
// Handle CORS preflight
|
|
16
|
-
export async function OPTIONS() {
|
|
17
|
-
return handleCorsPreflightRequest()
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// GET /api/v1/team-invitations - List pending invitations for current user
|
|
21
|
-
export const GET = withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
|
|
22
|
-
try {
|
|
23
|
-
// Authenticate using dual auth
|
|
24
|
-
const authResult = await authenticateRequest(req)
|
|
25
|
-
|
|
26
|
-
if (!authResult.success) {
|
|
27
|
-
return NextResponse.json(
|
|
28
|
-
{ success: false, error: 'Authentication required', code: 'AUTHENTICATION_FAILED' },
|
|
29
|
-
{ status: 401 }
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (authResult.rateLimitResponse) {
|
|
34
|
-
return authResult.rateLimitResponse as NextResponse
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Get user email to find invitations
|
|
38
|
-
const userEmail = authResult.user!.email
|
|
39
|
-
|
|
40
|
-
// Parse query parameters
|
|
41
|
-
const { searchParams } = new URL(req.url)
|
|
42
|
-
const queryParams = {
|
|
43
|
-
page: searchParams.get('page'),
|
|
44
|
-
limit: searchParams.get('limit'),
|
|
45
|
-
status: searchParams.get('status'),
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const validatedQuery = invitationListQuerySchema.parse(queryParams)
|
|
49
|
-
const { page, limit, status } = validatedQuery
|
|
50
|
-
const offset = (page - 1) * limit
|
|
51
|
-
|
|
52
|
-
// Build WHERE clause based on filters
|
|
53
|
-
let whereClause = 'WHERE ti.email = $1'
|
|
54
|
-
const queryValues: unknown[] = [userEmail]
|
|
55
|
-
let paramCount = 2
|
|
56
|
-
|
|
57
|
-
if (status) {
|
|
58
|
-
whereClause += ` AND ti.status = $${paramCount}`
|
|
59
|
-
queryValues.push(status)
|
|
60
|
-
paramCount++
|
|
61
|
-
} else {
|
|
62
|
-
// Default to pending invitations only
|
|
63
|
-
whereClause += ` AND ti.status = $${paramCount}`
|
|
64
|
-
queryValues.push('pending')
|
|
65
|
-
paramCount++
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Add pagination params
|
|
69
|
-
queryValues.push(limit, offset)
|
|
70
|
-
|
|
71
|
-
const invitations = await queryWithRLS<
|
|
72
|
-
TeamInvitation & {
|
|
73
|
-
teamName: string
|
|
74
|
-
teamSlug: string
|
|
75
|
-
inviterName: string | null
|
|
76
|
-
inviterEmail: string
|
|
77
|
-
}
|
|
78
|
-
>(
|
|
79
|
-
`SELECT
|
|
80
|
-
ti.*,
|
|
81
|
-
t.name as "teamName",
|
|
82
|
-
t.slug as "teamSlug",
|
|
83
|
-
u.name as "inviterName",
|
|
84
|
-
u.email as "inviterEmail"
|
|
85
|
-
FROM "team_invitations" ti
|
|
86
|
-
INNER JOIN "teams" t ON ti."teamId" = t.id
|
|
87
|
-
INNER JOIN "users" u ON ti."invitedBy" = u.id
|
|
88
|
-
${whereClause}
|
|
89
|
-
ORDER BY ti."createdAt" DESC
|
|
90
|
-
LIMIT $${paramCount++} OFFSET $${paramCount++}`,
|
|
91
|
-
queryValues,
|
|
92
|
-
authResult.user!.id
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
// Get total count for pagination
|
|
96
|
-
const totalResult = await queryWithRLS<{ count: string }>(
|
|
97
|
-
`SELECT COUNT(*) as count
|
|
98
|
-
FROM "team_invitations" ti
|
|
99
|
-
${whereClause}`,
|
|
100
|
-
queryValues.slice(0, -2), // Remove limit and offset
|
|
101
|
-
authResult.user!.id
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
const total = parseInt(totalResult[0]?.count || '0', 10)
|
|
105
|
-
const paginationMeta = createPaginationMeta(page, limit, total)
|
|
106
|
-
|
|
107
|
-
const response = createApiResponse(invitations, paginationMeta)
|
|
108
|
-
return addCorsHeaders(response)
|
|
109
|
-
} catch (error) {
|
|
110
|
-
console.error('Error fetching invitations:', error)
|
|
111
|
-
const response = createApiError('Internal server error', 500)
|
|
112
|
-
return addCorsHeaders(response)
|
|
113
|
-
}
|
|
114
|
-
})
|