@redocly/realm 0.129.2 → 0.130.0-custom.2
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/CHANGELOG.md +392 -83
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +1 -1
- package/dist/cli/develop.js +1 -1
- package/dist/cli/eject/resolveEjectParams.js +1 -1
- package/dist/cli/prepare/copy-env-files.js +1 -1
- package/dist/cli/prepare/index.js +1 -1
- package/dist/cli/stats/collectors/openapi.d.ts +3 -0
- package/dist/cli/stats/collectors/openapi.js +1 -0
- package/dist/cli/stats/index.d.ts +7 -0
- package/dist/cli/stats/index.js +1 -0
- package/dist/cli/stats/options.d.ts +3 -0
- package/dist/cli/stats/options.js +1 -0
- package/dist/cli/telemetry/index.d.ts +2 -2
- package/dist/cli/telemetry/index.js +1 -1
- package/dist/client/App.js +1 -1
- package/dist/client/ErrorBoundary.js +1 -1
- package/dist/client/app/Sidebar/RequestAccessButton.js +2 -2
- package/dist/client/app/Sidebar/Sidebar.js +2 -2
- package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.d.ts +23 -0
- package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.js +1 -0
- package/dist/client/app/Sidebar/useSidebarItems.d.ts +2 -2
- package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogClassic.d.ts +1 -1
- package/dist/client/app/hooks/catalog/useCatalogClassic.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogFilter.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogViewMode.js +1 -1
- package/dist/client/app/hooks/catalog/useSearchTracker.js +1 -1
- package/dist/client/app/hooks/codeHighlight/useCodeHighlight.js +1 -1
- package/dist/client/app/hooks/usePageTimeTracker.js +1 -1
- package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
- package/dist/client/app/hooks/useTelemetry.d.ts +2 -2
- package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
- package/dist/client/app/search/message-handlers.d.ts +29 -0
- package/dist/client/app/search/message-handlers.js +1 -0
- package/dist/client/app/search/sse-parser.d.ts +10 -0
- package/dist/client/app/search/sse-parser.js +2 -0
- package/dist/client/app/search/useAiSearch.d.ts +9 -11
- package/dist/client/app/search/useAiSearch.js +1 -1
- package/dist/client/app/search/useSearch.js +1 -1
- package/dist/client/app/telemetry/index.d.ts +11 -1
- package/dist/client/app/telemetry/index.js +1 -1
- package/dist/client/browser-entry.js +5 -5
- package/dist/client/constants/ai-search.d.ts +30 -0
- package/dist/client/constants/ai-search.js +1 -0
- package/dist/client/constants/index.d.ts +2 -0
- package/dist/client/constants/index.js +1 -0
- package/dist/client/providers/hooks.js +1 -1
- package/dist/client/runtime/loader.js +1 -1
- package/dist/client/types/ai-search.d.ts +73 -0
- package/dist/client/types/ai-search.js +0 -0
- package/dist/client/types/index.d.ts +1 -0
- package/dist/config/env-config.d.ts +17 -0
- package/dist/config/env-config.js +1 -0
- package/dist/config/env-schema.d.ts +242 -0
- package/dist/config/env-schema.js +3 -0
- package/dist/config/env-schemas/api-urls.d.ts +24 -0
- package/dist/config/env-schemas/api-urls.js +1 -0
- package/dist/config/env-schemas/auth.d.ts +42 -0
- package/dist/config/env-schemas/auth.js +1 -0
- package/dist/config/env-schemas/catalog.d.ts +12 -0
- package/dist/config/env-schemas/catalog.js +1 -0
- package/dist/config/env-schemas/database.d.ts +15 -0
- package/dist/config/env-schemas/database.js +1 -0
- package/dist/config/env-schemas/environment-detection.d.ts +24 -0
- package/dist/config/env-schemas/environment-detection.js +1 -0
- package/dist/config/env-schemas/feature-flags.d.ts +24 -0
- package/dist/config/env-schemas/feature-flags.js +1 -0
- package/dist/config/env-schemas/organization-project.d.ts +27 -0
- package/dist/config/env-schemas/organization-project.js +1 -0
- package/dist/config/env-schemas/scorecards.d.ts +12 -0
- package/dist/config/env-schemas/scorecards.js +1 -0
- package/dist/config/env-schemas/search.d.ts +21 -0
- package/dist/config/env-schemas/search.js +1 -0
- package/dist/config/env-schemas/server-config.d.ts +51 -0
- package/dist/config/env-schemas/server-config.js +1 -0
- package/dist/config/env-schemas/site.d.ts +12 -0
- package/dist/config/env-schemas/site.js +1 -0
- package/dist/config/env-schemas/ssr.d.ts +18 -0
- package/dist/config/env-schemas/ssr.js +1 -0
- package/dist/config/env-schemas/telemetry.d.ts +15 -0
- package/dist/config/env-schemas/telemetry.js +1 -0
- package/dist/config/env-schemas/test.d.ts +22 -0
- package/dist/config/env-schemas/test.js +1 -0
- package/dist/constants/common.d.ts +4 -2
- package/dist/constants/common.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/server/api-routes/execute-api-route.js +1 -1
- package/dist/server/api-routes/import-api-routes-handlers.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/constants/common.js +1 -1
- package/dist/server/constants/plugins/catalog-entities.d.ts +1 -0
- package/dist/server/constants/plugins/catalog-entities.js +1 -1
- package/dist/server/entitlements/entitlements-provider.js +1 -1
- package/dist/server/esbuild/esbuild-logger.js +2 -2
- package/dist/server/esbuild/esbuild.js +3 -3
- package/dist/server/esbuild/plugins/assets-resolver.js +1 -1
- package/dist/server/esbuild/plugins/esbuild-compile-resolver.js +1 -1
- package/dist/server/esbuild/plugins/styled-components-ssr.js +1 -1
- package/dist/server/fs/cache.js +1 -1
- package/dist/server/fs/content-fs.d.ts +1 -0
- package/dist/server/fs/content-fs.js +1 -1
- package/dist/server/fs/last-modified-tracker.js +1 -1
- package/dist/server/fs/utils/is-loader-cache-enabled.js +1 -1
- package/dist/server/node-bundle-entry.js +1 -1
- package/dist/server/persistence/kv/repositories/kv-remote-repository.d.ts +1 -0
- package/dist/server/persistence/kv/repositories/kv-remote-repository.js +2 -1
- package/dist/server/persistence/kv/services/kv-service.js +1 -1
- package/dist/server/plugins/analytics/adobe/index.js +1 -1
- package/dist/server/plugins/analytics/amplitude/index.js +1 -1
- package/dist/server/plugins/analytics/fullstory/index.js +1 -1
- package/dist/server/plugins/analytics/ga/index.js +1 -1
- package/dist/server/plugins/analytics/gtm/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/gtm/index.js +1 -1
- package/dist/server/plugins/analytics/heap/index.js +1 -1
- package/dist/server/plugins/analytics/rudderstack/index.js +1 -1
- package/dist/server/plugins/analytics/segment/index.js +1 -1
- package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.js +3 -3
- package/dist/server/plugins/asyncapi-docs/get-server-props.js +1 -1
- package/dist/server/plugins/asyncapi-docs/index.js +1 -1
- package/dist/server/plugins/asyncapi-docs/search/schema-processor.js +1 -1
- package/dist/server/plugins/asyncapi-docs/search/search-resolver.js +1 -1
- package/dist/server/plugins/asyncapi-docs/store-definition-bundles.js +1 -1
- package/dist/server/plugins/asyncapi-docs/template/AsyncApiDocs.d.ts +2 -1
- package/dist/server/plugins/asyncapi-docs/template/AsyncApiDocs.js +9 -3
- package/dist/server/plugins/catalog-classic/get-server-props.d.ts +8 -3
- package/dist/server/plugins/catalog-classic/get-server-props.js +1 -1
- package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +38 -64
- package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.d.ts +8 -0
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.js +1 -0
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-db-record.d.ts +2 -1
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-read-model.js +1 -1
- package/dist/server/plugins/catalog-entities/database/mappers/{create-entity-relation.d.ts → create-entity-relation-read-model.d.ts} +2 -2
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-read-model.js +1 -0
- package/dist/server/plugins/catalog-entities/database/mappers/map-entity-relation-row.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +27 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +36 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.d.ts +15 -4
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +38 -27
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +36 -9
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +37 -21
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +41 -42
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.d.ts +3 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.d.ts +7 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +5 -9
- package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.d.ts +13 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.d.ts +31 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.js +9 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.d.ts +34 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.js +13 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.d.ts +23 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.d.ts +78 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.js +34 -0
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +6 -4
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/get-server-props.js +1 -1
- package/dist/server/plugins/catalog-entities/plugin.js +1 -1
- package/dist/server/plugins/catalog-entities/schemas/database-schemas.d.ts +3 -0
- package/dist/server/plugins/catalog-entities/schemas/database-schemas.js +1 -1
- package/dist/server/plugins/catalog-entities/schemas/dto-schemas.d.ts +15 -1
- package/dist/server/plugins/catalog-entities/schemas/dto-schemas.js +1 -1
- package/dist/server/plugins/catalog-entities/schemas/read-model-schemas.d.ts +26 -164
- package/dist/server/plugins/catalog-entities/schemas/read-model-schemas.js +0 -1
- package/dist/server/plugins/catalog-entities/types/extractors.d.ts +4 -4
- package/dist/server/plugins/catalog-entities/types/openapi.d.ts +11 -0
- package/dist/server/plugins/catalog-entities/types/openapi.js +0 -0
- package/dist/server/plugins/catalog-entities/types/params.d.ts +6 -0
- package/dist/server/plugins/catalog-entities/types/params.js +0 -0
- package/dist/server/plugins/catalog-entities/utils/ajv-validator.js +1 -1
- package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.js +1 -1
- package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.d.ts +11 -0
- package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.js +1 -0
- package/dist/server/plugins/config-parser/index.js +1 -1
- package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
- package/dist/server/plugins/config-parser/loaders/nearest-redocly-config-loader.js +1 -1
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/default-theme/index.js +1 -1
- package/dist/server/plugins/entitlements/index.js +1 -1
- package/dist/server/plugins/graphql-docs/graphql-doc-loader.js +1 -1
- package/dist/server/plugins/graphql-docs/index.js +1 -1
- package/dist/server/plugins/graphql-docs/search/search-resolver.js +1 -1
- package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +6 -2
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
- package/dist/server/plugins/markdown/compiler.d.ts +1 -0
- package/dist/server/plugins/markdown/compiler.js +1 -1
- package/dist/server/plugins/markdown/index.js +1 -1
- package/dist/server/plugins/markdown/is-partial.d.ts +1 -1
- package/dist/server/plugins/markdown/is-partial.js +1 -1
- package/dist/server/plugins/markdown/markdoc/import-user-tags.js +1 -1
- package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +1 -1
- package/dist/server/plugins/markdown/markdoc/resolve-raw-partials.d.ts +1 -1
- package/dist/server/plugins/markdown/markdoc/resolve-raw-partials.js +2 -2
- package/dist/server/plugins/markdown/markdown-static-data-loader.js +1 -1
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +54 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +9 -8
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +9 -8
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +9 -8
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +9 -8
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +7 -13
- package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +9 -6
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +9 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/search.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +2 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +9 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/errors.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.d.ts +5 -0
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -0
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +1 -1
- package/dist/server/plugins/mcp/servers/base-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +40 -0
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +3 -0
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -0
- package/dist/server/plugins/nav-utils.d.ts +1 -1
- package/dist/server/plugins/nav-utils.js +1 -1
- package/dist/server/plugins/openapi-docs/decorators.d.ts +3 -0
- package/dist/server/plugins/openapi-docs/decorators.js +1 -1
- package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.d.ts +2 -4
- package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.js +1 -1
- package/dist/server/plugins/openapi-docs/get-server-props.js +1 -1
- package/dist/server/plugins/openapi-docs/index.js +1 -1
- package/dist/server/plugins/openapi-docs/load-definition.d.ts +1 -0
- package/dist/server/plugins/openapi-docs/load-definition.js +3 -3
- package/dist/server/plugins/openapi-docs/openrpc-converter.d.ts +2 -0
- package/dist/server/plugins/openapi-docs/openrpc-converter.js +1 -0
- package/dist/server/plugins/openapi-docs/search/search-resolver.js +1 -1
- package/dist/server/plugins/openapi-docs/search-indexer.js +1 -1
- package/dist/server/plugins/openapi-docs/store-definition-bundles.js +1 -1
- package/dist/server/plugins/openapi-docs/template/OpenAPIDocs.js +8 -4
- package/dist/server/plugins/openapi-docs/template/helpers.d.ts +2 -2
- package/dist/server/plugins/openapi-docs/template/helpers.js +3 -3
- package/dist/server/plugins/openapi-docs/utils.d.ts +1 -0
- package/dist/server/plugins/scorecard-classic/compute-scorecard.d.ts +2 -1
- package/dist/server/plugins/scorecard-classic/compute-scorecard.js +4 -4
- package/dist/server/plugins/scorecard-classic/get-scorecard-config.d.ts +2 -1
- package/dist/server/plugins/scorecard-classic/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/lint.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/lint.js +1 -1
- package/dist/server/plugins/scorecard-classic/loaders/scorecard-config.js +1 -1
- package/dist/server/plugins/scorecard-classic/loaders/scorecard.d.ts +6 -4
- package/dist/server/plugins/scorecard-classic/loaders/scorecard.js +1 -1
- package/dist/server/plugins/scorecard-classic/shared-utils.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/shared-utils.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/Grid/Grid.d.ts +2 -1
- package/dist/server/plugins/scorecard-classic/template/Grid/Grid.js +3 -3
- package/dist/server/plugins/scorecard-classic/template/LevelIndicator.d.ts +1 -0
- package/dist/server/plugins/scorecard-classic/template/LevelIndicator.js +4 -4
- package/dist/server/plugins/scorecard-classic/template/components.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/index.styles.d.ts +1 -0
- package/dist/server/plugins/scorecard-classic/template/index.styles.js +93 -19
- package/dist/server/plugins/scorecard-classic/template/index.types.d.ts +5 -1
- package/dist/server/plugins/scorecard-classic/template/useData.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/views.js +1 -1
- package/dist/server/plugins/scorecard-classic/types.d.ts +5 -3
- package/dist/server/plugins/scorecard-classic/types.js +1 -1
- package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.d.ts +12 -0
- package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.js +1 -0
- package/dist/server/plugins/scorecards/database/scorecards-config-service.d.ts +11 -0
- package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -0
- package/dist/server/plugins/scorecards/plugin.js +1 -1
- package/dist/server/plugins/scorecards/workers/run-scorecards-worker.d.ts +2 -1
- package/dist/server/plugins/scorecards/workers/run-scorecards-worker.js +1 -1
- package/dist/server/plugins/scorecards/workers/scorecards.d.ts +1 -12
- package/dist/server/plugins/scorecards/workers/scorecards.js +1 -1
- package/dist/server/plugins/search/ai-indexer/prepare-ai-search-documents.js +1 -1
- package/dist/server/plugins/search/documents/search-documents.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
- package/dist/server/plugins/search/engines/typesense/index.js +1 -1
- package/dist/server/plugins/search/index.js +1 -1
- package/dist/server/plugins/search/llmstxt/index.js +5 -5
- package/dist/server/plugins/search/utils.js +2 -2
- package/dist/server/plugins/sidebars/index.d.ts +0 -2
- package/dist/server/plugins/sidebars/index.js +3 -3
- package/dist/server/plugins/sso/index.js +1 -1
- package/dist/server/providers/database/base-repository.d.ts +1 -0
- package/dist/server/providers/database/base-repository.js +1 -1
- package/dist/server/providers/database/database-connection-factory.js +1 -1
- package/dist/server/providers/database/database-initialization-strategy.js +1 -1
- package/dist/server/providers/database/database-preconnect-service.js +1 -1
- package/dist/server/providers/database/databases/catalog-sqlite/migrations/0005_catalog-relations-constraint-fix.sql +2 -0
- package/dist/server/providers/database/databases/catalog-sqlite/migrations/0006_add-catalog-entitities-attributes-table.sql +11 -0
- package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0005_snapshot.json +393 -0
- package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0006_snapshot.json +458 -0
- package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/_journal.json +14 -0
- package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.d.ts +143 -0
- package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js +1 -0
- package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js +1 -1
- package/dist/server/providers/database/databases/main-sqlite/migrations/0006_change-scorecards-config-timestamps-field-types.sql +19 -0
- package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0006_snapshot.json +261 -0
- package/dist/server/providers/database/databases/main-sqlite/migrations/meta/_journal.json +7 -0
- package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.d.ts +24 -18
- package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.js +1 -1
- package/dist/server/providers/database/databases/sqld-sqlite/drizzle.config.js +1 -1
- package/dist/server/providers/database/databases/sqld-sqlite/migrations/0007_catalog-relations-constraint-fix.sql +2 -0
- package/dist/server/providers/database/databases/sqld-sqlite/migrations/0008_add-catalog-entitities-attributes-table.sql +11 -0
- package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/0007_snapshot.json +833 -0
- package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/0008_snapshot.json +898 -0
- package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/_journal.json +14 -0
- package/dist/server/providers/database/pagination/entities-to-filter.d.ts +15 -0
- package/dist/server/providers/database/pagination/entities-to-filter.js +1 -0
- package/dist/server/providers/database/pagination/utils/index.d.ts +4 -0
- package/dist/server/providers/database/pagination/utils/index.js +1 -1
- package/dist/server/providers/database/pagination/utils/is-nested-condition.d.ts +16 -0
- package/dist/server/providers/database/pagination/utils/is-nested-condition.js +1 -0
- package/dist/server/providers/database/pagination/utils/is-simple-condition.d.ts +18 -0
- package/dist/server/providers/database/pagination/utils/is-simple-condition.js +1 -0
- package/dist/server/providers/database/pagination/utils/map-operator.d.ts +10 -0
- package/dist/server/providers/database/pagination/utils/map-operator.js +1 -0
- package/dist/server/providers/database/pagination/utils/transform-condition.d.ts +12 -0
- package/dist/server/providers/database/pagination/utils/transform-condition.js +1 -0
- package/dist/server/providers/database/sqld-not-running-error.d.ts +5 -0
- package/dist/server/providers/database/sqld-not-running-error.js +1 -0
- package/dist/server/ssr/render.js +1 -1
- package/dist/server/ssr/server-side-props/get-server-props-from-user-handler.js +1 -1
- package/dist/server/ssr/utils.js +8 -8
- package/dist/server/store.d.ts +14 -6
- package/dist/server/store.js +1 -1
- package/dist/server/telemetry/index.js +1 -1
- package/dist/server/tools/notifiers/formatter.js +3 -3
- package/dist/server/tools/notifiers/helpers/colors.js +1 -1
- package/dist/server/tools/notifiers/logger.js +2 -2
- package/dist/server/tools/notifiers/reporter.js +9 -9
- package/dist/server/tools/notifiers/terminal-manager.js +4 -4
- package/dist/server/types/plugins/common.d.ts +7 -1
- package/dist/server/types/plugins/markdown.d.ts +2 -0
- package/dist/server/types/plugins/scorecards.d.ts +30 -0
- package/dist/server/types/plugins/scorecards.js +0 -0
- package/dist/server/utils/envs/get-api-route-allowed-env-variables.js +1 -1
- package/dist/server/utils/envs/load-env-variables.d.ts +1 -1
- package/dist/server/utils/envs/load-env-variables.js +1 -1
- package/dist/server/utils/envs/sanitize-branch-name.d.ts +6 -0
- package/dist/server/utils/envs/sanitize-branch-name.js +1 -0
- package/dist/server/utils/globs.js +1 -1
- package/dist/server/utils/is-catalog-entities-enabled.js +1 -1
- package/dist/server/utils/is-scorecards-enabled.js +1 -1
- package/dist/server/utils/lifecycle-hooks.js +1 -1
- package/dist/server/utils/rbac.d.ts +76 -7
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/utils/report-all-errors.js +1 -1
- package/dist/server/utils/set-execution-mode.d.ts +5 -0
- package/dist/server/utils/set-execution-mode.js +1 -0
- package/dist/server/utils/time/with-timestamp.d.ts +42 -10
- package/dist/server/utils/time/with-timestamp.js +1 -1
- package/dist/server/version.js +1 -1
- package/dist/server/web-server/auth.js +3 -3
- package/dist/server/web-server/dev-server.js +1 -1
- package/dist/server/web-server/handle-api-route-request.js +1 -1
- package/dist/server/web-server/http.js +2 -2
- package/dist/server/web-server/middleware/apiKeyMiddleware.js +1 -1
- package/dist/server/web-server/middleware/catalogAuthMiddleware.d.ts +4 -6
- package/dist/server/web-server/middleware/catalogAuthMiddleware.js +1 -1
- package/dist/server/web-server/middleware/corsMiddleware.js +1 -1
- package/dist/server/web-server/middleware/dynamic-middleware/dynamic-middleware.js +1 -1
- package/dist/server/web-server/middleware/idleTimeoutMiddleware.js +1 -1
- package/dist/server/web-server/routes/ask-ai.js +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/dto/read-entity-dto.d.ts +3 -0
- package/dist/server/web-server/routes/catalog/dto/read-entity-dto.js +0 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-relation-update-schema.d.ts +43 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-relation-update-schema.js +1 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +6823 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.js +1 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +1102 -0
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.js +1 -0
- package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.d.ts +10 -0
- package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.js +1 -0
- package/dist/server/web-server/routes/catalog/mappers/map-entity-read-model-schema-to-entity-read-dto.d.ts +4 -0
- package/dist/server/web-server/routes/catalog/mappers/map-entity-read-model-schema-to-entity-read-dto.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entities.d.ts +4 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entities.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity-update-data.d.ts +4 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity-update-data.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity.d.ts +4 -0
- package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entities-relations.d.ts +13 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entities-relations.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation-update-data.d.ts +13 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation-update-data.js +1 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation.d.ts +13 -0
- package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation.js +1 -0
- package/dist/server/web-server/routes/dynamic-route.js +1 -1
- package/dist/server/web-server/routes/error.js +1 -1
- package/dist/server/web-server/routes/helpers/get-current-rbac-teams.d.ts +3 -0
- package/dist/server/web-server/routes/helpers/get-current-rbac-teams.js +1 -0
- package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.d.ts +11 -0
- package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.js +1 -0
- package/dist/server/web-server/routes/index.js +1 -1
- package/dist/server/web-server/routes/info.js +1 -1
- package/dist/server/web-server/routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/web-server/routes/page-data.js +1 -1
- package/dist/server/web-server/routes/path-prefix-redirect.js +1 -1
- package/dist/server/web-server/utils.d.ts +2 -2
- package/dist/server/workers/mcp-tool-worker-pool.d.ts +4 -0
- package/dist/server/workers/mcp-tool-worker-pool.js +1 -0
- package/dist/server/workers/mcp-tool-worker.d.ts +2 -0
- package/dist/server/workers/mcp-tool-worker.js +1 -0
- package/dist/server/workers/types.d.ts +7 -1
- package/dist/server/workers/worker-pool.js +1 -1
- package/package.json +21 -23
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation.js +0 -1
- package/dist/server/plugins/catalog-entities/entities/validate-entity.d.ts +0 -6
- package/dist/server/plugins/catalog-entities/entities/validate-entity.js +0 -1
- package/dist/server/plugins/mcp/workers/run-api-routes-worker.d.ts +0 -5
- package/dist/server/plugins/mcp/workers/run-api-routes-worker.js +0 -1
- package/dist/server/utils/envs/is-build-mode.d.ts +0 -2
- package/dist/server/utils/envs/is-build-mode.js +0 -1
- package/dist/server/utils/envs/is-develop-mode.d.ts +0 -7
- package/dist/server/utils/envs/is-develop-mode.js +0 -1
- package/dist/server/utils/envs/is-production-mode.d.ts +0 -10
- package/dist/server/utils/envs/is-production-mode.js +0 -1
- package/dist/server/workers/mcp-worker-pool.d.ts +0 -4
- package/dist/server/workers/mcp-worker-pool.js +0 -1
- package/dist/utils/env/is-local-development.d.ts +0 -13
- package/dist/utils/env/is-local-development.js +0 -1
- package/dist/utils/env/is-production.d.ts +0 -13
- package/dist/utils/env/is-production.js +0 -1
- package/dist/utils/env/is-web-view.d.ts +0 -14
- package/dist/utils/env/is-web-view.js +0 -1
|
@@ -11,6 +11,7 @@ export type CreateEntityParams = {
|
|
|
11
11
|
isRootEntity?: boolean;
|
|
12
12
|
revision?: string;
|
|
13
13
|
isDeleted?: boolean;
|
|
14
|
+
rbacTeams?: string[];
|
|
14
15
|
};
|
|
15
16
|
export type CreateEntityResult = {
|
|
16
17
|
result: 'created';
|
|
@@ -24,7 +25,7 @@ export type CreateEntityResult = {
|
|
|
24
25
|
export declare class CatalogEntitiesLocalWriteRepository {
|
|
25
26
|
#private;
|
|
26
27
|
constructor(db: DatabaseClient, organizationId: string, projectId: string);
|
|
27
|
-
createEntity({ entity, fileHash, sourceFile, revision, isRootEntity, isDeleted, }: CreateEntityParams): Promise<CreateEntityResult>;
|
|
28
|
+
createEntity({ entity, fileHash, sourceFile, revision, isRootEntity, isDeleted, rbacTeams, }: CreateEntityParams): Promise<CreateEntityResult>;
|
|
28
29
|
deleteEntity(entityKey: string): Promise<string | null>;
|
|
29
30
|
/**
|
|
30
31
|
* Deletes entities based on a filter.
|
|
@@ -37,5 +38,6 @@ export declare class CatalogEntitiesLocalWriteRepository {
|
|
|
37
38
|
upsertEntityRelation(entityRelation: DatabaseEntityRelationDto): Promise<DatabaseEntityRelation | null>;
|
|
38
39
|
updateEntityScorecardsStatus(entityId: string, status: ScorecardsStatus): Promise<boolean>;
|
|
39
40
|
updateEntityScorecardsStatusIfCalculating(entityId: string, status: Extract<ScorecardsStatus, 'UP_TO_DATE' | 'OUTDATED'>): Promise<boolean>;
|
|
41
|
+
setEntitiesAsOutdated(filter: Filter): Promise<void>;
|
|
40
42
|
}
|
|
41
43
|
//# sourceMappingURL=catalog-entities-local-write-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{and as
|
|
1
|
+
import{and as m,eq as c,isNull as v,or as T,sql as F}from"drizzle-orm";import{logger as u}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as O}from"../../../../../utils/crypto/sha1.js";import{envConfig as V}from"../../../../../../config/env-config.js";import{VERSION_NOT_SPECIFIED as U}from"@redocly/theme/core/constants";import{entitiesAttributesTable as I}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js";import{createEntityDbRecord as b}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as K}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as C}from"../../../../../providers/database/pagination/filter.js";import{createEntityAttributesDbRecord as z}from"../../mappers/create-entity-attributes-db-record.js";import{RevisionRepository as L}from"../common/revision-repository.js";import{VersionRepository as P}from"../common/version-repository.js";const w=15;class re{#e;#t;#r;#i;#s;constructor(e,t,s){this.#e=e,this.#t=t,this.#r=s,this.#i=new L(e),this.#s=new P(e)}async createEntity({entity:e,fileHash:t,sourceFile:s,revision:a=new Date().toISOString(),isRootEntity:o=!1,isDeleted:n=!1,rbacTeams:d}){try{const{relations:l=[],...f}=e,p=O(JSON.stringify(f)),y=e.version??U,g=await this.#i.shouldSkipRevisionCreation(e.key,y,p,o,n);if(Array.isArray(d)&&await this.#o({entityKey:e.key,rbacTeams:d}),g)return{result:"skipped",entityKey:e.key};const h=await this.#i.shouldSetNewCurrentRevision({key:e.key,version:y,revision:a}),R=b({entity:{...e,revision:a,hash:p,isCurrent:h,isDefaultVersion:h,isDeleted:n,version:y},sourceFile:s,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:t}),{key:D,source:x,...S}=R;if(h&&(await this.#i.markAllRevisionsAsNotCurrent(D),await this.#s.markAllVersionsAsNotDefault(D)),V.isDevelopMode&&V.REDOCLY_INTERNAL_DEV!=="true")return await this.#n(R,l),{result:"created",entityKey:e.key,entityRevision:a,entityVersion:y};const A=this.#e.client.insert(r).values(R).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:S}),N=l?.length&&l.length>0?this.#e.client.insert(i).values(l.map(k=>K({relation:k,sourceFile:s,fileHash:t,sourceKey:e.key,sourceVersion:y,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation]}).run():Promise.resolve();return await E([A,N],w,async k=>k),{result:"created",entityKey:e.key,entityRevision:a,entityVersion:y}}catch(l){return u.error("Error adding entity",l),{result:"error",entityKey:e.key}}}async deleteEntity(e){try{return await this.#e.client.delete(r).where(c(r.key,e)),e}catch(t){return u.error("Error deleting entity",t),null}}async deleteEntities(e){try{const t=C(e);if(!t)return!1;const s=await this.#e.client.delete(r).where(t).returning({key:r.key,source:r.source,isCurrent:r.isCurrent,isDefaultVersion:r.isDefaultVersion,version:r.version});if(s.length===0)return!0;const a=s.reduce((o,n)=>((n.isCurrent||n.isDefaultVersion)&&o.add(n.key),o),new Set);if(a.size===0)return!0;await E(Array.from(a),w,async o=>this.#i.ensureDefaultAndCurrentRevisionForKey(o));for(const o of s)await this.#e.client.delete(i).where(T(m(c(i.sourceKey,o.key),...o.version?[c(i.sourceVersion,o.version)]:[v(i.sourceVersion)]),m(c(i.targetKey,o.key),...o.version?[c(i.targetVersion,o.version)]:[v(i.targetVersion)])));return!0}catch(t){return u.error("Error deleting entities",t),!1}}async deleteEntityRelation(e){try{return await this.#e.client.delete(i).where(c(i.id,e)),e}catch{return null}}async softDeleteEntities(e,t,s){try{const a=e.map(n=>{const d={type:n.type,key:n.key,title:n.title,summary:n.summary??void 0,tags:n.tags??void 0,metadata:n.metadata??void 0,git:n.git??void 0,contact:n.contact??void 0,links:n.links??void 0,version:n.version??void 0};return this.createEntity({entity:d,revision:t,sourceFile:n.sourceFile??"",fileHash:s,isDeleted:!0})});return await E(a,w,async n=>n)}catch(a){return u.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(e){try{const t=C(e);return t?(await this.#e.client.delete(i).where(t),!0):!1}catch(t){return u.error("Error deleting entity relations",t),!1}}async upsertEntityRelation(e){if(!e)return null;try{const{sourceKey:t,targetKey:s,sourceVersion:a,targetVersion:o,sourceRevision:n,targetRevision:d,...l}=e,f=await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation],set:l}).returning();return f?.length?f[0]:null}catch(t){return u.error("Error creating entity relation",t),null}}async#n(e,t){const{key:s,source:a,version:o,isDefaultVersion:n,...d}=e,p=(await this.#e.client.select({id:r.id}).from(r).where(m(c(r.key,s),c(r.source,a??"file"),o?c(r.version,o):v(r.version))).limit(1).run()).rows.length>0?this.#e.client.update(r).set(d).where(m(c(r.key,s),c(r.source,a??"file"),o?c(r.version,o):v(r.version))).run():this.#e.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:d}).run(),y=t?.map(g=>{const h=K({relation:g,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(i).values(h).onConflictDoUpdate({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation],set:h}).run()})??[];await E([p,...y],w,async g=>g)}async updateEntityScorecardsStatus(e,t){try{return(await this.#e.client.update(r).set({scorecardsStatus:t}).where(c(r.id,e)).returning()).length>0}catch(s){return u.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(e,t){try{return(await this.#e.client.update(r).set({scorecardsStatus:t}).where(F`${r.id} = ${e} AND ${r.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return u.error("Error updating entity scorecards status if calculating",s),!1}}async#o({entityKey:e,rbacTeams:t}){try{await this.#e.client.insert(I).values(z({rbacTeams:t,entityKey:e,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[I.entityKey],set:{rbacTeams:JSON.stringify(t)}}).run()}catch(s){u.error("Error saving entity attributes",s)}}async setEntitiesAsOutdated(e){try{const t=C(e);await this.#e.client.update(r).set({scorecardsStatus:"OUTDATED"}).where(t)}catch(t){u.error("Error updating entities as outdated",t)}}}export{re as CatalogEntitiesLocalWriteRepository};
|
|
@@ -12,6 +12,12 @@ export declare class CatalogEntitiesRelationsRepository {
|
|
|
12
12
|
direction: "outgoing" | "incoming";
|
|
13
13
|
priority: number;
|
|
14
14
|
}[]>;
|
|
15
|
-
getRelatedEntities(key
|
|
15
|
+
getRelatedEntities({ key, paginationParams, rbacTeams, excludedTypes, excludedEntities, }: {
|
|
16
|
+
key: string;
|
|
17
|
+
paginationParams: PaginationParams;
|
|
18
|
+
rbacTeams?: string[];
|
|
19
|
+
excludedTypes?: string[];
|
|
20
|
+
excludedEntities?: string[];
|
|
21
|
+
}): Promise<ListResult<BffCatalogRelatedEntity>>;
|
|
16
22
|
}
|
|
17
23
|
//# sourceMappingURL=catalog-entities-relations-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{unionAll as
|
|
1
|
+
import{unionAll as C}from"drizzle-orm/sqlite-core";import{and as d,desc as D,eq as u,notExists as N,sql as i}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as A}from"@redocly/theme/core/constants";import{entitiesTable as e}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as t}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{entitiesAttributesTable as p}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js";import{excludeFieldsFromFilter as W,getFirstFilterFieldValue as O}from"../../../../../providers/database/pagination/filter.js";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{createBffRelatedEntityFromQueryRow as k}from"../../mappers/create-bff-related-entity.js";import{mapEntityRelationRow as H}from"../../mappers/map-entity-relation-row.js";import{buildEntitiesExclusionFilter as L}from"../utils/build-entities-exclusion-filter.js";import{buildRbacFilter as q}from"../utils/build-rbac-filter.js";class te{#e;#i;constructor(n,r){this.#e=n,this.#i=r}async getRelationsForEntity(n,r,m){const y=await this.#t(n,r,m);return y?(await this.#e.client.select().from(y).run()).rows.map(a=>H(a)):[]}async getRelatedEntities({key:n,paginationParams:r,rbacTeams:m,excludedTypes:y,excludedEntities:l}){const a=O(r.filter,"version"),v=O(r.filter,"revision"),o=await this.#t(n,a,v);if(!o)return{items:[],total:0};const R=this.#e.client.select({relationType:o.relationName,direction:o.direction,key:e.key,revision:e.revision,id:e.id,type:e.type,title:e.title,summary:e.summary,tags:e.tags,metadata:e.metadata,createdAt:e.createdAt,updatedAt:e.updatedAt,source:e.source,sourceFile:e.sourceFile,version:e.version,isDeleted:e.isDeleted,isCurrent:e.isCurrent,rbacTeams:p.rbacTeams,dedupRn:i`ROW_NUMBER() OVER (PARTITION BY ${o.entityKey} ORDER BY ${o.priority} ASC, CASE WHEN ${o.entityRevision} = ${e.revision} THEN 1 ELSE 0 END DESC, CASE WHEN ${o.entityVersion} = ${e.version} THEN 1 ELSE 0 END DESC, ${e.isCurrent} DESC, ${e.revision} DESC)`.as("dedupRn")}).from(o).innerJoin(e,i`${o.entityKey} = ${e.key} AND (${o.entityRevision} = ${e.revision} OR ${o.entityRevision} = '' OR ${e.isCurrent} = 1) AND (${o.entityVersion} = ${e.version} OR ${o.entityVersion} = '' OR ${e.version} = ${A})`).leftJoin(p,u(e.key,p.entityKey)).as("unique_relations"),$=q(m,"unique_relations"),f=L(y,l,"unique_relations");let s=i`${R.dedupRn} = 1 AND COALESCE(${R.isDeleted}, 0) = 0`;$&&(s=i`${s} AND ${$}`),f&&(s=i`${s} AND ${f}`);const c=this.#e.client.select().from(R).$dynamic(),V=this.#e.client.select().from(R).$dynamic(),T=W(r.filter,["version","revision"]),g={...r,filter:T,baseWhereCondition:s},F=S(V,{...g,limit:void 0,skip:void 0,after:void 0,before:void 0}),B=this.#e.client.$count(F),h=r.limit||10,K=S(c,{...g,limit:h+1}),[b,_]=await Promise.all([K.run(),B]),w=b.rows.filter(E=>E.id!=null).map(E=>k(E)).filter(E=>E!==null),Q=w.slice(0,h),I=w.length>h;return{items:Q,hasMore:I,total:_}}async#r(n,r){if(r){const a=await(this.#i?C(this.#e.client.select({version:i.raw("version"),revision:i.raw("revision")}).from(i`remote.entities`).where(d(i`key = ${n}`,i`version = ${r}`)).orderBy(i.raw("revision DESC")),this.#e.client.select({version:e.version,revision:e.revision}).from(e).where(d(u(e.key,n),u(e.version,r),N(this.#e.client.select({id:i.raw("id")}).from(i`remote.entities as remote`).where(d(i`remote.key = ${e.key}`,i`remote.version = ${r}`))))).orderBy(D(e.revision))):this.#e.client.select({version:e.version,revision:e.revision}).from(e).where(d(u(e.key,n),u(e.version,r))).orderBy(D(e.revision))).limit(1).run();if(a.rows.length>0){const v=a.rows[0];return{version:v.version||null,revision:v.revision||null}}return null}const y=await(this.#i?C(this.#e.client.select({version:i.raw("version"),revision:i.raw("revision")}).from(i`remote.entities`).where(d(i`key = ${n}`,i`is_current = 1`)),this.#e.client.select({version:e.version,revision:e.revision}).from(e).where(d(u(e.key,n),u(e.isCurrent,!0),N(this.#e.client.select({id:i.raw("id")}).from(i`remote.entities as remote`).where(d(i`remote.key = ${e.key}`,i`remote.is_current = 1`)))))):this.#e.client.select({version:e.version,revision:e.revision}).from(e).where(d(u(e.key,n),u(e.isCurrent,!0)))).limit(1).run();if(y.rows.length>0){const l=y.rows[0];return{version:l.version||null,revision:l.revision||null}}return null}async#t(n,r,m){const y=m?{version:r||null,revision:m}:await this.#r(n,r||null),l=r||y?.version||null,a=m||y?.revision||null,v=!l||l===A,o=v?i`1 = 1`:i`(${t.sourceVersion} = ${l} OR ${t.sourceVersion} = '')`,R=v?i`1 = 1`:i`(${t.targetVersion} = ${l} OR ${t.targetVersion} = '')`,$=a?i`(${t.sourceRevision} <= ${a} OR ${t.sourceRevision} = '')`:i`1 = 0`,f=a?i`(${t.targetRevision} <= ${a} OR ${t.targetRevision} = '')`:i`1 = 0`,s=this.#e.client.select({entityKey:t.targetKey,entityRevision:t.targetRevision,entityVersion:t.targetVersion,relationName:t.sourceToTargetRelation,direction:i`'outgoing'`.as("direction"),priority:i`1`.as("priority"),isDeleted:t.isDeleted,rn:i`ROW_NUMBER() OVER (PARTITION BY ${t.targetKey}, ${t.sourceToTargetRelation} ORDER BY CASE WHEN ${t.sourceVersion} != '' THEN 1 ELSE 0 END DESC, ${t.sourceRevision} DESC)`.as("rn")}).from(t).where(d(u(t.sourceKey,n),o,$)).as("outgoing_filtered"),c=this.#e.client.select({entityKey:t.sourceKey,entityRevision:t.sourceRevision,entityVersion:t.sourceVersion,relationName:t.targetToSourceRelation,direction:i`'incoming'`.as("direction"),priority:i`2`.as("priority"),isDeleted:t.isDeleted,rn:i`ROW_NUMBER() OVER (PARTITION BY ${t.sourceKey}, ${t.targetToSourceRelation} ORDER BY CASE WHEN ${t.targetVersion} != '' THEN 1 ELSE 0 END DESC, ${t.targetRevision} DESC)`.as("rn")}).from(t).where(d(u(t.targetKey,n),R,f)).as("incoming_filtered");return this.#e.client.select({entityKey:s.entityKey,entityRevision:s.entityRevision,entityVersion:s.entityVersion,relationName:s.relationName,direction:s.direction,priority:s.priority}).from(s).where(i`${s.rn} = 1 AND COALESCE(${s.isDeleted}, 0) = 0`).unionAll(this.#e.client.select({entityKey:c.entityKey,entityRevision:c.entityRevision,entityVersion:c.entityVersion,relationName:c.relationName,direction:c.direction,priority:c.priority}).from(c).where(i`${c.rn} = 1 AND COALESCE(${c.isDeleted}, 0) = 0`)).as("all_relations")}}export{te as CatalogEntitiesRelationsRepository};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { EntityReadModelSchema } from '../../../schemas/read-model-schemas.js';
|
|
1
|
+
import type { EntityReadModelSchema, EntityRelationReadModelSchema } from '../../../schemas/read-model-schemas.js';
|
|
2
2
|
import type { EntityDtoSchema, EntityRelationDtoSchema } from '../../../schemas/dto-schemas.js';
|
|
3
3
|
import type { Filter } from '../../../../../providers/database/pagination/types.js';
|
|
4
4
|
import type { DatabaseConnection, RepositoryInstanceOptions } from '../../../../../providers/database/types.js';
|
|
5
|
-
import type { DatabaseEntityRelation } from '../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js';
|
|
6
5
|
import { BaseRepository } from '../../../../../providers/database/base-repository.js';
|
|
7
6
|
export declare class CatalogEntitiesRemoteRepository extends BaseRepository {
|
|
8
7
|
#private;
|
|
@@ -11,13 +10,10 @@ export declare class CatalogEntitiesRemoteRepository extends BaseRepository {
|
|
|
11
10
|
sync(): Promise<void>;
|
|
12
11
|
static getInstance(options: RepositoryInstanceOptions): Promise<CatalogEntitiesRemoteRepository | null>;
|
|
13
12
|
createEntity(entity: EntityDtoSchema): Promise<EntityReadModelSchema | null>;
|
|
14
|
-
updateEntity(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
deleteEntity(entityKey: string): Promise<string | null>;
|
|
19
|
-
createEntityRelations(relations: EntityRelationDtoSchema[]): Promise<(DatabaseEntityRelation | null)[]>;
|
|
20
|
-
createEntityRelation(entityRelation: EntityRelationDtoSchema): Promise<DatabaseEntityRelation | null>;
|
|
13
|
+
updateEntity(incomingEntity: Partial<EntityDtoSchema>, entityToBeUpdated: EntityReadModelSchema): Promise<EntityReadModelSchema | null>;
|
|
14
|
+
deleteEntity(entityToBeRemoved: EntityReadModelSchema): Promise<string | null>;
|
|
15
|
+
createEntityRelations(relations: EntityRelationDtoSchema[]): Promise<(EntityRelationReadModelSchema | null)[]>;
|
|
16
|
+
createEntityRelation(entityRelation: EntityRelationDtoSchema): Promise<EntityRelationReadModelSchema | null>;
|
|
21
17
|
deleteEntityRelation(id: string): Promise<string | null>;
|
|
22
18
|
deleteEntitiesRelations(filter: Filter): Promise<boolean>;
|
|
23
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{eq as
|
|
1
|
+
import{and as g,eq as n,ne as C,or as w,sql as p}from"drizzle-orm";import{convertFilterToWhereCondition as D}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as V}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as E}from"../../../../../utils/crypto/sha1.js";import{logger as a}from"../../../../../tools/notifiers/logger.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{telemetryTraceStep as c}from"../../../../../telemetry/helpers/trace-step.js";import{BaseRepository as A}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as I}from"../../../../../providers/database/database-connection-factory.js";import{entitiesRelationsTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{VERSION_NOT_SPECIFIED as b}from"@redocly/theme/core/constants";import{createEntityDbRecord as _}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as k}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as O}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{RevisionRepository as K}from"../common/revision-repository.js";import{VersionRepository as F}from"../common/version-repository.js";import{createEntityRelationReadModel as S}from"../../mappers/create-entity-relation-read-model.js";const L=15;class h extends A{static#r;#t;#i;#n=!1;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t),this.#t=new K(t.client),this.#i=new F(t.client)}async sync(){if(!this.#n&&this.isNonRemoteDatabaseMode()){a.warn("Catalog entities database is currently operating in local mode: not connected to the remote database. All changes and data will only persist locally and will not be synced remotely."),this.#n=!0;return}return c("catalog_entities.remote_repository.sync",async()=>{await this.#e(),await this.databaseClient.sync()})}static async getInstance(t){return await c("catalog_entities.remote_repository.get_instance",async e=>{if(!h.#r)try{const o=await I.create("sqld-remote",t);if(!o)return a.error("Failed to create db connection for catalog entities remote repository"),e?.error(new Error("Failed to create db connection for catalog entities remote repository")),h.#r=null,null;h.#r=new h(o)}catch(o){return a.error("Error creating db connection for catalog entities remote repository",o),e?.error(o),h.#r=null,null}return h.#r})}async createEntity(t){return c("catalog_entities.remote_repository.create_entity",async()=>{await this.#e();try{a.info(`Adding entity ${t.key} to remote database`);const{relations:e=[],...o}=t,l=E(JSON.stringify(o)),s=t.version??b,y=t.revision??new Date().toISOString();if(await this.#t.shouldSkipRevisionCreation(t.key,s,l))throw new Error("Entity validation failed: entity already exists");const d=await this.#t.shouldSetNewCurrentRevision({key:t.key,version:s,revision:y}),u=_({entity:{...t,revision:y,hash:l,isCurrent:d,isDefaultVersion:d,version:s},organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:m,source:M,...N}=u;d&&(await this.#t.markAllRevisionsAsNotCurrent(m),await this.#i.markAllVersionsAsNotDefault(m));const v=await this.databaseClient.client.insert(i).values(u).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:N}).returning();return v.length?(e&&await this.createEntityRelations(e.map(R=>({...R,sourceKey:t.key,targetKey:R.key}))),k(v[0])):null}catch(e){throw a.error("Error adding entity",e),e}})}async updateEntity(t,e){return c("catalog_entities.remote_repository.update_entity",async()=>{await this.#e();try{a.info(`Updating entity ${e.key} in remote database`);const o=await this.#t.shouldSetNewCurrentRevision({key:e.key,version:t.version??e.version??b,revision:e.revision});o&&(await this.#t.markAllRevisionsAsNotCurrent(e.key),await this.#i.markAllVersionsAsNotDefault(e.key));const l=_({entity:{...e,...t,hash:E(JSON.stringify({...e,...t})),isCurrent:o,isDefaultVersion:o,createdAt:e.createdAt??void 0},organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:s,source:y,scorecardsStatus:f,...d}=l,u=await this.databaseClient.client.insert(i).values(l).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...d,scorecardsStatus:p`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return u.length?k(u[0]):null}catch(o){return a.error("Error updating entity",o),null}})}async deleteEntity(t){return c("catalog_entities.remote_repository.delete_entity",async()=>{await this.#e();try{return await this.#o(t),await this.databaseClient.client.delete(i).where(n(i.id,t.id)),await this.#t.ensureDefaultAndCurrentRevisionForKey(t.key),t.id}catch(e){return a.error("Error deleting entity",e),null}})}async createEntityRelations(t){return c("catalog_entities.remote_repository.create_entity_relations",async()=>(await this.#e(),await V(t,L,async e=>this.createEntityRelation(e))))}async createEntityRelation(t){return c("catalog_entities.remote_repository.create_entity_relation",async()=>{if(await this.#e(),!t)return null;try{const e=O(t,this.organizationId,this.projectId),{sourceKey:o,targetKey:l,sourceVersion:s,targetVersion:y,sourceRevision:f,targetRevision:d,...u}=e,m=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.sourceKey,r.targetKey,r.sourceVersion,r.targetVersion,r.sourceRevision,r.targetRevision,r.sourceToTargetRelation],set:u}).returning();return m.length?S(m[0]):null}catch(e){throw a.error("Error creating entity relation",e),e}})}async deleteEntityRelation(t){return c("catalog_entities.remote_repository.delete_entity_relation",async()=>{await this.#e();try{return await this.databaseClient.client.delete(r).where(n(r.id,t)),t}catch(e){return a.error("Error deleting entity relation",e),null}})}async deleteEntitiesRelations(t){return c("catalog_entities.remote_repository.delete_entities_relations",async()=>{await this.#e();try{const e=D(t);return e?(await this.databaseClient.client.delete(r).where(e),!0):!1}catch(e){return a.error("Error deleting entities relations",e),!1}})}async#o(t){const{key:e,version:o,revision:l}=t,s=o??"",y=l??"";if(((await this.databaseClient.client.select({count:p`COUNT(*)`}).from(i).where(g(n(i.key,e),C(i.id,t.id))).get())?.count??0)===0){await this.databaseClient.client.delete(r).where(w(n(r.sourceKey,e),n(r.targetKey,e)));return}if(((await this.databaseClient.client.select({count:p`COUNT(*)`}).from(i).where(g(n(i.key,e),n(i.version,s),C(i.id,t.id))).get())?.count??0)===0){await this.databaseClient.client.delete(r).where(w(g(n(r.sourceKey,e),n(r.sourceVersion,s)),g(n(r.targetKey,e),n(r.targetVersion,s))));return}await this.databaseClient.client.delete(r).where(w(g(n(r.sourceKey,e),n(r.sourceVersion,s),n(r.sourceRevision,y)),g(n(r.targetKey,e),n(r.targetVersion,s),n(r.targetRevision,y))))}#e(){return c("catalog_entities.remote_repository.db_health",async t=>{if(this.databaseClient.dbClient.$client.closed){const e=new Error("The remote database connection is closed!");throw t?.error(e),e}})}}export{h as CatalogEntitiesRemoteRepository};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Builds an exclusion filter condition as a drizzle SQL object.
|
|
4
|
+
* Use this with drizzle query builder to exclude specific entity types or keys.
|
|
5
|
+
*
|
|
6
|
+
* Exclusion filter logic:
|
|
7
|
+
* 1. If excludedEntities is provided -> exclude entities matching those keys
|
|
8
|
+
* 2. If excludedTypes is provided -> exclude entities matching those types
|
|
9
|
+
* 3. Multiple conditions are combined with AND
|
|
10
|
+
* 4. Returns undefined if no exclusions are specified
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildEntitiesExclusionFilter(excludedTypes?: string[], excludedEntities?: string[], tableAlias?: string): SQL | undefined;
|
|
13
|
+
//# sourceMappingURL=build-entities-exclusion-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sql as n}from"drizzle-orm";function u(r,i,t){const o=[],f=t?n.raw(`${t}.type`):n.raw("type"),p=t?n.raw(`${t}.key`):n.raw("key");if(i?.length&&o.push(n`${p} NOT IN (${n.join(i.map(e=>n`${e}`),n`, `)})`),r?.length)for(const e of r)o.push(n`${f} != ${e}`);if(o.length!==0)return o.length===1?o[0]:n`(${n.join(o,n` AND `)})`}export{u as buildEntitiesExclusionFilter};
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Builds an RBAC filter condition as a drizzle SQL object.
|
|
4
|
+
* Use this with drizzle query builder.
|
|
5
|
+
*
|
|
6
|
+
* RBAC filter logic:
|
|
7
|
+
* 1. If rbac_teams is NULL -> allow access (no restrictions)
|
|
8
|
+
* 2. If rbac_teams is empty array -> allow access (no restrictions)
|
|
9
|
+
* 3. Otherwise, check if any of user's teams match using json_each
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildRbacFilter(rbacTeams?: string[], tableAlias?: string): SQL | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Builds an RBAC filter condition as a raw SQL string.
|
|
14
|
+
* Use this when constructing raw SQL queries with sql.raw().
|
|
15
|
+
*
|
|
16
|
+
* Same RBAC filter logic as buildRbacFilter but returns a string for raw SQL usage.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildRbacFilterRaw(rbacTeams?: string[], tableAlias?: string): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Builds RBAC JOIN and filter for subqueries that need to join with combined_target_attributes CTE.
|
|
21
|
+
* Returns both the LEFT JOIN clause and the AND filter condition for use in raw SQL subqueries.
|
|
22
|
+
*
|
|
23
|
+
* @param rbacTeams - Array of team names the user belongs to
|
|
24
|
+
* @param entityKeyAlias - The alias for the entity key column (e.g., 'd.key', 'o.key')
|
|
25
|
+
* @returns Object with `join` and `filter` SQL fragments (both empty if no RBAC teams)
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildSubqueryRbacJoinAndFilter(rbacTeams?: string[], entityKeyAlias?: string): {
|
|
28
|
+
join: SQL;
|
|
29
|
+
filter: SQL;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=build-rbac-filter.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{sql as t}from"drizzle-orm";function E(e,r){if(!e||e.length===0)return;const n=r?`${r}.rbac_teams`:"rbac_teams",a=t.join(e.map(o=>t`${o}`),t`, `);return t`(${t.raw(n)} IS NULL OR json_array_length(COALESCE(${t.raw(n)}, '[]')) = 0 OR EXISTS (SELECT 1 FROM json_each(COALESCE(${t.raw(n)}, '[]')) AS t WHERE t.value IN (${a})))`}function s(e,r){if(!e||e.length===0)return null;const n=r?`${r}.rbac_teams`:"rbac_teams",a=e.map(o=>`'${o.replace(/'/g,"''")}'`).join(", ");return`(${n} IS NULL OR json_array_length(COALESCE(${n}, '[]')) = 0 OR EXISTS (SELECT 1 FROM json_each(COALESCE(${n}, '[]')) AS t WHERE t.value IN (${a})))`}function u(e,r){if(!(e&&e.length>0))return{join:t``,filter:t``};const a=t`LEFT JOIN combined_target_attributes attr ON attr.entity_key = ${t.raw(r??"key")}`,o=t`
|
|
2
|
+
AND (
|
|
3
|
+
attr.rbac_teams IS NULL
|
|
4
|
+
OR json_array_length(attr.rbac_teams) = 0
|
|
5
|
+
OR EXISTS (
|
|
6
|
+
SELECT 1 FROM json_each(attr.rbac_teams) as t
|
|
7
|
+
WHERE t.value IN (${t.join(e.map(i=>t`${i}`),t`, `)})
|
|
8
|
+
)
|
|
9
|
+
)`;return{join:a,filter:o}}export{E as buildRbacFilter,s as buildRbacFilterRaw,u as buildSubqueryRbacJoinAndFilter};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Creates merged entity fields for SELECT when joining remote and local entities.
|
|
4
|
+
* JSON fields (metadata, git, contact, links, tags) are merged using json_patch.
|
|
5
|
+
* Simple fields prefer the newer value based on updated_at.
|
|
6
|
+
* @param remoteAlias - Alias for remote table (default: 'r')
|
|
7
|
+
* @param localAlias - Alias for local table (default: 'l')
|
|
8
|
+
*/
|
|
9
|
+
export declare function createMergedEntityFieldsForSelect(remoteAlias?: string, localAlias?: string): {
|
|
10
|
+
id: SQL<unknown>;
|
|
11
|
+
organizationId: SQL<unknown>;
|
|
12
|
+
projectId: SQL<unknown>;
|
|
13
|
+
key: SQL<unknown>;
|
|
14
|
+
type: SQL<unknown>;
|
|
15
|
+
title: SQL<unknown>;
|
|
16
|
+
summary: SQL<unknown>;
|
|
17
|
+
tags: SQL<unknown>;
|
|
18
|
+
metadata: SQL<unknown>;
|
|
19
|
+
git: SQL<unknown>;
|
|
20
|
+
contact: SQL<unknown>;
|
|
21
|
+
links: SQL<unknown>;
|
|
22
|
+
createdAt: SQL<unknown>;
|
|
23
|
+
updatedAt: SQL<unknown>;
|
|
24
|
+
source: SQL<unknown>;
|
|
25
|
+
sourceFile: SQL<unknown>;
|
|
26
|
+
fileHash: SQL<unknown>;
|
|
27
|
+
version: SQL<unknown>;
|
|
28
|
+
revision: SQL<unknown>;
|
|
29
|
+
hash: SQL<unknown>;
|
|
30
|
+
isCurrent: SQL<unknown>;
|
|
31
|
+
isDeleted: SQL<unknown>;
|
|
32
|
+
scorecardsStatus: SQL<unknown>;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=create-merged-entity-fields-for-select.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{sql as u}from"drizzle-orm";function p(t="r",d="l"){return{id:$("id","id",t,d),organizationId:$("organization_id","organization_id",t,d),projectId:$("project_id","project_id",t,d),key:u.raw(`${t}.key AS key`),type:$("type","type",t,d),title:$("title","title",t,d),summary:$("summary","summary",t,d),tags:_("tags","tags",t,d),metadata:_("metadata","metadata",t,d),git:_("git","git",t,d),contact:_("contact","contact",t,d),links:_("links","links",t,d),createdAt:u.raw(`MIN(${t}.created_at, ${d}.created_at) AS created_at`),updatedAt:u.raw(`MAX(${t}.updated_at, ${d}.updated_at) AS updated_at`),source:$("source","source",t,d),sourceFile:$("source_file","source_file",t,d),fileHash:$("file_hash","file_hash",t,d),version:u.raw(`${t}.version AS version`),revision:u.raw(`${t}.revision AS revision`),hash:$("hash","hash",t,d),isCurrent:$("is_current","is_current",t,d),isDeleted:$("is_deleted","is_deleted",t,d),scorecardsStatus:$("scorecards_status","scorecards_status",t,d)}}function _(t,d,n="r",r="l"){return u.raw(`
|
|
2
|
+
CASE
|
|
3
|
+
WHEN ${n}.${t} IS NULL THEN ${r}.${t}
|
|
4
|
+
WHEN ${r}.${t} IS NULL THEN ${n}.${t}
|
|
5
|
+
WHEN ${n}.updated_at >= ${r}.updated_at THEN json_patch(${r}.${t}, ${n}.${t})
|
|
6
|
+
ELSE json_patch(${n}.${t}, ${r}.${t})
|
|
7
|
+
END AS ${d}
|
|
8
|
+
`)}function $(t,d,n="r",r="l"){return u.raw(`
|
|
9
|
+
CASE
|
|
10
|
+
WHEN ${n}.updated_at >= ${r}.updated_at THEN COALESCE(${n}.${t}, ${r}.${t})
|
|
11
|
+
ELSE COALESCE(${r}.${t}, ${n}.${t})
|
|
12
|
+
END AS ${d}
|
|
13
|
+
`)}export{p as createMergedEntityFieldsForSelect};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a revision with flags that can be normalized.
|
|
3
|
+
*/
|
|
4
|
+
export type RevisionWithFlags = {
|
|
5
|
+
version: string | null;
|
|
6
|
+
revision: string;
|
|
7
|
+
isCurrent: boolean;
|
|
8
|
+
isDefaultVersion: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes revision flags to ensure only one revision is marked as current/default.
|
|
12
|
+
*
|
|
13
|
+
* When multiple revisions are flagged (isCurrent or isDefaultVersion), the one with
|
|
14
|
+
* the highest semantic version wins. If versions are equal, the highest revision string wins.
|
|
15
|
+
* All other flagged revisions have their flags reset to false.
|
|
16
|
+
*
|
|
17
|
+
* Note: In this system, isCurrent and isDefaultVersion are coupled - if a revision
|
|
18
|
+
* is current, it is also the default version.
|
|
19
|
+
*
|
|
20
|
+
* @param revisions - Array of revisions to normalize (mutated in place)
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeRevisionFlags<T extends RevisionWithFlags>(revisions: T[]): void;
|
|
23
|
+
//# sourceMappingURL=normalize-revision-flags.d.ts.map
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{VERSION_NOT_SPECIFIED as t}from"@redocly/theme/core/constants";import{compareVersionsDescending as f}from"../../../utils/version-compare.js";function s(n){return!n||n===t}function c(n,i){const e=s(n.version),r=s(i.version);if(e&&!r)return 1;if(!e&&r)return-1;const o=f(n.version??"",i.version??"");return o!==0?o:(i.revision??"").localeCompare(n.revision??"")}function a(n){const i=n.filter(e=>e.isCurrent||e.isDefaultVersion);if(!(i.length<=1)){i.sort(c);for(let e=1;e<i.length;e++)i[e].isCurrent=!1,i[e].isDefaultVersion=!1}}export{a as normalizeRevisionFlags};
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* SEMANTIC VERSION SORTING IN SQLITE
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* SQLite lacks native semantic version comparison, so we convert versions
|
|
8
|
+
* into sortable strings. The key insight is that string comparison uses
|
|
9
|
+
* ASCII/Unicode ordering, so we can control sort order through prefixes
|
|
10
|
+
* and zero-padding.
|
|
11
|
+
*
|
|
12
|
+
* ## Sort Strategy (for descending order)
|
|
13
|
+
*
|
|
14
|
+
* We transform versions into strings that sort correctly when compared lexicographically:
|
|
15
|
+
*
|
|
16
|
+
* | Version Type | Transformation | Example Result |
|
|
17
|
+
* |----------------------|-------------------------------------|-------------------------|
|
|
18
|
+
* | not_specified_version| Prefix with '!' | '!not_specified' |
|
|
19
|
+
* | null/empty | Padded zeros | '0000000000.0000...' |
|
|
20
|
+
* | Numeric (1.2.3) | Zero-padded to 10 digits per part | '0000000001.0000000002.0000000003' |
|
|
21
|
+
* | Text (latest) | Prefix with 'Z' | 'ZZZZZZZZZZ.latest' |
|
|
22
|
+
*
|
|
23
|
+
* ASCII ordering ensures: '!' < '0' < 'Z', giving us:
|
|
24
|
+
* latest > 10.0.0 > 3.1 > 1 > null > not_specified_version
|
|
25
|
+
*
|
|
26
|
+
* ## Why Zero-Padding?
|
|
27
|
+
*
|
|
28
|
+
* Without padding, string comparison fails for multi-digit numbers:
|
|
29
|
+
* '9' > '10' (wrong!) vs '0000000009' < '0000000010' (correct!)
|
|
30
|
+
*
|
|
31
|
+
* We use 10 digits to support versions up to 9,999,999,999 per component.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Builds SQL expression for semantic version sorting in SQLite.
|
|
35
|
+
* Handles versions like: 1, 1.0, 1.0.0, 10.2.3, latest, etc.
|
|
36
|
+
*
|
|
37
|
+
* @param versionColumn - The column name or expression containing the version
|
|
38
|
+
* @returns SQL expression that can be used in ORDER BY for descending version sort
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```sql
|
|
42
|
+
* ORDER BY ${buildSemanticVersionSortExpr('version')} DESC
|
|
43
|
+
* -- Sorts: latest, 10.0.0, 3.1, 3, 2.0.1, 1, not_specified_version
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildSemanticVersionSortExpr(versionColumn: string): SQL;
|
|
47
|
+
/**
|
|
48
|
+
* ============================================================================
|
|
49
|
+
* VERSION COMPARISON FILTER
|
|
50
|
+
* ============================================================================
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* Builds a SQL condition that checks no higher semantic version exists
|
|
54
|
+
* for the same key in either local or remote database.
|
|
55
|
+
*
|
|
56
|
+
* This is used to find the "current" version of an entity when multiple
|
|
57
|
+
* versions exist across local and remote databases.
|
|
58
|
+
*
|
|
59
|
+
* ## Logic
|
|
60
|
+
*
|
|
61
|
+
* Returns TRUE if there is NO other entity with the same key that has:
|
|
62
|
+
* 1. A higher semantic version, OR
|
|
63
|
+
* 2. The same version but a higher revision number
|
|
64
|
+
*
|
|
65
|
+
* ## Example
|
|
66
|
+
*
|
|
67
|
+
* Given entities with key='my-api':
|
|
68
|
+
* - Local: version='1.0.0', revision=1
|
|
69
|
+
* - Remote: version='1.0.0', revision=2 ← This one wins (same version, higher revision)
|
|
70
|
+
* - Remote: version='2.0.0', revision=1 ← This one wins (higher version)
|
|
71
|
+
*
|
|
72
|
+
* @param keyExpr - SQL expression for the entity's key (e.g., 'entities.key')
|
|
73
|
+
* @param versionExpr - SQL expression for the entity's version (e.g., 'entities.version')
|
|
74
|
+
* @param revisionExpr - SQL expression for the entity's revision (e.g., 'entities.revision')
|
|
75
|
+
* @returns SQL expression that evaluates to TRUE if this is the highest version
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildNoHigherVersionExistsFilter(keyExpr: string, versionExpr: string, revisionExpr: string): SQL;
|
|
78
|
+
//# sourceMappingURL=semantic-version-sort.d.ts.map
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import{sql as o}from"drizzle-orm";const $="not_specified_version";function h(e){return o.raw(`
|
|
2
|
+
CASE
|
|
3
|
+
${s(e)}
|
|
4
|
+
${S(e)}
|
|
5
|
+
${a(e)}
|
|
6
|
+
${E(e)}
|
|
7
|
+
END
|
|
8
|
+
`)}function s(e){return`WHEN ${e} = '${$}' THEN '!not_specified'`}function S(e){return`WHEN ${e} IS NULL OR ${e} = '' THEN '0000000000.0000000000.0000000000'`}function a(e){return`WHEN ${e} GLOB '*[^0-9.]*' THEN 'ZZZZZZZZZZ.' || ${e}`}function E(e){return`ELSE ${c(e)}`}function c(e){const r=u(e),i=N(e),t=T(e);return`PRINTF('%010d.%010d.%010d', ${r}, ${i}, ${t})`}function u(e){const r=`${e} || '.0.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${r}, 1, INSTR(${r}, '.') - 1), ''), '0') AS INTEGER)`}function N(e){const r=`${e} || '.0.0'`,i=`SUBSTR(${r}, INSTR(${r}, '.') + 1) || '.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${i}, 1, INSTR(${i}, '.') - 1), ''), '0') AS INTEGER)`}function T(e){const r=`${e} || '.0.0'`,i=`SUBSTR(${r}, INSTR(${r}, '.') + 1) || '.0'`,t=`SUBSTR(${i}, INSTR(${i}, '.') + 1) || '.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${t}, 1, INSTR(${t}, '.') - 1), ''), '0') AS INTEGER)`}function d(e){return`
|
|
9
|
+
CASE
|
|
10
|
+
${s(e)}
|
|
11
|
+
${S(e)}
|
|
12
|
+
${a(e)}
|
|
13
|
+
${E(e)}
|
|
14
|
+
END
|
|
15
|
+
`}function l(e,r,i){const t=d("higher_version.version"),n=d(r);return o.raw(`
|
|
16
|
+
NOT EXISTS (
|
|
17
|
+
SELECT 1 FROM (
|
|
18
|
+
-- Combine all current, non-deleted entities from both databases
|
|
19
|
+
SELECT key, version, revision FROM remote.entities WHERE is_current = 1 AND is_deleted = 0
|
|
20
|
+
UNION ALL
|
|
21
|
+
SELECT key, version, revision FROM entities WHERE is_current = 1 AND is_deleted = 0
|
|
22
|
+
) higher_version
|
|
23
|
+
WHERE higher_version.key = ${e}
|
|
24
|
+
AND (
|
|
25
|
+
-- Case 1: Another entity has a strictly higher version
|
|
26
|
+
(${t}) > (${n})
|
|
27
|
+
OR (
|
|
28
|
+
-- Case 2: Same version, but another entity has a higher revision
|
|
29
|
+
(${t}) = (${n})
|
|
30
|
+
AND higher_version.revision > ${i}
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
`)}export{l as buildNoHigherVersionExistsFilter,h as buildSemanticVersionSortExpr};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import y from"node:path";import{removeLeadingSlash as f}from"@redocly/theme/core/utils";import{toKebabCase as m}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as g}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as w}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";const d=15;class D extends E{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t,i){const a=f(t.realRelativePath),h=t.document.info.title,r=a.replace(/\.[^.]+$/,""),o=m(r.replace(/[\\/]/g,"-")),n=t.document["x-redocly-catalog-key"],e=typeof n=="string"&&n.trim()?m(n.trim()):o;return{type:this.type,key:e,title:h,summary:t.document.info.description?w(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a},version:i}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t,i,a,h){if(!this.#t(t)){this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`);return}const r=this.getRbacTeamsForDefinition(t.relativePath),o=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:o,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,revision:i,rbacTeams:r}),h.delete(`${o.key}:${a}`),await this.#e(t,o.key,o.version,a,i,h,r);const n=t.document.sourceDescriptions||[];await g(n,d,async e=>{if(!(e.type!=="openapi"||!e.url))try{const c=this.resolveSourceDescriptionUrl(e.url,t.realRelativePath);if(!c){!e.url.startsWith("http://")&&!e.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${e.url}`);return}const l=await this.context.cache.load(c,"load-oas");if(!(l.data&&Array.isArray(l.data)&&l.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${c}`);return}const p=l.data[0],u=m(f(p.realRelativePath).replace(/\.[^.]+$/,"").replace(/[\\/]/g,"-"));await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o.key,type:"relatesTo",targetKey:u,fileHash:t.hash}),await this.#r(t,e.name,p,o.key,u,o.version,i)}catch(c){this.context.logger.warn(`Failed to create relation to OpenAPI source "${e.url}": ${c instanceof Error?c.message:"Unknown error"}`)}})}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,i,a,h,r,o,n)=>{try{const e=t.document.components?.inputs,c=e?Object.entries(e):[],l=[];for(const[s,p]of c)l.push(async()=>{const u=await this.#a({schemaName:s,schema:p,description:t,parentKey:i,parentVersion:a,parentRevision:r,rbacTeams:n});o.delete(`${u.entityKey}:${h}`),u.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:i,type:"uses",targetKey:u.entityKey,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:r,targetRevision:r})});if(l.length===0)return;await g(l,d,s=>s())}catch(e){this.context.logger.warn(`Failed to create data schema entities for Arazzo description: ${e instanceof Error?e.message:"Unknown error"}`)}};#a=async({schemaName:t,schema:i,description:a,parentKey:h,parentVersion:r,parentRevision:o,rbacTeams:n})=>{const e={type:"data-schema",key:`${h}-${m(t)}`,title:t,summary:i.description||i.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:r};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:e,sourceFile:a.realRelativePath,fileHash:a.hash,revision:o,rbacTeams:n})};#r=async(t,i,a,h,r,o,n)=>{const e=t.document.workflows||[];if(e.length===0)return;const c=new Set;for(const l of e)for(const s of l.steps||[]){if(!s.operationId)continue;const p=s.operationId.startsWith(`${i}.`)?s.operationId.substring(`${i}.`.length):s.operationId;p&&c.add(p)}c.size!==0&&await g(Array.from(c),d,async l=>{try{const s=`${r}-${m(l)}`;await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:h,type:"uses",targetKey:s,fileHash:t.hash,sourceVersion:o,targetVersion:o,sourceRevision:n,targetRevision:n})}catch(s){this.context.logger.warn(`Failed to create relation to operation "${l}": ${s instanceof Error?s.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,i){try{const a=t.trim(),h=a.startsWith("@")?a.slice(1):a,[r]=h.split("#");if(r.startsWith("http://")||r.startsWith("https://"))return null;if(r.startsWith("/"))return f(y.posix.normalize(r));const o=y.posix.dirname(i);return r.startsWith(o+"/")?y.posix.normalize(r):y.posix.normalize(y.posix.join(o,r))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{D as ArazzoEntitiesExtractor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{removeLeadingSlash as
|
|
1
|
+
import{removeLeadingSlash as d}from"@redocly/theme/core/utils";import{toKebabCase as m}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{removeMarkdocTags as R}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";import{extractPartsFromComponentsRef as f}from"../../../utils/extract-parts-from-components-ref.js";import{extractPartsFromChannelsMessageRef as w}from"../../../utils/extract-parts-from-channels-message-ref.js";const u=15;class N extends E{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,a){const s=d(e.realRelativePath),r=e.document.info.title,t=s.replace(/\.[^.]+$/,""),n=m(t.replace(/[\\/]/g,"-")),c=e.document["x-redocly-catalog-key"],o=typeof c=="string"&&c.trim()?m(c.trim()):n;return{type:this.type,key:o,title:r,summary:R(e.document.info.description),tags:e.document.info.tags?.map(i=>i.name),metadata:{specType:this.specType,descriptionFile:s},version:a}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,a,s,r){const t=this.getRbacTeamsForDefinition(e.relativePath),n=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:n,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,revision:a,rbacTeams:t}),r.delete(`${n.key}:${s}`);const c=this.#a(e),[o,i]=await Promise.allSettled([this.#s(e,n.key,n.version,s,a,r,t),this.#r(c,e,n.key,n.version,s,a,r,t)]);o.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",o.reason),i.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",i.reason)}#a=e=>{const a=e.documentWithReferences.operations;return a?Object.entries(a).map(([s,r])=>({operationName:s,operation:r})):[]};#s=async(e,a,s,r,t,n,c)=>{const o=e.document.components?.schemas;if(!o)return;const i=Object.entries(o);if(i.length===0)return;const l=await $(i,u,async([h,y])=>{const g=await this.#n({schemaName:h,schema:y,description:e,parentKey:a,parentVersion:s,parentRevision:t,rbacTeams:c});n.delete(`${g.entityKey}:${r}`),g.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:g.entityKey,fileHash:e.hash,sourceVersion:s,targetVersion:s,sourceRevision:t,targetRevision:t})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${i.length} schemas for ${e.realRelativePath}`)};#n=async({schemaName:e,schema:a,description:s,parentKey:r,parentVersion:t,parentRevision:n,rbacTeams:c})=>{const o=`${r}-${m(e)}`,i="title"in a?a.title??a.description:null,l=JSON.stringify(a),h={type:"data-schema",key:o,title:e,summary:i,tags:[],metadata:{specType:this.specType,schema:l},version:t};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:h,sourceFile:s.realRelativePath,fileHash:s.hash,revision:n,rbacTeams:c})};#r=async(e,a,s,r,t,n,c,o)=>{if(!e.length)return;const i=await $(e,u,async({operationName:l,operation:h})=>{const y=await this.#c(h,l,a,s,r,n,o);y&&c.delete(`${y}:${t}`)},this.context.logger);i.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${i.count.failed} failures out of ${e.length} operations for ${a.realRelativePath}`)};#c=async(e,a,s,r,t,n,c)=>{const o=await this.#o(e.messages??[],s,r),i=await this.#i(a,e,o,s,r,t,n,c);return i.result==="created"&&await this.#l({apiOperationKey:i.entityKey,operation:e,descriptionUniqueKey:r,description:s,descriptionVersion:t,parentRevision:n}),i.entityKey??null};#o=async(e,a,s)=>{if(!e||e.length===0)return[];const r=new Set;for(const t of e){let n=null;if("$ref"in t){const c=t.$ref.startsWith("#/channels/")?this.#e(t.$ref,a):t.$ref;if(c){const o=f(c);if(o?.componentName&&o.componentType==="messages"){const i=a.documentWithReferences.components?.messages[o.componentName];i?.payload&&"$ref"in i.payload&&i.payload.$ref&&(n=i.payload.$ref)}}}else t.payload&&"$ref"in t.payload&&t.payload.$ref&&(n=t.payload.$ref);if(n){const c=f(n);c?.componentName&&c.componentType==="schemas"&&r.add(`${s}-${m(c.componentName)}`)}}return Array.from(r)};#i=async(e,a,s,r,t,n,c,o)=>{const i={type:"api-operation",key:`${t}-${m(e)}`,title:a.title||e,summary:a.summary??"",tags:a.tags?.map(h=>h.name)??[],metadata:{method:a.action==="send"?"PUBLISH":"SUBSCRIBE",path:a.channel.address??"",payload:a.action==="receive"?s:[],responses:a.action==="send"?s:[]},version:n};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:i,sourceFile:r.realRelativePath,fileHash:r.hash,revision:c,rbacTeams:o})};#l=async({apiOperationKey:e,operation:a,descriptionUniqueKey:s,description:r,descriptionVersion:t,parentRevision:n})=>(await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"partOf",targetKey:s,fileHash:r.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),await this.#h(a,e,t,n),!Array.isArray(a.messages)||!a.messages?.length?[]:await this.#m(a.messages,e,r,s,t,n));#h=async(e,a,s,r)=>{e["x-catalog-relations"]?.length&&await p(e["x-catalog-relations"],u,async t=>{try{this.validateEntityRelationFileSchema(t),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:t.type,targetKey:t.key,sourceVersion:s,targetVersion:"",sourceRevision:r,targetRevision:""})}catch(n){this.context.logger.warn(`Error creating entity relation for operation ${a} based on custom property: ${n instanceof Error?n.message:"Unknown error"}`)}})};#m=async(e,a,s,r,t,n)=>e.length===0?[]:(await p(e,u,async o=>await this.#y(o,a,s,r,t,n)??"")).filter(o=>!!o);#y=async(e,a,s,r,t,n)=>"$ref"in e?this.#f(e,a,s,r,t,n):e.payload?this.#u(e,a,s,r,t,n):null;#f=async(e,a,s,r,t,n)=>{const c=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,s):e.$ref;if(!c)return null;const o=f(c);if(!o||!o.componentName||o.componentType!=="messages")return null;const i=s.documentWithReferences.components?.messages[o.componentName];return!i?.payload||!("$ref"in i.payload)||!i.payload.$ref?null:this.#t(i.payload.$ref,a,s,r,t,n)};#e=(e,a)=>{const s=w(e);if(!s||!s.channelName||!s.messageName)return null;const r=a.documentWithReferences.channels?.[s.channelName];if(!r?.messages)return null;const t=r.messages[s.messageName];return!t||!("$ref"in t)||typeof t.$ref!="string"||!t.$ref.startsWith("#/components/messages/")?null:t.$ref};#u=async(e,a,s,r,t,n)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,a,s,r,t,n);#t=async(e,a,s,r,t,n)=>{const c=f(e);if(!c||!c.componentName||c.componentType!=="schemas")return null;const o=`${r}-${m(c.componentName)}`;return await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:o,fileHash:s.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),o}}export{N as AsyncApiEntitiesExtractor};
|
package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type EntityFileSchema } from '@redocly/config';
|
|
2
|
+
import type { AfterRoutesCreatedActions, FileInfo, LifecycleContext } from '../../../../../types';
|
|
2
3
|
import type { CatalogEntitiesService } from '../../../database/catalog-entities-service.js';
|
|
3
|
-
import type { EntityFileSchema } from '@redocly/config';
|
|
4
4
|
import type { BaseEntitiesExtractor } from '../base';
|
|
5
5
|
import type { FileType } from '../../../../../persistence/file-hashes/types.js';
|
|
6
6
|
import type { HashManager } from '../../../utils/hash-manager.js';
|
|
@@ -10,15 +10,17 @@ export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition exte
|
|
|
10
10
|
protected type: "api-description";
|
|
11
11
|
protected specType: SpecType;
|
|
12
12
|
protected fileType: FileType;
|
|
13
|
-
protected actions:
|
|
13
|
+
protected actions: AfterRoutesCreatedActions;
|
|
14
14
|
protected context: LifecycleContext;
|
|
15
15
|
protected catalogEntitiesService: CatalogEntitiesService;
|
|
16
16
|
protected fileHashManager: HashManager;
|
|
17
17
|
protected entitySources: Record<string, string>;
|
|
18
18
|
constructor(specType: SpecType, params: BaseApiEntitiesExtractorParams);
|
|
19
19
|
extract(): Promise<void>;
|
|
20
|
+
protected validateEntityRelationFileSchema(relation: unknown): void;
|
|
21
|
+
protected getRbacTeamsForDefinition(relativePath: string): string[];
|
|
20
22
|
protected abstract loadApiDescriptions(): Promise<BundledApiDefinition[]>;
|
|
21
|
-
protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string): EntityFileSchema;
|
|
23
|
+
protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string, rbacTeams: string[]): EntityFileSchema;
|
|
22
24
|
protected abstract processApiDescription(definition: BundledApiDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
|
|
23
25
|
}
|
|
24
26
|
//# sourceMappingURL=base.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FileHashStatus as c}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as
|
|
1
|
+
import{entityRelationFileSchema as g}from"@redocly/config";import{FileHashStatus as c}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{OPERATORS as u}from"../../../../../providers/database/pagination/constants.js";import{VERSION_NOT_SPECIFIED as p}from"@redocly/theme/core/constants";import{getRbacTeamsListForResource as v}from"../../../../../utils/rbac.js";import{envConfig as h}from"../../../../../../config/env-config.js";import{resolveEntityVersion as y}from"../../../utils/resolve-entity-version.js";import{catalogDataCollector as f}from"../../../utils/catalog-data-collector.js";import{createValidator as d}from"../../../utils/ajv-validator.js";const R=3;class x{type="api-description";specType;fileType;actions;context;catalogEntitiesService;fileHashManager;entitySources={};#e;constructor(t,e){this.specType=t,this.fileType=e.fileType,this.actions=e.actions,this.context=e.context,this.catalogEntitiesService=e.catalogEntitiesService,this.fileHashManager=e.fileHashManager,this.#e=e.shouldCalculateEntities??!1}async extract(){const t=await this.loadApiDescriptions();await this.fileHashManager.markAllAsOutdated(this.fileType),t.length&&f.addExtractor(this.specType),await m(t,R,async e=>{try{if(e.isVirtual||!e.hash)return;if(!((await this.fileHashManager.getByPath(e.realRelativePath))?.hash!==e.hash||this.#e||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")){f.increaseSkippedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,c.UP_TO_DATE);return}const a=await this.catalogEntitiesService.getEntityKeysAndVersionsBySourceFile(e.realRelativePath);h.FORCE_CATALOG_CACHE_REVALIDATE==="true"&&(await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:Array.from(a).map(o=>o.split(":")[0])}),a.clear());const s=new Date().toISOString(),n=this.#a(e);await this.processApiDescription(e,s,n,a),await this.#i(a,e.realRelativePath,s,e.hash),f.increaseProcessedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,c.UP_TO_DATE)}catch(i){this.context.logger.warn(`Error extracting entities from ${this.specType} description: ${e.realRelativePath}`),this.context.logger.warn(i)}}),await this.#t()}#t=async()=>{const t=await this.fileHashManager.getAllOutdated(this.fileType);if(!t||t.length===0)return;const e=await this.catalogEntitiesService.getEntities({paginationParams:{limit:1e3,filter:{op:"AND",conditions:[{field:"source_file",operator:"in",value:t.map(({filePath:i})=>i)},{field:"is_current",operator:"equal",value:!0}]}}});e&&e.items.length>0&&await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:e.items.map(({key:i})=>i)}),await this.fileHashManager.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:this.fileType},{field:"status",operator:"equal",value:c.OUTDATED}]})};#i=async(t,e,i,r)=>{if(t.size===0||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")return;const a=Array.from(t).map(o=>{const[l,E]=o.split(":");return{key:l,version:E}}),s=Array.from(new Set(a.map(({key:o})=>o))),n=a.map(({key:o,version:l})=>({op:u.AND,conditions:[{field:"key",operator:"equal",value:o},{field:"version",operator:"equal",value:l}]}));await this.catalogEntitiesService.softDeleteEntitiesInLocalDatabase({revision:i,fileHash:r,filter:{op:"AND",conditions:[{field:"key",operator:"in",value:s},{op:u.OR,conditions:n},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]}})};#a(t){const e=t.document?.info?.version??t.definition?.info?.version??null,i=y(e,t.realRelativePath);return i.success?i.version??p:p}validateEntityRelationFileSchema(t){d(g,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"})(t)}getRbacTeamsForDefinition(t){const e=this.actions.getConfig().rbac,i=this.actions.getRouteByFsPath(t);return v(i||{fsPath:t},e||{})}}export{x as BaseApiEntitiesExtractor};
|