@redocly/realm 0.129.0-next.5 → 0.129.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +58 -1
  2. package/dist/constants/common.d.ts +1 -0
  3. package/dist/constants/common.js +1 -1
  4. package/dist/server/plugins/catalog-entities/database/constants/relation-normalization.d.ts +3 -0
  5. package/dist/server/plugins/catalog-entities/database/constants/relation-normalization.js +1 -0
  6. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-db-record-from-dto.js +1 -1
  7. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-db-record-from-file-schema.js +1 -1
  8. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.d.ts +14 -0
  9. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +112 -0
  10. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +12 -130
  11. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
  12. package/dist/server/plugins/catalog-entities/utils/normalize-relation.d.ts +77 -0
  13. package/dist/server/plugins/catalog-entities/utils/normalize-relation.js +1 -0
  14. package/dist/server/plugins/config-parser/format-error.js +13 -5
  15. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  16. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0003_catalog_versions_and_revisions_relations.sql +12 -6
  17. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0004_normalize_relation_types.sql +147 -0
  18. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0004_snapshot.json +392 -0
  19. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/_journal.json +7 -0
  20. package/dist/server/providers/database/databases/sqld-sqlite/migrations/0006_catalog-versions-and-revisions-relations.sql +12 -6
  21. package/dist/server/providers/database/pagination/filter.d.ts +1 -0
  22. package/dist/server/providers/database/pagination/filter.js +1 -1
  23. package/dist/server/web-server/auth.js +2 -2
  24. package/dist/server/web-server/routes/auth.d.ts +1 -0
  25. package/dist/server/web-server/routes/auth.js +1 -1
  26. package/dist/server/web-server/routes/index.js +1 -1
  27. package/dist/server/web-server/routes/mcp-oauth.d.ts +10 -0
  28. package/dist/server/web-server/routes/mcp-oauth.js +1 -1
  29. package/dist/server/web-server/utils/get-request-origin.d.ts +3 -0
  30. package/dist/server/web-server/utils/get-request-origin.js +1 -0
  31. package/package.json +9 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # @redocly/realm
2
2
 
3
+ ## 0.129.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 13cdd871a0: Added `access` configuration object to group authentication settings (`requiresLogin`, `logoutReturnUrl`, `residency`, `sso`, `rbac`) and `logoutReturnUrl` option to customize post-logout redirect URL.
8
+
9
+ Fixed config validation error formatting to handle cases where location source may be undefined or not a proper Source object, preventing errors when formatting validation problems.
10
+
11
+ - ebaff45e00: Added tooltips to items in the API docs overview section.
12
+ - 39c941417d: Added support for OpenAPI 3.2 `dataValue` and `serializedValue`.
13
+ - eb3abbb06e: Added support for OpenAPI 3.2 Sequential and Streaming Data.
14
+ - 8fdaab071f: Added `useColorSwitcher` React hook to receive color mode updates in components.
15
+ - dd42fb73d2: Added support for the `json-example` Markdoc tag to embed JSON snippets in documentation.
16
+ - b28161bbc8: Added product-specific CSS class to the root element for targeted styling by product name.
17
+
18
+ ### Patch Changes
19
+
20
+ - e408a095cf: Fixed a bug where scorecard custom targets did not match.
21
+ - 77452207bf: Fixed an issue where a trailing slash was automatically added to URLs in the **Servers** section of API docs.
22
+ - edb34c5f33: Fixed an issue where breadcrumbs appeared on non-nested pages in projects with a path prefix.
23
+ - 1937581907: Fixed layout shift in `x-tags` with `schemaDefinition`.
24
+ - 93df42565c: Fixed an issue where image assets were incorrectly flagged as broken links in OpenAPI description.
25
+ - b63f469f50: Improved loading of description files for the MCP Docs server.
26
+ - ecc3ea32aa: Fixed an issue where the path prefix was added twice to the login page.
27
+ - 1245fefad6: Fixed an issue where Docs MCP required authentication for publicly available docs.
28
+ - 49ac84d0cb: Fixed a bug that prevented `scorecard` configurations from applying in development mode.
29
+ - 49ddba9c14: Fixed Y-axis scroll position when deep linking to pages with banners.
30
+ - 29a7308fe1: Updated `@redocly/openapi-core` to version `2.14.3`.
31
+ - Updated dependencies [77452207bf]
32
+ - Updated dependencies [ebaff45e00]
33
+ - Updated dependencies [edb34c5f33]
34
+ - Updated dependencies [1937581907]
35
+ - Updated dependencies [4c662c0042]
36
+ - Updated dependencies [39c941417d]
37
+ - Updated dependencies [eb3abbb06e]
38
+ - Updated dependencies [de9da5f277]
39
+ - Updated dependencies [8fdaab071f]
40
+ - Updated dependencies [9f686fedb3]
41
+ - Updated dependencies [b28161bbc8]
42
+ - Updated dependencies [49ddba9c14]
43
+ - Updated dependencies [29a7308fe1]
44
+ - @redocly/openapi-docs@3.17.0
45
+ - @redocly/theme@0.61.0
46
+ - @redocly/portal-plugin-mock-server@0.14.0
47
+ - @redocly/realm-asyncapi-sdk@0.7.0
48
+ - @redocly/asyncapi-docs@1.6.0
49
+ - @redocly/graphql-docs@1.6.0
50
+ - @redocly/portal-legacy-ui@0.12.0
51
+
52
+ ## 0.129.0-next.6
53
+
54
+ ### Minor Changes
55
+
56
+ - 13cdd871a0: Added `access` configuration object to group authentication settings (`requiresLogin`, `logoutReturnUrl`, `residency`, `sso`, `rbac`) and `logoutReturnUrl` option to customize post-logout redirect URL.
57
+
58
+ Fixed config validation error formatting to handle cases where location source may be undefined or not a proper Source object, preventing errors when formatting validation problems.
59
+
3
60
  ## 0.129.0-next.5
4
61
 
5
62
  ### Patch Changes
@@ -72,7 +129,7 @@
72
129
 
73
130
  - 8d09c7d474: Updated `@redocly/openapi-core` to version `2.13.0`.
74
131
  - e408a095cf: Fixed a bug where scorecard custom targets did not match.
75
- - 49ddba9c14: Fixed dismissed banner briefly appearing after page refresh.
132
+ - 49ddba9c14: Fixed an issue where the dismissed banner briefly appeared back after page refresh.
76
133
  - b28161bbc8: Added product-specific CSS class to the root element for targeted styling by product name.
77
134
  - 49ddba9c14: Fixed Y-axis scroll position when deep linking to pages with banners.
78
135
  - Updated dependencies [8d09c7d474]
