@nextsparkjs/core 0.1.0-beta.92 → 0.1.0-beta.94
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/dashboard/block-editor/array-field.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/array-field.js +55 -3
- package/dist/components/dashboard/block-editor/dynamic-form.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/dynamic-form.js +82 -2
- package/dist/components/dashboard/navigation/DynamicNavigation.d.ts.map +1 -1
- package/dist/components/dashboard/navigation/DynamicNavigation.js +7 -1
- package/dist/components/devtools/scheduled-actions/actions-table.d.ts +1 -0
- package/dist/components/devtools/scheduled-actions/actions-table.d.ts.map +1 -1
- package/dist/components/devtools/scheduled-actions/actions-table.js +182 -46
- package/dist/components/devtools/scheduled-actions/types.d.ts +1 -0
- package/dist/components/devtools/scheduled-actions/types.d.ts.map +1 -1
- package/dist/components/media/MediaCard.d.ts +23 -0
- package/dist/components/media/MediaCard.d.ts.map +1 -0
- package/dist/components/media/MediaCard.js +154 -0
- package/dist/components/media/MediaDetailPanel.d.ts +17 -0
- package/dist/components/media/MediaDetailPanel.d.ts.map +1 -0
- package/dist/components/media/MediaDetailPanel.js +331 -0
- package/dist/components/media/MediaGrid.d.ts +26 -0
- package/dist/components/media/MediaGrid.d.ts.map +1 -0
- package/dist/components/media/MediaGrid.js +77 -0
- package/dist/components/media/MediaLibrary.d.ts +20 -0
- package/dist/components/media/MediaLibrary.d.ts.map +1 -0
- package/dist/components/media/MediaLibrary.js +229 -0
- package/dist/components/media/MediaList.d.ts +24 -0
- package/dist/components/media/MediaList.d.ts.map +1 -0
- package/dist/components/media/MediaList.js +181 -0
- package/dist/components/media/MediaSelector.d.ts +19 -0
- package/dist/components/media/MediaSelector.d.ts.map +1 -0
- package/dist/components/media/MediaSelector.js +145 -0
- package/dist/components/media/MediaTagFilter.d.ts +16 -0
- package/dist/components/media/MediaTagFilter.d.ts.map +1 -0
- package/dist/components/media/MediaTagFilter.js +122 -0
- package/dist/components/media/MediaToolbar.d.ts +25 -0
- package/dist/components/media/MediaToolbar.d.ts.map +1 -0
- package/dist/components/media/MediaToolbar.js +136 -0
- package/dist/components/media/MediaUploadZone.d.ts +19 -0
- package/dist/components/media/MediaUploadZone.d.ts.map +1 -0
- package/dist/components/media/MediaUploadZone.js +248 -0
- package/dist/components/media/index.d.ts +15 -0
- package/dist/components/media/index.d.ts.map +1 -0
- package/dist/components/media/index.js +20 -0
- package/dist/contexts/TeamContext.js +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useEnsureUserMetadata.d.ts +4 -0
- package/dist/hooks/useEnsureUserMetadata.d.ts.map +1 -1
- package/dist/hooks/useEnsureUserMetadata.js +85 -60
- package/dist/hooks/useEntityMutations.d.ts.map +1 -1
- package/dist/hooks/useEntityMutations.js +5 -9
- package/dist/hooks/useMedia.d.ts +56 -0
- package/dist/hooks/useMedia.d.ts.map +1 -0
- package/dist/hooks/useMedia.js +181 -0
- package/dist/hooks/useMediaUpload.d.ts +27 -0
- package/dist/hooks/useMediaUpload.d.ts.map +1 -0
- package/dist/hooks/useMediaUpload.js +36 -0
- package/dist/hooks/useUserSettings.d.ts +5 -4
- package/dist/hooks/useUserSettings.d.ts.map +1 -1
- package/dist/hooks/useUserSettings.js +42 -40
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/lib/api/auth/dual-auth.d.ts +6 -2
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +5 -9
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +3 -3
- package/dist/lib/config/app.config.d.ts.map +1 -1
- package/dist/lib/config/app.config.js +37 -0
- package/dist/lib/config/config-sync.d.ts +1 -0
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +2 -0
- package/dist/lib/config/types.d.ts +29 -0
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/media/schemas.d.ts +39 -0
- package/dist/lib/media/schemas.d.ts.map +1 -0
- package/dist/lib/media/schemas.js +32 -0
- package/dist/lib/media/types.d.ts +69 -0
- package/dist/lib/media/types.d.ts.map +1 -0
- package/dist/lib/media/types.js +0 -0
- package/dist/lib/media/utils.d.ts +26 -0
- package/dist/lib/media/utils.d.ts.map +1 -0
- package/dist/lib/media/utils.js +33 -0
- package/dist/lib/rate-limit-redis.d.ts.map +1 -1
- package/dist/lib/rate-limit-redis.js +13 -4
- package/dist/lib/scheduled-actions/initializer.d.ts +6 -3
- package/dist/lib/scheduled-actions/initializer.d.ts.map +1 -1
- package/dist/lib/scheduled-actions/initializer.js +11 -6
- package/dist/lib/scheduled-actions/processor.d.ts +20 -4
- package/dist/lib/scheduled-actions/processor.d.ts.map +1 -1
- package/dist/lib/scheduled-actions/processor.js +128 -34
- package/dist/lib/scheduled-actions/registry.d.ts +3 -0
- package/dist/lib/scheduled-actions/registry.d.ts.map +1 -1
- package/dist/lib/scheduled-actions/registry.js +2 -1
- package/dist/lib/scheduled-actions/scheduler.d.ts +1 -1
- package/dist/lib/scheduled-actions/scheduler.d.ts.map +1 -1
- package/dist/lib/scheduled-actions/scheduler.js +76 -38
- package/dist/lib/scheduled-actions/types.d.ts +73 -0
- package/dist/lib/scheduled-actions/types.d.ts.map +1 -1
- package/dist/lib/selectors/core-selectors.d.ts +102 -0
- package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
- package/dist/lib/selectors/core-selectors.js +3 -1
- package/dist/lib/selectors/domains/block-editor.selectors.d.ts +8 -0
- package/dist/lib/selectors/domains/block-editor.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/block-editor.selectors.js +9 -0
- package/dist/lib/selectors/domains/devtools.selectors.d.ts +6 -0
- package/dist/lib/selectors/domains/devtools.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/devtools.selectors.js +6 -0
- package/dist/lib/selectors/domains/index.d.ts +1 -0
- package/dist/lib/selectors/domains/index.d.ts.map +1 -1
- package/dist/lib/selectors/domains/index.js +2 -0
- package/dist/lib/selectors/domains/media.selectors.d.ts +96 -0
- package/dist/lib/selectors/domains/media.selectors.d.ts.map +1 -0
- package/dist/lib/selectors/domains/media.selectors.js +103 -0
- package/dist/lib/selectors/selectors.d.ts +204 -0
- package/dist/lib/selectors/selectors.d.ts.map +1 -1
- package/dist/lib/services/index.d.ts +2 -0
- package/dist/lib/services/index.d.ts.map +1 -1
- package/dist/lib/services/index.js +2 -0
- package/dist/lib/services/media.service.d.ts +158 -0
- package/dist/lib/services/media.service.d.ts.map +1 -0
- package/dist/lib/services/media.service.js +410 -0
- package/dist/messages/de/devtools.json +16 -0
- package/dist/messages/de/index.d.ts +16 -0
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/en/admin.json +4 -1
- package/dist/messages/en/devtools.json +16 -0
- package/dist/messages/en/index.d.ts +167 -0
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/en/index.js +2 -0
- package/dist/messages/en/index.ts +2 -0
- package/dist/messages/en/media.json +147 -0
- package/dist/messages/en/navigation.json +1 -0
- package/dist/messages/es/admin.json +4 -1
- package/dist/messages/es/devtools.json +16 -0
- package/dist/messages/es/index.d.ts +167 -0
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/es/index.js +2 -0
- package/dist/messages/es/index.ts +2 -0
- package/dist/messages/es/media.json +147 -0
- package/dist/messages/es/navigation.json +1 -0
- package/dist/messages/fr/devtools.json +16 -0
- package/dist/messages/fr/index.d.ts +16 -0
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/it/devtools.json +16 -0
- package/dist/messages/it/index.d.ts +16 -0
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/pt/devtools.json +16 -0
- package/dist/messages/pt/index.d.ts +16 -0
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/migrations/017_scheduled_actions_table.sql +21 -0
- package/dist/migrations/021_media.sql +154 -0
- package/dist/migrations/090_sample_data.sql +53 -0
- package/dist/styles/classes.json +36 -3
- package/dist/styles/ui.css +1 -1
- package/dist/templates/app/api/devtools/config/entities/route.ts +18 -11
- package/dist/templates/app/api/devtools/config/theme/route.ts +5 -4
- package/dist/templates/app/api/devtools/tests/[...path]/route.ts +6 -5
- package/dist/templates/app/api/devtools/tests/route.ts +5 -4
- package/dist/templates/app/api/health/route.ts +6 -4
- package/dist/templates/app/api/internal/user-metadata/route.ts +3 -2
- package/dist/templates/app/api/superadmin/subscriptions/route.ts +5 -6
- package/dist/templates/app/api/superadmin/teams/[teamId]/route.ts +6 -7
- package/dist/templates/app/api/superadmin/teams/route.ts +5 -6
- package/dist/templates/app/api/superadmin/users/[userId]/route.ts +11 -16
- package/dist/templates/app/api/superadmin/users/route.ts +9 -10
- package/dist/templates/app/api/user/delete-account/route.ts +3 -2
- package/dist/templates/app/api/user/plan-flags/route.ts +11 -24
- package/dist/templates/app/api/user/profile/route.ts +7 -6
- package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +16 -18
- package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +17 -19
- package/dist/templates/app/api/v1/[entity]/[id]/route.ts +10 -12
- package/dist/templates/app/api/v1/[entity]/route.ts +9 -11
- package/dist/templates/app/api/v1/api-keys/[id]/route.ts +9 -8
- package/dist/templates/app/api/v1/api-keys/route.ts +7 -6
- package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +3 -2
- package/dist/templates/app/api/v1/billing/cancel/route.ts +15 -14
- package/dist/templates/app/api/v1/billing/change-plan/route.ts +10 -9
- package/dist/templates/app/api/v1/billing/check-action/route.ts +8 -7
- package/dist/templates/app/api/v1/billing/checkout/route.ts +10 -9
- package/dist/templates/app/api/v1/billing/plans/route.ts +5 -4
- package/dist/templates/app/api/v1/billing/portal/route.ts +9 -8
- package/dist/templates/app/api/v1/blocks/[slug]/route.ts +4 -3
- package/dist/templates/app/api/v1/blocks/route.ts +3 -2
- package/dist/templates/app/api/v1/blocks/validate/route.ts +5 -3
- package/dist/templates/app/api/v1/cron/process/route.ts +4 -6
- package/dist/templates/app/api/v1/devtools/blocks/route.ts +3 -2
- package/dist/templates/app/api/v1/devtools/docs/route.ts +3 -2
- package/dist/templates/app/api/v1/devtools/features/route.ts +3 -2
- package/dist/templates/app/api/v1/devtools/flows/route.ts +3 -2
- package/dist/templates/app/api/v1/devtools/scheduled-actions/route.ts +125 -3
- package/dist/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +110 -0
- package/dist/templates/app/api/v1/devtools/testing/route.ts +3 -2
- package/dist/templates/app/api/v1/media/[id]/route.ts +144 -0
- package/dist/templates/app/api/v1/media/[id]/tags/route.ts +154 -0
- package/dist/templates/app/api/v1/media/check-duplicates/route.ts +56 -0
- package/dist/templates/app/api/v1/media/route.ts +56 -0
- package/dist/templates/app/api/v1/media/upload/route.ts +157 -33
- package/dist/templates/app/api/v1/media-tags/route.ts +65 -0
- package/dist/templates/app/api/v1/plugin/[...path]/route.ts +16 -15
- package/dist/templates/app/api/v1/plugin/route.ts +3 -2
- package/dist/templates/app/api/v1/post-categories/[id]/route.ts +10 -9
- package/dist/templates/app/api/v1/post-categories/route.ts +5 -4
- package/dist/templates/app/api/v1/team-invitations/[token]/accept/route.ts +3 -3
- package/dist/templates/app/api/v1/team-invitations/[token]/decline/route.ts +3 -3
- package/dist/templates/app/api/v1/team-invitations/[token]/route.ts +3 -2
- package/dist/templates/app/api/v1/team-invitations/route.ts +3 -2
- package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +5 -4
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +3 -2
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +3 -2
- package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +5 -4
- package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +5 -5
- package/dist/templates/app/api/v1/teams/[teamId]/route.ts +31 -58
- package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -2
- package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +5 -4
- package/dist/templates/app/api/v1/teams/route.ts +18 -17
- package/dist/templates/app/api/v1/teams/switch/route.ts +3 -2
- package/dist/templates/app/api/v1/theme/[...path]/route.ts +16 -15
- package/dist/templates/app/api/v1/theme/route.ts +3 -2
- package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +7 -6
- package/dist/templates/app/api/v1/users/[id]/route.ts +9 -8
- package/dist/templates/app/api/v1/users/route.ts +7 -6
- package/dist/templates/app/dashboard/(main)/media/page.tsx +607 -0
- package/dist/templates/contents/themes/starter/messages/de/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/de/index.ts +2 -0
- package/dist/templates/contents/themes/starter/messages/en/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/en/index.ts +2 -0
- package/dist/templates/contents/themes/starter/messages/es/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/es/index.ts +2 -0
- package/dist/templates/contents/themes/starter/messages/fr/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/fr/index.ts +2 -0
- package/dist/templates/contents/themes/starter/messages/it/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/it/index.ts +2 -0
- package/dist/templates/contents/themes/starter/messages/pt/dev.json +106 -0
- package/dist/templates/contents/themes/starter/messages/pt/index.ts +2 -0
- package/dist/templates/contents/themes/starter/styles/globals.css +14 -0
- package/dist/templates/instrumentation.ts +33 -0
- package/dist/types/blocks.d.ts +1 -1
- package/dist/types/blocks.d.ts.map +1 -1
- package/migrations/017_scheduled_actions_table.sql +21 -0
- package/migrations/021_media.sql +154 -0
- package/migrations/090_sample_data.sql +53 -0
- package/package.json +3 -2
- package/scripts/build/registry/config.mjs +41 -0
- package/scripts/build/registry/discovery/templates.mjs +0 -1
- package/scripts/build/registry/generators/entity-registry.mjs +16 -6
- package/scripts/build/registry/generators/route-handlers.mjs +8 -2
- package/scripts/build/registry/generators/template-registry.mjs +16 -4
- package/scripts/build/registry/post-build/route-cleanup.mjs +0 -1
- package/scripts/build/registry/validate-env.test.mjs +92 -0
- package/scripts/build/registry.mjs +18 -1
- package/scripts/deploy/vercel-deploy.mjs +1 -1
- package/templates/app/api/devtools/config/entities/route.ts +18 -11
- package/templates/app/api/devtools/config/theme/route.ts +5 -4
- package/templates/app/api/devtools/tests/[...path]/route.ts +6 -5
- package/templates/app/api/devtools/tests/route.ts +5 -4
- package/templates/app/api/health/route.ts +6 -4
- package/templates/app/api/internal/user-metadata/route.ts +3 -2
- package/templates/app/api/superadmin/subscriptions/route.ts +5 -6
- package/templates/app/api/superadmin/teams/[teamId]/route.ts +6 -7
- package/templates/app/api/superadmin/teams/route.ts +5 -6
- package/templates/app/api/superadmin/users/[userId]/route.ts +11 -16
- package/templates/app/api/superadmin/users/route.ts +9 -10
- package/templates/app/api/user/delete-account/route.ts +3 -2
- package/templates/app/api/user/plan-flags/route.ts +11 -24
- package/templates/app/api/user/profile/route.ts +7 -6
- package/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +16 -18
- package/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +17 -19
- package/templates/app/api/v1/[entity]/[id]/route.ts +10 -12
- package/templates/app/api/v1/[entity]/route.ts +9 -11
- package/templates/app/api/v1/api-keys/[id]/route.ts +9 -8
- package/templates/app/api/v1/api-keys/route.ts +7 -6
- package/templates/app/api/v1/auth/signup-with-invite/route.ts +3 -2
- package/templates/app/api/v1/billing/cancel/route.ts +15 -14
- package/templates/app/api/v1/billing/change-plan/route.ts +10 -9
- package/templates/app/api/v1/billing/check-action/route.ts +8 -7
- package/templates/app/api/v1/billing/checkout/route.ts +10 -9
- package/templates/app/api/v1/billing/plans/route.ts +5 -4
- package/templates/app/api/v1/billing/portal/route.ts +9 -8
- package/templates/app/api/v1/blocks/[slug]/route.ts +4 -3
- package/templates/app/api/v1/blocks/route.ts +3 -2
- package/templates/app/api/v1/blocks/validate/route.ts +5 -3
- package/templates/app/api/v1/cron/process/route.ts +4 -6
- package/templates/app/api/v1/devtools/blocks/route.ts +3 -2
- package/templates/app/api/v1/devtools/docs/route.ts +3 -2
- package/templates/app/api/v1/devtools/features/route.ts +3 -2
- package/templates/app/api/v1/devtools/flows/route.ts +3 -2
- package/templates/app/api/v1/devtools/scheduled-actions/route.ts +125 -3
- package/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +110 -0
- package/templates/app/api/v1/devtools/testing/route.ts +3 -2
- package/templates/app/api/v1/media/[id]/route.ts +144 -0
- package/templates/app/api/v1/media/[id]/tags/route.ts +154 -0
- package/templates/app/api/v1/media/check-duplicates/route.ts +56 -0
- package/templates/app/api/v1/media/route.ts +56 -0
- package/templates/app/api/v1/media/upload/route.ts +157 -33
- package/templates/app/api/v1/media-tags/route.ts +65 -0
- package/templates/app/api/v1/plugin/[...path]/route.ts +16 -15
- package/templates/app/api/v1/plugin/route.ts +3 -2
- package/templates/app/api/v1/post-categories/[id]/route.ts +10 -9
- package/templates/app/api/v1/post-categories/route.ts +5 -4
- package/templates/app/api/v1/team-invitations/[token]/accept/route.ts +3 -3
- package/templates/app/api/v1/team-invitations/[token]/decline/route.ts +3 -3
- package/templates/app/api/v1/team-invitations/[token]/route.ts +3 -2
- package/templates/app/api/v1/team-invitations/route.ts +3 -2
- package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +5 -4
- package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +3 -2
- package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +3 -2
- package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +5 -4
- package/templates/app/api/v1/teams/[teamId]/members/route.ts +5 -5
- package/templates/app/api/v1/teams/[teamId]/route.ts +31 -58
- package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -2
- package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +5 -4
- package/templates/app/api/v1/teams/route.ts +18 -17
- package/templates/app/api/v1/teams/switch/route.ts +3 -2
- package/templates/app/api/v1/theme/[...path]/route.ts +16 -15
- package/templates/app/api/v1/theme/route.ts +3 -2
- package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +7 -6
- package/templates/app/api/v1/users/[id]/route.ts +9 -8
- package/templates/app/api/v1/users/route.ts +7 -6
- package/templates/app/dashboard/(main)/media/page.tsx +607 -0
- package/templates/contents/themes/starter/messages/de/dev.json +106 -0
- package/templates/contents/themes/starter/messages/de/index.ts +2 -0
- package/templates/contents/themes/starter/messages/en/dev.json +106 -0
- package/templates/contents/themes/starter/messages/en/index.ts +2 -0
- package/templates/contents/themes/starter/messages/es/dev.json +106 -0
- package/templates/contents/themes/starter/messages/es/index.ts +2 -0
- package/templates/contents/themes/starter/messages/fr/dev.json +106 -0
- package/templates/contents/themes/starter/messages/fr/index.ts +2 -0
- package/templates/contents/themes/starter/messages/it/dev.json +106 -0
- package/templates/contents/themes/starter/messages/it/index.ts +2 -0
- package/templates/contents/themes/starter/messages/pt/dev.json +106 -0
- package/templates/contents/themes/starter/messages/pt/index.ts +2 -0
- package/templates/contents/themes/starter/styles/globals.css +14 -0
- package/templates/instrumentation.ts +33 -0
- package/dist/presets/plugin/.env.example.template +0 -19
- package/dist/presets/plugin/entities/.gitkeep +0 -18
- package/dist/presets/theme/blocks/.gitkeep +0 -17
- package/dist/presets/theme/public/brand/.gitkeep +0 -8
- package/dist/presets/theme/tests/cypress/.gitkeep +0 -10
- package/dist/templates/contents/plugins/starter/plugin/.env.example.template +0 -19
- package/templates/contents/plugins/starter/plugin/.env.example.template +0 -19
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server'
|
|
2
|
+
import { authenticateRequest, hasRequiredScope } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
3
|
+
import { createApiResponse, createApiError } from '@nextsparkjs/core/lib/api/helpers'
|
|
4
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
5
|
+
import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* GET /api/v1/media-tags
|
|
9
|
+
*
|
|
10
|
+
* List all available media tags (taxonomies of type 'media_tag').
|
|
11
|
+
*
|
|
12
|
+
* Authentication: Requires valid session or API key with media:read scope
|
|
13
|
+
*/
|
|
14
|
+
export const GET = withRateLimitTier(async (request: NextRequest) => {
|
|
15
|
+
try {
|
|
16
|
+
const authResult = await authenticateRequest(request)
|
|
17
|
+
if (!authResult.success) {
|
|
18
|
+
return createApiError('Unauthorized', 401)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!hasRequiredScope(authResult, 'media:read')) {
|
|
22
|
+
return createApiError('Insufficient permissions', 403)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const tags = await MediaService.getTags(authResult.user!.id)
|
|
26
|
+
return createApiResponse(tags)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('[Media Tags API] Error listing tags:', error)
|
|
29
|
+
return createApiError('Failed to list media tags', 500)
|
|
30
|
+
}
|
|
31
|
+
}, 'read')
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* POST /api/v1/media-tags
|
|
35
|
+
*
|
|
36
|
+
* Create a new media tag.
|
|
37
|
+
* Body: { name: string }
|
|
38
|
+
*
|
|
39
|
+
* Authentication: Requires valid session or API key with media:write scope
|
|
40
|
+
*/
|
|
41
|
+
export const POST = withRateLimitTier(async (request: NextRequest) => {
|
|
42
|
+
try {
|
|
43
|
+
const authResult = await authenticateRequest(request)
|
|
44
|
+
if (!authResult.success) {
|
|
45
|
+
return createApiError('Unauthorized', 401)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!hasRequiredScope(authResult, 'media:write')) {
|
|
49
|
+
return createApiError('Insufficient permissions', 403)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const body = await request.json()
|
|
53
|
+
const { name } = body
|
|
54
|
+
|
|
55
|
+
if (!name || typeof name !== 'string' || !name.trim()) {
|
|
56
|
+
return createApiError('Tag name is required', 400)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const tag = await MediaService.createTag(name, authResult.user!.id)
|
|
60
|
+
return createApiResponse(tag, undefined, 201)
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('[Media Tags API] Error creating tag:', error)
|
|
63
|
+
return createApiError('Failed to create media tag', 500)
|
|
64
|
+
}
|
|
65
|
+
}, 'write')
|
|
@@ -8,46 +8,47 @@
|
|
|
8
8
|
import { NextRequest, NextResponse } from 'next/server'
|
|
9
9
|
import { PluginService, type RouteFileEndpoint, type PluginRegistryEntry } from '@nextsparkjs/core/lib/services'
|
|
10
10
|
import { PLUGIN_REGISTRY } from '@nextsparkjs/registries/plugin-registry'
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
12
|
|
|
12
|
-
export
|
|
13
|
+
export const GET = withRateLimitTier(async (
|
|
13
14
|
request: NextRequest,
|
|
14
15
|
{ params }: { params: Promise<{ path: string[] }> }
|
|
15
|
-
) {
|
|
16
|
+
) => {
|
|
16
17
|
const { path } = await params
|
|
17
18
|
return handlePluginRequest(request, path, 'GET')
|
|
18
|
-
}
|
|
19
|
+
}, 'read');
|
|
19
20
|
|
|
20
|
-
export
|
|
21
|
+
export const POST = withRateLimitTier(async (
|
|
21
22
|
request: NextRequest,
|
|
22
23
|
{ params }: { params: Promise<{ path: string[] }> }
|
|
23
|
-
) {
|
|
24
|
+
) => {
|
|
24
25
|
const { path } = await params
|
|
25
26
|
return handlePluginRequest(request, path, 'POST')
|
|
26
|
-
}
|
|
27
|
+
}, 'write');
|
|
27
28
|
|
|
28
|
-
export
|
|
29
|
+
export const PUT = withRateLimitTier(async (
|
|
29
30
|
request: NextRequest,
|
|
30
31
|
{ params }: { params: Promise<{ path: string[] }> }
|
|
31
|
-
) {
|
|
32
|
+
) => {
|
|
32
33
|
const { path } = await params
|
|
33
34
|
return handlePluginRequest(request, path, 'PUT')
|
|
34
|
-
}
|
|
35
|
+
}, 'write');
|
|
35
36
|
|
|
36
|
-
export
|
|
37
|
+
export const DELETE = withRateLimitTier(async (
|
|
37
38
|
request: NextRequest,
|
|
38
39
|
{ params }: { params: Promise<{ path: string[] }> }
|
|
39
|
-
) {
|
|
40
|
+
) => {
|
|
40
41
|
const { path } = await params
|
|
41
42
|
return handlePluginRequest(request, path, 'DELETE')
|
|
42
|
-
}
|
|
43
|
+
}, 'write');
|
|
43
44
|
|
|
44
|
-
export
|
|
45
|
+
export const PATCH = withRateLimitTier(async (
|
|
45
46
|
request: NextRequest,
|
|
46
47
|
{ params }: { params: Promise<{ path: string[] }> }
|
|
47
|
-
) {
|
|
48
|
+
) => {
|
|
48
49
|
const { path } = await params
|
|
49
50
|
return handlePluginRequest(request, path, 'PATCH')
|
|
50
|
-
}
|
|
51
|
+
}, 'write');
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* Handle plugin API requests with nested paths
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
import { NextResponse } from 'next/server'
|
|
9
9
|
import { PluginService, type PluginRegistryEntry } from '@nextsparkjs/core/lib/services'
|
|
10
10
|
import { PLUGIN_REGISTRY } from '@nextsparkjs/registries/plugin-registry'
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
12
|
|
|
12
|
-
export
|
|
13
|
+
export const GET = withRateLimitTier(async () => {
|
|
13
14
|
return listPluginsWithAPI()
|
|
14
|
-
}
|
|
15
|
+
}, 'read');
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* List all plugins with their API status
|
|
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
|
2
2
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
3
3
|
import { query as dbQuery } from '@nextsparkjs/core/lib/db'
|
|
4
4
|
import { z } from 'zod'
|
|
5
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
5
6
|
|
|
6
7
|
const updateCategorySchema = z.object({
|
|
7
8
|
name: z.string().min(1).max(255).optional(),
|
|
@@ -16,10 +17,10 @@ const updateCategorySchema = z.object({
|
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
// GET /api/v1/post-categories/:id - Get category by ID
|
|
19
|
-
export
|
|
20
|
+
export const GET = withRateLimitTier(async (
|
|
20
21
|
request: NextRequest,
|
|
21
22
|
{ params }: { params: Promise<{ id: string }> }
|
|
22
|
-
): Promise<NextResponse> {
|
|
23
|
+
): Promise<NextResponse> => {
|
|
23
24
|
try {
|
|
24
25
|
const { id } = await params
|
|
25
26
|
|
|
@@ -43,13 +44,13 @@ export async function GET(
|
|
|
43
44
|
console.error('Error in post-categories API:', err)
|
|
44
45
|
return NextResponse.json({ success: false, error: 'Internal server error' }, { status: 500 })
|
|
45
46
|
}
|
|
46
|
-
}
|
|
47
|
+
}, 'read');
|
|
47
48
|
|
|
48
49
|
// PUT /api/v1/post-categories/:id - Update category
|
|
49
|
-
export
|
|
50
|
+
export const PUT = withRateLimitTier(async (
|
|
50
51
|
request: NextRequest,
|
|
51
52
|
{ params }: { params: Promise<{ id: string }> }
|
|
52
|
-
): Promise<NextResponse> {
|
|
53
|
+
): Promise<NextResponse> => {
|
|
53
54
|
try {
|
|
54
55
|
// Dual authentication: API key or session
|
|
55
56
|
const authResult = await authenticateRequest(request)
|
|
@@ -183,13 +184,13 @@ export async function PUT(
|
|
|
183
184
|
const errorMessage = err instanceof Error ? err.message : 'Internal server error'
|
|
184
185
|
return NextResponse.json({ success: false, error: errorMessage }, { status: 500 })
|
|
185
186
|
}
|
|
186
|
-
}
|
|
187
|
+
}, 'write');
|
|
187
188
|
|
|
188
189
|
// DELETE /api/v1/post-categories/:id - Delete category
|
|
189
|
-
export
|
|
190
|
+
export const DELETE = withRateLimitTier(async (
|
|
190
191
|
request: NextRequest,
|
|
191
192
|
{ params }: { params: Promise<{ id: string }> }
|
|
192
|
-
): Promise<NextResponse> {
|
|
193
|
+
): Promise<NextResponse> => {
|
|
193
194
|
try {
|
|
194
195
|
// Dual authentication: API key or session
|
|
195
196
|
const authResult = await authenticateRequest(request)
|
|
@@ -252,4 +253,4 @@ export async function DELETE(
|
|
|
252
253
|
console.error('Error in post-categories API DELETE:', err)
|
|
253
254
|
return NextResponse.json({ success: false, error: 'Internal server error' }, { status: 500 })
|
|
254
255
|
}
|
|
255
|
-
}
|
|
256
|
+
}, 'write');
|
|
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
|
|
2
2
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
3
3
|
import { query as dbQuery } from '@nextsparkjs/core/lib/db'
|
|
4
4
|
import { z } from 'zod'
|
|
5
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
5
6
|
|
|
6
7
|
const createCategorySchema = z.object({
|
|
7
8
|
name: z.string().min(1).max(255),
|
|
@@ -26,7 +27,7 @@ function generateSlug(name: string): string {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
// GET /api/v1/post-categories - List categories (filters taxonomies by type = 'post_category')
|
|
29
|
-
export
|
|
30
|
+
export const GET = withRateLimitTier(async () => {
|
|
30
31
|
try {
|
|
31
32
|
const result = await dbQuery(
|
|
32
33
|
`SELECT id, name, slug, description, icon, color, "parentId", "order", "isDefault", "isActive",
|
|
@@ -44,10 +45,10 @@ export async function GET() {
|
|
|
44
45
|
console.error('Error fetching post categories:', error)
|
|
45
46
|
return NextResponse.json({ success: false, error: 'Internal server error' }, { status: 500 })
|
|
46
47
|
}
|
|
47
|
-
}
|
|
48
|
+
}, 'read');
|
|
48
49
|
|
|
49
50
|
// POST /api/v1/post-categories - Create category
|
|
50
|
-
export
|
|
51
|
+
export const POST = withRateLimitTier(async (request: NextRequest) => {
|
|
51
52
|
try {
|
|
52
53
|
// Dual authentication: API key or session
|
|
53
54
|
const authResult = await authenticateRequest(request)
|
|
@@ -116,4 +117,4 @@ export async function POST(request: NextRequest) {
|
|
|
116
117
|
console.error('Error creating post category:', error)
|
|
117
118
|
return NextResponse.json({ success: false, error: 'Internal server error' }, { status: 500 })
|
|
118
119
|
}
|
|
119
|
-
}
|
|
120
|
+
}, 'write');
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
-
import { checkRateLimit } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
|
+
import { checkRateLimit, withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
12
|
import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
|
|
13
13
|
import type { TeamInvitation, TeamMember } from '@nextsparkjs/core/lib/teams/types'
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ export async function OPTIONS() {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// POST /api/v1/team-invitations/:token/accept - Accept invitation and become member
|
|
21
|
-
export const POST = withApiLogging(
|
|
21
|
+
export const POST = withRateLimitTier(withApiLogging(
|
|
22
22
|
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
23
23
|
try {
|
|
24
24
|
// Authenticate using dual auth
|
|
@@ -176,4 +176,4 @@ export const POST = withApiLogging(
|
|
|
176
176
|
return addCorsHeaders(response)
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
)
|
|
179
|
+
), 'write');
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
-
import { checkRateLimit } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
|
+
import { checkRateLimit, withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
12
|
import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
|
|
13
13
|
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ export async function OPTIONS() {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// POST /api/v1/team-invitations/:token/decline - Decline invitation
|
|
21
|
-
export const POST = withApiLogging(
|
|
21
|
+
export const POST = withRateLimitTier(withApiLogging(
|
|
22
22
|
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
23
23
|
try {
|
|
24
24
|
// Authenticate using dual auth
|
|
@@ -117,4 +117,4 @@ export const POST = withApiLogging(
|
|
|
117
117
|
return addCorsHeaders(response)
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
)
|
|
120
|
+
), 'write');
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
12
|
|
|
12
13
|
// Handle CORS preflight
|
|
13
14
|
export async function OPTIONS() {
|
|
@@ -15,7 +16,7 @@ export async function OPTIONS() {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
// GET /api/v1/team-invitations/:token - Get invitation details (public endpoint for preview)
|
|
18
|
-
export const GET = withApiLogging(
|
|
19
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
19
20
|
async (req: NextRequest, { params }: { params: Promise<{ token: string }> }): Promise<NextResponse> => {
|
|
20
21
|
try {
|
|
21
22
|
const { token } = await params
|
|
@@ -86,4 +87,4 @@ export const GET = withApiLogging(
|
|
|
86
87
|
return addCorsHeaders(response)
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
|
-
)
|
|
90
|
+
), 'read');
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
12
|
import { invitationListQuerySchema } from '@nextsparkjs/core/lib/teams/schema'
|
|
13
13
|
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
14
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
14
15
|
|
|
15
16
|
// Handle CORS preflight
|
|
16
17
|
export async function OPTIONS() {
|
|
@@ -18,7 +19,7 @@ export async function OPTIONS() {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// GET /api/v1/team-invitations - List pending invitations for current user
|
|
21
|
-
export const GET = withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
|
|
22
|
+
export const GET = withRateLimitTier(withApiLogging(async (req: NextRequest): Promise<NextResponse> => {
|
|
22
23
|
try {
|
|
23
24
|
// Authenticate using dual auth
|
|
24
25
|
const authResult = await authenticateRequest(req)
|
|
@@ -111,4 +112,4 @@ export const GET = withApiLogging(async (req: NextRequest): Promise<NextResponse
|
|
|
111
112
|
const response = createApiError('Internal server error', 500)
|
|
112
113
|
return addCorsHeaders(response)
|
|
113
114
|
}
|
|
114
|
-
})
|
|
115
|
+
}), 'read');
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
addCorsHeaders,
|
|
10
10
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
11
11
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
13
|
import { TeamMemberService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
13
14
|
import type { TeamInvitation } from '@nextsparkjs/core/lib/teams/types'
|
|
14
15
|
|
|
@@ -18,7 +19,7 @@ export async function OPTIONS() {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// GET /api/v1/teams/:teamId/invitations - List pending invitations for a team
|
|
21
|
-
export const GET = withApiLogging(
|
|
22
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
22
23
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
23
24
|
try {
|
|
24
25
|
// Authenticate using dual auth
|
|
@@ -98,10 +99,10 @@ export const GET = withApiLogging(
|
|
|
98
99
|
return addCorsHeaders(response)
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
|
-
)
|
|
102
|
+
), 'read')
|
|
102
103
|
|
|
103
104
|
// DELETE /api/v1/teams/:teamId/invitations/:invitationId - Cancel/revoke an invitation
|
|
104
|
-
export const DELETE = withApiLogging(
|
|
105
|
+
export const DELETE = withRateLimitTier(withApiLogging(
|
|
105
106
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
106
107
|
try {
|
|
107
108
|
// Authenticate using dual auth
|
|
@@ -168,4 +169,4 @@ export const DELETE = withApiLogging(
|
|
|
168
169
|
return addCorsHeaders(response)
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
|
-
)
|
|
172
|
+
), 'write')
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
12
|
import { MembershipService } from '@nextsparkjs/core/lib/services'
|
|
12
13
|
import type { InvoiceResponse } from '@nextsparkjs/core/lib/validation/invoices'
|
|
13
14
|
|
|
@@ -17,7 +18,7 @@ export async function OPTIONS() {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
// GET /api/v1/teams/:teamId/invoices/:invoiceNumber - Get single invoice (owner only)
|
|
20
|
-
export const GET = withApiLogging(
|
|
21
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
21
22
|
async (
|
|
22
23
|
req: NextRequest,
|
|
23
24
|
{ params }: { params: Promise<{ teamId: string; invoiceNumber: string }> }
|
|
@@ -102,4 +103,4 @@ export const GET = withApiLogging(
|
|
|
102
103
|
return addCorsHeaders(response)
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
|
-
)
|
|
106
|
+
), 'read')
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
addCorsHeaders,
|
|
10
10
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
11
11
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
13
|
import { MembershipService } from '@nextsparkjs/core/lib/services'
|
|
13
14
|
import { invoiceQuerySchema } from '@nextsparkjs/core/lib/validation/invoices'
|
|
14
15
|
import type { InvoiceResponse } from '@nextsparkjs/core/lib/validation/invoices'
|
|
@@ -19,7 +20,7 @@ export async function OPTIONS() {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
// GET /api/v1/teams/:teamId/invoices - List team invoices (owner only)
|
|
22
|
-
export const GET = withApiLogging(
|
|
23
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
23
24
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
24
25
|
try {
|
|
25
26
|
// Authenticate using dual auth (API key OR session)
|
|
@@ -122,4 +123,4 @@ export const GET = withApiLogging(
|
|
|
122
123
|
return addCorsHeaders(response)
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
|
-
)
|
|
126
|
+
), 'read')
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
11
12
|
import { updateMemberRoleSchema } from '@nextsparkjs/core/lib/teams/schema'
|
|
12
13
|
import { MembershipService } from '@nextsparkjs/core/lib/services'
|
|
13
14
|
import { validateRoleTransition, canManageRole } from '@nextsparkjs/core/lib/teams/permissions'
|
|
@@ -19,7 +20,7 @@ export async function OPTIONS() {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
// PATCH /api/v1/teams/:teamId/members/:memberId - Update member role
|
|
22
|
-
export const PATCH = withApiLogging(
|
|
23
|
+
export const PATCH = withRateLimitTier(withApiLogging(
|
|
23
24
|
async (
|
|
24
25
|
req: NextRequest,
|
|
25
26
|
{ params }: { params: Promise<{ teamId: string; memberId: string }> }
|
|
@@ -155,10 +156,10 @@ export const PATCH = withApiLogging(
|
|
|
155
156
|
return addCorsHeaders(response)
|
|
156
157
|
}
|
|
157
158
|
}
|
|
158
|
-
)
|
|
159
|
+
), 'write')
|
|
159
160
|
|
|
160
161
|
// DELETE /api/v1/teams/:teamId/members/:memberId - Remove member from team
|
|
161
|
-
export const DELETE = withApiLogging(
|
|
162
|
+
export const DELETE = withRateLimitTier(withApiLogging(
|
|
162
163
|
async (
|
|
163
164
|
req: NextRequest,
|
|
164
165
|
{ params }: { params: Promise<{ teamId: string; memberId: string }> }
|
|
@@ -260,4 +261,4 @@ export const DELETE = withApiLogging(
|
|
|
260
261
|
return addCorsHeaders(response)
|
|
261
262
|
}
|
|
262
263
|
}
|
|
263
|
-
)
|
|
264
|
+
), 'write')
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
11
11
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
12
12
|
import { isSuperAdmin } from '@nextsparkjs/core/lib/api/auth/permissions'
|
|
13
|
-
import { checkRateLimit } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
13
|
+
import { checkRateLimit, withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
14
14
|
import { RATE_LIMITS } from '@nextsparkjs/core/lib/api/keys'
|
|
15
15
|
import { inviteMemberSchema, memberListQuerySchema } from '@nextsparkjs/core/lib/teams/schema'
|
|
16
16
|
import { TeamMemberService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
@@ -37,7 +37,7 @@ export async function OPTIONS() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// GET /api/v1/teams/:teamId/members - List team members
|
|
40
|
-
export const GET = withApiLogging(
|
|
40
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
41
41
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
42
42
|
try {
|
|
43
43
|
// Authenticate using dual auth
|
|
@@ -159,10 +159,10 @@ export const GET = withApiLogging(
|
|
|
159
159
|
return addCorsHeaders(response)
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
)
|
|
162
|
+
), 'read')
|
|
163
163
|
|
|
164
164
|
// POST /api/v1/teams/:teamId/members - Invite new member (creates invitation)
|
|
165
|
-
export const POST = withApiLogging(
|
|
165
|
+
export const POST = withRateLimitTier(withApiLogging(
|
|
166
166
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
167
167
|
try {
|
|
168
168
|
// Authenticate using dual auth
|
|
@@ -355,4 +355,4 @@ export const POST = withApiLogging(
|
|
|
355
355
|
return addCorsHeaders(response)
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
|
-
)
|
|
358
|
+
), 'write')
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
addCorsHeaders,
|
|
9
9
|
} from '@nextsparkjs/core/lib/api/helpers'
|
|
10
10
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
11
|
-
import {
|
|
11
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
12
|
+
import { updateTeamSchema } from '@nextsparkjs/core/lib/teams/schema'
|
|
12
13
|
import { TeamService, MembershipService } from '@nextsparkjs/core/lib/services'
|
|
13
14
|
import type { Team, TeamRole } from '@nextsparkjs/core/lib/teams/types'
|
|
14
15
|
|
|
@@ -18,7 +19,7 @@ export async function OPTIONS() {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// GET /api/v1/teams/:teamId - Get team details
|
|
21
|
-
export const GET = withApiLogging(
|
|
22
|
+
export const GET = withRateLimitTier(withApiLogging(
|
|
22
23
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
23
24
|
try {
|
|
24
25
|
// Authenticate using dual auth
|
|
@@ -87,10 +88,10 @@ export const GET = withApiLogging(
|
|
|
87
88
|
return addCorsHeaders(response)
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
|
-
)
|
|
91
|
+
), 'read')
|
|
91
92
|
|
|
92
93
|
// PATCH /api/v1/teams/:teamId - Update team (owners/admins only)
|
|
93
|
-
export const PATCH = withApiLogging(
|
|
94
|
+
export const PATCH = withRateLimitTier(withApiLogging(
|
|
94
95
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
95
96
|
try {
|
|
96
97
|
// Authenticate using dual auth
|
|
@@ -115,56 +116,28 @@ export const PATCH = withApiLogging(
|
|
|
115
116
|
return addCorsHeaders(response)
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const response = createApiError(
|
|
134
|
-
'Only team owners can edit team name and description',
|
|
135
|
-
403,
|
|
136
|
-
null,
|
|
137
|
-
'OWNER_ONLY'
|
|
138
|
-
)
|
|
139
|
-
return addCorsHeaders(response)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Proceed with owner update (skip general permission check)
|
|
143
|
-
} else {
|
|
144
|
-
// Check general teams.update permission for non-owner-only fields
|
|
145
|
-
const membership = await MembershipService.get(authResult.user!.id, teamId)
|
|
146
|
-
const actionResult = membership.canPerformAction('teams.update')
|
|
147
|
-
|
|
148
|
-
if (!actionResult.allowed) {
|
|
149
|
-
const response = NextResponse.json(
|
|
150
|
-
{
|
|
151
|
-
success: false,
|
|
152
|
-
error: actionResult.message,
|
|
153
|
-
reason: actionResult.reason,
|
|
154
|
-
meta: actionResult.meta,
|
|
155
|
-
},
|
|
156
|
-
{ status: 403 }
|
|
157
|
-
)
|
|
158
|
-
return addCorsHeaders(response)
|
|
159
|
-
}
|
|
119
|
+
// Check if user has permission to edit team using MembershipService
|
|
120
|
+
const membership = await MembershipService.get(authResult.user!.id, teamId)
|
|
121
|
+
const actionResult = membership.canPerformAction('teams.update')
|
|
122
|
+
|
|
123
|
+
if (!actionResult.allowed) {
|
|
124
|
+
const response = NextResponse.json(
|
|
125
|
+
{
|
|
126
|
+
success: false,
|
|
127
|
+
error: actionResult.message,
|
|
128
|
+
reason: actionResult.reason,
|
|
129
|
+
meta: actionResult.meta,
|
|
130
|
+
},
|
|
131
|
+
{ status: 403 }
|
|
132
|
+
)
|
|
133
|
+
return addCorsHeaders(response)
|
|
160
134
|
}
|
|
161
135
|
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
const validatedData = schema.parse(body) as Record<string, unknown>
|
|
136
|
+
const body = await req.json()
|
|
137
|
+
const validatedData = updateTeamSchema.parse(body)
|
|
165
138
|
|
|
166
139
|
// Check if slug is being changed and if it's available
|
|
167
|
-
if (
|
|
140
|
+
if (validatedData.slug) {
|
|
168
141
|
const slugAvailable = await TeamService.isSlugAvailable(validatedData.slug, teamId)
|
|
169
142
|
if (!slugAvailable) {
|
|
170
143
|
const response = createApiError('Team slug already exists', 409, null, 'SLUG_EXISTS')
|
|
@@ -177,27 +150,27 @@ export const PATCH = withApiLogging(
|
|
|
177
150
|
const values = []
|
|
178
151
|
let paramCount = 1
|
|
179
152
|
|
|
180
|
-
if (
|
|
153
|
+
if (validatedData.name !== undefined) {
|
|
181
154
|
updates.push(`name = $${paramCount++}`)
|
|
182
155
|
values.push(validatedData.name)
|
|
183
156
|
}
|
|
184
157
|
|
|
185
|
-
if (
|
|
158
|
+
if (validatedData.slug !== undefined) {
|
|
186
159
|
updates.push(`slug = $${paramCount++}`)
|
|
187
160
|
values.push(validatedData.slug)
|
|
188
161
|
}
|
|
189
162
|
|
|
190
|
-
if (
|
|
163
|
+
if (validatedData.description !== undefined) {
|
|
191
164
|
updates.push(`description = $${paramCount++}`)
|
|
192
165
|
values.push(validatedData.description)
|
|
193
166
|
}
|
|
194
167
|
|
|
195
|
-
if (
|
|
168
|
+
if (validatedData.avatarUrl !== undefined) {
|
|
196
169
|
updates.push(`"avatarUrl" = $${paramCount++}`)
|
|
197
170
|
values.push(validatedData.avatarUrl)
|
|
198
171
|
}
|
|
199
172
|
|
|
200
|
-
if (
|
|
173
|
+
if (validatedData.settings !== undefined) {
|
|
201
174
|
updates.push(`settings = $${paramCount++}`)
|
|
202
175
|
values.push(JSON.stringify(validatedData.settings))
|
|
203
176
|
}
|
|
@@ -256,10 +229,10 @@ export const PATCH = withApiLogging(
|
|
|
256
229
|
return addCorsHeaders(response)
|
|
257
230
|
}
|
|
258
231
|
}
|
|
259
|
-
)
|
|
232
|
+
), 'write')
|
|
260
233
|
|
|
261
234
|
// DELETE /api/v1/teams/:teamId - Delete team (owners only, NOT personal teams)
|
|
262
|
-
export const DELETE = withApiLogging(
|
|
235
|
+
export const DELETE = withRateLimitTier(withApiLogging(
|
|
263
236
|
async (req: NextRequest, { params }: { params: Promise<{ teamId: string }> }): Promise<NextResponse> => {
|
|
264
237
|
try {
|
|
265
238
|
// Authenticate using dual auth
|
|
@@ -319,4 +292,4 @@ export const DELETE = withApiLogging(
|
|
|
319
292
|
return addCorsHeaders(response)
|
|
320
293
|
}
|
|
321
294
|
}
|
|
322
|
-
)
|
|
295
|
+
), 'write')
|