@nextsparkjs/core 0.1.0-beta.184 → 0.1.0-beta.186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/app/guards/DeveloperGuard.d.ts.map +1 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts.map +1 -1
- package/dist/components/app/layouts/PublicFooter.d.ts.map +1 -1
- package/dist/components/app/layouts/PublicFooter.js +2 -2
- package/dist/components/app/layouts/PublicNavbar.d.ts.map +1 -1
- package/dist/components/app/layouts/PublicNavbar.js +2 -2
- package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
- package/dist/components/app/misc/ThemeToggle.js +4 -1
- package/dist/components/auth/DevKeyring.d.ts.map +1 -1
- package/dist/components/auth/DevKeyring.js +10 -2
- package/dist/components/auth/SessionCookieRefresher.d.ts +21 -0
- package/dist/components/auth/SessionCookieRefresher.d.ts.map +1 -0
- package/dist/components/auth/SessionCookieRefresher.js +11 -0
- package/dist/components/auth/forms/LoginForm.d.ts.map +1 -1
- package/dist/components/auth/forms/LoginForm.js +300 -6
- package/dist/components/auth/index.d.ts +1 -0
- package/dist/components/auth/index.d.ts.map +1 -1
- package/dist/components/auth/index.js +2 -0
- package/dist/components/billing/InvoicesTable.d.ts.map +1 -1
- package/dist/components/billing/InvoicesTable.js +4 -3
- package/dist/components/dashboard/block-editor/dynamic-form.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthGuard.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthGuard.js +2 -2
- package/dist/components/dashboard/layouts/DashboardAuthLayout.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/DashboardAuthLayout.js +2 -2
- package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts +17 -0
- package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts.map +1 -0
- package/dist/components/dashboard/layouts/DashboardAuthSkeleton.js +52 -0
- package/dist/components/dashboard/layouts/Sidebar.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/Sidebar.js +2 -3
- package/dist/components/dashboard/layouts/TopNavbar.js +2 -2
- package/dist/components/dashboard/layouts/index.d.ts +1 -0
- package/dist/components/dashboard/layouts/index.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/index.js +2 -0
- package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
- package/dist/components/entities/EntityFieldRenderer.js +3 -0
- package/dist/components/entities/EntityTable.d.ts.map +1 -1
- package/dist/components/entities/EntityTable.js +2 -1
- package/dist/components/entities/wrappers/EntityFormWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityFormWrapper.js +7 -2
- package/dist/components/ui/combobox.d.ts +8 -1
- package/dist/components/ui/combobox.d.ts.map +1 -1
- package/dist/components/ui/combobox.js +37 -44
- package/dist/components/ui/country-select.d.ts +3 -1
- package/dist/components/ui/country-select.d.ts.map +1 -1
- package/dist/components/ui/country-select.js +3 -1
- package/dist/components/ui/currency-select.d.ts +3 -1
- package/dist/components/ui/currency-select.d.ts.map +1 -1
- package/dist/components/ui/currency-select.js +3 -1
- package/dist/components/ui/sheet.d.ts +5 -0
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sheet.js +46 -26
- package/dist/components/ui/timezone-select.d.ts +3 -1
- package/dist/components/ui/timezone-select.d.ts.map +1 -1
- package/dist/components/ui/timezone-select.js +3 -1
- package/dist/contexts/TeamContext.d.ts +6 -0
- package/dist/contexts/TeamContext.d.ts.map +1 -1
- package/dist/contexts/TeamContext.js +8 -1
- package/dist/emails/otp-verification.d.ts.map +1 -1
- package/dist/emails/reset-password.d.ts.map +1 -1
- package/dist/emails/team-invitation.d.ts.map +1 -1
- package/dist/emails/team-invitation.js +3 -2
- package/dist/emails/verify-email.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useAuth.d.ts +103 -25
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +24 -0
- package/dist/hooks/useEnsureUserMetadata.d.ts +22 -0
- package/dist/hooks/useEnsureUserMetadata.d.ts.map +1 -1
- package/dist/hooks/useEnsureUserMetadata.js +18 -5
- package/dist/hooks/useSessionCookieRefresh.d.ts +35 -0
- package/dist/hooks/useSessionCookieRefresh.d.ts.map +1 -0
- package/dist/hooks/useSessionCookieRefresh.js +49 -0
- package/dist/hooks/useValidationSchemas.d.ts +7 -7
- package/dist/lib/api/api-error.d.ts +3 -1
- package/dist/lib/api/api-error.d.ts.map +1 -1
- package/dist/lib/api/api-error.js +4 -2
- package/dist/lib/api/auth/dual-auth.d.ts +45 -3
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +42 -7
- package/dist/lib/api/auth/permissions.d.ts +7 -2
- package/dist/lib/api/auth/permissions.d.ts.map +1 -1
- package/dist/lib/api/auth/permissions.js +2 -2
- package/dist/lib/api/auth/scope-policy.d.ts +71 -0
- package/dist/lib/api/auth/scope-policy.d.ts.map +1 -0
- package/dist/lib/api/auth/scope-policy.js +53 -0
- package/dist/lib/api/auth.d.ts +35 -3
- package/dist/lib/api/auth.d.ts.map +1 -1
- package/dist/lib/api/auth.js +54 -23
- package/dist/lib/api/entity/audit-log.d.ts +35 -0
- package/dist/lib/api/entity/audit-log.d.ts.map +1 -0
- package/dist/lib/api/entity/audit-log.js +35 -0
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +333 -155
- package/dist/lib/api/helpers.d.ts +29 -4
- package/dist/lib/api/helpers.d.ts.map +1 -1
- package/dist/lib/api/helpers.js +30 -6
- package/dist/lib/api/keys.d.ts +16 -0
- package/dist/lib/api/keys.d.ts.map +1 -1
- package/dist/lib/api/keys.js +19 -1
- package/dist/lib/api/routes/patterns-usages.d.ts.map +1 -1
- package/dist/lib/api/routes/patterns-usages.js +3 -11
- package/dist/lib/auth/auth-methods.d.ts +52 -0
- package/dist/lib/auth/auth-methods.d.ts.map +1 -0
- package/dist/lib/auth/auth-methods.js +63 -0
- package/dist/lib/auth/registration-guard-plugin.d.ts.map +1 -1
- package/dist/lib/auth/registration-helpers.d.ts +9 -0
- package/dist/lib/auth/registration-helpers.d.ts.map +1 -1
- package/dist/lib/auth/registration-helpers.js +8 -2
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts +52 -0
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/device-fingerprint.js +42 -0
- package/dist/lib/auth/security-notifications/dispatcher.d.ts +37 -0
- package/dist/lib/auth/security-notifications/dispatcher.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/dispatcher.js +157 -0
- package/dist/lib/auth/security-notifications/index.d.ts +20 -0
- package/dist/lib/auth/security-notifications/index.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/index.js +22 -0
- package/dist/lib/auth/security-notifications/registry.d.ts +36 -0
- package/dist/lib/auth/security-notifications/registry.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/registry.js +26 -0
- package/dist/lib/auth/security-notifications/templates/email-changed.d.ts +12 -0
- package/dist/lib/auth/security-notifications/templates/email-changed.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/templates/email-changed.js +43 -0
- package/dist/lib/auth/security-notifications/templates/new-device-login.d.ts +7 -0
- package/dist/lib/auth/security-notifications/templates/new-device-login.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/templates/new-device-login.js +46 -0
- package/dist/lib/auth/security-notifications/templates/password-changed.d.ts +7 -0
- package/dist/lib/auth/security-notifications/templates/password-changed.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/templates/password-changed.js +35 -0
- package/dist/lib/auth/security-notifications/templates/shared.d.ts +36 -0
- package/dist/lib/auth/security-notifications/templates/shared.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/templates/shared.js +68 -0
- package/dist/lib/auth/security-notifications/types.d.ts +74 -0
- package/dist/lib/auth/security-notifications/types.d.ts.map +1 -0
- package/dist/lib/auth/security-notifications/types.js +0 -0
- package/dist/lib/auth/session-config.d.ts +37 -0
- package/dist/lib/auth/session-config.d.ts.map +1 -0
- package/dist/lib/auth/session-config.js +59 -0
- package/dist/lib/auth/session-refresh.d.ts +46 -0
- package/dist/lib/auth/session-refresh.d.ts.map +1 -0
- package/dist/lib/auth/session-refresh.js +11 -0
- package/dist/lib/auth-client.d.ts +1489 -3445
- package/dist/lib/auth-client.d.ts.map +1 -1
- package/dist/lib/auth-client.js +4 -0
- package/dist/lib/auth.d.ts +1 -3057
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +21 -8
- package/dist/lib/billing/gateways/factory.d.ts +8 -3
- package/dist/lib/billing/gateways/factory.d.ts.map +1 -1
- package/dist/lib/billing/gateways/factory.js +37 -23
- package/dist/lib/billing/schema.d.ts +1 -1
- package/dist/lib/billing/stripe-webhook.d.ts.map +1 -1
- package/dist/lib/billing/stripe-webhook.js +2 -1
- package/dist/lib/config/app.config.d.ts.map +1 -1
- package/dist/lib/config/app.config.js +71 -0
- package/dist/lib/config/config-sync.d.ts +1 -4
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +6 -2
- package/dist/lib/config/types.d.ts +130 -0
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/entities/entity-hooks.d.ts +9 -1
- package/dist/lib/entities/entity-hooks.d.ts.map +1 -1
- package/dist/lib/entities/entity-hooks.js +77 -4
- package/dist/lib/entities/schema-generator.d.ts.map +1 -1
- package/dist/lib/entities/schema-generator.js +20 -4
- package/dist/lib/entities/serialization.d.ts +2 -2
- package/dist/lib/entities/serialization.d.ts.map +1 -1
- package/dist/lib/entities/serialization.js +3 -2
- package/dist/lib/entities/types.d.ts +8 -0
- package/dist/lib/entities/types.d.ts.map +1 -1
- package/dist/lib/locale.d.ts.map +1 -1
- package/dist/lib/locale.js +4 -1
- package/dist/lib/mcp/audit.d.ts +21 -0
- package/dist/lib/mcp/audit.d.ts.map +1 -0
- package/dist/lib/mcp/audit.js +48 -0
- package/dist/lib/mcp/engine.d.ts +28 -0
- package/dist/lib/mcp/engine.d.ts.map +1 -0
- package/dist/lib/mcp/engine.js +158 -0
- package/dist/lib/mcp/errors.d.ts +16 -0
- package/dist/lib/mcp/errors.d.ts.map +1 -0
- package/dist/lib/mcp/errors.js +66 -0
- package/dist/lib/mcp/executor.d.ts +15 -0
- package/dist/lib/mcp/executor.d.ts.map +1 -0
- package/dist/lib/mcp/executor.js +63 -0
- package/dist/lib/mcp/index.d.ts +9 -0
- package/dist/lib/mcp/index.d.ts.map +1 -0
- package/dist/lib/mcp/index.js +32 -0
- package/dist/lib/mcp/schema-builder.d.ts +45 -0
- package/dist/lib/mcp/schema-builder.d.ts.map +1 -0
- package/dist/lib/mcp/schema-builder.js +212 -0
- package/dist/lib/mcp/tool-generator.d.ts +31 -0
- package/dist/lib/mcp/tool-generator.d.ts.map +1 -0
- package/dist/lib/mcp/tool-generator.js +271 -0
- package/dist/lib/mcp/transport.d.ts +31 -0
- package/dist/lib/mcp/transport.d.ts.map +1 -0
- package/dist/lib/mcp/transport.js +58 -0
- package/dist/lib/mcp/types.d.ts +184 -0
- package/dist/lib/mcp/types.d.ts.map +1 -0
- package/dist/lib/mcp/types.js +11 -0
- package/dist/lib/plugins/hook-system.d.ts +13 -0
- package/dist/lib/plugins/hook-system.d.ts.map +1 -1
- package/dist/lib/plugins/hook-system.js +32 -2
- package/dist/lib/scheduled-actions/handlers/index.d.ts +1 -0
- package/dist/lib/scheduled-actions/handlers/index.d.ts.map +1 -1
- package/dist/lib/scheduled-actions/handlers/index.js +3 -1
- package/dist/lib/scheduled-actions/handlers/security-notification.d.ts +26 -0
- package/dist/lib/scheduled-actions/handlers/security-notification.d.ts.map +1 -0
- package/dist/lib/scheduled-actions/handlers/security-notification.js +54 -0
- package/dist/lib/selectors/core-selectors.d.ts +12 -0
- package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/auth.selectors.d.ts +12 -0
- package/dist/lib/selectors/domains/auth.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/auth.selectors.js +14 -1
- package/dist/lib/selectors/selectors.d.ts +24 -0
- package/dist/lib/selectors/selectors.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.js +16 -32
- package/dist/lib/services/membership.service.d.ts +10 -2
- package/dist/lib/services/membership.service.d.ts.map +1 -1
- package/dist/lib/services/membership.service.js +37 -16
- package/dist/lib/services/subscription.service.d.ts.map +1 -1
- package/dist/lib/services/subscription.service.js +2 -1
- package/dist/lib/services/team-member.service.d.ts +15 -3
- package/dist/lib/services/team-member.service.d.ts.map +1 -1
- package/dist/lib/services/team-member.service.js +27 -6
- package/dist/lib/services/team.service.d.ts.map +1 -1
- package/dist/lib/teams/permissions.d.ts +3 -1
- package/dist/lib/teams/permissions.d.ts.map +1 -1
- package/dist/lib/teams/permissions.js +6 -0
- package/dist/lib/teams/schema.d.ts.map +1 -1
- package/dist/lib/teams/schema.js +3 -0
- package/dist/lib/theme/forced-theme.d.ts +34 -0
- package/dist/lib/theme/forced-theme.d.ts.map +1 -0
- package/dist/lib/theme/forced-theme.js +27 -0
- package/dist/lib/theme/get-default-theme-mode.d.ts +3 -0
- package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
- package/dist/lib/theme/get-default-theme-mode.js +5 -3
- package/dist/messages/de/auth.json +25 -2
- package/dist/messages/de/index.d.ts +81 -0
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/de/index.js +2 -0
- package/dist/messages/de/index.ts +2 -0
- package/dist/messages/en/auth.json +25 -2
- package/dist/messages/en/index.d.ts +81 -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/es/auth.json +25 -2
- package/dist/messages/es/index.d.ts +81 -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/fr/auth.json +25 -2
- package/dist/messages/fr/index.d.ts +81 -0
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/fr/index.js +2 -0
- package/dist/messages/fr/index.ts +2 -0
- package/dist/messages/it/auth.json +25 -2
- package/dist/messages/it/index.d.ts +81 -0
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/it/index.js +2 -0
- package/dist/messages/it/index.ts +2 -0
- package/dist/messages/pt/auth.json +25 -2
- package/dist/messages/pt/index.d.ts +81 -0
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/messages/pt/index.js +2 -0
- package/dist/messages/pt/index.ts +2 -0
- package/dist/migrations/005_api_audit_log.sql +2 -1
- package/dist/migrations/025_api_audit_log_nullable_api_key.sql +12 -0
- package/dist/migrations/026_login_events.sql +91 -0
- package/dist/migrations/027_rls_bypass_developer_and_system_admin_team.sql +197 -0
- package/dist/providers/DashboardProviders.d.ts +12 -3
- package/dist/providers/DashboardProviders.d.ts.map +1 -1
- package/dist/providers/DashboardProviders.js +6 -2
- package/dist/providers/theme-provider.d.ts +19 -2
- package/dist/providers/theme-provider.d.ts.map +1 -1
- package/dist/providers/theme-provider.js +6 -2
- package/dist/templates/app/(auth)/signup/page.tsx +8 -0
- package/dist/templates/app/(public)/[...slug]/page.tsx +9 -14
- package/dist/templates/app/api/auth/[...all]/route.ts +23 -1
- package/dist/templates/app/api/health/route.ts +4 -2
- package/dist/templates/app/api/internal/user-metadata/route.ts +5 -3
- package/dist/templates/app/api/mcp/route.ts +176 -0
- package/dist/templates/app/api/superadmin/subscriptions/route.ts +2 -1
- package/dist/templates/app/api/superadmin/teams/[teamId]/route.ts +4 -3
- package/dist/templates/app/api/superadmin/users/[userId]/route.ts +10 -3
- package/dist/templates/app/api/v1/api-keys/[id]/route.ts +50 -71
- package/dist/templates/app/api/v1/api-keys/route.ts +35 -45
- package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +14 -14
- package/dist/templates/app/api/v1/billing/cancel/route.ts +7 -6
- package/dist/templates/app/api/v1/billing/change-plan/route.ts +5 -4
- package/dist/templates/app/api/v1/billing/check-action/route.ts +6 -4
- package/dist/templates/app/api/v1/billing/checkout/route.ts +7 -5
- package/dist/templates/app/api/v1/billing/plans/route.ts +8 -12
- package/dist/templates/app/api/v1/billing/portal/route.ts +7 -5
- package/dist/templates/app/api/v1/billing/webhooks/polar/route.ts +1 -1
- package/dist/templates/app/api/v1/devtools/blocks/route.ts +5 -4
- package/dist/templates/app/api/v1/devtools/features/route.ts +5 -4
- package/dist/templates/app/api/v1/devtools/flows/route.ts +5 -4
- package/dist/templates/app/api/v1/devtools/scheduled-actions/route.ts +9 -7
- package/dist/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +5 -4
- package/dist/templates/app/api/v1/devtools/testing/route.ts +5 -4
- package/dist/templates/app/api/v1/media/[id]/route.ts +13 -25
- package/dist/templates/app/api/v1/media/[id]/tags/route.ts +17 -25
- package/dist/templates/app/api/v1/media/check-duplicates/route.ts +5 -7
- package/dist/templates/app/api/v1/media/route.ts +5 -9
- package/dist/templates/app/api/v1/media/upload/route.ts +9 -21
- package/dist/templates/app/api/v1/media-tags/route.ts +9 -13
- package/dist/templates/app/api/v1/patterns/[id]/usages/route.ts +11 -19
- package/dist/templates/app/api/v1/post-categories/[id]/route.ts +9 -7
- package/dist/templates/app/api/v1/post-categories/route.ts +5 -4
- package/dist/templates/app/api/v1/team-invitations/[token]/accept/route.ts +16 -18
- package/dist/templates/app/api/v1/team-invitations/[token]/decline/route.ts +15 -17
- package/dist/templates/app/api/v1/team-invitations/[token]/route.ts +8 -8
- package/dist/templates/app/api/v1/team-invitations/route.ts +9 -11
- package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +41 -32
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +15 -16
- package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +14 -15
- package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +32 -36
- package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +33 -33
- package/dist/templates/app/api/v1/teams/[teamId]/route.ts +35 -41
- package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +5 -3
- package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +10 -6
- package/dist/templates/app/api/v1/teams/route.ts +33 -27
- package/dist/templates/app/api/v1/teams/switch/route.ts +11 -13
- package/dist/templates/app/api/v1/theme/[...path]/route.ts +23 -2
- package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +32 -77
- package/dist/templates/app/api/v1/users/[id]/route.ts +35 -68
- package/dist/templates/app/api/v1/users/route.ts +21 -25
- package/dist/templates/app/dashboard/layout.tsx +2 -6
- package/dist/templates/app/layout.ppr.tsx +9 -14
- package/dist/templates/app/layout.tsx +39 -19
- package/dist/templates/contents/themes/starter/config/app.config.ts +19 -0
- package/dist/templates/contents/themes/starter/config/theme.config.ts +6 -0
- package/dist/templates/contents/themes/starter/styles/globals.css +6 -2
- package/dist/templates/proxy.ts +46 -10
- package/dist/templates/tsconfig.json +4 -0
- package/dist/types/theme.d.ts +9 -0
- package/dist/types/theme.d.ts.map +1 -1
- package/migrations/005_api_audit_log.sql +2 -1
- package/migrations/025_api_audit_log_nullable_api_key.sql +12 -0
- package/migrations/026_login_events.sql +91 -0
- package/migrations/027_rls_bypass_developer_and_system_admin_team.sql +197 -0
- package/package.json +20 -12
- package/scripts/build/registry/__tests__/mcp-registry.test.mjs +64 -0
- package/scripts/build/registry/__tests__/scope-registry.test.mjs +106 -0
- package/scripts/build/registry/discovery/mcp-overrides.mjs +72 -0
- package/scripts/build/registry/discovery/mcp-overrides.test.mjs +86 -0
- package/scripts/build/registry/generators/mcp-registry.mjs +61 -0
- package/scripts/build/registry/generators/scope-registry.mjs +140 -88
- package/scripts/build/registry.mjs +8 -4
- package/templates/app/(auth)/signup/page.tsx +8 -0
- package/templates/app/(public)/[...slug]/page.tsx +9 -14
- package/templates/app/api/auth/[...all]/route.ts +23 -1
- package/templates/app/api/health/route.ts +4 -2
- package/templates/app/api/internal/user-metadata/route.ts +5 -3
- package/templates/app/api/mcp/route.ts +176 -0
- package/templates/app/api/superadmin/subscriptions/route.ts +2 -1
- package/templates/app/api/superadmin/teams/[teamId]/route.ts +4 -3
- package/templates/app/api/superadmin/users/[userId]/route.ts +10 -3
- package/templates/app/api/v1/api-keys/[id]/route.ts +50 -71
- package/templates/app/api/v1/api-keys/route.ts +35 -45
- package/templates/app/api/v1/auth/signup-with-invite/route.ts +14 -14
- package/templates/app/api/v1/billing/cancel/route.ts +7 -6
- package/templates/app/api/v1/billing/change-plan/route.ts +5 -4
- package/templates/app/api/v1/billing/check-action/route.ts +6 -4
- package/templates/app/api/v1/billing/checkout/route.ts +7 -5
- package/templates/app/api/v1/billing/plans/route.ts +8 -12
- package/templates/app/api/v1/billing/portal/route.ts +7 -5
- package/templates/app/api/v1/billing/webhooks/polar/route.ts +1 -1
- package/templates/app/api/v1/devtools/blocks/route.ts +5 -4
- package/templates/app/api/v1/devtools/features/route.ts +5 -4
- package/templates/app/api/v1/devtools/flows/route.ts +5 -4
- package/templates/app/api/v1/devtools/scheduled-actions/route.ts +9 -7
- package/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +5 -4
- package/templates/app/api/v1/devtools/testing/route.ts +5 -4
- package/templates/app/api/v1/media/[id]/route.ts +13 -25
- package/templates/app/api/v1/media/[id]/tags/route.ts +17 -25
- package/templates/app/api/v1/media/check-duplicates/route.ts +5 -7
- package/templates/app/api/v1/media/route.ts +5 -9
- package/templates/app/api/v1/media/upload/route.ts +9 -21
- package/templates/app/api/v1/media-tags/route.ts +9 -13
- package/templates/app/api/v1/patterns/[id]/usages/route.ts +11 -19
- package/templates/app/api/v1/post-categories/[id]/route.ts +9 -7
- package/templates/app/api/v1/post-categories/route.ts +5 -4
- package/templates/app/api/v1/team-invitations/[token]/accept/route.ts +16 -18
- package/templates/app/api/v1/team-invitations/[token]/decline/route.ts +15 -17
- package/templates/app/api/v1/team-invitations/[token]/route.ts +8 -8
- package/templates/app/api/v1/team-invitations/route.ts +9 -11
- package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +41 -32
- package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +15 -16
- package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +14 -15
- package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +32 -36
- package/templates/app/api/v1/teams/[teamId]/members/route.ts +33 -33
- package/templates/app/api/v1/teams/[teamId]/route.ts +35 -41
- package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +5 -3
- package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +10 -6
- package/templates/app/api/v1/teams/route.ts +33 -27
- package/templates/app/api/v1/teams/switch/route.ts +11 -13
- package/templates/app/api/v1/theme/[...path]/route.ts +23 -2
- package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +32 -77
- package/templates/app/api/v1/users/[id]/route.ts +35 -68
- package/templates/app/api/v1/users/route.ts +21 -25
- package/templates/app/dashboard/layout.tsx +2 -6
- package/templates/app/layout.ppr.tsx +9 -14
- package/templates/app/layout.tsx +39 -19
- package/templates/contents/themes/starter/config/app.config.ts +19 -0
- package/templates/contents/themes/starter/config/theme.config.ts +6 -0
- package/templates/contents/themes/starter/styles/globals.css +6 -2
- package/templates/proxy.ts +46 -10
- package/templates/tsconfig.json +4 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +23 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/scope-registry.ts +56 -6
- package/tests/jest/__mocks__/next-server.js +24 -0
- package/dist/styles/classes.json +0 -1093
- package/dist/styles/ui.css +0 -2
- package/scripts/build/build-ui-css.mjs +0 -351
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function translateApiError(result, context) {
|
|
2
|
+
var _a;
|
|
3
|
+
const { status, body } = result;
|
|
4
|
+
const code = body.code ?? `HTTP_${status}`;
|
|
5
|
+
const detail = body.error ? ` (API: ${body.error})` : "";
|
|
6
|
+
switch (code) {
|
|
7
|
+
case "AUTHENTICATION_FAILED":
|
|
8
|
+
return "API key inv\xE1lida, expirada o revocada. Gener\xE1 una nueva en Settings \u2192 API Keys y actualiz\xE1 la configuraci\xF3n del cliente MCP.";
|
|
9
|
+
case "TEAM_CONTEXT_REQUIRED":
|
|
10
|
+
return "Falta el contexto de equipo (team). Verific\xE1 que tu API key pertenezca a un usuario con un team activo, o envi\xE1 el header x-team-id.";
|
|
11
|
+
case "TEAM_ACCESS_DENIED":
|
|
12
|
+
return "El usuario de la API key no es miembro del team indicado. Verific\xE1 el x-team-id o us\xE1 el team por defecto.";
|
|
13
|
+
case "VALIDATION_ERROR":
|
|
14
|
+
return `Datos inv\xE1lidos para ${context.slug}.${formatDetails(body.details)} Correg\xED los campos y reintent\xE1.`;
|
|
15
|
+
case "INVALID_FIELD_VALUE":
|
|
16
|
+
return `Un campo tiene un valor no permitido${detail}. Revis\xE1 los valores del schema de la tool y reintent\xE1.`;
|
|
17
|
+
case "UNIQUE_CONSTRAINT_VIOLATION":
|
|
18
|
+
return `Ya existe un registro de ${context.slug} con ese valor \xFAnico${detail}. Buscalo con la tool de list y actualizalo en vez de crearlo.`;
|
|
19
|
+
case "RATE_LIMIT_EXCEEDED":
|
|
20
|
+
return "L\xEDmite de requests alcanzado. Esper\xE1 un minuto antes de reintentar; para cargas grandes us\xE1 las tools de batch si el entity las expone.";
|
|
21
|
+
default:
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
switch (status) {
|
|
25
|
+
case 401:
|
|
26
|
+
return "No autenticado: la API key no fue aceptada. Gener\xE1 una nueva en Settings \u2192 API Keys.";
|
|
27
|
+
case 403:
|
|
28
|
+
return `Sin permiso para ${context.operation} en ${context.slug}. Si es un problema de scope, tu API key necesita el scope ${context.slug}:${scopeFor(context.operation)}. Si es un problema de rol, tu rol en el team no permite esta acci\xF3n.`;
|
|
29
|
+
case 404:
|
|
30
|
+
return `No se encontr\xF3 el registro de ${context.slug}. El ID puede ser incorrecto o el registro fue eliminado \u2014 us\xE1 la tool de list para encontrar el ID correcto.`;
|
|
31
|
+
case 409:
|
|
32
|
+
return `No se puede completar: el registro de ${context.slug} tiene registros relacionados que dependen de \xE9l${detail}. Elimin\xE1 o reasign\xE1 los registros dependientes primero.`;
|
|
33
|
+
case 429:
|
|
34
|
+
return "L\xEDmite de requests alcanzado. Esper\xE1 un minuto antes de reintentar.";
|
|
35
|
+
case 500: {
|
|
36
|
+
const hints = ((_a = context.hints) == null ? void 0 : _a.length) ? ` Posibles causas conocidas: ${context.hints.join(" \xB7 ")}.` : "";
|
|
37
|
+
return `Error interno de la API al ejecutar ${context.operation} en ${context.slug}.${hints} Si persiste, reportalo.`;
|
|
38
|
+
}
|
|
39
|
+
default:
|
|
40
|
+
return `Error ${status} (${code}) al ejecutar ${context.operation} en ${context.slug}${detail}.`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function scopeFor(operation) {
|
|
44
|
+
if (operation === "list" || operation === "get") return "read";
|
|
45
|
+
if (operation === "delete") return "delete";
|
|
46
|
+
return "write";
|
|
47
|
+
}
|
|
48
|
+
function formatDetails(details) {
|
|
49
|
+
if (!details) return "";
|
|
50
|
+
if (Array.isArray(details)) {
|
|
51
|
+
const lines = details.map((issue) => {
|
|
52
|
+
if (issue && typeof issue === "object") {
|
|
53
|
+
const record = issue;
|
|
54
|
+
const path = Array.isArray(record.path) ? record.path.join(".") : String(record.path ?? "");
|
|
55
|
+
const message = String(record.message ?? JSON.stringify(record));
|
|
56
|
+
return path ? `${path}: ${message}` : message;
|
|
57
|
+
}
|
|
58
|
+
return String(issue);
|
|
59
|
+
}).slice(0, 8);
|
|
60
|
+
return ` Problemas: ${lines.join(" \xB7 ")}.`;
|
|
61
|
+
}
|
|
62
|
+
return ` Detalle: ${JSON.stringify(details).slice(0, 300)}.`;
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
translateApiError
|
|
66
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process entity executor.
|
|
3
|
+
*
|
|
4
|
+
* Invokes the core generic handlers directly (exactly like
|
|
5
|
+
* app/api/v1/[entity]/route.ts does) with a synthesized NextRequest carrying
|
|
6
|
+
* the caller's Authorization and the resolved x-team-id. NO fetch fallback:
|
|
7
|
+
* if the in-process path fails it fails loudly; we never degrade to HTTP,
|
|
8
|
+
* which would send the credential to an env-derived URL.
|
|
9
|
+
*
|
|
10
|
+
* Team context is injected in ALL FIVE operations — the handler only reads
|
|
11
|
+
* the x-team-id header, and validates it on every operation.
|
|
12
|
+
*/
|
|
13
|
+
import type { EntityExecutor } from './types';
|
|
14
|
+
export declare const executeEntityOperation: EntityExecutor;
|
|
15
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,OAAO,KAAK,EAAmB,cAAc,EAA2C,MAAM,SAAS,CAAA;AAKvG,eAAO,MAAM,sBAAsB,EAAE,cA8BpC,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { NextRequest } from "next/server";
|
|
2
|
+
import {
|
|
3
|
+
handleGenericList,
|
|
4
|
+
handleGenericCreate,
|
|
5
|
+
handleGenericRead,
|
|
6
|
+
handleGenericUpdate,
|
|
7
|
+
handleGenericDelete
|
|
8
|
+
} from "../api/entity/generic-handler.js";
|
|
9
|
+
const INTERNAL_ORIGIN = "http://mcp.internal";
|
|
10
|
+
const executeEntityOperation = async (args, ctx) => {
|
|
11
|
+
const request = buildRequest(args, ctx);
|
|
12
|
+
const params = Promise.resolve({ entity: args.slug, id: args.id ?? "" });
|
|
13
|
+
let response;
|
|
14
|
+
switch (args.operation) {
|
|
15
|
+
case "list":
|
|
16
|
+
response = await handleGenericList(request);
|
|
17
|
+
break;
|
|
18
|
+
case "create":
|
|
19
|
+
response = await handleGenericCreate(request);
|
|
20
|
+
break;
|
|
21
|
+
case "get":
|
|
22
|
+
response = await handleGenericRead(request, { params });
|
|
23
|
+
break;
|
|
24
|
+
case "update":
|
|
25
|
+
response = await handleGenericUpdate(request, { params });
|
|
26
|
+
break;
|
|
27
|
+
case "delete":
|
|
28
|
+
response = await handleGenericDelete(request, { params });
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Unsupported entity operation: ${String(args.operation)}`);
|
|
32
|
+
}
|
|
33
|
+
const body = await response.json();
|
|
34
|
+
return { status: response.status, body };
|
|
35
|
+
};
|
|
36
|
+
function buildRequest(args, ctx) {
|
|
37
|
+
const path = args.id ? `/api/v1/${args.slug}/${args.id}` : `/api/v1/${args.slug}`;
|
|
38
|
+
const url = new URL(path, INTERNAL_ORIGIN);
|
|
39
|
+
for (const [key, value] of Object.entries(args.query ?? {})) {
|
|
40
|
+
if (value !== void 0 && value !== "") url.searchParams.set(key, value);
|
|
41
|
+
}
|
|
42
|
+
const method = METHODS[args.operation];
|
|
43
|
+
const headers = {
|
|
44
|
+
authorization: ctx.authHeader,
|
|
45
|
+
"x-team-id": ctx.teamId
|
|
46
|
+
};
|
|
47
|
+
let body;
|
|
48
|
+
if (args.body !== void 0) {
|
|
49
|
+
body = JSON.stringify(args.body);
|
|
50
|
+
headers["content-type"] = "application/json";
|
|
51
|
+
}
|
|
52
|
+
return new NextRequest(url, { method, headers, body });
|
|
53
|
+
}
|
|
54
|
+
const METHODS = {
|
|
55
|
+
list: "GET",
|
|
56
|
+
get: "GET",
|
|
57
|
+
create: "POST",
|
|
58
|
+
update: "PATCH",
|
|
59
|
+
delete: "DELETE"
|
|
60
|
+
};
|
|
61
|
+
export {
|
|
62
|
+
executeEntityOperation
|
|
63
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createMcpEngine, type McpEngine } from './engine';
|
|
2
|
+
export { executeEntityOperation } from './executor';
|
|
3
|
+
export { auditToolCall } from './audit';
|
|
4
|
+
export { translateApiError } from './errors';
|
|
5
|
+
export { buildEntitySchemas, type EntitySchemaBundle, type SchemaBuilderContext } from './schema-builder';
|
|
6
|
+
export { StatelessJsonRpcTransport } from './transport';
|
|
7
|
+
export { generateEntityTools, toolToken, listArgsToQuery, normalizeDateFields, errorResult, } from './tool-generator';
|
|
8
|
+
export { McpToolError, MUTATION_OPERATIONS, type AuditEntry, type EngineApi, type EntityApiResult, type EntityExecutor, type EntityPresetInfo, type ExecuteEntityArgs, type McpEngineOptions, type McpEntityOverride, type McpOperation, type McpShape, type McpToolAnnotations, type McpToolDefinition, type McpToolResult, type McpToolResultContent, type ToolExecutionContext, } from './types';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,WAAW,GACZ,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createMcpEngine } from "./engine.js";
|
|
2
|
+
import { executeEntityOperation } from "./executor.js";
|
|
3
|
+
import { auditToolCall } from "./audit.js";
|
|
4
|
+
import { translateApiError } from "./errors.js";
|
|
5
|
+
import { buildEntitySchemas } from "./schema-builder.js";
|
|
6
|
+
import { StatelessJsonRpcTransport } from "./transport.js";
|
|
7
|
+
import {
|
|
8
|
+
generateEntityTools,
|
|
9
|
+
toolToken,
|
|
10
|
+
listArgsToQuery,
|
|
11
|
+
normalizeDateFields,
|
|
12
|
+
errorResult
|
|
13
|
+
} from "./tool-generator.js";
|
|
14
|
+
import {
|
|
15
|
+
McpToolError,
|
|
16
|
+
MUTATION_OPERATIONS
|
|
17
|
+
} from "./types.js";
|
|
18
|
+
export {
|
|
19
|
+
MUTATION_OPERATIONS,
|
|
20
|
+
McpToolError,
|
|
21
|
+
StatelessJsonRpcTransport,
|
|
22
|
+
auditToolCall,
|
|
23
|
+
buildEntitySchemas,
|
|
24
|
+
createMcpEngine,
|
|
25
|
+
errorResult,
|
|
26
|
+
executeEntityOperation,
|
|
27
|
+
generateEntityTools,
|
|
28
|
+
listArgsToQuery,
|
|
29
|
+
normalizeDateFields,
|
|
30
|
+
toolToken,
|
|
31
|
+
translateApiError
|
|
32
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema builder — derives MCP tool input schemas from entity configs.
|
|
3
|
+
*
|
|
4
|
+
* DESIGN NOTE: the core's generateEntitySchemas output cannot back tools/list
|
|
5
|
+
* — its fields are built as z.union([..., z.undefined()]).transform(...),
|
|
6
|
+
* which zod 4 cannot convert to JSON Schema ("Undefined cannot be
|
|
7
|
+
* represented"). So this builder emits PRESENTATION schemas (JSON-Schema-
|
|
8
|
+
* friendly, LLM-documented) derived from the same field definitions. The core
|
|
9
|
+
* still validates: every call runs in-process through the generic handler,
|
|
10
|
+
* which validates with the real core schemas. The MCP layer enforces
|
|
11
|
+
* shape/enums/strictness; the core enforces semantics. This presentation
|
|
12
|
+
* layer must never be stricter than what the real API accepts.
|
|
13
|
+
*
|
|
14
|
+
* MCP-side hardening against the API's silent failures:
|
|
15
|
+
* - strict objects: unknown keys are rejected, not stripped
|
|
16
|
+
* - sortBy: enum of the entity's actually-sortable fields
|
|
17
|
+
* - filters: only real filterable fields; date/datetime EXCLUDED (the core
|
|
18
|
+
* applies `=` equality which never matches a timestamptz → silent [])
|
|
19
|
+
* - dateField/from/to validated as a trio (a lone `from` is silently ignored)
|
|
20
|
+
* - search only exposed when the entity has one of name|title|slug|content
|
|
21
|
+
* - `distinct` NEVER exposed (identifier interpolation risk in the core)
|
|
22
|
+
*/
|
|
23
|
+
import { z } from 'zod';
|
|
24
|
+
import type { EntityConfig } from '../entities/types';
|
|
25
|
+
import type { McpEntityOverride, McpShape } from './types';
|
|
26
|
+
export interface EntitySchemaBundle {
|
|
27
|
+
createShape: McpShape;
|
|
28
|
+
createStrict: z.ZodTypeAny;
|
|
29
|
+
updateShape: McpShape;
|
|
30
|
+
updateStrict: z.ZodTypeAny;
|
|
31
|
+
listShape: McpShape;
|
|
32
|
+
listStrict: z.ZodTypeAny;
|
|
33
|
+
getShape: McpShape;
|
|
34
|
+
getStrict: z.ZodTypeAny;
|
|
35
|
+
/** Field names of type date (DATE column) — outputs get normalized to YYYY-MM-DD. */
|
|
36
|
+
dateFields: string[];
|
|
37
|
+
/** Which field the core search param actually scans for this entity (or null). */
|
|
38
|
+
searchField: string | null;
|
|
39
|
+
}
|
|
40
|
+
export interface SchemaBuilderContext {
|
|
41
|
+
translateOption?: (slug: string, fieldName: string, value: string) => string | undefined;
|
|
42
|
+
override?: McpEntityOverride;
|
|
43
|
+
}
|
|
44
|
+
export declare function buildEntitySchemas(entityConfig: EntityConfig, context?: SchemaBuilderContext): EntitySchemaBundle;
|
|
45
|
+
//# sourceMappingURL=schema-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-builder.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp/schema-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAwB1D,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,QAAQ,CAAA;IACrB,YAAY,EAAE,CAAC,CAAC,UAAU,CAAA;IAC1B,WAAW,EAAE,QAAQ,CAAA;IACrB,YAAY,EAAE,CAAC,CAAC,UAAU,CAAA;IAC1B,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,CAAC,CAAC,UAAU,CAAA;IACxB,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,CAAC,CAAC,UAAU,CAAA;IACvB,qFAAqF;IACrF,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IACxF,QAAQ,CAAC,EAAE,iBAAiB,CAAA;CAC7B;AAED,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,YAAY,EAC1B,OAAO,GAAE,oBAAyB,GACjC,kBAAkB,CAwBpB"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const SEARCHED_FIELDS = ["name", "title", "slug", "content"];
|
|
3
|
+
const INPUT_EXCLUDED_TYPES = /* @__PURE__ */ new Set(["media-library", "file", "image", "video", "audio"]);
|
|
4
|
+
const FILTER_EXCLUDED_TYPES = /* @__PURE__ */ new Set([
|
|
5
|
+
"datetime",
|
|
6
|
+
"json",
|
|
7
|
+
"media-library",
|
|
8
|
+
"textarea",
|
|
9
|
+
"richtext",
|
|
10
|
+
"markdown"
|
|
11
|
+
]);
|
|
12
|
+
function buildEntitySchemas(entityConfig, context = {}) {
|
|
13
|
+
const createShape = buildInputShape(entityConfig, "create", context);
|
|
14
|
+
const updateShape = buildInputShape(entityConfig, "update", context);
|
|
15
|
+
const listShape = buildListShape(entityConfig, context);
|
|
16
|
+
const getShape = {
|
|
17
|
+
id: z.string().min(1).describe(`ID del registro de ${entityConfig.names.singular} (uuid)`)
|
|
18
|
+
};
|
|
19
|
+
const dateFields = entityConfig.fields.filter((f) => f.type === "date").map((f) => f.name);
|
|
20
|
+
const searchField = SEARCHED_FIELDS.find((name) => entityConfig.fields.some((f) => f.name === name)) ?? null;
|
|
21
|
+
return {
|
|
22
|
+
createShape,
|
|
23
|
+
createStrict: z.object(createShape).strict(),
|
|
24
|
+
updateShape,
|
|
25
|
+
updateStrict: z.object(updateShape).strict(),
|
|
26
|
+
listShape,
|
|
27
|
+
listStrict: buildListStrict(listShape),
|
|
28
|
+
getShape,
|
|
29
|
+
getStrict: z.object(getShape).strict(),
|
|
30
|
+
dateFields,
|
|
31
|
+
searchField
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function presentationType(field) {
|
|
35
|
+
switch (field.type) {
|
|
36
|
+
case "select":
|
|
37
|
+
case "radio":
|
|
38
|
+
case "buttongroup":
|
|
39
|
+
case "combobox": {
|
|
40
|
+
const values = (field.options ?? []).map((opt) => String(opt.value));
|
|
41
|
+
return values.length ? z.enum(values) : z.string();
|
|
42
|
+
}
|
|
43
|
+
case "multiselect":
|
|
44
|
+
case "tags":
|
|
45
|
+
return z.array(z.string());
|
|
46
|
+
case "doublerange":
|
|
47
|
+
return z.array(z.number()).length(2);
|
|
48
|
+
case "number":
|
|
49
|
+
case "rating":
|
|
50
|
+
case "range":
|
|
51
|
+
case "currency": {
|
|
52
|
+
let type = z.number();
|
|
53
|
+
if (field.min !== void 0) type = type.min(field.min);
|
|
54
|
+
if (field.max !== void 0) type = type.max(field.max);
|
|
55
|
+
return type;
|
|
56
|
+
}
|
|
57
|
+
case "boolean":
|
|
58
|
+
return z.boolean();
|
|
59
|
+
case "date":
|
|
60
|
+
case "datetime":
|
|
61
|
+
case "email":
|
|
62
|
+
case "url":
|
|
63
|
+
case "phone":
|
|
64
|
+
case "timezone":
|
|
65
|
+
case "country":
|
|
66
|
+
return z.string().min(1);
|
|
67
|
+
case "relation":
|
|
68
|
+
case "relation-prop":
|
|
69
|
+
case "reference":
|
|
70
|
+
case "user":
|
|
71
|
+
return z.string().min(1);
|
|
72
|
+
case "relation-multi":
|
|
73
|
+
case "relation-prop-multi":
|
|
74
|
+
return z.array(z.string());
|
|
75
|
+
case "json":
|
|
76
|
+
case "address":
|
|
77
|
+
return z.record(z.string(), z.unknown());
|
|
78
|
+
case "text":
|
|
79
|
+
case "textarea":
|
|
80
|
+
case "markdown":
|
|
81
|
+
case "richtext":
|
|
82
|
+
case "code": {
|
|
83
|
+
let type = z.string();
|
|
84
|
+
if (field.maxLength) type = type.max(field.maxLength);
|
|
85
|
+
return type;
|
|
86
|
+
}
|
|
87
|
+
default:
|
|
88
|
+
console.warn(`[mcp] unmapped field type "${field.type}" (${field.name}) \u2014 using permissive schema`);
|
|
89
|
+
return z.unknown();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function buildInputShape(entityConfig, operation, context) {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
const shape = {};
|
|
95
|
+
const relax = new Set(((_a = context.override) == null ? void 0 : _a.relaxRequired) ?? []);
|
|
96
|
+
for (const field of entityConfig.fields) {
|
|
97
|
+
if (INPUT_EXCLUDED_TYPES.has(field.type)) continue;
|
|
98
|
+
if ((_b = field.api) == null ? void 0 : _b.readOnly) continue;
|
|
99
|
+
let type = presentationType(field);
|
|
100
|
+
const required = operation === "create" && field.required && !relax.has(field.name);
|
|
101
|
+
if (!required) type = type.optional();
|
|
102
|
+
shape[field.name] = type.describe(describeField(entityConfig, field, field.name, context));
|
|
103
|
+
}
|
|
104
|
+
return shape;
|
|
105
|
+
}
|
|
106
|
+
function buildListShape(entityConfig, context) {
|
|
107
|
+
var _a;
|
|
108
|
+
const sortable = entityConfig.fields.filter((f) => {
|
|
109
|
+
var _a2;
|
|
110
|
+
return (_a2 = f.api) == null ? void 0 : _a2.sortable;
|
|
111
|
+
}).map((f) => f.name);
|
|
112
|
+
const sortableValues = [...sortable, "createdAt", "updatedAt"];
|
|
113
|
+
const dateFieldNames = entityConfig.fields.filter((f) => f.type === "date" || f.type === "datetime").map((f) => f.name);
|
|
114
|
+
const shape = {
|
|
115
|
+
page: z.number().int().min(1).optional().describe("P\xE1gina (1)"),
|
|
116
|
+
limit: z.number().int().min(1).max(100).optional().describe("Por p\xE1gina (10, m\xE1x 100)"),
|
|
117
|
+
sortBy: z.enum(sortableValues).optional().describe("Ordenar por"),
|
|
118
|
+
sortOrder: z.enum(["ASC", "DESC"]).optional().describe("Orden (DESC)")
|
|
119
|
+
};
|
|
120
|
+
const searchField = SEARCHED_FIELDS.find(
|
|
121
|
+
(name) => entityConfig.fields.some((f) => f.name === name)
|
|
122
|
+
);
|
|
123
|
+
if (searchField) {
|
|
124
|
+
shape.search = z.string().min(1).optional().describe(`Busca SOLO en "${searchField}"`);
|
|
125
|
+
}
|
|
126
|
+
if (dateFieldNames.length) {
|
|
127
|
+
shape.dateField = z.enum(dateFieldNames).optional().describe("Campo de fecha del rango (obligatorio con from/to)");
|
|
128
|
+
shape.from = z.string().optional().describe("Desde (YYYY-MM-DD)");
|
|
129
|
+
shape.to = z.string().optional().describe("Hasta (YYYY-MM-DD)");
|
|
130
|
+
}
|
|
131
|
+
const filterShape = {};
|
|
132
|
+
for (const field of entityConfig.fields) {
|
|
133
|
+
if (FILTER_EXCLUDED_TYPES.has(field.type)) continue;
|
|
134
|
+
if (INPUT_EXCLUDED_TYPES.has(field.type)) continue;
|
|
135
|
+
if (((_a = field.api) == null ? void 0 : _a.filterable) === false) continue;
|
|
136
|
+
filterShape[field.name] = presentationType(field).optional().describe(describeField(entityConfig, field, field.name, context, true));
|
|
137
|
+
}
|
|
138
|
+
if (Object.keys(filterShape).length) {
|
|
139
|
+
shape.filters = z.object(filterShape).strict().optional().describe("Filtros exactos. Fechas NO ac\xE1: us\xE1 dateField/from/to.");
|
|
140
|
+
}
|
|
141
|
+
const projectable = entityConfig.fields.map((f) => f.name);
|
|
142
|
+
if (projectable.length) {
|
|
143
|
+
shape.fields = z.array(z.enum(projectable)).min(1).optional().describe("Devolver solo estos campos (achica la respuesta)");
|
|
144
|
+
}
|
|
145
|
+
return shape;
|
|
146
|
+
}
|
|
147
|
+
function buildListStrict(listShape) {
|
|
148
|
+
return z.object(listShape).strict().superRefine((value, ctx) => {
|
|
149
|
+
const v = value;
|
|
150
|
+
if ((v.from || v.to) && !v.dateField) {
|
|
151
|
+
ctx.addIssue({
|
|
152
|
+
code: "custom",
|
|
153
|
+
path: ["dateField"],
|
|
154
|
+
message: "from/to requieren dateField \u2014 sin \xE9l la API los ignora en silencio"
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function describeField(entityConfig, field, name, context, compact = false) {
|
|
160
|
+
var _a, _b, _c, _d, _e, _f;
|
|
161
|
+
const overrideDescription = (_c = (_b = (_a = context.override) == null ? void 0 : _a.describe) == null ? void 0 : _b.fields) == null ? void 0 : _c[name];
|
|
162
|
+
if (overrideDescription) return compact ? shorten(overrideDescription) : overrideDescription;
|
|
163
|
+
if (!field) return name;
|
|
164
|
+
const label = ((_d = field.display) == null ? void 0 : _d.label) || name;
|
|
165
|
+
if (compact) return label;
|
|
166
|
+
const parts = [label];
|
|
167
|
+
if (((_e = field.display) == null ? void 0 : _e.description) && field.display.description !== label) {
|
|
168
|
+
parts.push(field.display.description);
|
|
169
|
+
}
|
|
170
|
+
switch (field.type) {
|
|
171
|
+
case "select":
|
|
172
|
+
case "multiselect":
|
|
173
|
+
case "radio":
|
|
174
|
+
case "buttongroup":
|
|
175
|
+
case "combobox": {
|
|
176
|
+
const options = (field.options ?? []).map((opt) => {
|
|
177
|
+
var _a2;
|
|
178
|
+
const value = String(opt.value);
|
|
179
|
+
const translated = ((_a2 = context.translateOption) == null ? void 0 : _a2.call(context, entityConfig.slug, field.name, value)) ?? opt.label;
|
|
180
|
+
return translated && translated !== value ? `${value}=${translated}` : value;
|
|
181
|
+
}).join(", ");
|
|
182
|
+
if (options) parts.push(options);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case "relation":
|
|
186
|
+
if ((_f = field.relation) == null ? void 0 : _f.entity) {
|
|
187
|
+
parts.push(`uuid de ${field.relation.entity} (us\xE1 su tool de list)`);
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
case "user":
|
|
191
|
+
parts.push("uuid de un miembro del team");
|
|
192
|
+
break;
|
|
193
|
+
case "date":
|
|
194
|
+
parts.push("YYYY-MM-DD");
|
|
195
|
+
break;
|
|
196
|
+
case "datetime":
|
|
197
|
+
parts.push("ISO 8601 con offset, ej. 2026-08-05T10:00:00-03:00");
|
|
198
|
+
break;
|
|
199
|
+
case "boolean":
|
|
200
|
+
parts.push("true/false (booleano, no string)");
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
return parts.join(". ");
|
|
206
|
+
}
|
|
207
|
+
function shorten(text) {
|
|
208
|
+
return text.length <= 60 ? text : `${text.slice(0, 57)}...`;
|
|
209
|
+
}
|
|
210
|
+
export {
|
|
211
|
+
buildEntitySchemas
|
|
212
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool generator — one entity config → its CRUD tool definitions.
|
|
3
|
+
*
|
|
4
|
+
* Names come from the entity config (names.singular/plural), never from naive
|
|
5
|
+
* singularization. Descriptions are fed primarily from the entity's API
|
|
6
|
+
* presets (summary → entity description, preset descriptions/payloads →
|
|
7
|
+
* few-shot examples). Delete tools require confirm:true and carry destructive
|
|
8
|
+
* warnings.
|
|
9
|
+
*
|
|
10
|
+
* No separate authorization gate is re-implemented here: every tool call
|
|
11
|
+
* round-trips in-process through the real generic entity handler (see
|
|
12
|
+
* executor.ts), which already runs `checkAuthPermission` + `hasRequiredScope`
|
|
13
|
+
* + ownership/field guards for API-key auth (fixed for #94/#95). A denied
|
|
14
|
+
* call surfaces as a normal API error, translated via errors.ts.
|
|
15
|
+
*/
|
|
16
|
+
import type { EntityConfig } from '../entities/types';
|
|
17
|
+
import { type EntityExecutor, type EntityPresetInfo, type McpEngineOptions, type McpEntityOverride, type McpOperation, type McpToolDefinition, type McpToolResult } from './types';
|
|
18
|
+
interface GeneratorDeps {
|
|
19
|
+
executor: EntityExecutor;
|
|
20
|
+
toolPrefix: string;
|
|
21
|
+
translateOption?: McpEngineOptions['translateOption'];
|
|
22
|
+
presets?: EntityPresetInfo;
|
|
23
|
+
}
|
|
24
|
+
export declare function generateEntityTools(entityConfig: EntityConfig, operations: McpOperation[], override: McpEntityOverride | undefined, deps: GeneratorDeps): McpToolDefinition[];
|
|
25
|
+
export declare function toolToken(name: string): string;
|
|
26
|
+
export declare function listArgsToQuery(args: Record<string, unknown>): Record<string, string>;
|
|
27
|
+
/** DATE columns come back serialized as timestamptz — normalize to YYYY-MM-DD. */
|
|
28
|
+
export declare function normalizeDateFields(row: unknown, dateFields: string[]): unknown;
|
|
29
|
+
export declare function errorResult(message: string): McpToolResult;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=tool-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp/tool-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAEjB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAA;AAEhB,UAAU,aAAa;IACrB,QAAQ,EAAE,cAAc,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAA;IACrD,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,YAAY,EAAE,EAC1B,QAAQ,EAAE,iBAAiB,GAAG,SAAS,EACvC,IAAI,EAAE,aAAa,GAClB,iBAAiB,EAAE,CA6NrB;AAID,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AA0BD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBrF;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAU/E;AAkBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAE1D"}
|