@@ -54,6 +54,7 @@ export declare const ServerRoutes: {
54
54
  readonly SEARCH: "/_search";
55
55
  readonly SEARCH_FACETS: "/_search-facets";
56
56
  readonly LOGOUT: "/logout";
57
+ readonly POST_LOGOUT: "/post-logout";
57
58
  readonly LOGIN: "/login";
58
59
  readonly IDP_LOGIN: "/_auth/idp-login";
59
60
  readonly INVITE: "/invite/:code";
@@ -1 +1 @@
1
- const E="openapi_docs",n="asyncapi_docs",A="graphql_docs",T="/_spec-gql",O="markdoc",p="tags",i="*",R={"*":"read"},L=["openid","email"],I=1440*60,C="anonymous",l="authenticated",S="**",d="Reunite",N="translations.yaml",P="redocly.yaml",u="@redocly/theme",D="@theme",h="/app-data.json",x="/eject-component",e=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",g=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(o=>o.trim()).filter(Boolean).concat(e):[e];var a;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(a||(a={}));var r;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(r||(r={}));const t="entityKey",c="entityRelationId",U={INFO:"/_info",EJECT_COMPONENT:"/eject-component/:componentName",SHARED_PAGE_DATA:"/page-data/shared/*",PAGE_DATA:"/page-data/*",APP_DATA:"/app-data.json",AUTHORIZATION:"/authorize",OIDC_CALLBACK:"/_auth/oidc",SAML_CALLBACK:"/_auth/saml2",REDOCLY_CALLBACK:"/_auth/redocly",REPLAY_OAUTH2_CALLBACK:"/_auth/replay-oauth2",REDOCLY_LOGIN_CALLBACK:"/_auth/redocly/redocly-login",REDOCLY_TOKEN_LOGIN:"/_auth/redocly-token-login",SEARCH:"/_search",SEARCH_FACETS:"/_search-facets",LOGOUT:"/logout",LOGIN:"/login",IDP_LOGIN:"/_auth/idp-login",INVITE:"/invite/:code",RESOLVE_ROUTE_BY_PATH:"/resolve-route-by-path",RESOLVE_ROUTES_BY_PATHS:"/resolve-routes-by-paths",RESOLVE_ROUTE_BY_SLUG:"/resolve-route-by-slug",GET_ROUTES_BY_LINE:"/get-routes-by-line",FEEDBACK:"/feedback",TELEMETRY:"/_events",OTEL_TRACES:"/_otel/v1/traces",HEALTH:"/_health",ASK_AI:"/_ask-ai",CATALOG_ENTITIES:`/catalog-entities/:${t}?`,CATALOG_ENTITIES_RELATIONS:`/catalog-entities-relations/:${c}?`,BFF_CATALOG_ENTITIES:`/bff/catalog-entities/:${t}?`,BFF_CATALOG_RELATED_ENTITIES:`/bff/catalog-related-entities/:${t}`,BFF_CATALOG_REVISIONS:`/bff/catalog-revisions/:${t}`,MCP_OAUTH_AUTHORIZATION_SERVER:"/.well-known/oauth-authorization-server",MCP_OAUTH_PROTECTED_RESOURCE:"/.well-known/oauth-protected-resource/mcp",MCP_DYNAMIC_CLIENT_REGISTRATION:"/_mcp/register",MCP_AUTHORIZATION:"/_mcp/oauth2/auth",MCP_TOKEN_PORTAL:"/_mcp/oauth2/token-portal",MCP_CALLBACK:"/_mcp/oauth/callback",SCORECARDS:"/scorecards"};var _;(function(o){o.AI_SEARCH="aiSearch"})(_||(_={}));const m="/login",M="/invite",G={AUTH0_PASS:"/auth/auth0-pass"},b={NotExist:"ENOENT"},H="default_locale",v="sidebar-",F="PUBLIC_",y=["BROKEN_LINK","MARKDOC","RESOLVE"],B=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],s="redocly_category",k="redocly_product",f="redocly_version",K="redocly_teams",V=s,Y={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",mcp:"mcp",banner:"banner"};export{g as ALLOWED_CORS_ORIGINS,n as ASYNC_API_DOCS_TEMPLATE_ID,t as CATALOG_ENTITY_KEY,c as CATALOG_ENTITY_RELATION_ID,P as CONFIG_FILE_NAME,O as CUSTOM_MARKDOC_OPTIONS_PATH,p as CUSTOM_MARKDOC_TAGS_PATH,C as DEFAULT_ANONYMOUS_VISITOR_TEAM,l as DEFAULT_AUTHENTICATED_TEAM,I as DEFAULT_COOKIE_EXPIRATION,H as DEFAULT_LOCALE_PLACEHOLDER,S as DEFAULT_RBAC_SCOPE,d as DEFAULT_SSO_IDP_TITLE,u as DEFAULT_THEME_NAME,m as DEV_LOGIN_SLUG,x as EJECT_COMPONENT_URL,G as ExternalRoutes,Y as FEATURE,r as FEEDBACK_TYPES,b as FsErrors,h as GLOBAL_DATA_URL,T as GRAPHQL_SPEC_SLUG,A as GRAPHQL_TEMPLATE_ID,M as INVITE_SLUG,y as MARKDOC_ERROR_TYPES,E as OPENAPI_DOCS_TEMPLATE_ID,F as PUBLIC_ENV_PREFIX,R as PUBLIC_RBAC_SCOPE_ITEM,i as RBAC_ALL_OTHER_TEAMS,L as REQUIRED_OIDC_SCOPES,_ as RbacFeatures,s as SEARCH_CATEGORY_FIELD,V as SEARCH_GROUP_FACET_FIELD,k as SEARCH_PRODUCT_FIELD,K as SEARCH_RBAC_FIELD,f as SEARCH_VERSION_FIELD,e as SERVER_EDITOR_APP_URL,v as SIDEBAR_PREFIX,U as ServerRoutes,N as TRANSLATIONS_FILE_NAME,B as UI_ACCESSIBLE_CONFIG_PROPS,D as USER_THEME_ALIAS,a as cliCommandNames};
1
+ const E="openapi_docs",n="asyncapi_docs",A="graphql_docs",T="/_spec-gql",O="markdoc",p="tags",i="*",R={"*":"read"},L=["openid","email"],I=1440*60,C="anonymous",l="authenticated",S="**",d="Reunite",N="translations.yaml",P="redocly.yaml",u="@redocly/theme",D="@theme",h="/app-data.json",x="/eject-component",e=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",g=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(o=>o.trim()).filter(Boolean).concat(e):[e];var a;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(a||(a={}));var r;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(r||(r={}));const t="entityKey",c="entityRelationId",U={INFO:"/_info",EJECT_COMPONENT:"/eject-component/:componentName",SHARED_PAGE_DATA:"/page-data/shared/*",PAGE_DATA:"/page-data/*",APP_DATA:"/app-data.json",AUTHORIZATION:"/authorize",OIDC_CALLBACK:"/_auth/oidc",SAML_CALLBACK:"/_auth/saml2",REDOCLY_CALLBACK:"/_auth/redocly",REPLAY_OAUTH2_CALLBACK:"/_auth/replay-oauth2",REDOCLY_LOGIN_CALLBACK:"/_auth/redocly/redocly-login",REDOCLY_TOKEN_LOGIN:"/_auth/redocly-token-login",SEARCH:"/_search",SEARCH_FACETS:"/_search-facets",LOGOUT:"/logout",POST_LOGOUT:"/post-logout",LOGIN:"/login",IDP_LOGIN:"/_auth/idp-login",INVITE:"/invite/:code",RESOLVE_ROUTE_BY_PATH:"/resolve-route-by-path",RESOLVE_ROUTES_BY_PATHS:"/resolve-routes-by-paths",RESOLVE_ROUTE_BY_SLUG:"/resolve-route-by-slug",GET_ROUTES_BY_LINE:"/get-routes-by-line",FEEDBACK:"/feedback",TELEMETRY:"/_events",OTEL_TRACES:"/_otel/v1/traces",HEALTH:"/_health",ASK_AI:"/_ask-ai",CATALOG_ENTITIES:`/catalog-entities/:${t}?`,CATALOG_ENTITIES_RELATIONS:`/catalog-entities-relations/:${c}?`,BFF_CATALOG_ENTITIES:`/bff/catalog-entities/:${t}?`,BFF_CATALOG_RELATED_ENTITIES:`/bff/catalog-related-entities/:${t}`,BFF_CATALOG_REVISIONS:`/bff/catalog-revisions/:${t}`,MCP_OAUTH_AUTHORIZATION_SERVER:"/.well-known/oauth-authorization-server",MCP_OAUTH_PROTECTED_RESOURCE:"/.well-known/oauth-protected-resource/mcp",MCP_DYNAMIC_CLIENT_REGISTRATION:"/_mcp/register",MCP_AUTHORIZATION:"/_mcp/oauth2/auth",MCP_TOKEN_PORTAL:"/_mcp/oauth2/token-portal",MCP_CALLBACK:"/_mcp/oauth/callback",SCORECARDS:"/scorecards"};var _;(function(o){o.AI_SEARCH="aiSearch"})(_||(_={}));const m="/login",M="/invite",G={AUTH0_PASS:"/auth/auth0-pass"},b={NotExist:"ENOENT"},H="default_locale",v="sidebar-",F="PUBLIC_",y=["BROKEN_LINK","MARKDOC","RESOLVE"],B=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],s="redocly_category",k="redocly_product",f="redocly_version",K="redocly_teams",V=s,Y={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",mcp:"mcp",banner:"banner"};export{g as ALLOWED_CORS_ORIGINS,n as ASYNC_API_DOCS_TEMPLATE_ID,t as CATALOG_ENTITY_KEY,c as CATALOG_ENTITY_RELATION_ID,P as CONFIG_FILE_NAME,O as CUSTOM_MARKDOC_OPTIONS_PATH,p as CUSTOM_MARKDOC_TAGS_PATH,C as DEFAULT_ANONYMOUS_VISITOR_TEAM,l as DEFAULT_AUTHENTICATED_TEAM,I as DEFAULT_COOKIE_EXPIRATION,H as DEFAULT_LOCALE_PLACEHOLDER,S as DEFAULT_RBAC_SCOPE,d as DEFAULT_SSO_IDP_TITLE,u as DEFAULT_THEME_NAME,m as DEV_LOGIN_SLUG,x as EJECT_COMPONENT_URL,G as ExternalRoutes,Y as FEATURE,r as FEEDBACK_TYPES,b as FsErrors,h as GLOBAL_DATA_URL,T as GRAPHQL_SPEC_SLUG,A as GRAPHQL_TEMPLATE_ID,M as INVITE_SLUG,y as MARKDOC_ERROR_TYPES,E as OPENAPI_DOCS_TEMPLATE_ID,F as PUBLIC_ENV_PREFIX,R as PUBLIC_RBAC_SCOPE_ITEM,i as RBAC_ALL_OTHER_TEAMS,L as REQUIRED_OIDC_SCOPES,_ as RbacFeatures,s as SEARCH_CATEGORY_FIELD,V as SEARCH_GROUP_FACET_FIELD,k as SEARCH_PRODUCT_FIELD,K as SEARCH_RBAC_FIELD,f as SEARCH_VERSION_FIELD,e as SERVER_EDITOR_APP_URL,v as SIDEBAR_PREFIX,U as ServerRoutes,N as TRANSLATIONS_FILE_NAME,B as UI_ACCESSIBLE_CONFIG_PROPS,D as USER_THEME_ALIAS,a as cliCommandNames};
@@ -0,0 +1,3 @@
1
+ import type { EntityRelationType } from '@redocly/theme/core/types';
2
+ export declare const RELATION_NORMALIZATION_MAP: Record<EntityRelationType, EntityRelationType>;
3
+ //# sourceMappingURL=relation-normalization.d.ts.map
@@ -0,0 +1 @@
1
+ const e={owns:"owns",ownedBy:"owns",hasParts:"hasParts",partOf:"hasParts",creates:"creates",createdBy:"creates",implements:"implements",implementedBy:"implements",dependsOn:"dependsOn",dependencyOf:"dependsOn",uses:"uses",usedBy:"uses",extends:"extends",extendedBy:"extends",supersedes:"supersedes",supersededBy:"supersedes",hasMember:"hasMember",memberOf:"hasMember",triggers:"triggers",triggeredBy:"triggers",returns:"returns",returnedBy:"returns",produces:"produces",consumes:"consumes",linksTo:"linksTo",compatibleWith:"compatibleWith",relatesTo:"relatesTo"};export{e as RELATION_NORMALIZATION_MAP};
@@ -1 +1 @@
1
- import{ulid as o}from"ulid";function i(e,r,s){const t=new Date().toISOString();return{id:e.id||`cer_${o()}`,organizationId:r,projectId:s,sourceKey:e.sourceKey,sourceVersion:e.sourceVersion??"",sourceRevision:e.sourceRevision??"",sourceToTargetRelation:e.type,targetKey:e.targetKey,targetVersion:e.targetVersion??"",targetRevision:e.targetRevision??"",targetToSourceRelation:`reverse:${e.type}`,sourceFile:e.sourceFile||null,fileHash:e.fileHash||null,isDeleted:e.isDeleted??!1,createdAt:e.createdAt||t,updatedAt:t}}export{i as createEntityRelationDbRecordFromDto};
1
+ import{ulid as i}from"ulid";import{normalizeRelation as c}from"../../utils/normalize-relation.js";function a(e,o,s){const r=new Date().toISOString(),t=c({type:e.type,sourceKey:e.sourceKey,targetKey:e.targetKey,sourceVersion:e.sourceVersion,targetVersion:e.targetVersion,sourceRevision:e.sourceRevision,targetRevision:e.targetRevision});return{id:e.id||`cer_${i()}`,organizationId:o,projectId:s,sourceKey:t.sourceKey,sourceVersion:t.sourceVersion??"",sourceRevision:t.sourceRevision??"",sourceToTargetRelation:t.type,targetKey:t.targetKey,targetVersion:t.targetVersion??"",targetRevision:t.targetRevision??"",targetToSourceRelation:`reverse:${t.type}`,sourceFile:e.sourceFile||null,fileHash:e.fileHash||null,isDeleted:e.isDeleted??!1,createdAt:e.createdAt||r,updatedAt:r}}export{a as createEntityRelationDbRecordFromDto};
@@ -1 +1 @@
1
- import{ulid as v}from"ulid";function g({relation:e,sourceFile:o,fileHash:n,sourceKey:s,sourceVersion:t,sourceRevision:r,organizationId:c,projectId:d}){const i=new Date().toISOString();return{id:`cer_${v()}`,organizationId:c,projectId:d,sourceKey:s,sourceVersion:t&&e.version?t:"",sourceRevision:r&&e.revision?r:"",sourceToTargetRelation:e.type,targetKey:e.key,targetVersion:t&&e.version?e.version:"",targetRevision:r&&e.revision?e.revision:"",targetToSourceRelation:`reverse:${e.type}`,sourceFile:o,fileHash:n,isDeleted:!1,createdAt:i,updatedAt:i}}export{g as createEntityRelationDbRecordFromFileSchema};
1
+ import{ulid as g}from"ulid";import{normalizeRelation as l}from"../../utils/normalize-relation.js";function R({relation:e,sourceFile:n,fileHash:s,sourceKey:a,sourceVersion:r,sourceRevision:o,organizationId:c,projectId:u}){const i=new Date().toISOString(),t=l({type:e.type,sourceKey:a,targetKey:e.key,sourceVersion:r&&e.version?r:null,targetVersion:r&&e.version?e.version:null,sourceRevision:o&&e.revision?o:null,targetRevision:o&&e.revision?e.revision:null});return{id:`cer_${g()}`,organizationId:c,projectId:u,sourceKey:t.sourceKey,sourceVersion:t.sourceVersion??"",sourceRevision:t.sourceRevision??"",sourceToTargetRelation:t.type,targetKey:t.targetKey,targetVersion:t.targetVersion??"",targetRevision:t.targetRevision??"",targetToSourceRelation:`reverse:${t.type}`,sourceFile:n,fileHash:s,isDeleted:!1,createdAt:i,updatedAt:i}}export{R as createEntityRelationDbRecordFromFileSchema};
@@ -0,0 +1,14 @@
1
+ import type { BffCatalogEntity } from '@redocly/theme/core/types';
2
+ import type { PaginationParams } from '../../../../../providers/database/pagination/schemas.js';
3
+ import type { DatabaseClient } from '../../../../../providers/database/client.js';
4
+ import type { ListResult } from './catalog-entities-local-read-repository.js';
5
+ export declare class CatalogEntitiesBffRepository {
6
+ #private;
7
+ constructor(db: DatabaseClient, attachedDatabasePath: string);
8
+ getEntitiesWithRelations(paginationParams?: PaginationParams): Promise<ListResult<BffCatalogEntity>>;
9
+ getEntityWithRelationsByKey(entityKey: string, filter?: {
10
+ revision?: string | null;
11
+ version?: string | null;
12
+ }): Promise<BffCatalogEntity | null>;
13
+ }
14
+ //# sourceMappingURL=catalog-entities-bff-repository.d.ts.map
@@ -0,0 +1,112 @@
1
+ import{and as c,desc as H,eq as s,notExists as v,sql as e}from"drizzle-orm";import{unionAll as C}from"drizzle-orm/sqlite-core";import{logger as M}from"../../../../../tools/notifiers/logger.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as k}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{applyFilter as q,excludeFieldsFromFilter as j,getAllFilterFieldValues as O}from"../../../../../providers/database/pagination/filter.js";import{createBffEntity as A}from"../../mappers/create-bff-entity.js";import{FIELDS_TO_SELECT_FOR_ENTITY as n,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as $,createEntityFieldsForSelect as W}from"../utils.js";class Z{#e;#t;constructor(t,o){this.#e=t,this.#t=o}async getEntitiesWithRelations(t={}){const o=O(t.filter,"owners");if(o.length>0)return this.#c(t,o);const m=O(t.filter,"domains");return m.length>0?this.#l(t,m):this.#a(t)}async#c(t,o){const m=this.#s(),l=this.#n(),d=this.#o(),y=l.as("combined_relations"),u=d.as("combined_target_entities"),h=o.map(r=>e`
2
+ EXISTS (
3
+ SELECT 1 FROM (${l}) cr
4
+ WHERE cr.source_key = ${r}
5
+ AND cr.source_to_target_relation = 'owns'
6
+ AND cr.target_key = base_entities.key
7
+ )
8
+ `),_=h.length===1?h[0]:e`(${e.join(h,e` OR `)})`,b=O(t.filter,"domains");let w=_;if(b.length>0){const r=b.map(a=>e`
9
+ EXISTS (
10
+ SELECT 1 FROM (${l}) cr
11
+ JOIN (${d}) d ON d.key = ${a}
12
+ WHERE d.type = 'domain'
13
+ AND d.is_current = 1
14
+ AND cr.source_key = ${a}
15
+ AND cr.target_key = base_entities.key
16
+ AND cr.source_to_target_relation = 'hasParts'
17
+ )
18
+ `),f=r.length===1?r[0]:e`(${e.join(r,e` OR `)})`;w=e`(${_} AND ${f})`}const R=j(t.filter,["owners","domains"]),g={...t,filter:R,baseWhereCondition:w},E=this.#e.client.select(n).from(m.as("base_entities")).$dynamic();try{const r=this.#e.client.select(n).from(m.as("base_entities")).$dynamic();S(r,{...g,limit:void 0,skip:void 0,after:void 0,before:void 0});const f=this.#e.client.select({count:e`count(*)`}).from(r.as("count_subquery")),a=t.limit||10;S(E,{...g,limit:a+1});const p=E.as("paged_entities"),N=this.#e.client.with(y,u,p).select({...W("paged_entities"),domains:this.#i("paged_entities").as("domains"),owners:this.#r("paged_entities").as("owners")}).from(p),[F,I]=await Promise.all([N.run(),f.run()]),D=F.rows,L=Number(I.rows[0]?.count||0),Q=D.length>a;return{items:D.slice(0,a).map(T=>A(T)).filter(T=>T!==null),hasMore:Q,total:L}}catch(r){return M.error("Error getting entities with relations (owner optimized path):",r),{items:[],hasMore:!1,total:0}}}async#l(t,o){const m=this.#s(),l=this.#n(),d=this.#o(),y=l.as("combined_relations"),u=d.as("combined_target_entities"),h=o.map(r=>e`
19
+ EXISTS (
20
+ SELECT 1 FROM (${l}) cr
21
+ JOIN (${d}) d ON d.key = ${r}
22
+ WHERE d.type = 'domain'
23
+ AND d.is_current = 1
24
+ AND cr.source_key = ${r}
25
+ AND cr.target_key = base_entities.key
26
+ AND cr.source_to_target_relation = 'hasParts'
27
+ )
28
+ `),_=h.length===1?h[0]:e`(${e.join(h,e` OR `)})`,b=O(t.filter,"owners");let w=_;if(b.length>0){const r=b.map(a=>e`
29
+ EXISTS (
30
+ SELECT 1 FROM (${l}) cr
31
+ WHERE cr.source_key = ${a}
32
+ AND cr.source_to_target_relation = 'owns'
33
+ AND cr.target_key = base_entities.key
34
+ )
35
+ `),f=r.length===1?r[0]:e`(${e.join(r,e` OR `)})`;w=e`(${_} AND ${f})`}const R=j(t.filter,["domains","owners"]),g={...t,filter:R,baseWhereCondition:w},E=this.#e.client.select(n).from(m.as("base_entities")).$dynamic();try{const r=this.#e.client.select(n).from(m.as("base_entities")).$dynamic();S(r,{...g,limit:void 0,skip:void 0,after:void 0,before:void 0});const f=this.#e.client.select({count:e`count(*)`}).from(r.as("count_subquery")),a=t.limit||10;S(E,{...g,limit:a+1});const p=E.as("paged_entities"),N=this.#e.client.with(y,u,p).select({...W("paged_entities"),domains:this.#i("paged_entities").as("domains"),owners:this.#r("paged_entities").as("owners")}).from(p),[F,I]=await Promise.all([N.run(),f.run()]),D=F.rows,L=Number(I.rows[0]?.count||0),Q=D.length>a;return{items:D.slice(0,a).map(T=>A(T)).filter(T=>T!==null),hasMore:Q,total:L}}catch(r){return M.error("Error getting entities with relations (domain optimized path):",r),{items:[],hasMore:!1,total:0}}}async#a(t){const o=this.#s(),m=this.#n(),l=this.#o(),d=m.as("combined_relations"),y=l.as("combined_target_entities"),u=this.#e.client.select(n).from(o.as("base_entities")).$dynamic(),{whereCondition:h}=q(u,t.filter);h&&u.where(h);try{const _=this.#e.client.select(n).from(o.as("base_entities_count")).$dynamic();h&&_.where(h);const b=this.#e.client.select({count:e`count(*)`}).from(_.as("count_subquery")),w=t.limit||10;S(u,{...t,limit:w+1});const R=u.as("paged_entities"),g=this.#e.client.with(d,y,R).select({...W("paged_entities"),domains:this.#i("paged_entities").as("domains"),owners:this.#r("paged_entities").as("owners")}).from(R),[E,r]=await Promise.all([g.run(),b.run()]),f=E.rows,a=Number(r.rows[0]?.count||0),p=f.length>w;return{items:f.slice(0,w).map(N=>A(N)).filter(N=>N!==null),hasMore:p,total:a}}catch(_){return M.error("Error getting entities with relations (optimized path):",_),{items:[],hasMore:!1,total:0}}}#s(){return this.#t?C(this.#e.client.select(n).from(e`remote.entities`).where(c(s(e.raw("is_current"),1),s(e.raw("is_deleted"),!1))),this.#e.client.select(n).from(i).where(c(s(i.isCurrent,!0),s(i.isDeleted,!1),v(this.#e.client.select({id:n.id}).from(e`remote.entities as remote`).where(c(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(n).from(i).where(c(s(i.isCurrent,!0),s(i.isDeleted,!1)))}#n(){return this.#t?C(this.#e.client.select($).from(e`remote.entities_relations`),this.#e.client.select($).from(k).where(v(this.#e.client.select({id:$.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${k.sourceKey}`)))):this.#e.client.select($).from(k)}#o(){return this.#t?C(this.#e.client.select(n).from(e`remote.entities`).where(c(s(e.raw("is_current"),1),s(e.raw("is_deleted"),!1))),this.#e.client.select(n).from(i).where(c(s(i.isCurrent,!0),s(i.isDeleted,!1),v(this.#e.client.select({id:n.id}).from(e`remote.entities as remote`).where(c(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(n).from(i).where(c(s(i.isCurrent,!0),s(i.isDeleted,!1)))}async getEntityWithRelationsByKey(t,o){if(!t||t.trim()==="")return null;const m=o?.revision,l=o?.version,d=m?null:await this.#m(t,l||null),y=l??d?.version,u=m||d?.revision||null,_=(this.#t?C(this.#e.client.select(n).from(e`remote.entities`).where(s(i.key,t)),this.#e.client.select(n).from(i).where(c(s(i.key,t),v(this.#e.client.select({id:n.id}).from(e`remote.entities as remote`).where(e`remote.key = ${i.key}`))))):this.#e.client.select(n).from(i).where(s(i.key,t))).as("e"),w=(this.#t?C(this.#e.client.select($).from(e`remote.entities_relations`),this.#e.client.select($).from(k).where(v(this.#e.client.select({id:$.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${k.sourceKey}`)))):this.#e.client.select($).from(k)).as("combined_relations"),g=(this.#t?C(this.#e.client.select(n).from(e`remote.entities`),this.#e.client.select(n).from(i).where(v(this.#e.client.select({id:n.id}).from(e`remote.entities as remote`).where(e`remote.key = ${i.key}`)))):this.#e.client.select(n).from(i)).as("combined_target_entities"),E=this.#e.client.with(_,w,g).select({...W("e"),domains:this.#i("e").as("domains"),owners:this.#r("e").as("owners")}).from(_).$dynamic();u?E.where(c(s(e.raw("revision"),u),y?s(e.raw("version"),y):void 0)):E.where(s(e.raw("is_current"),1)),E.limit(1);const r=await E.run();if(r.rows.length===0)return null;const f=r.rows[0];return A(f)}async#m(t,o){if(o){const y=await(this.#t?C(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision")}).from(e`remote.entities`).where(c(e`key = ${t}`,e`version = ${o}`)).orderBy(e.raw("revision DESC")),this.#e.client.select({version:i.version,revision:i.revision}).from(i).where(c(s(i.key,t),s(i.version,o),v(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(c(e`remote.key = ${i.key}`,e`remote.version = ${o}`))))).orderBy(H(i.revision))):this.#e.client.select({version:i.version,revision:i.revision}).from(i).where(c(s(i.key,t),s(i.version,o))).orderBy(H(i.revision))).limit(1).run();if(y.rows.length>0){const u=y.rows[0];return{version:u.version||null,revision:u.revision||null}}return null}const l=await(this.#t?C(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision")}).from(e`remote.entities`).where(c(e`key = ${t}`,e`is_current = 1`)),this.#e.client.select({version:i.version,revision:i.revision}).from(i).where(c(s(i.key,t),s(i.isCurrent,!0),v(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(c(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select({version:i.version,revision:i.revision}).from(i).where(c(s(i.key,t),s(i.isCurrent,!0)))).limit(1).run();if(l.rows.length>0){const d=l.rows[0];return{version:d.version||null,revision:d.revision||null}}return null}#i(t){return e`
36
+ COALESCE(
37
+ (
38
+ SELECT json_group_array(
39
+ json_object(
40
+ 'id', d.id,
41
+ 'key', d.key,
42
+ 'type', d.type,
43
+ 'title', d.title,
44
+ 'summary', d.summary,
45
+ 'created_at', d.created_at,
46
+ 'updated_at', d.updated_at,
47
+ 'source', d.source,
48
+ 'source_file', d.source_file
49
+ )
50
+ )
51
+ FROM (
52
+ SELECT DISTINCT d.*
53
+ FROM combined_relations er
54
+ JOIN combined_target_entities d ON d.key = er.source_key
55
+ WHERE er.source_to_target_relation = 'hasParts'
56
+ AND er.target_key = ${e.raw(`${t}.key`)}
57
+ AND d.type = 'domain'
58
+ AND d.is_current = 1
59
+ AND CASE
60
+ WHEN ${e.raw(`${t}.version`)} = ''
61
+ THEN er.target_version = ''
62
+ ELSE (er.target_version = ${e.raw(`${t}.version`)} OR er.target_version = '')
63
+ END
64
+ AND CASE
65
+ WHEN ${e.raw(`${t}.revision`)} = ''
66
+ THEN 1 = 1
67
+ ELSE (er.target_revision <= ${e.raw(`${t}.revision`)} OR er.target_revision = '')
68
+ END
69
+ LIMIT 10
70
+ ) d
71
+ ),
72
+ json_array()
73
+ )
74
+ `}#r(t){return e`
75
+ COALESCE(
76
+ (
77
+ SELECT json_group_array(
78
+ json_object(
79
+ 'id', o.id,
80
+ 'key', o.key,
81
+ 'type', o.type,
82
+ 'title', o.title,
83
+ 'summary', o.summary,
84
+ 'created_at', o.created_at,
85
+ 'updated_at', o.updated_at,
86
+ 'source', o.source,
87
+ 'source_file', o.source_file
88
+ )
89
+ )
90
+ FROM (
91
+ SELECT DISTINCT o.*
92
+ FROM combined_relations er
93
+ JOIN combined_target_entities o ON o.key = er.source_key
94
+ WHERE er.source_to_target_relation = 'owns'
95
+ AND er.target_key = ${e.raw(`${t}.key`)}
96
+ AND o.is_current = 1
97
+ AND CASE
98
+ WHEN ${e.raw(`${t}.version`)} = ''
99
+ THEN er.target_version = ''
100
+ ELSE (er.target_version = ${e.raw(`${t}.version`)} OR er.target_version = '')
101
+ END
102
+ AND CASE
103
+ WHEN ${e.raw(`${t}.revision`)} = ''
104
+ THEN 1 = 1
105
+ ELSE (er.target_revision <= ${e.raw(`${t}.revision`)} OR er.target_revision = '')
106
+ END
107
+ LIMIT 10
108
+ ) o
109
+ ),
110
+ json_array()
111
+ )
112
+ `}}export{Z as CatalogEntitiesBffRepository};
@@ -1,4 +1,4 @@
1
- import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as X,sql as e}from"drizzle-orm";import{unionAll as y}from"drizzle-orm/sqlite-core";import{logger as L}from"../../../../../tools/notifiers/logger.js";import{VERSION_NOT_SPECIFIED as O}from"@redocly/theme/core/constants";import{applyPagination as T}from"../../../../../providers/database/pagination/index.js";import{applyFilter as b}from"../../../../../providers/database/pagination/filter.js";import{createBffEntity as F}from"../../mappers/create-bff-entity.js";import{FIELDS_TO_SELECT_FOR_ENTITY as a,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as d,createEntityFieldsForSelect as B}from"../utils.js";import{createEntityReadModel as g}from"../../mappers/create-entity-read-model.js";import{createEntityRelation as H}from"../../mappers/create-entity-relation.js";import{entitiesTable as t}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as h}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{CatalogEntitiesRelationsRepository as W}from"./catalog-entities-relations-repository.js";class ne{#e;#t=void 0;#i;constructor(i){this.#e=i,this.#i=new W(this.#e,"")}async attachDatabase(i){this.#t!==i&&(this.#t=i,await this.#e.client.run(e`ATTACH DATABASE ${i} AS remote`),this.#i=new W(this.#e,i))}async getEntities(i={}){const s=this.#t?y(this.#e.client.select(a).from(e`remote.entities`),this.#e.client.select(a).from(t).where(E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`)))):this.#e.client.select(a).from(t),n=this.#e.client.select(a).from(s.as("combined_entities")),c=this.#e.client.select(a).from(s.as("combined_entities")).$dynamic(),m=T(c,{...i,limit:void 0,skip:void 0,after:void 0,before:void 0}),l=this.#e.client.$count(m),u=n.$dynamic(),_=i.limit||10,f=T(u,{...i,limit:_+1}),[N,k]=await Promise.all([f.run(),l]),S=N.rows,v=S.length>_;return{items:S.slice(0,_).map(w=>g(w)).filter(w=>w!==null),hasMore:v,total:k}}async getEntityKeysAndVersionsBySourceFile(i){const s=this.#t?y(this.#e.client.select({keyVersion:e`key || ':' || COALESCE(version, ${O})`.as("keyVersion")}).from(e`remote.entities`).where(o(e`source_file = ${i}`,e`source = 'file'`,e`key IS NOT NULL`)),this.#e.client.select({keyVersion:e`${t.key} || ':' || COALESCE(${t.version}, ${O})`.as("keyVersion")}).from(t).where(o(r(t.sourceFile,i),r(t.source,"file"),e`${t.key} IS NOT NULL`,E(this.#e.client.select({key:e.raw("key")}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`))))):this.#e.client.select({keyVersion:e`${t.key} || ':' || COALESCE(${t.version}, ${O})`.as("keyVersion")}).from(t).where(o(r(t.sourceFile,i),r(t.source,"file"),Q(t.key))),n=await this.#e.client.selectDistinct({keyVersion:e`combined_keys_versions.keyVersion`}).from(s.as("combined_keys_versions")).run();return new Set(n.rows.map(c=>c.keyVersion))}async listEntityRevisions(i,s){const n=[r(t.key,i),r(t.isDeleted,!1),...s?[r(t.version,s)]:[]],c=this.#t?y(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")}).from(e`remote.entities`).where(o(e`key = ${i}`,s?e`version = ${s}`:void 0)),this.#e.client.select({version:t.version,revision:t.revision,isCurrent:t.isCurrent,createdAt:t.createdAt,updatedAt:t.updatedAt,isDefaultVersion:t.isDefaultVersion}).from(t).where(o(...n,E(this.#e.client.select({version:e.raw("version")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.version = ${t.version}`,e`remote.revision = ${t.revision}`)))))):this.#e.client.select({version:t.version,revision:t.revision,isCurrent:t.isCurrent,createdAt:t.createdAt,updatedAt:t.updatedAt,isDefaultVersion:t.isDefaultVersion}).from(t).where(o(...n));return(await this.#e.client.select({version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")}).from(c.as("combined_revisions")).orderBy(e.raw("is_current DESC"),e.raw("updated_at DESC"),e.raw("created_at DESC")).run()).rows.map(l=>({version:l.version||null,revision:l.revision??"",isCurrent:l.is_current!==null?!!l.is_current:!1,createdAt:l.created_at||null,updatedAt:l.updated_at||null,isDefaultVersion:l.is_default_version!==null?!!l.is_default_version:!1}))}async getEntitiesCountByTypes(){const i=this.#t?y(this.#e.client.select({type:e`type`}).from(e`remote.entities`).where(o(r(e.raw("is_current"),1),r(e.raw("is_deleted"),!1))),this.#e.client.select({type:t.type}).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1),E(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select({type:t.type}).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1)));return this.#e.client.select({type:t.type,count:V()}).from(i.as("combined_entities")).groupBy(t.type).where(r(t.isDeleted,!1))}async getEntityByKey(i){const c=(await(this.#t?y(this.#e.client.select(a).from(e`remote.entities`).where(o(r(t.key,i),r(e.raw("is_current"),1),r(e.raw("is_deleted"),!1))),this.#e.client.select(a).from(t).where(o(r(t.key,i),r(t.isCurrent,!0),r(t.isDeleted,!1),E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(a).from(t).where(o(r(t.key,i),r(t.isCurrent,!0),r(t.isDeleted,!1)))).run()).rows[0];return c?g(c):null}async getOneOutdatedEntity(){const i=this.#t?y(this.#e.client.select(a).from(e`remote.entities`),this.#e.client.select(a).from(t).where(E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`)))):this.#e.client.select(a).from(t),n=(await this.#e.client.select(a).from(i.as("combined_entities")).where(X(e`combined_entities.scorecards_status = 'OUTDATED'`,e`combined_entities.scorecards_status IS NULL`)).orderBy(e`combined_entities.updated_at ASC`).limit(1).run()).rows[0];return n?g(n):null}async getEntitiesRelations(i={}){const s=this.#t?y(this.#e.client.select(d).from(e`remote.entities_relations`),this.#e.client.select(d).from(h).where(E(this.#e.client.select({id:d.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${h.sourceKey}`)))):this.#e.client.select(d).from(h),n=this.#e.client.select(d).from(s.as("combined_entities_relations")).$dynamic(),c=this.#e.client.select(d).from(s.as("combined_entities_relations")).$dynamic(),m=T(c,{...i,limit:void 0,skip:void 0,after:void 0,before:void 0}),l=this.#e.client.$count(m),u=i.limit||10,_=T(n,{...i,limit:u+1}),[f,N]=await Promise.all([_.run(),l]),k=f.rows,S=k.length>u;return{items:k.slice(0,u).map(v=>H(v)).filter(v=>v!==null),hasMore:S,total:N}}async getEntityRelationById(i){const c=(await(this.#t?y(this.#e.client.select(d).from(e`remote.entities_relations`).where(r(h.id,i)),this.#e.client.select(d).from(h).where(o(r(h.id,i),E(this.#e.client.select({id:d.id}).from(e`remote.entities_relations as remote`).where(e`remote.id = ${h.id}`))))):this.#e.client.select(d).from(h).where(r(h.id,i))).run()).rows[0];return c?H(c):null}async getEntitiesWithRelations(i={}){const n=(this.#t?y(this.#e.client.select(a).from(e`remote.entities`).where(o(r(e.raw("is_current"),1),r(e.raw("is_deleted"),!1))),this.#e.client.select(a).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1),E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(a).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1)))).as("e"),m=(this.#t?y(this.#e.client.select(d).from(e`remote.entities_relations`),this.#e.client.select(d).from(h).where(E(this.#e.client.select({id:d.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${h.sourceKey}`)))):this.#e.client.select(d).from(h)).as("combined_relations"),u=(this.#t?y(this.#e.client.select(a).from(e`remote.entities`).where(o(r(e.raw("is_current"),1),r(e.raw("is_deleted"),!1))),this.#e.client.select(a).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1),E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(a).from(t).where(o(r(t.isCurrent,!0),r(t.isDeleted,!1)))).as("combined_target_entities"),_=this.#e.client.with(n,m,u).select({...B("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(n).as("entities_with_relations"),f={...a,domains:_.domains,owners:_.owners},N=this.#e.client.with(_).select(f).from(_).$dynamic(),k=this.#e.client.with(_).select(f).from(_).$dynamic(),{whereCondition:S}=b(N,i.filter);S&&N.where(S);const{whereCondition:v}=b(k,i.filter);v&&k.where(v);try{const w=T(k,{...i,limit:void 0,skip:void 0,after:void 0,before:void 0}),p=this.#e.client.$count(w),R=i.limit||10,A=T(N,{...i,limit:R+1}),[M,U]=await Promise.all([A.run(),p]),D=M.rows,q=D.length>R;return{items:D.slice(0,R).map(C=>F(C)).filter(C=>C!==null),hasMore:q,total:U}}catch(w){return L.error("Error getting entities with relations:",w),{items:[],hasMore:!1,total:0}}}async#n(i,s){if(s){const l=await(this.#t?y(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision")}).from(e`remote.entities`).where(o(e`key = ${i}`,e`version = ${s}`)).orderBy(e.raw("revision DESC")),this.#e.client.select({version:t.version,revision:t.revision}).from(t).where(o(r(t.key,i),r(t.version,s),E(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.version = ${s}`))))).orderBy(I(t.revision))):this.#e.client.select({version:t.version,revision:t.revision}).from(t).where(o(r(t.key,i),r(t.version,s))).orderBy(I(t.revision))).limit(1).run();if(l.rows.length>0){const u=l.rows[0];return{version:u.version||null,revision:u.revision||null}}return null}const c=await(this.#t?y(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision")}).from(e`remote.entities`).where(o(e`key = ${i}`,e`is_current = 1`)),this.#e.client.select({version:t.version,revision:t.revision}).from(t).where(o(r(t.key,i),r(t.isCurrent,!0),E(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select({version:t.version,revision:t.revision}).from(t).where(o(r(t.key,i),r(t.isCurrent,!0)))).limit(1).run();if(c.rows.length>0){const m=c.rows[0];return{version:m.version||null,revision:m.revision||null}}return null}async getEntityWithRelationsByKey(i,s){const n=s?.revision,c=s?.version,m=n?null:await this.#n(i,c||null),l=c??m?.version,u=n||m?.revision||null,f=(this.#t?y(this.#e.client.select(a).from(e`remote.entities`).where(r(t.key,i)),this.#e.client.select(a).from(t).where(o(r(t.key,i),E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`))))):this.#e.client.select(a).from(t).where(r(t.key,i))).as("e"),k=(this.#t?y(this.#e.client.select(d).from(e`remote.entities_relations`),this.#e.client.select(d).from(h).where(E(this.#e.client.select({id:d.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${h.sourceKey}`)))):this.#e.client.select(d).from(h)).as("combined_relations"),v=(this.#t?y(this.#e.client.select(a).from(e`remote.entities`),this.#e.client.select(a).from(t).where(E(this.#e.client.select({id:a.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`)))):this.#e.client.select(a).from(t)).as("combined_target_entities"),w=this.#e.client.with(f,k,v).select({...B("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(f).$dynamic();u?w.where(o(r(e.raw("revision"),u),l?r(e.raw("version"),l):void 0)):w.where(r(e.raw("is_current"),1)),w.limit(1);const p=await w.run();if(p.rows.length===0)return null;const R=p.rows[0];return F(R)}async getRelationsForEntity(i,s,n){return this.#i.getRelationsForEntity(i,s,n)}async getRelatedEntities(i,s={}){return this.#i.getRelatedEntities(i,s)}async getCatalogFilters({entitiesTypes:i=[],emptyFilters:s=[]}){if(!s.length)return{};try{return await this.#o(i),(s.includes("domains")||s.includes("owners"))&&await this.#a(),await this.#c(s)}catch(n){return console.error("Error fetching catalog filters:",n),{}}finally{await this.#u()}}async#o(i){if(this.#t?await this.#e.client.run(e`
1
+ import{and as l,count as L,eq as n,isNotNull as v,notExists as E,or as D,sql as e}from"drizzle-orm";import{unionAll as f}from"drizzle-orm/sqlite-core";import{logger as b}from"../../../../../tools/notifiers/logger.js";import{VERSION_NOT_SPECIFIED as R}from"@redocly/theme/core/constants";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{FIELDS_TO_SELECT_FOR_ENTITY as c,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as m}from"../utils.js";import{createEntityReadModel as O}from"../../mappers/create-entity-read-model.js";import{createEntityRelation as C}from"../../mappers/create-entity-relation.js";import{entitiesTable as t}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as y}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{CatalogEntitiesRelationsRepository as I}from"./catalog-entities-relations-repository.js";import{CatalogEntitiesBffRepository as g}from"./catalog-entities-bff-repository.js";class j{#e;#t=void 0;#i;#s;constructor(i){this.#e=i,this.#i=new I(this.#e,this.#t||""),this.#s=new g(this.#e,this.#t||"")}async attachDatabase(i){this.#t!==i&&(this.#t=i,await this.#e.client.run(e`ATTACH DATABASE ${i} AS remote`),this.#i=new I(this.#e,i),this.#s=new g(this.#e,i))}async getEntities(i={}){const s=this.#t?f(this.#e.client.select(c).from(e`remote.entities`),this.#e.client.select(c).from(t).where(E(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`)))):this.#e.client.select(c).from(t),r=this.#e.client.select(c).from(s.as("combined_entities")),o=this.#e.client.select(c).from(s.as("combined_entities")).$dynamic(),_=S(o,{...i,limit:void 0,skip:void 0,after:void 0,before:void 0}),a=this.#e.client.$count(_),u=r.$dynamic(),d=i.limit||10,h=S(u,{...i,limit:d+1}),[T,N]=await Promise.all([h.run(),a]),p=T.rows,w=p.length>d;return{items:p.slice(0,d).map(k=>O(k)).filter(k=>k!==null),hasMore:w,total:N}}async getEntityKeysAndVersionsBySourceFile(i){const s=this.#t?f(this.#e.client.select({keyVersion:e`key || ':' || COALESCE(version, ${R})`.as("keyVersion")}).from(e`remote.entities`).where(l(e`source_file = ${i}`,e`source = 'file'`,e`key IS NOT NULL`)),this.#e.client.select({keyVersion:e`${t.key} || ':' || COALESCE(${t.version}, ${R})`.as("keyVersion")}).from(t).where(l(n(t.sourceFile,i),n(t.source,"file"),e`${t.key} IS NOT NULL`,E(this.#e.client.select({key:e.raw("key")}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`))))):this.#e.client.select({keyVersion:e`${t.key} || ':' || COALESCE(${t.version}, ${R})`.as("keyVersion")}).from(t).where(l(n(t.sourceFile,i),n(t.source,"file"),v(t.key))),r=await this.#e.client.selectDistinct({keyVersion:e`combined_keys_versions.keyVersion`}).from(s.as("combined_keys_versions")).run();return new Set(r.rows.map(o=>o.keyVersion))}async listEntityRevisions(i,s){const r=[n(t.key,i),n(t.isDeleted,!1),...s?[n(t.version,s)]:[]],o=this.#t?f(this.#e.client.select({version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")}).from(e`remote.entities`).where(l(e`key = ${i}`,s?e`version = ${s}`:void 0)),this.#e.client.select({version:t.version,revision:t.revision,isCurrent:t.isCurrent,createdAt:t.createdAt,updatedAt:t.updatedAt,isDefaultVersion:t.isDefaultVersion}).from(t).where(l(...r,E(this.#e.client.select({version:e.raw("version")}).from(e`remote.entities as remote`).where(l(e`remote.key = ${t.key}`,e`remote.version = ${t.version}`,e`remote.revision = ${t.revision}`)))))):this.#e.client.select({version:t.version,revision:t.revision,isCurrent:t.isCurrent,createdAt:t.createdAt,updatedAt:t.updatedAt,isDefaultVersion:t.isDefaultVersion}).from(t).where(l(...r));return(await this.#e.client.select({version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")}).from(o.as("combined_revisions")).orderBy(e.raw("is_current DESC"),e.raw("updated_at DESC"),e.raw("created_at DESC")).run()).rows.map(a=>({version:a.version||null,revision:a.revision??"",isCurrent:a.is_current!==null?!!a.is_current:!1,createdAt:a.created_at||null,updatedAt:a.updated_at||null,isDefaultVersion:a.is_default_version!==null?!!a.is_default_version:!1}))}async getEntitiesCountByTypes(){const i=this.#t?f(this.#e.client.select({type:e`type`}).from(e`remote.entities`).where(l(n(e.raw("is_current"),1),n(e.raw("is_deleted"),!1))),this.#e.client.select({type:t.type}).from(t).where(l(n(t.isCurrent,!0),n(t.isDeleted,!1),E(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as remote`).where(l(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select({type:t.type}).from(t).where(l(n(t.isCurrent,!0),n(t.isDeleted,!1)));return this.#e.client.select({type:t.type,count:L()}).from(i.as("combined_entities")).groupBy(t.type).where(n(t.isDeleted,!1))}async getEntityByKey(i){const o=(await(this.#t?f(this.#e.client.select(c).from(e`remote.entities`).where(l(n(t.key,i),n(e.raw("is_current"),1),n(e.raw("is_deleted"),!1))),this.#e.client.select(c).from(t).where(l(n(t.key,i),n(t.isCurrent,!0),n(t.isDeleted,!1),E(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(l(e`remote.key = ${t.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(t).where(l(n(t.key,i),n(t.isCurrent,!0),n(t.isDeleted,!1)))).run()).rows[0];return o?O(o):null}async getOneOutdatedEntity(){const i=this.#t?f(this.#e.client.select(c).from(e`remote.entities`),this.#e.client.select(c).from(t).where(E(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(e`remote.key = ${t.key}`)))):this.#e.client.select(c).from(t),r=(await this.#e.client.select(c).from(i.as("combined_entities")).where(D(e`combined_entities.scorecards_status = 'OUTDATED'`,e`combined_entities.scorecards_status IS NULL`)).orderBy(e`combined_entities.updated_at ASC`).limit(1).run()).rows[0];return r?O(r):null}async getEntitiesRelations(i={}){const s=this.#t?f(this.#e.client.select(m).from(e`remote.entities_relations`),this.#e.client.select(m).from(y).where(E(this.#e.client.select({id:m.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${y.sourceKey}`)))):this.#e.client.select(m).from(y),r=this.#e.client.select(m).from(s.as("combined_entities_relations")).$dynamic(),o=this.#e.client.select(m).from(s.as("combined_entities_relations")).$dynamic(),_=S(o,{...i,limit:void 0,skip:void 0,after:void 0,before:void 0}),a=this.#e.client.$count(_),u=i.limit||10,d=S(r,{...i,limit:u+1}),[h,T]=await Promise.all([d.run(),a]),N=h.rows,p=N.length>u;return{items:N.slice(0,u).map(w=>C(w)).filter(w=>w!==null),hasMore:p,total:T}}async getEntityRelationById(i){const o=(await(this.#t?f(this.#e.client.select(m).from(e`remote.entities_relations`).where(n(y.id,i)),this.#e.client.select(m).from(y).where(l(n(y.id,i),E(this.#e.client.select({id:m.id}).from(e`remote.entities_relations as remote`).where(e`remote.id = ${y.id}`))))):this.#e.client.select(m).from(y).where(n(y.id,i))).run()).rows[0];return o?C(o):null}async getEntitiesWithRelations(i={}){return this.#s.getEntitiesWithRelations(i)}async getEntityWithRelationsByKey(i,s){return this.#s.getEntityWithRelationsByKey(i,s)}async getRelationsForEntity(i,s,r){return this.#i.getRelationsForEntity(i,s,r)}async getRelatedEntities(i,s={}){return this.#i.getRelatedEntities(i,s)}async getCatalogFilters({entitiesTypes:i=[],emptyFilters:s=[]}){if(!s.length)return{};try{return await this.#r(i),(s.includes("domains")||s.includes("owners"))&&await this.#n(),await this.#o(s)}catch(r){return console.error("Error fetching catalog filters:",r),{}}finally{await this.#l()}}async#r(i){if(this.#t?await this.#e.client.run(e`
2
2
  CREATE TEMP TABLE IF NOT EXISTS temp_combined_entities AS
3
3
  SELECT
4
4
  e.key,
@@ -25,7 +25,7 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
25
25
  metadata
26
26
  FROM entities
27
27
  WHERE is_current = 1
28
- `),i.length){const s=i.map(n=>`'${n.replace(/'/g,"''")}'`).join(",");await this.#e.client.run(e.raw(`
28
+ `),i.length){const s=i.map(r=>`'${r.replace(/'/g,"''")}'`).join(",");await this.#e.client.run(e.raw(`
29
29
  CREATE TEMP TABLE IF NOT EXISTS temp_filtered_entities AS
30
30
  SELECT * FROM temp_combined_entities
31
31
  WHERE type IN (${s})
@@ -34,7 +34,7 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
34
34
  SELECT * FROM temp_combined_entities
35
35
  `);await this.#e.client.run(e`
36
36
  CREATE INDEX IF NOT EXISTS idx_temp_filtered_type ON temp_filtered_entities(type)
37
- `)}async#a(){this.#t?await this.#e.client.run(e`
37
+ `)}async#n(){this.#t?await this.#e.client.run(e`
38
38
  CREATE TEMP TABLE IF NOT EXISTS temp_combined_relations AS
39
39
  SELECT
40
40
  source_key,
@@ -62,12 +62,12 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
62
62
  CREATE INDEX IF NOT EXISTS idx_temp_rel_target ON temp_combined_relations(target_key)
63
63
  `),await this.#e.client.run(e`
64
64
  CREATE INDEX IF NOT EXISTS idx_temp_rel_relation ON temp_combined_relations(source_to_target_relation)
65
- `)}async#c(i){const s={},n=[],c=i.filter(u=>u.startsWith("metadata."));i.includes("type")&&n.push(`
65
+ `)}async#o(i){const s={},r=[],o=i.filter(u=>u.startsWith("metadata."));i.includes("type")&&r.push(`
66
66
  SELECT 'type' as filter_name, type as value, COUNT(*) as count
67
67
  FROM temp_filtered_entities
68
68
  WHERE type IS NOT NULL
69
69
  GROUP BY type
70
- `),i.includes("tags")&&n.push(`
70
+ `),i.includes("tags")&&r.push(`
71
71
  SELECT 'tags' as filter_name, tag.value as value, COUNT(DISTINCT tfe.key) as count
72
72
  FROM temp_filtered_entities tfe,
73
73
  json_each(COALESCE(tfe.tags, json_array())) as tag
@@ -76,7 +76,7 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
76
76
  AND tag.value IS NOT NULL
77
77
  AND tag.value != ''
78
78
  GROUP BY tag.value
79
- `),i.includes("domains")&&n.push(`
79
+ `),i.includes("domains")&&r.push(`
80
80
  SELECT 'domains' as filter_name, tce.key as value, COUNT(DISTINCT tfe.key) as count
81
81
  FROM temp_combined_relations tcr
82
82
  INNER JOIN temp_filtered_entities tfe ON (
@@ -89,7 +89,7 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
89
89
  )
90
90
  WHERE tce.type = 'domain'
91
91
  GROUP BY tce.key
92
- `),i.includes("owners")&&n.push(`
92
+ `),i.includes("owners")&&r.push(`
93
93
  SELECT 'owners' as filter_name, owner_key as value, COUNT(DISTINCT entity_key) as count
94
94
  FROM (
95
95
  SELECT
@@ -109,130 +109,12 @@ import{and as o,count as V,desc as I,eq as r,isNotNull as Q,notExists as E,or as
109
109
  INNER JOIN temp_combined_entities tce ON tce.key = owner_key
110
110
  WHERE owner_key IS NOT NULL
111
111
  GROUP BY owner_key
112
- `);for(const u of c)await this.#l(u,s);if(n.length===0)return s;const m=n.join(" UNION ALL "),l=await this.#e.client.run(e.raw(m));if(l?.rows)for(const u of l.rows){const _=u.filter_name,f=u.value,N=Number(u.count)||0;s[_]||(s[_]=[]),f&&s[_].push({value:f,count:N})}return s}async#l(i,s){const n=i.substring(9),c=`$.${j(n)}`,m=await this.#e.client.run(e.raw(`
113
- SELECT json_extract(metadata, '${c}') as value, COUNT(*) as count
112
+ `);for(const u of o)await this.#a(u,s);if(r.length===0)return s;const _=r.join(" UNION ALL "),a=await this.#e.client.run(e.raw(_));if(a?.rows)for(const u of a.rows){const d=u.filter_name,h=u.value,T=Number(u.count)||0;s[d]||(s[d]=[]),h&&s[d].push({value:h,count:T})}return s}async#a(i,s){const r=i.substring(9),o=`$.${$(r)}`,_=await this.#e.client.run(e.raw(`
113
+ SELECT json_extract(metadata, '${o}') as value, COUNT(*) as count
114
114
  FROM temp_filtered_entities
115
115
  WHERE metadata IS NOT NULL
116
116
  AND metadata != ''
117
- AND json_extract(metadata, '${c}') IS NOT NULL
118
- AND json_extract(metadata, '${c}') != ''
117
+ AND json_extract(metadata, '${o}') IS NOT NULL
118
+ AND json_extract(metadata, '${o}') != ''
119
119
  GROUP BY value
120
- `));m?.rows&&(s[i]=m.rows.map(l=>({value:l.value,count:Number(l.count)||0})).filter(l=>l.value))}async#u(){try{await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_filtered_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_relations`)}catch(i){L.error("Error cleaning up temp tables:",i)}}#r(i){return e`
121
- COALESCE(
122
- (
123
- SELECT json_group_array(
124
- json_object(
125
- 'id', d.id,
126
- 'key', d.key,
127
- 'type', d.type,
128
- 'title', d.title,
129
- 'summary', d.summary,
130
- 'created_at', d.created_at,
131
- 'updated_at', d.updated_at,
132
- 'source', d.source,
133
- 'source_file', d.source_file
134
- )
135
- )
136
- FROM (
137
- SELECT DISTINCT d.*
138
- FROM combined_relations er
139
- JOIN combined_target_entities d ON d.key = CASE
140
- WHEN er.source_key = ${e.raw(`${i}.key`)} THEN er.target_key
141
- WHEN er.target_key = ${e.raw(`${i}.key`)} THEN er.source_key
142
- END
143
- WHERE d.type = 'domain'
144
- AND d.is_current = 1
145
- AND (
146
- (
147
- er.source_key = ${e.raw(`${i}.key`)}
148
- AND CASE
149
- WHEN ${e.raw(`${i}.version`)} = ''
150
- THEN er.source_version = ''
151
- ELSE (er.source_version = ${e.raw(`${i}.version`)} OR er.source_version = '')
152
- END
153
- AND CASE
154
- WHEN ${e.raw(`${i}.revision`)} = ''
155
- THEN 1 = 1
156
- ELSE (er.source_revision <= ${e.raw(`${i}.revision`)} OR er.source_revision = '')
157
- END
158
- )
159
- OR (
160
- er.target_key = ${e.raw(`${i}.key`)}
161
- AND CASE
162
- WHEN ${e.raw(`${i}.version`)} = ''
163
- THEN er.target_version = ''
164
- ELSE (er.target_version = ${e.raw(`${i}.version`)} OR er.target_version = '')
165
- END
166
- AND CASE
167
- WHEN ${e.raw(`${i}.revision`)} = ''
168
- THEN 1 = 1
169
- ELSE (er.target_revision <= ${e.raw(`${i}.revision`)} OR er.target_revision = '')
170
- END
171
- )
172
- )
173
- LIMIT 10
174
- ) d
175
- ),
176
- json_array()
177
- )
178
- `}#s(i){return e`
179
- COALESCE(
180
- (
181
- SELECT json_group_array(
182
- json_object(
183
- 'id', o.id,
184
- 'key', o.key,
185
- 'type', o.type,
186
- 'title', o.title,
187
- 'summary', o.summary,
188
- 'created_at', o.created_at,
189
- 'updated_at', o.updated_at,
190
- 'source', o.source,
191
- 'source_file', o.source_file
192
- )
193
- )
194
- FROM (
195
- SELECT DISTINCT o.*
196
- FROM combined_relations er
197
- JOIN combined_target_entities o
198
- ON o.key = CASE
199
- WHEN er.source_key = ${e.raw(`${i}.key`)} THEN er.target_key
200
- ELSE er.source_key
201
- END
202
- WHERE ((er.source_key = ${e.raw(`${i}.key`)} AND er.source_to_target_relation = 'ownedBy')
203
- OR (er.target_key = ${e.raw(`${i}.key`)} AND er.source_to_target_relation = 'owns'))
204
- AND o.is_current = 1
205
- AND (
206
- (
207
- er.source_key = ${e.raw(`${i}.key`)}
208
- AND CASE
209
- WHEN ${e.raw(`${i}.version`)} = ''
210
- THEN er.source_version = ''
211
- ELSE (er.source_version = ${e.raw(`${i}.version`)} OR er.source_version = '')
212
- END
213
- AND CASE
214
- WHEN ${e.raw(`${i}.revision`)} = ''
215
- THEN 1 = 1
216
- ELSE (er.source_revision <= ${e.raw(`${i}.revision`)} OR er.source_revision = '')
217
- END
218
- )
219
- OR (
220
- er.target_key = ${e.raw(`${i}.key`)}
221
- AND CASE
222
- WHEN ${e.raw(`${i}.version`)} = ''
223
- THEN er.target_version = ''
224
- ELSE (er.target_version = ${e.raw(`${i}.version`)} OR er.target_version = '')
225
- END
226
- AND CASE
227
- WHEN ${e.raw(`${i}.revision`)} = ''
228
- THEN 1 = 1
229
- ELSE (er.target_revision <= ${e.raw(`${i}.revision`)} OR er.target_revision = '')
230
- END
231
- )
232
- )
233
- LIMIT 10
234
- ) o
235
- ),
236
- json_array()
237
- )
238
- `}}function j($){return $.replace(/[^a-zA-Z0-9._-]/g,"")}export{ne as CatalogEntitiesLocalReadRepository};
120
+ `));_?.rows&&(s[i]=_.rows.map(a=>({value:a.value,count:Number(a.count)||0})).filter(a=>a.value))}async#l(){try{await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_filtered_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_relations`)}catch(i){b.error("Error cleaning up temp tables:",i)}}}function $(A){return A.replace(/[^a-zA-Z0-9._-]/g,"")}export{j as CatalogEntitiesLocalReadRepository};
@@ -1 +1 @@
1
- import{and as d,desc as k,eq as u,isNull as v,or as R,sql as D}from"drizzle-orm";import{logger as h}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as T}from"../../../../../utils/crypto/sha1.js";import{isWebView as O}from"../../../../../../utils/env/is-web-view.js";import{VERSION_NOT_SPECIFIED as S}from"@redocly/theme/core/constants";import{createEntityDbRecord as x}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as I}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as e}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as o}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as K}from"../../../../../providers/database/pagination/filter.js";import{compareVersionsDescending as L}from"../../../utils/version-compare.js";const w=15;class Q{#e;#t;#r;constructor(t,r,s){this.#e=t,this.#t=r,this.#r=s}async createEntity({entity:t,fileHash:r,sourceFile:s,revision:a=new Date().toISOString(),isRootEntity:i=!1,isDeleted:n=!1}){try{const{relations:c=[],...l}=t,y=T(JSON.stringify(l)),f=t.version??S;if(await this.#s(t.key,f,y,i,n))return{result:"skipped",entityKey:t.key};const{shouldBeCurrent:g,shouldBeDefaultVersion:m}=await this.#o(t.key,f),E=x({entity:{...t,revision:a,hash:y,isCurrent:g,isDefaultVersion:m,isDeleted:n,version:f},sourceFile:s,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:r}),{key:A,source:$,...F}=E;if(await this.#a({key:A,isCurrent:g,isDefaultVersion:m}),O())return await this.#c(E,c),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f};const N=this.#e.client.insert(e).values(E).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:F}),B=c?.length&&c.length>0?this.#e.client.insert(o).values(c.map(V=>I({relation:V,sourceFile:s,fileHash:r,sourceKey:t.key,sourceVersion:f,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision]}).run():Promise.resolve();return await p([N,B],w,async V=>V),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f}}catch(c){return console.error(c),h.error("Error adding entity",c),{result:"error",entityKey:t.key}}}async deleteEntity(t){try{return await this.#e.client.delete(e).where(u(e.key,t)),t}catch(r){return h.error("Error deleting entity",r),null}}async deleteEntities(t){try{const r=K(t);if(!r)return!1;const s=await this.#e.client.delete(e).where(r).returning({key:e.key,source:e.source,isCurrent:e.isCurrent,isDefaultVersion:e.isDefaultVersion,version:e.version});if(s.length===0)return!0;const a=s.reduce((i,n)=>((n.isCurrent||n.isDefaultVersion)&&i.add(n.key),i),new Set);if(a.size===0)return!0;await p(Array.from(a),w,async i=>this.#u(i));for(const i of s)await this.#e.client.delete(o).where(R(d(u(o.sourceKey,i.key),...i.version?[u(o.sourceVersion,i.version)]:[v(o.sourceVersion)]),d(u(o.targetKey,i.key),...i.version?[u(o.targetVersion,i.version)]:[v(o.targetVersion)])));return!0}catch(r){return h.error("Error deleting entities",r),!1}}async deleteEntityRelation(t){try{return await this.#e.client.delete(o).where(u(o.id,t)),t}catch{return null}}async softDeleteEntities(t,r,s){try{const a=t.map(n=>{const c={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:c,revision:r,sourceFile:n.sourceFile??"",fileHash:s,isDeleted:!0})});return await p(a,w,async n=>n)}catch(a){return h.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(t){try{const r=K(t);return r?(await this.#e.client.delete(o).where(r),!0):!1}catch(r){return h.error("Error deleting entity relations",r),!1}}async upsertEntityRelation(t){if(!t)return null;try{const{sourceKey:r,targetKey:s,sourceVersion:a,targetVersion:i,sourceRevision:n,targetRevision:c,...l}=t,y=await this.#e.client.insert(o).values(t).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision],set:l}).returning();return y?.length?y[0]:null}catch(r){return h.error("Error creating entity relation",r),null}}async#s(t,r,s,a,i){if(a||i)return!1;const n=await this.#e.client.select({hash:e.hash,isDeleted:e.isDeleted}).from(e).where(d(u(e.key,t),u(e.source,"file"),r?u(e.version,r):v(e.version))).orderBy(k(e.revision)).limit(1).run();if(n.rows.length===0)return!1;const c=n.rows[0];return c.isDeleted?!1:c.hash===s}async#i(t){return(await this.#e.client.select({version:e.version,isDefaultVersion:e.isDefaultVersion,revision:e.revision,createdAt:e.createdAt}).from(e).where(d(u(e.key,t),u(e.source,"file"))).orderBy(k(e.createdAt)).run()).rows.map(s=>({version:s.version,isDefaultVersion:!!s.isDefaultVersion,revision:s.revision,createdAt:new Date(s.createdAt)}))}#n(t){const r=t.find(i=>i.isDefaultVersion);if(r)return r;const{versionedEntities:s,unversionedEntities:a}=t.reduce((i,n)=>(n.version!==null&&n.version!==S?i.versionedEntities.push(n):i.unversionedEntities.push(n),i),{versionedEntities:[],unversionedEntities:[]});if(s.length>0){s.sort((c,l)=>L(c.version,l.version));const i=s[0].version,n=s.filter(c=>c.version===i);return n.sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime()),n[0]}return a.length>0?(a.sort((i,n)=>n.createdAt.getTime()-i.createdAt.getTime()),a[0]):null}async#o(t,r){const s=await this.#e.client.select({currentDefaultVersion:D`max(case when ${e.isDefaultVersion} = 1 then ${e.version} else null end)`,versionMatchCount:D`count(case when ${e.version} = ${r} then 1 else null end)`}).from(e).where(d(u(e.key,t),u(e.source,"file"))).get(),a=s?.currentDefaultVersion,i=(s?.versionMatchCount??0)>0;return r&&r===a?{shouldBeCurrent:!0,shouldBeDefaultVersion:!1}:{shouldBeCurrent:!i,shouldBeDefaultVersion:!i}}async#a({key:t,isCurrent:r,isDefaultVersion:s}){if(!r&&!s)return;const a={},i=[];r&&(a.isCurrent=!1,i.push(u(e.isCurrent,!0))),s&&(a.isDefaultVersion=!1,i.push(u(e.isDefaultVersion,!0))),await this.#e.client.update(e).set(a).where(d(u(e.key,t),u(e.source,"file"),R(...i))).run()}#u=async t=>{const r=await this.#i(t),s=this.#n(r);if(!s){h.warn("No latest version found for key",t);return}await this.#e.client.update(e).set({isDefaultVersion:!0,isCurrent:!0}).where(d(u(e.key,t),u(e.revision,s.revision),s.version?u(e.version,s.version):v(e.version))).run()};async#c(t,r){const{key:s,source:a,version:i,isDefaultVersion:n,...c}=t,f=(await this.#e.client.select({id:e.id}).from(e).where(d(u(e.key,s),u(e.source,a??"file"),i?u(e.version,i):v(e.version))).limit(1).run()).rows.length>0?this.#e.client.update(e).set(c).where(d(u(e.key,s),u(e.source,a??"file"),i?u(e.version,i):v(e.version))).run():this.#e.client.insert(e).values(t).run(),C=r?.map(g=>{const m=I({relation:g,sourceFile:t.sourceFile??"",fileHash:t.fileHash??"",sourceKey:t.key,sourceVersion:t.version??null,sourceRevision:t.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(o).values(m).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision],set:m}).run()})??[];await p([f,...C],w,async g=>g)}async updateEntityScorecardsStatus(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(u(e.id,t)).returning()).length>0}catch(s){return h.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(D`${e.id} = ${t} AND ${e.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return h.error("Error updating entity scorecards status if calculating",s),!1}}}export{Q as CatalogEntitiesLocalWriteRepository};
1
+ import{and as d,desc as k,eq as u,isNull as v,or as R,sql as D}from"drizzle-orm";import{logger as h}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as T}from"../../../../../utils/crypto/sha1.js";import{isWebView as O}from"../../../../../../utils/env/is-web-view.js";import{VERSION_NOT_SPECIFIED as S}from"@redocly/theme/core/constants";import{createEntityDbRecord as x}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as I}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as e}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as o}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as K}from"../../../../../providers/database/pagination/filter.js";import{compareVersionsDescending as L}from"../../../utils/version-compare.js";const w=15;class Q{#e;#t;#r;constructor(t,r,s){this.#e=t,this.#t=r,this.#r=s}async createEntity({entity:t,fileHash:r,sourceFile:s,revision:a=new Date().toISOString(),isRootEntity:i=!1,isDeleted:n=!1}){try{const{relations:c=[],...l}=t,y=T(JSON.stringify(l)),f=t.version??S;if(await this.#s(t.key,f,y,i,n))return{result:"skipped",entityKey:t.key};const{shouldBeCurrent:g,shouldBeDefaultVersion:m}=await this.#o(t.key,f),E=x({entity:{...t,revision:a,hash:y,isCurrent:g,isDefaultVersion:m,isDeleted:n,version:f},sourceFile:s,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:r}),{key:A,source:U,...F}=E;if(await this.#a({key:A,isCurrent:g,isDefaultVersion:m}),O())return await this.#c(E,c),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f};const N=this.#e.client.insert(e).values(E).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:F}),B=c?.length&&c.length>0?this.#e.client.insert(o).values(c.map(V=>I({relation:V,sourceFile:s,fileHash:r,sourceKey:t.key,sourceVersion:f,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision]}).run():Promise.resolve();return await p([N,B],w,async V=>V),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f}}catch(c){return h.error("Error adding entity",c),{result:"error",entityKey:t.key}}}async deleteEntity(t){try{return await this.#e.client.delete(e).where(u(e.key,t)),t}catch(r){return h.error("Error deleting entity",r),null}}async deleteEntities(t){try{const r=K(t);if(!r)return!1;const s=await this.#e.client.delete(e).where(r).returning({key:e.key,source:e.source,isCurrent:e.isCurrent,isDefaultVersion:e.isDefaultVersion,version:e.version});if(s.length===0)return!0;const a=s.reduce((i,n)=>((n.isCurrent||n.isDefaultVersion)&&i.add(n.key),i),new Set);if(a.size===0)return!0;await p(Array.from(a),w,async i=>this.#u(i));for(const i of s)await this.#e.client.delete(o).where(R(d(u(o.sourceKey,i.key),...i.version?[u(o.sourceVersion,i.version)]:[v(o.sourceVersion)]),d(u(o.targetKey,i.key),...i.version?[u(o.targetVersion,i.version)]:[v(o.targetVersion)])));return!0}catch(r){return h.error("Error deleting entities",r),!1}}async deleteEntityRelation(t){try{return await this.#e.client.delete(o).where(u(o.id,t)),t}catch{return null}}async softDeleteEntities(t,r,s){try{const a=t.map(n=>{const c={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:c,revision:r,sourceFile:n.sourceFile??"",fileHash:s,isDeleted:!0})});return await p(a,w,async n=>n)}catch(a){return h.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(t){try{const r=K(t);return r?(await this.#e.client.delete(o).where(r),!0):!1}catch(r){return h.error("Error deleting entity relations",r),!1}}async upsertEntityRelation(t){if(!t)return null;try{const{sourceKey:r,targetKey:s,sourceVersion:a,targetVersion:i,sourceRevision:n,targetRevision:c,...l}=t,y=await this.#e.client.insert(o).values(t).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision],set:l}).returning();return y?.length?y[0]:null}catch(r){return h.error("Error creating entity relation",r),null}}async#s(t,r,s,a,i){if(a||i)return!1;const n=await this.#e.client.select({hash:e.hash,isDeleted:e.isDeleted}).from(e).where(d(u(e.key,t),u(e.source,"file"),r?u(e.version,r):v(e.version))).orderBy(k(e.revision)).limit(1).run();if(n.rows.length===0)return!1;const c=n.rows[0];return c.isDeleted?!1:c.hash===s}async#i(t){return(await this.#e.client.select({version:e.version,isDefaultVersion:e.isDefaultVersion,revision:e.revision,createdAt:e.createdAt}).from(e).where(d(u(e.key,t),u(e.source,"file"))).orderBy(k(e.createdAt)).run()).rows.map(s=>({version:s.version,isDefaultVersion:!!s.isDefaultVersion,revision:s.revision,createdAt:new Date(s.createdAt)}))}#n(t){const r=t.find(i=>i.isDefaultVersion);if(r)return r;const{versionedEntities:s,unversionedEntities:a}=t.reduce((i,n)=>(n.version!==null&&n.version!==S?i.versionedEntities.push(n):i.unversionedEntities.push(n),i),{versionedEntities:[],unversionedEntities:[]});if(s.length>0){s.sort((c,l)=>L(c.version,l.version));const i=s[0].version,n=s.filter(c=>c.version===i);return n.sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime()),n[0]}return a.length>0?(a.sort((i,n)=>n.createdAt.getTime()-i.createdAt.getTime()),a[0]):null}async#o(t,r){const s=await this.#e.client.select({currentDefaultVersion:D`max(case when ${e.isDefaultVersion} = 1 then ${e.version} else null end)`,versionMatchCount:D`count(case when ${e.version} = ${r} then 1 else null end)`}).from(e).where(d(u(e.key,t),u(e.source,"file"))).get(),a=s?.currentDefaultVersion,i=(s?.versionMatchCount??0)>0;return r&&r===a?{shouldBeCurrent:!0,shouldBeDefaultVersion:!1}:{shouldBeCurrent:!i,shouldBeDefaultVersion:!i}}async#a({key:t,isCurrent:r,isDefaultVersion:s}){if(!r&&!s)return;const a={},i=[];r&&(a.isCurrent=!1,i.push(u(e.isCurrent,!0))),s&&(a.isDefaultVersion=!1,i.push(u(e.isDefaultVersion,!0))),await this.#e.client.update(e).set(a).where(d(u(e.key,t),u(e.source,"file"),R(...i))).run()}#u=async t=>{const r=await this.#i(t),s=this.#n(r);if(!s){h.warn("No latest version found for key",t);return}await this.#e.client.update(e).set({isDefaultVersion:!0,isCurrent:!0}).where(d(u(e.key,t),u(e.revision,s.revision),s.version?u(e.version,s.version):v(e.version))).run()};async#c(t,r){const{key:s,source:a,version:i,isDefaultVersion:n,...c}=t,f=(await this.#e.client.select({id:e.id}).from(e).where(d(u(e.key,s),u(e.source,a??"file"),i?u(e.version,i):v(e.version))).limit(1).run()).rows.length>0?this.#e.client.update(e).set(c).where(d(u(e.key,s),u(e.source,a??"file"),i?u(e.version,i):v(e.version))).run():this.#e.client.insert(e).values(t).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:c}).run(),C=r?.map(g=>{const m=I({relation:g,sourceFile:t.sourceFile??"",fileHash:t.fileHash??"",sourceKey:t.key,sourceVersion:t.version??null,sourceRevision:t.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(o).values(m).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision],set:m}).run()})??[];await p([f,...C],w,async g=>g)}async updateEntityScorecardsStatus(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(u(e.id,t)).returning()).length>0}catch(s){return h.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(D`${e.id} = ${t} AND ${e.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return h.error("Error updating entity scorecards status if calculating",s),!1}}}export{Q as CatalogEntitiesLocalWriteRepository};