@graphoria/server 0.1.0
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/LICENSE +201 -0
- package/NOTICE +10 -0
- package/README.md +129 -0
- package/cli.ts +105 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/src/ai/agent/agent.d.ts +37 -0
- package/dist/src/ai/agent/agent.d.ts.map +1 -0
- package/dist/src/ai/agent/index.d.ts +3 -0
- package/dist/src/ai/agent/index.d.ts.map +1 -0
- package/dist/src/ai/agent/providers/anthropic.d.ts +10 -0
- package/dist/src/ai/agent/providers/anthropic.d.ts.map +1 -0
- package/dist/src/ai/agent/providers/index.d.ts +8 -0
- package/dist/src/ai/agent/providers/index.d.ts.map +1 -0
- package/dist/src/ai/agent/providers/ollama.d.ts +11 -0
- package/dist/src/ai/agent/providers/ollama.d.ts.map +1 -0
- package/dist/src/ai/agent/providers/openai.d.ts +14 -0
- package/dist/src/ai/agent/providers/openai.d.ts.map +1 -0
- package/dist/src/ai/agent/types.d.ts +51 -0
- package/dist/src/ai/agent/types.d.ts.map +1 -0
- package/dist/src/ai/ask-field.test.d.ts +2 -0
- package/dist/src/ai/ask-field.test.d.ts.map +1 -0
- package/dist/src/ai/index.d.ts +7 -0
- package/dist/src/ai/index.d.ts.map +1 -0
- package/dist/src/ai/mcp/create-server.d.ts +14 -0
- package/dist/src/ai/mcp/create-server.d.ts.map +1 -0
- package/dist/src/ai/mcp/create-server.test.d.ts +2 -0
- package/dist/src/ai/mcp/create-server.test.d.ts.map +1 -0
- package/dist/src/ai/mcp/index.d.ts +13 -0
- package/dist/src/ai/mcp/index.d.ts.map +1 -0
- package/dist/src/ai/mcp/index.test.d.ts +2 -0
- package/dist/src/ai/mcp/index.test.d.ts.map +1 -0
- package/dist/src/ai/mcp/instructions.d.ts +2 -0
- package/dist/src/ai/mcp/instructions.d.ts.map +1 -0
- package/dist/src/ai/tools/agent.d.ts +4 -0
- package/dist/src/ai/tools/agent.d.ts.map +1 -0
- package/dist/src/ai/tools/agent.test.d.ts +2 -0
- package/dist/src/ai/tools/agent.test.d.ts.map +1 -0
- package/dist/src/ai/tools/core.d.ts +75 -0
- package/dist/src/ai/tools/core.d.ts.map +1 -0
- package/dist/src/ai/tools/query-data.d.ts +35 -0
- package/dist/src/ai/tools/query-data.d.ts.map +1 -0
- package/dist/src/analyzeQuery/analyzers/fragmentAnalyzer.d.ts +5 -0
- package/dist/src/analyzeQuery/analyzers/fragmentAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzeQuery/analyzers/operationAnalyzer.d.ts +6 -0
- package/dist/src/analyzeQuery/analyzers/operationAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzeQuery/analyzers/selectionAnalyzer.d.ts +6 -0
- package/dist/src/analyzeQuery/analyzers/selectionAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzeQuery/analyzers/variableAnalyzer.d.ts +4 -0
- package/dist/src/analyzeQuery/analyzers/variableAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzeQuery/depthLimit.d.ts +16 -0
- package/dist/src/analyzeQuery/depthLimit.d.ts.map +1 -0
- package/dist/src/analyzeQuery/depthLimit.test.d.ts +2 -0
- package/dist/src/analyzeQuery/depthLimit.test.d.ts.map +1 -0
- package/dist/src/analyzeQuery/directiveUtils.d.ts +4 -0
- package/dist/src/analyzeQuery/directiveUtils.d.ts.map +1 -0
- package/dist/src/analyzeQuery/directiveUtils.test.d.ts +2 -0
- package/dist/src/analyzeQuery/directiveUtils.test.d.ts.map +1 -0
- package/dist/src/analyzeQuery/index.d.ts +5 -0
- package/dist/src/analyzeQuery/index.d.ts.map +1 -0
- package/dist/src/analyzeQuery/index.test.d.ts +2 -0
- package/dist/src/analyzeQuery/index.test.d.ts.map +1 -0
- package/dist/src/analyzeQuery/resolveVariables.d.ts +71 -0
- package/dist/src/analyzeQuery/resolveVariables.d.ts.map +1 -0
- package/dist/src/analyzeQuery/resolveVariables.test.d.ts +2 -0
- package/dist/src/analyzeQuery/resolveVariables.test.d.ts.map +1 -0
- package/dist/src/analyzeQuery/staticValues.test.d.ts +2 -0
- package/dist/src/analyzeQuery/staticValues.test.d.ts.map +1 -0
- package/dist/src/analyzeQuery/typeUtils.d.ts +9 -0
- package/dist/src/analyzeQuery/typeUtils.d.ts.map +1 -0
- package/dist/src/analyzeQuery/types.d.ts +54 -0
- package/dist/src/analyzeQuery/types.d.ts.map +1 -0
- package/dist/src/analyzeQuery/valueExtractors.d.ts +4 -0
- package/dist/src/analyzeQuery/valueExtractors.d.ts.map +1 -0
- package/dist/src/authentication/duration.d.ts +14 -0
- package/dist/src/authentication/duration.d.ts.map +1 -0
- package/dist/src/authentication/duration.test.d.ts +2 -0
- package/dist/src/authentication/duration.test.d.ts.map +1 -0
- package/dist/src/authentication/index.d.ts +4 -0
- package/dist/src/authentication/index.d.ts.map +1 -0
- package/dist/src/authentication/index.test.d.ts +2 -0
- package/dist/src/authentication/index.test.d.ts.map +1 -0
- package/dist/src/authentication/jwt.d.ts +10 -0
- package/dist/src/authentication/jwt.d.ts.map +1 -0
- package/dist/src/authentication/jwt.test.d.ts +2 -0
- package/dist/src/authentication/jwt.test.d.ts.map +1 -0
- package/dist/src/authentication/paseto.d.ts +7 -0
- package/dist/src/authentication/paseto.d.ts.map +1 -0
- package/dist/src/authentication/paseto.test.d.ts +2 -0
- package/dist/src/authentication/paseto.test.d.ts.map +1 -0
- package/dist/src/authentication/tokenRepository.d.ts +14 -0
- package/dist/src/authentication/tokenRepository.d.ts.map +1 -0
- package/dist/src/authentication/tokenRepository.test.d.ts +2 -0
- package/dist/src/authentication/tokenRepository.test.d.ts.map +1 -0
- package/dist/src/authentication/types.d.ts +42 -0
- package/dist/src/authentication/types.d.ts.map +1 -0
- package/dist/src/cli/seedAuth.d.ts +4 -0
- package/dist/src/cli/seedAuth.d.ts.map +1 -0
- package/dist/src/cli/seedAuth.test.d.ts +2 -0
- package/dist/src/cli/seedAuth.test.d.ts.map +1 -0
- package/dist/src/cli/seedAuthArgs.d.ts +9 -0
- package/dist/src/cli/seedAuthArgs.d.ts.map +1 -0
- package/dist/src/config/helpers/cronHelper.d.ts +21 -0
- package/dist/src/config/helpers/cronHelper.d.ts.map +1 -0
- package/dist/src/config/helpers/cronHelper.test.d.ts +2 -0
- package/dist/src/config/helpers/cronHelper.test.d.ts.map +1 -0
- package/dist/src/config/helpers/index.d.ts +4 -0
- package/dist/src/config/helpers/index.d.ts.map +1 -0
- package/dist/src/config/helpers/operationHelper.d.ts +44 -0
- package/dist/src/config/helpers/operationHelper.d.ts.map +1 -0
- package/dist/src/config/helpers/queueHelper.d.ts +20 -0
- package/dist/src/config/helpers/queueHelper.d.ts.map +1 -0
- package/dist/src/config/helpers/queueHelper.test.d.ts +2 -0
- package/dist/src/config/helpers/queueHelper.test.d.ts.map +1 -0
- package/dist/src/config/index.d.ts +236 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/types/ai.d.ts +29 -0
- package/dist/src/config/types/ai.d.ts.map +1 -0
- package/dist/src/config/types/auth.d.ts +112 -0
- package/dist/src/config/types/auth.d.ts.map +1 -0
- package/dist/src/config/types/configuration.d.ts +61 -0
- package/dist/src/config/types/configuration.d.ts.map +1 -0
- package/dist/src/config/types/cron.d.ts +81 -0
- package/dist/src/config/types/cron.d.ts.map +1 -0
- package/dist/src/config/types/db.d.ts +210 -0
- package/dist/src/config/types/db.d.ts.map +1 -0
- package/dist/src/config/types/index.d.ts +17 -0
- package/dist/src/config/types/index.d.ts.map +1 -0
- package/dist/src/config/types/operation.d.ts +226 -0
- package/dist/src/config/types/operation.d.ts.map +1 -0
- package/dist/src/config/types/queue.d.ts +142 -0
- package/dist/src/config/types/queue.d.ts.map +1 -0
- package/dist/src/config/types/remote-rest.d.ts +18 -0
- package/dist/src/config/types/remote-rest.d.ts.map +1 -0
- package/dist/src/config/types/remote-schema.d.ts +27 -0
- package/dist/src/config/types/remote-schema.d.ts.map +1 -0
- package/dist/src/config/types/virtual-columns.d.ts +89 -0
- package/dist/src/config/types/virtual-columns.d.ts.map +1 -0
- package/dist/src/config/types/virtual-columns.test.d.ts +2 -0
- package/dist/src/config/types/virtual-columns.test.d.ts.map +1 -0
- package/dist/src/configuration/getSchemas/index.d.ts +867 -0
- package/dist/src/configuration/getSchemas/index.d.ts.map +1 -0
- package/dist/src/configuration/getSchemas/mergeEntities/index.d.ts +412 -0
- package/dist/src/configuration/getSchemas/mergeEntities/index.d.ts.map +1 -0
- package/dist/src/configuration/getSchemas/type-definition-generator/index.d.ts +16 -0
- package/dist/src/configuration/getSchemas/type-definition-generator/index.d.ts.map +1 -0
- package/dist/src/configuration/getSchemas/type-definition-generator/index.test.d.ts +2 -0
- package/dist/src/configuration/getSchemas/type-definition-generator/index.test.d.ts.map +1 -0
- package/dist/src/configuration/gql/buildExecute.d.ts +31 -0
- package/dist/src/configuration/gql/buildExecute.d.ts.map +1 -0
- package/dist/src/configuration/gql/buildExecute.test.d.ts +2 -0
- package/dist/src/configuration/gql/buildExecute.test.d.ts.map +1 -0
- package/dist/src/configuration/gql/gqlAuthOperations.d.ts +9 -0
- package/dist/src/configuration/gql/gqlAuthOperations.d.ts.map +1 -0
- package/dist/src/configuration/gql/gqlAuthOperations.test.d.ts +2 -0
- package/dist/src/configuration/gql/gqlAuthOperations.test.d.ts.map +1 -0
- package/dist/src/configuration/gql/handleGraphQLRequestFactory.d.ts +28 -0
- package/dist/src/configuration/gql/handleGraphQLRequestFactory.d.ts.map +1 -0
- package/dist/src/configuration/gql/handleGraphQLRequestFactory.test.d.ts +2 -0
- package/dist/src/configuration/gql/handleGraphQLRequestFactory.test.d.ts.map +1 -0
- package/dist/src/configuration/gql/handleGraphQLSubscriptionFactory.d.ts +19 -0
- package/dist/src/configuration/gql/handleGraphQLSubscriptionFactory.d.ts.map +1 -0
- package/dist/src/configuration/index.d.ts +719 -0
- package/dist/src/configuration/index.d.ts.map +1 -0
- package/dist/src/configuration/rest/generateOpenAPI.d.ts +19 -0
- package/dist/src/configuration/rest/generateOpenAPI.d.ts.map +1 -0
- package/dist/src/configuration/rest/handleRESTRequestFactory.d.ts +12 -0
- package/dist/src/configuration/rest/handleRESTRequestFactory.d.ts.map +1 -0
- package/dist/src/configuration/rest/handleRESTRequestFactory.test.d.ts +2 -0
- package/dist/src/configuration/rest/handleRESTRequestFactory.test.d.ts.map +1 -0
- package/dist/src/configuration/rest/index.d.ts +20 -0
- package/dist/src/configuration/rest/index.d.ts.map +1 -0
- package/dist/src/configuration/rest/openApiErrors.d.ts +71 -0
- package/dist/src/configuration/rest/openApiErrors.d.ts.map +1 -0
- package/dist/src/console/App.d.ts +3 -0
- package/dist/src/console/App.d.ts.map +1 -0
- package/dist/src/console/Login.d.ts +6 -0
- package/dist/src/console/Login.d.ts.map +1 -0
- package/dist/src/console/api.d.ts +17 -0
- package/dist/src/console/api.d.ts.map +1 -0
- package/dist/src/console/api.test.d.ts +2 -0
- package/dist/src/console/api.test.d.ts.map +1 -0
- package/dist/src/console/client.d.ts +67 -0
- package/dist/src/console/client.d.ts.map +1 -0
- package/dist/src/console/frontend.d.ts +8 -0
- package/dist/src/console/frontend.d.ts.map +1 -0
- package/dist/src/console/pages/ConfigPage.d.ts +2 -0
- package/dist/src/console/pages/ConfigPage.d.ts.map +1 -0
- package/dist/src/console/pages/RolesPage.d.ts +2 -0
- package/dist/src/console/pages/RolesPage.d.ts.map +1 -0
- package/dist/src/console/pages/StatusPage.d.ts +2 -0
- package/dist/src/console/pages/StatusPage.d.ts.map +1 -0
- package/dist/src/console/pages/TablesPage.d.ts +2 -0
- package/dist/src/console/pages/TablesPage.d.ts.map +1 -0
- package/dist/src/console/useApi.d.ts +8 -0
- package/dist/src/console/useApi.d.ts.map +1 -0
- package/dist/src/cron/index.d.ts +63 -0
- package/dist/src/cron/index.d.ts.map +1 -0
- package/dist/src/databases/auth/auth-operations.d.ts +11 -0
- package/dist/src/databases/auth/auth-operations.d.ts.map +1 -0
- package/dist/src/databases/auth/password.d.ts +3 -0
- package/dist/src/databases/auth/password.d.ts.map +1 -0
- package/dist/src/databases/auth/password.test.d.ts +2 -0
- package/dist/src/databases/auth/password.test.d.ts.map +1 -0
- package/dist/src/databases/common.d.ts +53 -0
- package/dist/src/databases/common.d.ts.map +1 -0
- package/dist/src/databases/common.test.d.ts +2 -0
- package/dist/src/databases/common.test.d.ts.map +1 -0
- package/dist/src/databases/core/executor.d.ts +10 -0
- package/dist/src/databases/core/executor.d.ts.map +1 -0
- package/dist/src/databases/core/executor.test.d.ts +2 -0
- package/dist/src/databases/core/executor.test.d.ts.map +1 -0
- package/dist/src/databases/core/function-mapping.d.ts +38 -0
- package/dist/src/databases/core/function-mapping.d.ts.map +1 -0
- package/dist/src/databases/core/identifier.d.ts +2 -0
- package/dist/src/databases/core/identifier.d.ts.map +1 -0
- package/dist/src/databases/core/identifier.test.d.ts +2 -0
- package/dist/src/databases/core/identifier.test.d.ts.map +1 -0
- package/dist/src/databases/core/query-builder.d.ts +64 -0
- package/dist/src/databases/core/query-builder.d.ts.map +1 -0
- package/dist/src/databases/core/query-builder.test.d.ts +2 -0
- package/dist/src/databases/core/query-builder.test.d.ts.map +1 -0
- package/dist/src/databases/directives.d.ts +16 -0
- package/dist/src/databases/directives.d.ts.map +1 -0
- package/dist/src/databases/directives.test.d.ts +2 -0
- package/dist/src/databases/directives.test.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/auth.d.ts +9 -0
- package/dist/src/databases/engines/mssql/auth.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/auth.test.d.ts +2 -0
- package/dist/src/databases/engines/mssql/auth.test.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/connection.d.ts +14 -0
- package/dist/src/databases/engines/mssql/connection.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/format.d.ts +5 -0
- package/dist/src/databases/engines/mssql/format.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/getStructure.d.ts +48 -0
- package/dist/src/databases/engines/mssql/getStructure.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/getViews.d.ts +7 -0
- package/dist/src/databases/engines/mssql/getViews.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/query/index.d.ts +7 -0
- package/dist/src/databases/engines/mssql/query/index.d.ts.map +1 -0
- package/dist/src/databases/engines/mssql/query/index.test.d.ts +2 -0
- package/dist/src/databases/engines/mssql/query/index.test.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/auth.d.ts +9 -0
- package/dist/src/databases/engines/mysql/auth.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/auth.test.d.ts +2 -0
- package/dist/src/databases/engines/mysql/auth.test.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/connection.d.ts +14 -0
- package/dist/src/databases/engines/mysql/connection.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/format.d.ts +5 -0
- package/dist/src/databases/engines/mysql/format.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/getStructure.d.ts +48 -0
- package/dist/src/databases/engines/mysql/getStructure.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/getViews.d.ts +7 -0
- package/dist/src/databases/engines/mysql/getViews.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/query/index.d.ts +7 -0
- package/dist/src/databases/engines/mysql/query/index.d.ts.map +1 -0
- package/dist/src/databases/engines/mysql/query/index.test.d.ts +2 -0
- package/dist/src/databases/engines/mysql/query/index.test.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/auth.d.ts +9 -0
- package/dist/src/databases/engines/postgresql/auth.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/auth.test.d.ts +2 -0
- package/dist/src/databases/engines/postgresql/auth.test.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/connection.d.ts +14 -0
- package/dist/src/databases/engines/postgresql/connection.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/format.d.ts +5 -0
- package/dist/src/databases/engines/postgresql/format.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/getStructure.d.ts +48 -0
- package/dist/src/databases/engines/postgresql/getStructure.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/getViews.d.ts +7 -0
- package/dist/src/databases/engines/postgresql/getViews.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/query/index.d.ts +7 -0
- package/dist/src/databases/engines/postgresql/query/index.d.ts.map +1 -0
- package/dist/src/databases/engines/postgresql/query/index.test.d.ts +2 -0
- package/dist/src/databases/engines/postgresql/query/index.test.d.ts.map +1 -0
- package/dist/src/databases/engines/shared/claims.d.ts +2 -0
- package/dist/src/databases/engines/shared/claims.d.ts.map +1 -0
- package/dist/src/databases/engines/shared/types.d.ts +8 -0
- package/dist/src/databases/engines/shared/types.d.ts.map +1 -0
- package/dist/src/databases/high-level-operations.d.ts +146 -0
- package/dist/src/databases/high-level-operations.d.ts.map +1 -0
- package/dist/src/databases/high-level-operations.test.d.ts +2 -0
- package/dist/src/databases/high-level-operations.test.d.ts.map +1 -0
- package/dist/src/databases/index.d.ts +8 -0
- package/dist/src/databases/index.d.ts.map +1 -0
- package/dist/src/databases/metadata/structure.d.ts +56 -0
- package/dist/src/databases/metadata/structure.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/convert.d.ts +2 -0
- package/dist/src/databases/schemaBuilder/convert.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateCreateTable/index.d.ts +15 -0
- package/dist/src/databases/schemaBuilder/generateCreateTable/index.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateCreateTable/index.test.d.ts +2 -0
- package/dist/src/databases/schemaBuilder/generateCreateTable/index.test.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateCreateView/index.d.ts +18 -0
- package/dist/src/databases/schemaBuilder/generateCreateView/index.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateInsert/index.d.ts +8 -0
- package/dist/src/databases/schemaBuilder/generateInsert/index.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateInsert/index.test.d.ts +2 -0
- package/dist/src/databases/schemaBuilder/generateInsert/index.test.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateSchemaCreation/index.d.ts +7 -0
- package/dist/src/databases/schemaBuilder/generateSchemaCreation/index.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/generateSchemaCreation/index.test.d.ts +2 -0
- package/dist/src/databases/schemaBuilder/generateSchemaCreation/index.test.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/mssqlToPostgres/convertView.d.ts +2 -0
- package/dist/src/databases/schemaBuilder/mssqlToPostgres/convertView.d.ts.map +1 -0
- package/dist/src/databases/schemaBuilder/utils.d.ts +8 -0
- package/dist/src/databases/schemaBuilder/utils.d.ts.map +1 -0
- package/dist/src/databases/sqlTypeUtils.d.ts +24 -0
- package/dist/src/databases/sqlTypeUtils.d.ts.map +1 -0
- package/dist/src/databases/sqlTypeUtils.test.d.ts +2 -0
- package/dist/src/databases/sqlTypeUtils.test.d.ts.map +1 -0
- package/dist/src/databases/transformers/data-transformers.d.ts +215 -0
- package/dist/src/databases/transformers/data-transformers.d.ts.map +1 -0
- package/dist/src/databases/transformers/data-transformers.test.d.ts +2 -0
- package/dist/src/databases/transformers/data-transformers.test.d.ts.map +1 -0
- package/dist/src/databases/transformers/genResolverName.d.ts +2 -0
- package/dist/src/databases/transformers/genResolverName.d.ts.map +1 -0
- package/dist/src/databases/transformers/genResolverName.test.d.ts +2 -0
- package/dist/src/databases/transformers/genResolverName.test.d.ts.map +1 -0
- package/dist/src/index.d.ts +139 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/logging/index.d.ts +21 -0
- package/dist/src/logging/index.d.ts.map +1 -0
- package/dist/src/queues/kafka.d.ts +22 -0
- package/dist/src/queues/kafka.d.ts.map +1 -0
- package/dist/src/queues/rabbitmq.d.ts +34 -0
- package/dist/src/queues/rabbitmq.d.ts.map +1 -0
- package/dist/src/queues/rabbitmq.test.d.ts +2 -0
- package/dist/src/queues/rabbitmq.test.d.ts.map +1 -0
- package/dist/src/remoteREST/index.d.ts +13 -0
- package/dist/src/remoteREST/index.d.ts.map +1 -0
- package/dist/src/remoteREST/parse.d.ts +8 -0
- package/dist/src/remoteREST/parse.d.ts.map +1 -0
- package/dist/src/remoteREST/parse.test.d.ts +2 -0
- package/dist/src/remoteREST/parse.test.d.ts.map +1 -0
- package/dist/src/remoteREST/proxy.d.ts +6 -0
- package/dist/src/remoteREST/proxy.d.ts.map +1 -0
- package/dist/src/remoteREST/proxy.test.d.ts +2 -0
- package/dist/src/remoteREST/proxy.test.d.ts.map +1 -0
- package/dist/src/remoteREST/transform.d.ts +8 -0
- package/dist/src/remoteREST/transform.d.ts.map +1 -0
- package/dist/src/remoteREST/transform.test.d.ts +2 -0
- package/dist/src/remoteREST/transform.test.d.ts.map +1 -0
- package/dist/src/remoteREST/types.d.ts +37 -0
- package/dist/src/remoteREST/types.d.ts.map +1 -0
- package/dist/src/remoteSchemas/index.d.ts +13 -0
- package/dist/src/remoteSchemas/index.d.ts.map +1 -0
- package/dist/src/remoteSchemas/introspect.d.ts +7 -0
- package/dist/src/remoteSchemas/introspect.d.ts.map +1 -0
- package/dist/src/remoteSchemas/introspect.test.d.ts +2 -0
- package/dist/src/remoteSchemas/introspect.test.d.ts.map +1 -0
- package/dist/src/remoteSchemas/proxy.d.ts +7 -0
- package/dist/src/remoteSchemas/proxy.d.ts.map +1 -0
- package/dist/src/remoteSchemas/proxy.test.d.ts +2 -0
- package/dist/src/remoteSchemas/proxy.test.d.ts.map +1 -0
- package/dist/src/remoteSchemas/transform.d.ts +9 -0
- package/dist/src/remoteSchemas/transform.d.ts.map +1 -0
- package/dist/src/remoteSchemas/transform.test.d.ts +2 -0
- package/dist/src/remoteSchemas/transform.test.d.ts.map +1 -0
- package/dist/src/remoteSchemas/types.d.ts +41 -0
- package/dist/src/remoteSchemas/types.d.ts.map +1 -0
- package/dist/src/singletons/ai.d.ts +25 -0
- package/dist/src/singletons/ai.d.ts.map +1 -0
- package/dist/src/singletons/ai.test.d.ts +2 -0
- package/dist/src/singletons/ai.test.d.ts.map +1 -0
- package/dist/src/singletons/authentication.d.ts +4 -0
- package/dist/src/singletons/authentication.d.ts.map +1 -0
- package/dist/src/singletons/cache/index.d.ts +5 -0
- package/dist/src/singletons/cache/index.d.ts.map +1 -0
- package/dist/src/singletons/cache/lruCacheStore.d.ts +12 -0
- package/dist/src/singletons/cache/lruCacheStore.d.ts.map +1 -0
- package/dist/src/singletons/cache/lruCacheStore.test.d.ts +2 -0
- package/dist/src/singletons/cache/lruCacheStore.test.d.ts.map +1 -0
- package/dist/src/singletons/cache/redisCacheStore.d.ts +16 -0
- package/dist/src/singletons/cache/redisCacheStore.d.ts.map +1 -0
- package/dist/src/singletons/cache/redisClient.d.ts +3 -0
- package/dist/src/singletons/cache/redisClient.d.ts.map +1 -0
- package/dist/src/singletons/cache/registry.d.ts +7 -0
- package/dist/src/singletons/cache/registry.d.ts.map +1 -0
- package/dist/src/singletons/cache/registry.test.d.ts +2 -0
- package/dist/src/singletons/cache/registry.test.d.ts.map +1 -0
- package/dist/src/singletons/cache/types.d.ts +8 -0
- package/dist/src/singletons/cache/types.d.ts.map +1 -0
- package/dist/src/singletons/cron.d.ts +69 -0
- package/dist/src/singletons/cron.d.ts.map +1 -0
- package/dist/src/singletons/databases.d.ts +27 -0
- package/dist/src/singletons/databases.d.ts.map +1 -0
- package/dist/src/singletons/databases.test.d.ts +2 -0
- package/dist/src/singletons/databases.test.d.ts.map +1 -0
- package/dist/src/singletons/env.d.ts +494 -0
- package/dist/src/singletons/env.d.ts.map +1 -0
- package/dist/src/singletons/queues.d.ts +17 -0
- package/dist/src/singletons/queues.d.ts.map +1 -0
- package/dist/src/subscriptions/index.d.ts +4 -0
- package/dist/src/subscriptions/index.d.ts.map +1 -0
- package/dist/src/subscriptions/strategies/database.d.ts +12 -0
- package/dist/src/subscriptions/strategies/database.d.ts.map +1 -0
- package/dist/src/subscriptions/strategies/index.d.ts +12 -0
- package/dist/src/subscriptions/strategies/index.d.ts.map +1 -0
- package/dist/src/subscriptions/strategies/queue.d.ts +11 -0
- package/dist/src/subscriptions/strategies/queue.d.ts.map +1 -0
- package/dist/src/subscriptions/types.d.ts +67 -0
- package/dist/src/subscriptions/types.d.ts.map +1 -0
- package/dist/src/subscriptions/utils/polling.d.ts +17 -0
- package/dist/src/subscriptions/utils/polling.d.ts.map +1 -0
- package/dist/src/types/common.d.ts +44 -0
- package/dist/src/types/common.d.ts.map +1 -0
- package/dist/src/types/configuration.d.ts +28 -0
- package/dist/src/types/configuration.d.ts.map +1 -0
- package/dist/src/types/db.d.ts +43 -0
- package/dist/src/types/db.d.ts.map +1 -0
- package/dist/src/types/env.d.ts +2302 -0
- package/dist/src/types/env.d.ts.map +1 -0
- package/dist/src/types/env.test.d.ts +2 -0
- package/dist/src/types/env.test.d.ts.map +1 -0
- package/dist/src/types/resolver.d.ts +121 -0
- package/dist/src/types/resolver.d.ts.map +1 -0
- package/dist/src/types/zod/ai.d.ts +6 -0
- package/dist/src/types/zod/ai.d.ts.map +1 -0
- package/dist/src/types/zod/auth.d.ts +76 -0
- package/dist/src/types/zod/auth.d.ts.map +1 -0
- package/dist/src/types/zod/configuration.d.ts +1278 -0
- package/dist/src/types/zod/configuration.d.ts.map +1 -0
- package/dist/src/types/zod/configuration.test.d.ts +2 -0
- package/dist/src/types/zod/configuration.test.d.ts.map +1 -0
- package/dist/src/types/zod/cron.d.ts +32 -0
- package/dist/src/types/zod/cron.d.ts.map +1 -0
- package/dist/src/types/zod/db.d.ts +441 -0
- package/dist/src/types/zod/db.d.ts.map +1 -0
- package/dist/src/types/zod/db.test.d.ts +2 -0
- package/dist/src/types/zod/db.test.d.ts.map +1 -0
- package/dist/src/types/zod/mcp.d.ts +6 -0
- package/dist/src/types/zod/mcp.d.ts.map +1 -0
- package/dist/src/types/zod/operation.d.ts +9 -0
- package/dist/src/types/zod/operation.d.ts.map +1 -0
- package/dist/src/types/zod/queue.d.ts +656 -0
- package/dist/src/types/zod/queue.d.ts.map +1 -0
- package/dist/src/types/zod/queue.test.d.ts +2 -0
- package/dist/src/types/zod/queue.test.d.ts.map +1 -0
- package/dist/src/types/zod/remoteREST.d.ts +6 -0
- package/dist/src/types/zod/remoteREST.d.ts.map +1 -0
- package/dist/src/types/zod/remoteSchema.d.ts +6 -0
- package/dist/src/types/zod/remoteSchema.d.ts.map +1 -0
- package/dist/src/utils/benchmark.d.ts +2 -0
- package/dist/src/utils/benchmark.d.ts.map +1 -0
- package/dist/src/utils/event-emitter.d.ts +19 -0
- package/dist/src/utils/event-emitter.d.ts.map +1 -0
- package/dist/src/utils/responses.d.ts +19 -0
- package/dist/src/utils/responses.d.ts.map +1 -0
- package/dist/src/utils/responses.test.d.ts +2 -0
- package/dist/src/utils/responses.test.d.ts.map +1 -0
- package/dist/src/utils/safeJSONParse.d.ts +2 -0
- package/dist/src/utils/safeJSONParse.d.ts.map +1 -0
- package/dist/src/utils/selection.d.ts +3 -0
- package/dist/src/utils/selection.d.ts.map +1 -0
- package/dist/src/utils/selection.test.d.ts +2 -0
- package/dist/src/utils/selection.test.d.ts.map +1 -0
- package/dist/src/utils/sessionVariables.d.ts +47 -0
- package/dist/src/utils/sessionVariables.d.ts.map +1 -0
- package/dist/src/utils/sessionVariables.test.d.ts +2 -0
- package/dist/src/utils/sessionVariables.test.d.ts.map +1 -0
- package/dist/src/utils/writeSchema.d.ts +3 -0
- package/dist/src/utils/writeSchema.d.ts.map +1 -0
- package/dist/standalone.d.ts +3 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +119 -0
- package/playgrounds/console/index.html +25 -0
- package/playgrounds/graphiql/index.html +1144 -0
- package/playgrounds/scalar/index.html +19 -0
- package/src/ai/agent/agent.ts +222 -0
- package/src/ai/agent/index.ts +2 -0
- package/src/ai/agent/providers/anthropic.ts +113 -0
- package/src/ai/agent/providers/index.ts +62 -0
- package/src/ai/agent/providers/ollama.ts +128 -0
- package/src/ai/agent/providers/openai.ts +100 -0
- package/src/ai/agent/types.ts +65 -0
- package/src/ai/index.ts +8 -0
- package/src/ai/mcp/create-server.ts +444 -0
- package/src/ai/mcp/index.ts +80 -0
- package/src/ai/mcp/instructions.ts +103 -0
- package/src/ai/tools/agent.ts +111 -0
- package/src/ai/tools/core.ts +486 -0
- package/src/ai/tools/query-data.ts +109 -0
- package/src/analyzeQuery/analyzers/fragmentAnalyzer.ts +29 -0
- package/src/analyzeQuery/analyzers/operationAnalyzer.ts +50 -0
- package/src/analyzeQuery/analyzers/selectionAnalyzer.ts +135 -0
- package/src/analyzeQuery/analyzers/variableAnalyzer.ts +17 -0
- package/src/analyzeQuery/depthLimit.ts +124 -0
- package/src/analyzeQuery/directiveUtils.ts +99 -0
- package/src/analyzeQuery/index.ts +66 -0
- package/src/analyzeQuery/resolveVariables.ts +394 -0
- package/src/analyzeQuery/typeUtils.ts +47 -0
- package/src/analyzeQuery/types.ts +57 -0
- package/src/analyzeQuery/valueExtractors.ts +96 -0
- package/src/authentication/duration.ts +50 -0
- package/src/authentication/index.ts +34 -0
- package/src/authentication/jwt.ts +220 -0
- package/src/authentication/paseto.ts +256 -0
- package/src/authentication/tokenRepository.ts +75 -0
- package/src/authentication/types.ts +78 -0
- package/src/cli/seedAuth.ts +51 -0
- package/src/cli/seedAuthArgs.ts +50 -0
- package/src/config/helpers/cronHelper.ts +29 -0
- package/src/config/helpers/index.ts +8 -0
- package/src/config/helpers/operationHelper.ts +146 -0
- package/src/config/helpers/queueHelper.ts +27 -0
- package/src/config/index.ts +315 -0
- package/src/config/types/ai.ts +35 -0
- package/src/config/types/auth.ts +147 -0
- package/src/config/types/configuration.ts +69 -0
- package/src/config/types/cron.ts +140 -0
- package/src/config/types/db.ts +256 -0
- package/src/config/types/index.ts +129 -0
- package/src/config/types/operation.ts +253 -0
- package/src/config/types/queue.ts +172 -0
- package/src/config/types/remote-rest.ts +28 -0
- package/src/config/types/remote-schema.ts +39 -0
- package/src/config/types/virtual-columns.ts +157 -0
- package/src/configuration/getSchemas/index.ts +82 -0
- package/src/configuration/getSchemas/mergeEntities/index.ts +221 -0
- package/src/configuration/getSchemas/type-definition-generator/index.ts +511 -0
- package/src/configuration/gql/buildExecute.ts +54 -0
- package/src/configuration/gql/gqlAuthOperations.ts +150 -0
- package/src/configuration/gql/handleGraphQLRequestFactory.ts +415 -0
- package/src/configuration/gql/handleGraphQLSubscriptionFactory.ts +249 -0
- package/src/configuration/index.ts +138 -0
- package/src/configuration/rest/generateOpenAPI.ts +361 -0
- package/src/configuration/rest/handleRESTRequestFactory.ts +335 -0
- package/src/configuration/rest/index.ts +167 -0
- package/src/configuration/rest/openApiErrors.ts +106 -0
- package/src/console/api.ts +270 -0
- package/src/cron/index.ts +251 -0
- package/src/databases/auth/auth-operations.ts +36 -0
- package/src/databases/auth/password.ts +4 -0
- package/src/databases/common.ts +642 -0
- package/src/databases/core/executor.ts +97 -0
- package/src/databases/core/function-mapping.ts +176 -0
- package/src/databases/core/identifier.ts +8 -0
- package/src/databases/core/query-builder.ts +47 -0
- package/src/databases/directives.ts +112 -0
- package/src/databases/engines/mssql/auth.ts +112 -0
- package/src/databases/engines/mssql/connection.ts +151 -0
- package/src/databases/engines/mssql/format.ts +23 -0
- package/src/databases/engines/mssql/getStructure.ts +112 -0
- package/src/databases/engines/mssql/getViews.ts +17 -0
- package/src/databases/engines/mssql/query/index.ts +306 -0
- package/src/databases/engines/mysql/auth.ts +100 -0
- package/src/databases/engines/mysql/connection.ts +100 -0
- package/src/databases/engines/mysql/format.ts +23 -0
- package/src/databases/engines/mysql/getStructure.ts +116 -0
- package/src/databases/engines/mysql/getViews.ts +20 -0
- package/src/databases/engines/mysql/query/index.ts +291 -0
- package/src/databases/engines/postgresql/auth.ts +98 -0
- package/src/databases/engines/postgresql/connection.ts +99 -0
- package/src/databases/engines/postgresql/format.ts +23 -0
- package/src/databases/engines/postgresql/getStructure.ts +149 -0
- package/src/databases/engines/postgresql/getViews.ts +20 -0
- package/src/databases/engines/postgresql/query/index.ts +291 -0
- package/src/databases/engines/shared/claims.ts +26 -0
- package/src/databases/engines/shared/types.ts +7 -0
- package/src/databases/high-level-operations.ts +272 -0
- package/src/databases/index.ts +28 -0
- package/src/databases/metadata/structure.ts +12 -0
- package/src/databases/schemaBuilder/convert.ts +121 -0
- package/src/databases/schemaBuilder/generateCreateTable/index.ts +133 -0
- package/src/databases/schemaBuilder/generateCreateView/index.ts +101 -0
- package/src/databases/schemaBuilder/generateInsert/index.ts +47 -0
- package/src/databases/schemaBuilder/generateSchemaCreation/index.ts +29 -0
- package/src/databases/schemaBuilder/mssqlToPostgres/convertView.ts +47 -0
- package/src/databases/schemaBuilder/utils.ts +17 -0
- package/src/databases/sqlTypeUtils.ts +91 -0
- package/src/databases/transformers/data-transformers.ts +128 -0
- package/src/databases/transformers/genResolverName.ts +18 -0
- package/src/index.ts +461 -0
- package/src/logging/index.ts +69 -0
- package/src/queues/kafka.ts +409 -0
- package/src/queues/rabbitmq.ts +331 -0
- package/src/remoteREST/index.ts +46 -0
- package/src/remoteREST/parse.ts +68 -0
- package/src/remoteREST/proxy.ts +92 -0
- package/src/remoteREST/transform.ts +121 -0
- package/src/remoteREST/types.ts +38 -0
- package/src/remoteSchemas/index.ts +48 -0
- package/src/remoteSchemas/introspect.ts +44 -0
- package/src/remoteSchemas/proxy.ts +146 -0
- package/src/remoteSchemas/transform.ts +210 -0
- package/src/remoteSchemas/types.ts +43 -0
- package/src/singletons/ai.ts +91 -0
- package/src/singletons/authentication.ts +13 -0
- package/src/singletons/cache/index.ts +4 -0
- package/src/singletons/cache/lruCacheStore.ts +34 -0
- package/src/singletons/cache/redisCacheStore.ts +81 -0
- package/src/singletons/cache/redisClient.ts +12 -0
- package/src/singletons/cache/registry.ts +51 -0
- package/src/singletons/cache/types.ts +7 -0
- package/src/singletons/cron.ts +21 -0
- package/src/singletons/databases.ts +68 -0
- package/src/singletons/env.ts +3 -0
- package/src/singletons/queues.ts +101 -0
- package/src/subscriptions/index.ts +20 -0
- package/src/subscriptions/strategies/database.ts +68 -0
- package/src/subscriptions/strategies/index.ts +38 -0
- package/src/subscriptions/strategies/queue.ts +61 -0
- package/src/subscriptions/types.ts +74 -0
- package/src/subscriptions/utils/polling.ts +119 -0
- package/src/types/common.ts +57 -0
- package/src/types/configuration.ts +52 -0
- package/src/types/db.ts +87 -0
- package/src/types/env.ts +137 -0
- package/src/types/resolver.ts +181 -0
- package/src/types/zod/ai.ts +8 -0
- package/src/types/zod/auth.ts +96 -0
- package/src/types/zod/configuration.ts +46 -0
- package/src/types/zod/cron.ts +35 -0
- package/src/types/zod/db.ts +146 -0
- package/src/types/zod/mcp.ts +8 -0
- package/src/types/zod/operation.ts +37 -0
- package/src/types/zod/queue.ts +182 -0
- package/src/types/zod/remoteREST.ts +8 -0
- package/src/types/zod/remoteSchema.ts +11 -0
- package/src/utils/benchmark.ts +13 -0
- package/src/utils/event-emitter.ts +217 -0
- package/src/utils/responses.ts +42 -0
- package/src/utils/safeJSONParse.ts +10 -0
- package/src/utils/selection.ts +35 -0
- package/src/utils/sessionVariables.ts +131 -0
- package/src/utils/writeSchema.ts +13 -0
- package/standalone.ts +32 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { RoleEntities } from "./core";
|
|
4
|
+
import type { Tool } from "../agent/types";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
describeEntityCore,
|
|
8
|
+
ENTITY_KINDS,
|
|
9
|
+
executeGraphqlCore,
|
|
10
|
+
listEntitiesCore,
|
|
11
|
+
makeValidateQuery,
|
|
12
|
+
} from "./core";
|
|
13
|
+
import { buildStructuredQuery, queryDataSchema } from "./query-data";
|
|
14
|
+
import type { StructuredQueryInput } from "./query-data";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build the agent's tool set against a compiled role schema. The agent reaches
|
|
18
|
+
* the database ONLY through these tools, so it inherits that role's visibility.
|
|
19
|
+
* `graphql_execute` must keep its name — the agent loop's anti-hallucination
|
|
20
|
+
* guard recognises it as a data-access tool.
|
|
21
|
+
*/
|
|
22
|
+
/** Preserve per-tool schema inference, then widen to the heterogeneous `Tool`. */
|
|
23
|
+
const tool = <T extends z.ZodTypeAny>(t: Tool<T>): Tool => t as unknown as Tool;
|
|
24
|
+
|
|
25
|
+
export const buildAgentTools = (role: RoleEntities): Tool[] => {
|
|
26
|
+
const validateQuery = makeValidateQuery(role);
|
|
27
|
+
|
|
28
|
+
return [
|
|
29
|
+
tool({
|
|
30
|
+
name: "list_entities",
|
|
31
|
+
description:
|
|
32
|
+
"Lists entities exposed to this role: tables, operations, remote schemas, remote REST APIs, stored procedures, queue publishers. Requires at least one of `kind` or `search`. Use `kind` to browse a category, `search` to find by name fragment (matches resolverName AND table descriptions).",
|
|
33
|
+
schema: z.object({
|
|
34
|
+
kind: z.enum(ENTITY_KINDS).optional(),
|
|
35
|
+
search: z.string().min(1).optional(),
|
|
36
|
+
}),
|
|
37
|
+
execute: async ({ kind, search }) => {
|
|
38
|
+
if (kind === undefined && (search === undefined || search === "")) {
|
|
39
|
+
return {
|
|
40
|
+
error:
|
|
41
|
+
'list_entities requires at least one of `kind` or `search`. Pick a kind (e.g. kind: "table") or supply a search term.',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return listEntitiesCore(role, { kind, search });
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
tool({
|
|
48
|
+
name: "describe_entity",
|
|
49
|
+
description:
|
|
50
|
+
"Returns detailed information about an entity. For tables: columns, relationships, the generated GraphQL list-field and _aggregate-field signatures, and ready-to-run example queries (list / filter / aggregate) using the table's real column names.",
|
|
51
|
+
schema: z.object({
|
|
52
|
+
name: z.string(),
|
|
53
|
+
kind: z.enum(ENTITY_KINDS).optional(),
|
|
54
|
+
}),
|
|
55
|
+
execute: async ({ name, kind }) => {
|
|
56
|
+
const result = describeEntityCore(role, { name, kind });
|
|
57
|
+
return result ?? { error: `Entity '${name}' not found.` };
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
tool({
|
|
61
|
+
name: "query_data",
|
|
62
|
+
description:
|
|
63
|
+
"Query data using structured JSON instead of raw GraphQL. PREFERRED over graphql_execute for list and aggregate queries — simpler, less error-prone. The server builds the query internally from your JSON input.",
|
|
64
|
+
schema: queryDataSchema,
|
|
65
|
+
execute: async (args) => {
|
|
66
|
+
const query = buildStructuredQuery(args as StructuredQueryInput);
|
|
67
|
+
const outcome = await executeGraphqlCore(role, validateQuery, {
|
|
68
|
+
query,
|
|
69
|
+
});
|
|
70
|
+
switch (outcome.kind) {
|
|
71
|
+
case "non_query":
|
|
72
|
+
return { error: "Internal: built query is not a query." };
|
|
73
|
+
case "validation":
|
|
74
|
+
return { data: null, errors: outcome.errors };
|
|
75
|
+
case "error":
|
|
76
|
+
return { error: outcome.message };
|
|
77
|
+
case "ok":
|
|
78
|
+
return outcome.result;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
tool({
|
|
83
|
+
name: "graphql_execute",
|
|
84
|
+
description:
|
|
85
|
+
"Executes a read-only GraphQL query against this role's schema. Mutations and subscriptions are rejected. Returns { data, errors }.",
|
|
86
|
+
schema: z.object({
|
|
87
|
+
query: z.string(),
|
|
88
|
+
variables: z.record(z.string(), z.unknown()).optional(),
|
|
89
|
+
}),
|
|
90
|
+
execute: async ({ query, variables }) => {
|
|
91
|
+
const outcome = await executeGraphqlCore(role, validateQuery, {
|
|
92
|
+
query,
|
|
93
|
+
variables,
|
|
94
|
+
});
|
|
95
|
+
switch (outcome.kind) {
|
|
96
|
+
case "non_query":
|
|
97
|
+
return {
|
|
98
|
+
error:
|
|
99
|
+
"Only `query` operations are allowed. Mutations and subscriptions are rejected.",
|
|
100
|
+
};
|
|
101
|
+
case "validation":
|
|
102
|
+
return { data: null, errors: outcome.errors };
|
|
103
|
+
case "error":
|
|
104
|
+
return { error: outcome.message };
|
|
105
|
+
case "ok":
|
|
106
|
+
return outcome.result;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
];
|
|
111
|
+
};
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphQLEnumType,
|
|
3
|
+
GraphQLInputObjectType,
|
|
4
|
+
GraphQLInterfaceType,
|
|
5
|
+
GraphQLObjectType,
|
|
6
|
+
GraphQLScalarType,
|
|
7
|
+
GraphQLUnionType,
|
|
8
|
+
parse,
|
|
9
|
+
printType,
|
|
10
|
+
specifiedRules,
|
|
11
|
+
validate,
|
|
12
|
+
} from "graphql";
|
|
13
|
+
|
|
14
|
+
import type { BunRequest } from "bun";
|
|
15
|
+
import type { GraphQLNamedType, GraphQLSchema } from "graphql";
|
|
16
|
+
import type { GetSchemaReturn } from "../../configuration/getSchemas";
|
|
17
|
+
|
|
18
|
+
import { depthLimitRule } from "../../analyzeQuery/depthLimit";
|
|
19
|
+
import { categorizeSqlType, isNumericType, SqlTypeCategory } from "../../databases/sqlTypeUtils";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A per-role compiled schema bundle (tables, operations, handlers, …).
|
|
23
|
+
* Shared by the MCP server and the AI agent — both query the same surface.
|
|
24
|
+
*/
|
|
25
|
+
export type RoleEntities = GetSchemaReturn;
|
|
26
|
+
|
|
27
|
+
export const ENTITY_KINDS = [
|
|
28
|
+
"table",
|
|
29
|
+
"operation",
|
|
30
|
+
"remote_schema",
|
|
31
|
+
"remote_rest",
|
|
32
|
+
"stored_procedure",
|
|
33
|
+
"queue_publisher",
|
|
34
|
+
] as const;
|
|
35
|
+
export type EntityKind = (typeof ENTITY_KINDS)[number];
|
|
36
|
+
|
|
37
|
+
export const synthesizeRequest = (
|
|
38
|
+
url: string,
|
|
39
|
+
init?: RequestInit & { body?: BodyInit | null },
|
|
40
|
+
): BunRequest => new Request(url, init) as unknown as BunRequest;
|
|
41
|
+
|
|
42
|
+
export const containsNonQueryOperation = (query: string): boolean => {
|
|
43
|
+
const document = parse(query);
|
|
44
|
+
return document.definitions.some(
|
|
45
|
+
(def) => def.kind === "OperationDefinition" && def.operation !== "query",
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const describeNamedType = (type: GraphQLNamedType): Record<string, unknown> => {
|
|
50
|
+
if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) {
|
|
51
|
+
return {
|
|
52
|
+
kind: type instanceof GraphQLObjectType ? "object" : "interface",
|
|
53
|
+
name: type.name,
|
|
54
|
+
description: type.description ?? null,
|
|
55
|
+
fields: Object.values(type.getFields()).map((f) => ({
|
|
56
|
+
name: f.name,
|
|
57
|
+
type: f.type.toString(),
|
|
58
|
+
description: f.description ?? null,
|
|
59
|
+
args: f.args.map((a) => ({ name: a.name, type: a.type.toString() })),
|
|
60
|
+
})),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (type instanceof GraphQLInputObjectType) {
|
|
64
|
+
return {
|
|
65
|
+
kind: "input",
|
|
66
|
+
name: type.name,
|
|
67
|
+
fields: Object.values(type.getFields()).map((f) => ({
|
|
68
|
+
name: f.name,
|
|
69
|
+
type: f.type.toString(),
|
|
70
|
+
})),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (type instanceof GraphQLEnumType) {
|
|
74
|
+
return {
|
|
75
|
+
kind: "enum",
|
|
76
|
+
name: type.name,
|
|
77
|
+
values: type.getValues().map((v) => v.name),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (type instanceof GraphQLUnionType) {
|
|
81
|
+
return {
|
|
82
|
+
kind: "union",
|
|
83
|
+
name: type.name,
|
|
84
|
+
types: type.getTypes().map((t) => t.name),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (type instanceof GraphQLScalarType) {
|
|
88
|
+
return { kind: "scalar", name: type.name };
|
|
89
|
+
}
|
|
90
|
+
const fallback = type as GraphQLNamedType;
|
|
91
|
+
return { kind: "unknown", name: fallback.name, sdl: printType(fallback) };
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
type DescribableColumn = {
|
|
95
|
+
name: string;
|
|
96
|
+
dataType: string;
|
|
97
|
+
isNullable: boolean;
|
|
98
|
+
virtual?: boolean;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const realColumns = <T extends DescribableColumn>(cols: readonly T[]): T[] =>
|
|
102
|
+
cols.filter((c) => !c.virtual);
|
|
103
|
+
|
|
104
|
+
const pickGroupByColumn = (cols: readonly DescribableColumn[]): string | null => {
|
|
105
|
+
const real = realColumns(cols);
|
|
106
|
+
if (!real.length) return null;
|
|
107
|
+
const stringNonId = real.find(
|
|
108
|
+
(c) =>
|
|
109
|
+
categorizeSqlType(c.dataType) === SqlTypeCategory.STRING &&
|
|
110
|
+
!c.isNullable &&
|
|
111
|
+
c.name !== "id" &&
|
|
112
|
+
!c.name.endsWith("_id"),
|
|
113
|
+
);
|
|
114
|
+
return (stringNonId ?? real[0]).name;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const buildFilterExample = (
|
|
118
|
+
resolverName: string,
|
|
119
|
+
cols: readonly DescribableColumn[],
|
|
120
|
+
sampleFields: readonly string[],
|
|
121
|
+
): string | null => {
|
|
122
|
+
const real = realColumns(cols);
|
|
123
|
+
const sub = sampleFields.join("\n ");
|
|
124
|
+
const stringCol = real.find((c) => categorizeSqlType(c.dataType) === SqlTypeCategory.STRING);
|
|
125
|
+
if (stringCol) {
|
|
126
|
+
return `query {\n ${resolverName}(where: { ${stringCol.name}: { like: "%search%" } }, limit: 10) {\n ${sub}\n }\n}`;
|
|
127
|
+
}
|
|
128
|
+
const numericCol = real.find((c) => isNumericType(c.dataType));
|
|
129
|
+
if (numericCol) {
|
|
130
|
+
return `query {\n ${resolverName}(where: { ${numericCol.name}: { gt: 0 } }, limit: 10) {\n ${sub}\n }\n}`;
|
|
131
|
+
}
|
|
132
|
+
const boolCol = real.find((c) => categorizeSqlType(c.dataType) === SqlTypeCategory.BOOLEAN);
|
|
133
|
+
if (boolCol) {
|
|
134
|
+
return `query {\n ${resolverName}(where: { ${boolCol.name}: { eq: true } }, limit: 10) {\n ${sub}\n }\n}`;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const buildTableExamples = (
|
|
140
|
+
resolverName: string,
|
|
141
|
+
cols: readonly DescribableColumn[],
|
|
142
|
+
): {
|
|
143
|
+
list: string;
|
|
144
|
+
filter: string | null;
|
|
145
|
+
aggregate: string | null;
|
|
146
|
+
} | null => {
|
|
147
|
+
const real = realColumns(cols);
|
|
148
|
+
const sampleFields = real.slice(0, 4).map((c) => c.name);
|
|
149
|
+
if (!sampleFields.length) return null;
|
|
150
|
+
|
|
151
|
+
const sub = sampleFields.join("\n ");
|
|
152
|
+
const list = `query {\n ${resolverName}(limit: 10) {\n ${sub}\n }\n}`;
|
|
153
|
+
|
|
154
|
+
const filter = buildFilterExample(resolverName, cols, sampleFields);
|
|
155
|
+
|
|
156
|
+
const groupCol = pickGroupByColumn(cols);
|
|
157
|
+
let aggregate: string | null = null;
|
|
158
|
+
if (groupCol) {
|
|
159
|
+
const numericCol = real.find((c) => isNumericType(c.dataType));
|
|
160
|
+
const numericAggLines = numericCol
|
|
161
|
+
? `\n sum { ${numericCol.name} }\n avg { ${numericCol.name} }`
|
|
162
|
+
: "";
|
|
163
|
+
const itemFields = sampleFields.slice(0, 3).join(" ");
|
|
164
|
+
aggregate = `query {\n ${resolverName}_aggregate(groupBy: [${groupCol}]) {\n key { ${groupCol} }\n count${numericAggLines}\n items { ${itemFields} }\n }\n}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return { list, filter, aggregate };
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const findRootField = (
|
|
171
|
+
schema: GraphQLSchema,
|
|
172
|
+
name: string,
|
|
173
|
+
): {
|
|
174
|
+
rootKind: "Query" | "Mutation" | "Subscription";
|
|
175
|
+
signature: string;
|
|
176
|
+
} | null => {
|
|
177
|
+
const roots = [
|
|
178
|
+
["Query", schema.getQueryType()],
|
|
179
|
+
["Mutation", schema.getMutationType()],
|
|
180
|
+
["Subscription", schema.getSubscriptionType()],
|
|
181
|
+
] as const;
|
|
182
|
+
for (const [rootKind, root] of roots) {
|
|
183
|
+
if (!root) continue;
|
|
184
|
+
const field = root.getFields()[name];
|
|
185
|
+
if (field) {
|
|
186
|
+
const args = field.args.length
|
|
187
|
+
? `(${field.args.map((a) => `${a.name}: ${a.type.toString()}`).join(", ")})`
|
|
188
|
+
: "";
|
|
189
|
+
return {
|
|
190
|
+
rootKind,
|
|
191
|
+
signature: `${name}${args}: ${field.type.toString()}`,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// ---- Query validation ----
|
|
199
|
+
|
|
200
|
+
export type ValidationError = {
|
|
201
|
+
message: string;
|
|
202
|
+
locations?: ReadonlyArray<{ line: number; column: number }>;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type ValidateQueryFn = (query: string) => {
|
|
206
|
+
hasErrors: boolean;
|
|
207
|
+
validationErrors: readonly ValidationError[];
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Build a query validator for a role. Without a positive depth limit it
|
|
212
|
+
* delegates to the role's own `hasErrors`; with one it layers a depth-limit
|
|
213
|
+
* rule on the standard rule set.
|
|
214
|
+
*/
|
|
215
|
+
export const makeValidateQuery =
|
|
216
|
+
(role: RoleEntities, maxQueryDepth?: number): ValidateQueryFn =>
|
|
217
|
+
(query) => {
|
|
218
|
+
if (maxQueryDepth === undefined || maxQueryDepth <= 0) {
|
|
219
|
+
return role.handlers.gql.hasErrors(query);
|
|
220
|
+
}
|
|
221
|
+
const errors = validate(role.schema, parse(query), [
|
|
222
|
+
...specifiedRules,
|
|
223
|
+
depthLimitRule(maxQueryDepth),
|
|
224
|
+
]);
|
|
225
|
+
return { hasErrors: errors.length > 0, validationErrors: errors };
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// ---- graphql_execute ----
|
|
229
|
+
|
|
230
|
+
export type GraphqlExecOutcome =
|
|
231
|
+
| { kind: "non_query" }
|
|
232
|
+
| { kind: "validation"; errors: ValidationError[] }
|
|
233
|
+
| { kind: "ok"; result: unknown }
|
|
234
|
+
| { kind: "error"; message: string };
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Validate and execute a read-only GraphQL query against a role's handler.
|
|
238
|
+
* Mutations/subscriptions are rejected. Returns a discriminated outcome so
|
|
239
|
+
* callers (MCP, AI agent) shape their own responses.
|
|
240
|
+
*/
|
|
241
|
+
export const executeGraphqlCore = async (
|
|
242
|
+
role: RoleEntities,
|
|
243
|
+
validateQuery: ValidateQueryFn,
|
|
244
|
+
{ query, variables }: { query: string; variables?: Record<string, unknown> },
|
|
245
|
+
): Promise<GraphqlExecOutcome> => {
|
|
246
|
+
try {
|
|
247
|
+
if (containsNonQueryOperation(query)) return { kind: "non_query" };
|
|
248
|
+
|
|
249
|
+
const { hasErrors, validationErrors } = validateQuery(query);
|
|
250
|
+
if (hasErrors) {
|
|
251
|
+
return {
|
|
252
|
+
kind: "validation",
|
|
253
|
+
errors: validationErrors.map((e) => ({
|
|
254
|
+
message: e.message,
|
|
255
|
+
locations: e.locations,
|
|
256
|
+
})),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const req = synthesizeRequest("http://graphoria.local/graphql", {
|
|
261
|
+
method: "POST",
|
|
262
|
+
});
|
|
263
|
+
const result = await role.handlers.gql.handler(query, variables ?? {}, req);
|
|
264
|
+
return { kind: "ok", result };
|
|
265
|
+
} catch (error) {
|
|
266
|
+
return {
|
|
267
|
+
kind: "error",
|
|
268
|
+
message: error instanceof Error ? error.message : String(error),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// ---- list_entities ----
|
|
274
|
+
|
|
275
|
+
export type EntityListItem = {
|
|
276
|
+
kind: EntityKind;
|
|
277
|
+
name: string;
|
|
278
|
+
summary: string;
|
|
279
|
+
description?: string | null;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Filter the role's entities by category and/or name fragment.
|
|
284
|
+
* Callers enforce the "at least one of kind/search" guard.
|
|
285
|
+
*/
|
|
286
|
+
export const listEntitiesCore = (
|
|
287
|
+
role: RoleEntities,
|
|
288
|
+
{ kind, search }: { kind?: EntityKind; search?: string },
|
|
289
|
+
): EntityListItem[] => {
|
|
290
|
+
const term = search?.toLowerCase();
|
|
291
|
+
const items: EntityListItem[] = [];
|
|
292
|
+
|
|
293
|
+
const include = (k: EntityKind) => !kind || kind === k;
|
|
294
|
+
const matchesAny = (...candidates: Array<string | null | undefined>): boolean => {
|
|
295
|
+
if (!term) return true;
|
|
296
|
+
return candidates.some((c) => c != null && c.toLowerCase().includes(term));
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
if (include("table")) {
|
|
300
|
+
for (const t of role.tables) {
|
|
301
|
+
if (!matchesAny(t.resolverName, t.schema, t.name, t.tableDescription)) continue;
|
|
302
|
+
items.push({
|
|
303
|
+
kind: "table",
|
|
304
|
+
name: t.resolverName,
|
|
305
|
+
summary: `${t.schema}.${t.name} (${t.columns.length} columns, ${t.relationships.length + t.relationshipsReversed.length} relationships)`,
|
|
306
|
+
description: t.tableDescription ?? null,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (include("operation") && role.operations) {
|
|
312
|
+
for (const [name, op] of Object.entries(role.operations)) {
|
|
313
|
+
if (!matchesAny(name, op.description)) continue;
|
|
314
|
+
items.push({
|
|
315
|
+
kind: "operation",
|
|
316
|
+
name,
|
|
317
|
+
summary: op.query ? "GraphQL-query operation" : "Handler operation",
|
|
318
|
+
description: op.description ?? null,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (include("remote_schema")) {
|
|
324
|
+
for (const rs of role.remoteSchemas) {
|
|
325
|
+
if (!matchesAny(rs.config.name)) continue;
|
|
326
|
+
items.push({
|
|
327
|
+
kind: "remote_schema",
|
|
328
|
+
name: rs.config.name,
|
|
329
|
+
summary: `prefix=${rs.prefix}, ${rs.queryFields.length} queries, ${rs.mutationFields.length} mutations`,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (include("remote_rest")) {
|
|
335
|
+
for (const rr of role.remoteRESTApis) {
|
|
336
|
+
if (!matchesAny(rr.config.name)) continue;
|
|
337
|
+
items.push({
|
|
338
|
+
kind: "remote_rest",
|
|
339
|
+
name: rr.config.name,
|
|
340
|
+
summary: `prefix=${rr.prefix}, ${rr.routes.length} routes`,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (include("stored_procedure")) {
|
|
346
|
+
for (const sp of role.storedProcedures) {
|
|
347
|
+
if (!matchesAny(sp.resolverName, sp.schema, sp.name)) continue;
|
|
348
|
+
items.push({
|
|
349
|
+
kind: "stored_procedure",
|
|
350
|
+
name: sp.resolverName,
|
|
351
|
+
summary: `${sp.schema}.${sp.name}`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (include("queue_publisher")) {
|
|
357
|
+
for (const [name, pub] of Object.entries(role.queuesMap)) {
|
|
358
|
+
if (!matchesAny(name, pub.resolverName)) continue;
|
|
359
|
+
items.push({
|
|
360
|
+
kind: "queue_publisher",
|
|
361
|
+
name,
|
|
362
|
+
summary: `publisher → ${pub.resolverName}`,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return items;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// ---- describe_entity ----
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Describe one entity. When `kind` is given, only that category is looked up
|
|
374
|
+
* (no fallback). Without `kind`, every category is tried, then the raw GraphQL
|
|
375
|
+
* type. Returns `null` when nothing matches.
|
|
376
|
+
*/
|
|
377
|
+
export const describeEntityCore = (
|
|
378
|
+
role: RoleEntities,
|
|
379
|
+
{ name, kind }: { name: string; kind?: EntityKind },
|
|
380
|
+
): Record<string, unknown> | null => {
|
|
381
|
+
const schema = role.schema;
|
|
382
|
+
const lookup: Record<EntityKind, () => Record<string, unknown> | null> = {
|
|
383
|
+
table: () => {
|
|
384
|
+
const t = role.tables.find((x) => x.resolverName === name);
|
|
385
|
+
if (!t) return null;
|
|
386
|
+
return {
|
|
387
|
+
kind: "table",
|
|
388
|
+
name: t.resolverName,
|
|
389
|
+
schema: t.schema,
|
|
390
|
+
tableName: t.name,
|
|
391
|
+
description: t.tableDescription ?? null,
|
|
392
|
+
columns: t.columns.map((c) => ({
|
|
393
|
+
name: c.name,
|
|
394
|
+
dataType: c.dataType,
|
|
395
|
+
nullable: c.isNullable,
|
|
396
|
+
description: c.description ?? null,
|
|
397
|
+
virtual: "virtual" in c ? c.virtual : false,
|
|
398
|
+
})),
|
|
399
|
+
relationships: t.relationships.map((r) => ({
|
|
400
|
+
to: r.toResolverName,
|
|
401
|
+
columns: r.columns.map((c) => ({ from: c.source, to: c.target })),
|
|
402
|
+
})),
|
|
403
|
+
relationshipsReversed: t.relationshipsReversed.map((r) => ({
|
|
404
|
+
from: r.fromResolverName,
|
|
405
|
+
columns: r.columns.map((c) => ({ from: c.source, to: c.target })),
|
|
406
|
+
})),
|
|
407
|
+
graphqlField: findRootField(schema, name),
|
|
408
|
+
aggregateField: findRootField(schema, `${name}_aggregate`),
|
|
409
|
+
examples: buildTableExamples(t.resolverName, t.columns),
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
operation: () => {
|
|
413
|
+
const op = role.operations?.[name];
|
|
414
|
+
if (!op) return null;
|
|
415
|
+
return {
|
|
416
|
+
kind: "operation",
|
|
417
|
+
name,
|
|
418
|
+
description: op.description ?? null,
|
|
419
|
+
hasQuery: Boolean(op.query),
|
|
420
|
+
hasHandler: Boolean(op.handler),
|
|
421
|
+
rest: op.rest ?? null,
|
|
422
|
+
graphql: op.graphql ?? null,
|
|
423
|
+
};
|
|
424
|
+
},
|
|
425
|
+
remote_schema: () => {
|
|
426
|
+
const rs = role.remoteSchemas.find((x) => x.config.name === name);
|
|
427
|
+
if (!rs) return null;
|
|
428
|
+
return {
|
|
429
|
+
kind: "remote_schema",
|
|
430
|
+
name: rs.config.name,
|
|
431
|
+
url: rs.config.url,
|
|
432
|
+
prefix: rs.prefix,
|
|
433
|
+
queryFields: rs.queryFields.map((f) => ({
|
|
434
|
+
name: f.prefixedName,
|
|
435
|
+
sdl: f.sdl,
|
|
436
|
+
})),
|
|
437
|
+
mutationFields: rs.mutationFields.map((f) => ({
|
|
438
|
+
name: f.prefixedName,
|
|
439
|
+
sdl: f.sdl,
|
|
440
|
+
})),
|
|
441
|
+
typeDefsSDL: rs.typeDefsSDL,
|
|
442
|
+
};
|
|
443
|
+
},
|
|
444
|
+
remote_rest: () => {
|
|
445
|
+
const rr = role.remoteRESTApis.find((x) => x.config.name === name);
|
|
446
|
+
if (!rr) return null;
|
|
447
|
+
return {
|
|
448
|
+
kind: "remote_rest",
|
|
449
|
+
name: rr.config.name,
|
|
450
|
+
baseUrl: rr.baseUrl,
|
|
451
|
+
prefix: rr.prefix,
|
|
452
|
+
routes: rr.routes,
|
|
453
|
+
openApiPaths: rr.openApiPaths,
|
|
454
|
+
openApiSchemas: rr.openApiSchemas,
|
|
455
|
+
};
|
|
456
|
+
},
|
|
457
|
+
stored_procedure: () => {
|
|
458
|
+
const sp = role.storedProcedures.find((x) => x.resolverName === name);
|
|
459
|
+
if (!sp) return null;
|
|
460
|
+
return {
|
|
461
|
+
kind: "stored_procedure",
|
|
462
|
+
name: sp.resolverName,
|
|
463
|
+
schema: sp.schema,
|
|
464
|
+
procedureName: sp.name,
|
|
465
|
+
graphqlField: findRootField(schema, name),
|
|
466
|
+
};
|
|
467
|
+
},
|
|
468
|
+
queue_publisher: () => {
|
|
469
|
+
const pub = role.queuesMap[name];
|
|
470
|
+
if (!pub) return null;
|
|
471
|
+
return { kind: "queue_publisher", name, resolverName: pub.resolverName };
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
if (kind) return lookup[kind]();
|
|
476
|
+
|
|
477
|
+
for (const k of ENTITY_KINDS) {
|
|
478
|
+
const result = lookup[k]();
|
|
479
|
+
if (result) return result;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const named = schema.getType(name);
|
|
483
|
+
if (named) return describeNamedType(named);
|
|
484
|
+
|
|
485
|
+
return null;
|
|
486
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structured JSON query input — safer for LLMs than writing raw GraphQL.
|
|
5
|
+
* The server builds the correct GraphQL query internally.
|
|
6
|
+
*/
|
|
7
|
+
export const queryDataSchema = z.object({
|
|
8
|
+
entity: z
|
|
9
|
+
.string()
|
|
10
|
+
.describe(
|
|
11
|
+
"The EXACT resolverName from list_entities (e.g. 'pg_public_contacts', NOT 'contacts').",
|
|
12
|
+
),
|
|
13
|
+
operation: z
|
|
14
|
+
.enum(["list", "aggregate"])
|
|
15
|
+
.describe("'list' for rows, 'aggregate' for grouped counts."),
|
|
16
|
+
columns: z.array(z.string()).optional().describe("Columns to return. Omit for all columns."),
|
|
17
|
+
groupBy: z.array(z.string()).optional().describe("Columns to group by (aggregate only)."),
|
|
18
|
+
filters: z
|
|
19
|
+
.record(z.string(), z.unknown())
|
|
20
|
+
.optional()
|
|
21
|
+
.describe(
|
|
22
|
+
'Where conditions, e.g. { "deleted_at": { "is_null": true }, "role": { "eq": "admin" } }.',
|
|
23
|
+
),
|
|
24
|
+
limit: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(0)
|
|
28
|
+
.optional()
|
|
29
|
+
.default(100)
|
|
30
|
+
.describe("Max rows to return (default 100)."),
|
|
31
|
+
offset: z.number().int().min(0).optional().describe("Rows to skip."),
|
|
32
|
+
orderBy: z
|
|
33
|
+
.array(
|
|
34
|
+
z.object({
|
|
35
|
+
column: z.string(),
|
|
36
|
+
direction: z
|
|
37
|
+
.enum([
|
|
38
|
+
"ASC",
|
|
39
|
+
"DESC",
|
|
40
|
+
"ASC_NULLS_FIRST",
|
|
41
|
+
"ASC_NULLS_LAST",
|
|
42
|
+
"DESC_NULLS_FIRST",
|
|
43
|
+
"DESC_NULLS_LAST",
|
|
44
|
+
])
|
|
45
|
+
.default("ASC"),
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Sort order."),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export type StructuredQueryInput = z.infer<typeof queryDataSchema>;
|
|
53
|
+
|
|
54
|
+
const gqlLiteral = (value: unknown): string => {
|
|
55
|
+
if (value === null) return "null";
|
|
56
|
+
if (value === undefined) return "null";
|
|
57
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
58
|
+
if (typeof value === "number") return String(value);
|
|
59
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
60
|
+
if (Array.isArray(value)) return `[${value.map(gqlLiteral).join(", ")}]`;
|
|
61
|
+
if (typeof value === "object") {
|
|
62
|
+
const pairs = Object.entries(value as Record<string, unknown>).map(
|
|
63
|
+
([k, v]) => `${k}: ${gqlLiteral(v)}`,
|
|
64
|
+
);
|
|
65
|
+
return `{ ${pairs.join(", ")} }`;
|
|
66
|
+
}
|
|
67
|
+
return "null";
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build a read-only GraphQL query from structured JSON input.
|
|
72
|
+
* Returns the query string ready for `graphql_execute`.
|
|
73
|
+
*/
|
|
74
|
+
export const buildStructuredQuery = (input: StructuredQueryInput): string => {
|
|
75
|
+
const { entity, operation, columns, groupBy, filters, limit, offset, orderBy } = input;
|
|
76
|
+
|
|
77
|
+
const args: string[] = [];
|
|
78
|
+
const safeLimit = limit ?? 100;
|
|
79
|
+
if (safeLimit > 0) args.push(`limit: ${safeLimit}`);
|
|
80
|
+
if (offset !== undefined) args.push(`offset: ${offset}`);
|
|
81
|
+
if (filters && Object.keys(filters).length > 0) {
|
|
82
|
+
args.push(`where: ${gqlLiteral(filters)}`);
|
|
83
|
+
}
|
|
84
|
+
if (orderBy && orderBy.length > 0) {
|
|
85
|
+
args.push(`orderBy: ${gqlLiteral(orderBy)}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const argsStr = args.length > 0 ? `(${args.join(", ")})` : "";
|
|
89
|
+
|
|
90
|
+
if (operation === "aggregate") {
|
|
91
|
+
const groupCols = groupBy && groupBy.length > 0 ? groupBy : (columns ?? []);
|
|
92
|
+
if (groupCols.length === 0) {
|
|
93
|
+
throw new Error("aggregate requires at least one column for groupBy or columns.");
|
|
94
|
+
}
|
|
95
|
+
const groupByArg = `groupBy: [${groupCols}]`;
|
|
96
|
+
const aggArgs = [groupByArg];
|
|
97
|
+
if (safeLimit > 0) aggArgs.push(`limit: ${safeLimit}`);
|
|
98
|
+
if (filters && Object.keys(filters).length > 0) aggArgs.push(`where: ${gqlLiteral(filters)}`);
|
|
99
|
+
|
|
100
|
+
const keyCols = groupCols.map((c) => c).join(" ");
|
|
101
|
+
const itemCols = columns && columns.length > 0 ? columns.join(" ") : groupCols.join(" ");
|
|
102
|
+
|
|
103
|
+
return `query { ${entity}_aggregate(${aggArgs.join(", ")}) { key { ${keyCols} } count items { ${itemCols} } } }`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// list operation
|
|
107
|
+
const colSelection = columns && columns.length > 0 ? columns.join(" ") : "__typename";
|
|
108
|
+
return `query { ${entity}${argsStr} { ${colSelection} } }`;
|
|
109
|
+
};
|