@redocly/revel 0.128.0-next.5 → 0.128.0-next.6

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 (40) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
  3. package/dist/constants/common.d.ts +2 -0
  4. package/dist/constants/common.js +1 -1
  5. package/dist/server/constants/plugins/catalog-entities.d.ts +1 -0
  6. package/dist/server/constants/plugins/catalog-entities.js +1 -1
  7. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +4 -0
  8. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
  9. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +4 -0
  10. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +4 -4
  11. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +4 -0
  12. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +1 -1
  13. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +1 -0
  14. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
  15. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.d.ts +2 -1
  16. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  17. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.d.ts +2 -1
  18. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +1 -11
  19. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  20. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.d.ts +2 -1
  21. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +1 -1
  22. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.d.ts +2 -1
  23. package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
  24. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  25. package/dist/server/plugins/catalog-entities/types/extractors.d.ts +16 -0
  26. package/dist/server/plugins/catalog-entities/types/extractors.js +0 -0
  27. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.d.ts +20 -0
  28. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.js +1 -0
  29. package/dist/server/providers/database/pagination/types.d.ts +9 -0
  30. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  31. package/dist/server/web-server/routes/catalog/bff-catalog-revisions.d.ts +4 -0
  32. package/dist/server/web-server/routes/catalog/bff-catalog-revisions.js +1 -0
  33. package/dist/server/web-server/routes/catalog/bff-catalog.d.ts +0 -1
  34. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  35. package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
  36. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  37. package/dist/server/web-server/routes/index.js +1 -1
  38. package/dist/utils/object/allowlist-object.d.ts +16 -0
  39. package/dist/utils/object/allowlist-object.js +1 -0
  40. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @redocly/revel
2
2
 
3
+ ## 0.128.0-next.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [301d33c8b3]
8
+ - @redocly/realm-asyncapi-sdk@0.6.0-next.1
9
+ - @redocly/theme@0.60.0-next.5
10
+ - @redocly/asyncapi-docs@1.5.0-next.6
11
+ - @redocly/graphql-docs@1.5.0-next.1
12
+ - @redocly/openapi-docs@3.16.0-next.6
13
+ - @redocly/portal-plugin-mock-server@0.13.0-next.6
14
+
3
15
  ## 0.128.0-next.5
4
16
 
5
17
  ### Minor Changes
@@ -1 +1 @@
1
- import a from"react";import{ThemeDataContext as l}from"@redocly/theme/core/contexts";import{useBreadcrumbs as d,useCatalogClassic as g,useCurrentProduct as f,useGlobalData as o,useI18n as p,useI18nConfig as b,useL10n as C,useL10nConfig as h,usePageData as r,usePageSharedData as S,usePageVersions as P,usePreloadHistory as T,useProducts as D,useUserMenu as k,useSubmitFeedback as F,useTranslate as L,useSidebarSiblingsData as M,usePageProps as O,useUserTeams as v,useMarkdownText as E,useCodeHighlight as R,useLoadAndNavigate as w,useCatalog as x,useCatalogSort as y,useCatalogSearch as A,useFetchCatalogEntities as j,useFetchCatalogEntitiesRelations as I,useTelemetry as s,useMcpData as H}from"../../app/hooks";import{Link as N}from"../../app/Link";import{useFacetQuery as U,useSearch as _,useAiSearch as B}from"../../app/search";import{useSidebarItems as G}from"../../app/Sidebar/useSidebarItems";import{deepMerge as Q}from"../../../utils/object/deep-merge";const V=new Set(["title","description","seo","sidebar","excludeFromSearch","template","redirects","rbac","metadata","slug","codeSnippet","breadcrumbs","markdown","seo","navbar","footer","colorMode","feedback","navigation"]),W={useBreadcrumbs:d,useCatalog:x,useCatalogSort:y,useCatalogSearch:A,useFetchCatalogEntities:j,useFetchCatalogEntitiesRelations:I,useCatalogClassic:g,useCurrentProduct:f,useGlobalData:o,useSearch:_,useAiSearch:B,useFacetQuery:U,useI18n:p,useI18nConfig:b,useL10n:C,useL10nConfig:h,usePageData:r,usePageSharedData:S,usePageVersions:P,usePreloadHistory:T,useProducts:D,useUserMenu:k,useSidebarItems:G,useSidebarSiblingsData:M,useSubmitFeedback:F,useTranslate:L,useUserTeams:v,usePageProps:O,useMarkdownText:E,useCodeHighlight:R,useLoadAndNavigate:w,useTelemetry:s,useOtelTelemetry:s,useMcpData:H},q={LinkComponent:N};function ee({children:n}){const{props:e}=r()||{},t=o()||{},u=a.useMemo(()=>{const c=Object.fromEntries(Object.entries(e?.frontmatter||{}).filter(([m])=>V.has(m)));return Q(t,c)},[t,e?.frontmatter]),i={hooks:W,components:q,config:u};return a.createElement(l.Provider,{value:i},n)}export{ee as ThemeDataProvider};
1
+ import a from"react";import{ThemeDataContext as m}from"@redocly/theme/core/contexts";import{useBreadcrumbs as l,useCatalogClassic as d,useCurrentProduct as g,useGlobalData as o,useI18n as p,useI18nConfig as f,useL10n as b,useL10nConfig as C,usePageData as r,usePageSharedData as h,usePageVersions as P,usePreloadHistory as S,useProducts as T,useUserMenu as D,useSubmitFeedback as k,useTranslate as F,useSidebarSiblingsData as L,usePageProps as M,useUserTeams as v,useMarkdownText as O,useCodeHighlight as E,useLoadAndNavigate as R,useCatalog as w,useCatalogSort as x,useCatalogSearch as y,useFetchCatalogEntities as A,useFetchCatalogEntitiesRelations as I,useTelemetry as s,useMcpData as j}from"../../app/hooks";import{Link as H}from"../../app/Link";import{useFacetQuery as N,useSearch as U,useAiSearch as _}from"../../app/search";import{useSidebarItems as B}from"../../app/Sidebar/useSidebarItems";import{deepMerge as G}from"../../../utils/object/deep-merge";import{allowlistObject as Q}from"../../../utils/object/allowlist-object";const V=["title","description","seo","sidebar","excludeFromSearch","template","redirects","rbac","metadata","slug","codeSnippet","breadcrumbs","markdown","seo","navbar","footer","colorMode","feedback","navigation"],W={useBreadcrumbs:l,useCatalog:w,useCatalogSort:x,useCatalogSearch:y,useFetchCatalogEntities:A,useFetchCatalogEntitiesRelations:I,useCatalogClassic:d,useCurrentProduct:g,useGlobalData:o,useSearch:U,useAiSearch:_,useFacetQuery:N,useI18n:p,useI18nConfig:f,useL10n:b,useL10nConfig:C,usePageData:r,usePageSharedData:h,usePageVersions:P,usePreloadHistory:S,useProducts:T,useUserMenu:D,useSidebarItems:B,useSidebarSiblingsData:L,useSubmitFeedback:k,useTranslate:F,useUserTeams:v,usePageProps:M,useMarkdownText:O,useCodeHighlight:E,useLoadAndNavigate:R,useTelemetry:s,useOtelTelemetry:s,useMcpData:j},q={LinkComponent:H};function te({children:u}){const{props:e}=r()||{},t=o()||{},n=a.useMemo(()=>{const c=Q(e?.frontmatter||{},V);return G(t,c)},[t,e?.frontmatter]),i={hooks:W,components:q,config:n};return a.createElement(m.Provider,{value:i},u)}export{te as ThemeDataProvider};
@@ -36,6 +36,8 @@ export declare enum FEEDBACK_TYPES {
36
36
  PROBLEM = "problem",
37
37
  SCALE = "scale"
38
38
  }
39
+ export declare const CATALOG_ENTITY_KEY = "entityKey";
40
+ export declare const CATALOG_ENTITY_RELATION_ID = "entityRelationId";
39
41
  export declare const ServerRoutes: {
40
42
  readonly INFO: "/_info";
41
43
  readonly EJECT_COMPONENT: "/eject-component/:componentName";
@@ -1 +1 @@
1
- import{AuthProviderType as e}from"@redocly/config";import{withPathPrefix as o}from"@redocly/theme/core/utils";const O="openapi_docs",p="asyncapi_docs",T="graphql_docs",R="/_spec-gql",L="markdoc",I="tags",E="*",C={[E]:"read"},S=["openid","email"],l=1440*60,d="anonymous",P="authenticated",N="**",u="Reunite",D="translations.yaml",h="redocly.yaml",m="@redocly/theme",x="@theme",U="/app-data.json",g="/eject-component",r=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",M=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(t=>t.trim()).filter(Boolean).concat(r):[r];var a;(function(t){t.BUILD="build",t.DEVELOP="develop",t.PREPARE="prepare"})(a||(a={}));var _;(function(t){t.RATING="rating",t.SENTIMENT="sentiment",t.COMMENT="comment",t.MOOD="mood",t.PROBLEM="problem",t.SCALE="scale"})(_||(_={}));const c={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/:entityKey?",CATALOG_ENTITIES_RELATIONS:"/catalog-entities-relations/:entityRelationId?",BFF_CATALOG_ENTITIES:"/bff/catalog-entities/:entityKey?",BFF_CATALOG_RELATED_ENTITIES:"/bff/catalog-related-entities/:entityKey",BFF_CATALOG_REVISIONS:"/bff/catalog-revisions/:entityKey",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"},y={[e.SAML2]:o(c.IDP_LOGIN),[e.OIDC]:o(c.IDP_LOGIN)};var s;(function(t){t.AI_SEARCH="aiSearch"})(s||(s={}));const G="/login",v="/invite",F={AUTH0_PASS:"/auth/auth0-pass"},H={NotExist:"ENOENT"},b="default_locale",B="sidebar-",f="PUBLIC_",k=["BROKEN_LINK","MARKDOC","RESOLVE"],K=["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"],n="redocly_category",V="redocly_product",Y="redocly_version",w="redocly_teams",j=n,q={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"};export{M as ALLOWED_CORS_ORIGINS,p as ASYNC_API_DOCS_TEMPLATE_ID,h as CONFIG_FILE_NAME,L as CUSTOM_MARKDOC_OPTIONS_PATH,I as CUSTOM_MARKDOC_TAGS_PATH,d as DEFAULT_ANONYMOUS_VISITOR_TEAM,P as DEFAULT_AUTHENTICATED_TEAM,l as DEFAULT_COOKIE_EXPIRATION,b as DEFAULT_LOCALE_PLACEHOLDER,y as DEFAULT_PROVIDERS_LOGIN_URLS,N as DEFAULT_RBAC_SCOPE,u as DEFAULT_SSO_IDP_TITLE,m as DEFAULT_THEME_NAME,G as DEV_LOGIN_SLUG,g as EJECT_COMPONENT_URL,F as ExternalRoutes,q as FEATURE,_ as FEEDBACK_TYPES,H as FsErrors,U as GLOBAL_DATA_URL,R as GRAPHQL_SPEC_SLUG,T as GRAPHQL_TEMPLATE_ID,v as INVITE_SLUG,k as MARKDOC_ERROR_TYPES,O as OPENAPI_DOCS_TEMPLATE_ID,f as PUBLIC_ENV_PREFIX,C as PUBLIC_RBAC_SCOPE_ITEM,E as RBAC_ALL_OTHER_TEAMS,S as REQUIRED_OIDC_SCOPES,s as RbacFeatures,n as SEARCH_CATEGORY_FIELD,j as SEARCH_GROUP_FACET_FIELD,V as SEARCH_PRODUCT_FIELD,w as SEARCH_RBAC_FIELD,Y as SEARCH_VERSION_FIELD,r as SERVER_EDITOR_APP_URL,B as SIDEBAR_PREFIX,c as ServerRoutes,D as TRANSLATIONS_FILE_NAME,K as UI_ACCESSIBLE_CONFIG_PROPS,x as USER_THEME_ALIAS,a as cliCommandNames};
1
+ import{AuthProviderType as e}from"@redocly/config";import{withPathPrefix as r}from"@redocly/theme/core/utils";const i="openapi_docs",L="asyncapi_docs",R="graphql_docs",I="/_spec-gql",C="markdoc",S="tags",n="*",l={[n]:"read"},d=["openid","email"],P=1440*60,N="anonymous",u="authenticated",D="**",h="Reunite",x="translations.yaml",m="redocly.yaml",U="@redocly/theme",g="@theme",M="/app-data.json",G="/eject-component",_=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",v=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(o=>o.trim()).filter(Boolean).concat(_):[_];var a;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(a||(a={}));var c;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(c||(c={}));const t="entityKey",A="entityRelationId",s={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/:${A}?`,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"},F={[e.SAML2]:r(s.IDP_LOGIN),[e.OIDC]:r(s.IDP_LOGIN)};var E;(function(o){o.AI_SEARCH="aiSearch"})(E||(E={}));const y="/login",H="/invite",b={AUTH0_PASS:"/auth/auth0-pass"},B={NotExist:"ENOENT"},f="default_locale",k="sidebar-",V="PUBLIC_",K=["BROKEN_LINK","MARKDOC","RESOLVE"],Y=["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"],O="redocly_category",w="redocly_product",j="redocly_version",q="redocly_teams",$=O,Q={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"};export{v as ALLOWED_CORS_ORIGINS,L as ASYNC_API_DOCS_TEMPLATE_ID,t as CATALOG_ENTITY_KEY,A as CATALOG_ENTITY_RELATION_ID,m as CONFIG_FILE_NAME,C as CUSTOM_MARKDOC_OPTIONS_PATH,S as CUSTOM_MARKDOC_TAGS_PATH,N as DEFAULT_ANONYMOUS_VISITOR_TEAM,u as DEFAULT_AUTHENTICATED_TEAM,P as DEFAULT_COOKIE_EXPIRATION,f as DEFAULT_LOCALE_PLACEHOLDER,F as DEFAULT_PROVIDERS_LOGIN_URLS,D as DEFAULT_RBAC_SCOPE,h as DEFAULT_SSO_IDP_TITLE,U as DEFAULT_THEME_NAME,y as DEV_LOGIN_SLUG,G as EJECT_COMPONENT_URL,b as ExternalRoutes,Q as FEATURE,c as FEEDBACK_TYPES,B as FsErrors,M as GLOBAL_DATA_URL,I as GRAPHQL_SPEC_SLUG,R as GRAPHQL_TEMPLATE_ID,H as INVITE_SLUG,K as MARKDOC_ERROR_TYPES,i as OPENAPI_DOCS_TEMPLATE_ID,V as PUBLIC_ENV_PREFIX,l as PUBLIC_RBAC_SCOPE_ITEM,n as RBAC_ALL_OTHER_TEAMS,d as REQUIRED_OIDC_SCOPES,E as RbacFeatures,O as SEARCH_CATEGORY_FIELD,$ as SEARCH_GROUP_FACET_FIELD,w as SEARCH_PRODUCT_FIELD,q as SEARCH_RBAC_FIELD,j as SEARCH_VERSION_FIELD,_ as SERVER_EDITOR_APP_URL,k as SIDEBAR_PREFIX,s as ServerRoutes,x as TRANSLATIONS_FILE_NAME,Y as UI_ACCESSIBLE_CONFIG_PROPS,g as USER_THEME_ALIAS,a as cliCommandNames};
@@ -16,4 +16,5 @@ export declare const CATALOG_FILTERS_CACHE_NAMESPACE = "catalog-filters";
16
16
  export declare const CATALOG_FILTERS_CACHE_TTL_IN_SECONDS: number;
17
17
  export declare const CATALOG_ENTITIES_DEFAULT_CONFIG: EntitiesCatalogConfig;
18
18
  export declare const CATALOG_ENTITIES_FILES_REGEX: RegExp;
19
+ export declare const ALLOWED_CATALOG_QUERY_PARAMS: readonly ["after", "before", "sort", "filter", "search", "limit", "skip"];
19
20
  //# sourceMappingURL=catalog-entities.d.ts.map
@@ -1 +1 @@
1
- const e=["node_modules","dist","build",".git","@l10n"],l="/catalogs",a={ALL:"all",SERVICES:"services",DOMAINS:"domains",TEAMS:"teams",USERS:"users",API_DESCRIPTIONS:"api-descriptions",DATA_SCHEMAS:"data-schemas",API_OPERATIONS:"api-operations"},s="catalog:entitySources",i="catalog-filters",o=300,t=[{title:"Domains",property:"domains"},{title:"Owner",property:"owners"},{title:"Tags",property:"tags"}],c={show:!1,catalogs:{all:{slug:a.ALL,hide:!1,includes:[],excludes:[],filters:[{title:"Type",property:"type"},...t],titleTranslationKey:"catalog.catalogs.all.title",descriptionTranslationKey:"catalog.catalogs.all.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.all.switcherLabel"},services:{slug:a.SERVICES,hide:!1,includes:[{type:"service"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.service.title",descriptionTranslationKey:"catalog.catalogs.service.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.service.switcherLabel"},domains:{slug:a.DOMAINS,hide:!1,includes:[{type:"domain"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.domain.title",descriptionTranslationKey:"catalog.catalogs.domain.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.domain.switcherLabel"},teams:{slug:a.TEAMS,hide:!1,includes:[{type:"team"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.team.title",descriptionTranslationKey:"catalog.catalogs.team.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.team.switcherLabel"},users:{slug:a.USERS,hide:!1,includes:[{type:"user"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.user.title",descriptionTranslationKey:"catalog.catalogs.user.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.user.switcherLabel"},apiDescriptions:{slug:a.API_DESCRIPTIONS,hide:!1,includes:[{type:"api-description"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiDescription.title",descriptionTranslationKey:"catalog.catalogs.apiDescription.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiDescription.switcherLabel"},dataSchemas:{slug:a.DATA_SCHEMAS,hide:!1,includes:[{type:"data-schema"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.dataSchema.title",descriptionTranslationKey:"catalog.catalogs.dataSchema.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.dataSchema.switcherLabel"},apiOperations:{slug:a.API_OPERATIONS,hide:!1,includes:[{type:"api-operation"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiOperation.title",descriptionTranslationKey:"catalog.catalogs.apiOperation.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiOperation.switcherLabel"}}},n=/\.(entity|entities)\.(yaml|yml)$/;export{l as CATALOG_BASE_SLUG,c as CATALOG_ENTITIES_DEFAULT_CONFIG,n as CATALOG_ENTITIES_FILES_REGEX,i as CATALOG_FILTERS_CACHE_NAMESPACE,o as CATALOG_FILTERS_CACHE_TTL_IN_SECONDS,a as CATALOG_SLUGS,s as ENTITIES_MAP_GLOBAL_DATA_KEY,e as ENTITY_SCHEMA_EXCLUDED_FOLDERS};
1
+ const e=["node_modules","dist","build",".git","@l10n"],l="/catalogs",a={ALL:"all",SERVICES:"services",DOMAINS:"domains",TEAMS:"teams",USERS:"users",API_DESCRIPTIONS:"api-descriptions",DATA_SCHEMAS:"data-schemas",API_OPERATIONS:"api-operations"},s="catalog:entitySources",i="catalog-filters",o=300,t=[{title:"Domains",property:"domains"},{title:"Owner",property:"owners"},{title:"Tags",property:"tags"}],c={show:!1,catalogs:{all:{slug:a.ALL,hide:!1,includes:[],excludes:[],filters:[{title:"Type",property:"type"},...t],titleTranslationKey:"catalog.catalogs.all.title",descriptionTranslationKey:"catalog.catalogs.all.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.all.switcherLabel"},services:{slug:a.SERVICES,hide:!1,includes:[{type:"service"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.service.title",descriptionTranslationKey:"catalog.catalogs.service.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.service.switcherLabel"},domains:{slug:a.DOMAINS,hide:!1,includes:[{type:"domain"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.domain.title",descriptionTranslationKey:"catalog.catalogs.domain.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.domain.switcherLabel"},teams:{slug:a.TEAMS,hide:!1,includes:[{type:"team"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.team.title",descriptionTranslationKey:"catalog.catalogs.team.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.team.switcherLabel"},users:{slug:a.USERS,hide:!1,includes:[{type:"user"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.user.title",descriptionTranslationKey:"catalog.catalogs.user.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.user.switcherLabel"},apiDescriptions:{slug:a.API_DESCRIPTIONS,hide:!1,includes:[{type:"api-description"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiDescription.title",descriptionTranslationKey:"catalog.catalogs.apiDescription.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiDescription.switcherLabel"},dataSchemas:{slug:a.DATA_SCHEMAS,hide:!1,includes:[{type:"data-schema"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.dataSchema.title",descriptionTranslationKey:"catalog.catalogs.dataSchema.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.dataSchema.switcherLabel"},apiOperations:{slug:a.API_OPERATIONS,hide:!1,includes:[{type:"api-operation"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiOperation.title",descriptionTranslationKey:"catalog.catalogs.apiOperation.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiOperation.switcherLabel"}}},r=/\.(entity|entities)\.(yaml|yml)$/,n=["after","before","sort","filter","search","limit","skip"];export{n as ALLOWED_CATALOG_QUERY_PARAMS,l as CATALOG_BASE_SLUG,c as CATALOG_ENTITIES_DEFAULT_CONFIG,r as CATALOG_ENTITIES_FILES_REGEX,i as CATALOG_FILTERS_CACHE_NAMESPACE,o as CATALOG_FILTERS_CACHE_TTL_IN_SECONDS,a as CATALOG_SLUGS,s as ENTITIES_MAP_GLOBAL_DATA_KEY,e as ENTITY_SCHEMA_EXCLUDED_FOLDERS};
@@ -26,6 +26,10 @@ export declare class CatalogEntitiesService {
26
26
  transaction<T>(...args: Parameters<TransactionsManager['transaction']>): Promise<T>;
27
27
  getEntities(paginationParams: PaginationParams): Promise<ListResponseResult<EntityReadModelSchema>>;
28
28
  getEntityByKey(key: string): Promise<EntityReadModelSchema | null>;
29
+ getEntitiesCountByTypes(): Promise<{
30
+ type: string;
31
+ count: number;
32
+ }[]>;
29
33
  getCatalogFilters(params: CatalogFiltersParams): Promise<Record<string, import("./repositories/local/catalog-entities-local-read-repository.js").FilterOption[]>>;
30
34
  createEntity(entity: EntityDtoSchema): Promise<EntityReadModelSchema | null>;
31
35
  createEntities(entities: EntityDtoSchema[]): Promise<BulkSyncResult<EntityReadModelSchema>>;
@@ -1 +1 @@
1
- import{entityFileSchema as u}from"@redocly/config";import{deepMerge as y}from"../../../../utils/object/deep-merge.js";import{promiseMapLimit as c}from"../../../utils/async/promise-map-limit.js";import{logger as r}from"../../../tools/notifiers/logger.js";import{entityRelationDtoSchema as d}from"../schemas/dto-schemas.js";import{CatalogEntitiesLocalRepository as m}from"./repositories/local/catalog-entities-local-repository.js";import{CatalogEntitiesRemoteRepository as R}from"./repositories/remote/catalog-entities-remote-repository.js";import{prepareListResponse as o}from"../../../web-server/utils/prepare-list-response.js";import{ENTITY_RELATION_FROM_DATABASE as l}from"./mappers/field-transformations.js";import{createValidator as E}from"../utils/ajv-validator.js";import{hasOptionsChanged as w}from"../utils/has-options-changed.js";const h=15,f=E(d,{errorPrefix:"Entity relation validation failed:",dataVar:"entity relation"}),p=E(u,{errorPrefix:"Entity file validation failed:",dataVar:"entity"});class n{static#a;static#i;#t;#e;constructor(t,e){this.#t=t,this.#e=e}static async#n(t){const[e,a]=await Promise.all([m.getInstance(t),t.runOnlyLocalDatabase?void 0:R.getInstance(t)]),i=new n(e,a);a&&(process.env.NODE_ENV==="development"&&r.info("Attaching remote database to local database"),await i.#t.attachDatabase(a.path)),n.#a=i,n.#i=t}static async getInstance(t){return t.runOnlyLocalDatabase===void 0&&(t.runOnlyLocalDatabase=process.env.REDOCLY_LOCAL_DEV==="true"||process.env.CI==="true"),t.removeExisting===void 0&&(t.removeExisting=!1),(!n.#a||w(n.#i,t))&&await n.#n(t),n.#a}async transaction(...t){return this.#t.transactionsManager.transaction(...t)}async getEntities(t){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntities(t);return o({data:e,params:t,totalCount:a,hasMore:i})}async getEntityByKey(t){return await this.#e?.sync(),await this.#t.getEntityByKey(t)}async getCatalogFilters(t){return await this.#e?.sync(),this.#t.getCatalogFilters(t)}async createEntity(t){return this.#e?this.#e.createEntity(t):(r.warn("No remote database found"),null)}async createEntities(t){const e=this.#e;return e?await c(t,h,async a=>e.createEntity(a).then(i=>({status:"ok",resource:i})).catch(i=>({key:a.key,status:"error",error:i}))):(r.warn("No remote database found"),[])}getEntitySources(){return this.#t.getEntitySources()}async createEntityInLocalDatabase(t){await this.#t.createEntity(t)}async createEntitiesInLocalDatabase(t){await this.#t.createEntities(t)}async createEntityRelationInLocalDatabase(t){await this.#t.createEntityRelation(t)}async createEntityRelationsInLocalDatabase(t){await this.#t.createEntityRelations(t)}async updateEntityByKey(t,e){const a=await this.#t.getEntityByKey(t);if(!a)throw new Error(`Entity with key ${t} not found`);const i=y(a,e),s=p(i);return await this.#e?.updateEntity({...s,id:a.id,createdAt:a.createdAt||""})}async deleteEntityByKey(t){const e=await this.#e?.deleteEntity(t);return await this.#s(t),e}async deleteEntitiesInLocalDatabase(t){await this.#t.deleteEntities(t)}async getEntityRelationById(t){return await this.#e?.sync(),await this.#t.getEntityRelationById(t)}async getEntitiesRelations(t={}){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntitiesRelations(t);return o({data:e,params:t,totalCount:a,nameTransformationsFromDatabase:l,hasMore:i})}async createEntityRelation(t){return this.#e?.createEntityRelation(t)}async createEntitiesRelations(t){const e=this.#e;return e?await c(t,h,async a=>e.createEntityRelation(a).then(i=>({status:"ok",resource:i})).catch(i=>({key:a.sourceKey,status:"error",error:i}))):(r.warn("No remote database found"),[])}async updateEntityRelation(t,e){const a=await this.#t.getEntityRelationById(t);if(!a)throw new Error(`Entity relation with id ${t} not found`);const i=y(a,e),s=f(i);return this.#e?.createEntityRelation(s)}async deleteEntityRelation(t){let e=await this.#e?.deleteEntityRelation(t);return e||(e=await this.#t.deleteEntityRelation(t)),e}async deleteEntityRelationsInLocalDatabase(t){await this.#t.deleteEntityRelations(t)}async getEntitiesWithRelations(t={}){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntitiesWithRelations(t);return o({data:e,params:t,totalCount:a,hasMore:i})}async getEntityWithRelationsByKey(t,e={}){return this.#t.getEntityWithRelationsByKey(t,e)}async getRelatedEntities(t,e={}){await this.#e?.sync();const{items:a,total:i,hasMore:s}=await this.#t.getRelatedEntities(t,e);return o({data:a,params:e,totalCount:i,nameTransformationsFromDatabase:l,hasMore:s})}async#s(t){await this.#e?.deleteEntitiesRelations({op:"OR",conditions:[{field:"source_key",operator:"equal",value:t},{field:"target_key",operator:"equal",value:t}]})}async listEntityRevisions(t,e){return await this.#e?.sync(),this.#t.listEntityRevisions(t,e)}}export{n as CatalogEntitiesService};
1
+ import{entityFileSchema as h}from"@redocly/config";import{deepMerge as y}from"../../../../utils/object/deep-merge.js";import{promiseMapLimit as c}from"../../../utils/async/promise-map-limit.js";import{logger as r}from"../../../tools/notifiers/logger.js";import{entityRelationDtoSchema as d}from"../schemas/dto-schemas.js";import{CatalogEntitiesLocalRepository as m}from"./repositories/local/catalog-entities-local-repository.js";import{CatalogEntitiesRemoteRepository as R}from"./repositories/remote/catalog-entities-remote-repository.js";import{prepareListResponse as o}from"../../../web-server/utils/prepare-list-response.js";import{ENTITY_RELATION_FROM_DATABASE as l}from"./mappers/field-transformations.js";import{createValidator as E}from"../utils/ajv-validator.js";import{hasOptionsChanged as w}from"../utils/has-options-changed.js";const u=15,f=E(d,{errorPrefix:"Entity relation validation failed:",dataVar:"entity relation"}),p=E(h,{errorPrefix:"Entity file validation failed:",dataVar:"entity"});class n{static#a;static#i;#t;#e;constructor(t,e){this.#t=t,this.#e=e}static async#n(t){const[e,a]=await Promise.all([m.getInstance(t),t.runOnlyLocalDatabase?void 0:R.getInstance(t)]),i=new n(e,a);a&&(process.env.NODE_ENV==="development"&&r.info("Attaching remote database to local database"),await i.#t.attachDatabase(a.path)),n.#a=i,n.#i=t}static async getInstance(t){return t.runOnlyLocalDatabase===void 0&&(t.runOnlyLocalDatabase=process.env.REDOCLY_LOCAL_DEV==="true"||process.env.CI==="true"),t.removeExisting===void 0&&(t.removeExisting=!1),(!n.#a||w(n.#i,t))&&await n.#n(t),n.#a}async transaction(...t){return this.#t.transactionsManager.transaction(...t)}async getEntities(t){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntities(t);return o({data:e,params:t,totalCount:a,hasMore:i})}async getEntityByKey(t){return await this.#e?.sync(),await this.#t.getEntityByKey(t)}async getEntitiesCountByTypes(){return await this.#e?.sync(),this.#t.getEntitiesCountByTypes()}async getCatalogFilters(t){return await this.#e?.sync(),this.#t.getCatalogFilters(t)}async createEntity(t){return this.#e?this.#e.createEntity(t):(r.warn("No remote database found"),null)}async createEntities(t){const e=this.#e;return e?await c(t,u,async a=>e.createEntity(a).then(i=>({status:"ok",resource:i})).catch(i=>({key:a.key,status:"error",error:i}))):(r.warn("No remote database found"),[])}getEntitySources(){return this.#t.getEntitySources()}async createEntityInLocalDatabase(t){await this.#t.createEntity(t)}async createEntitiesInLocalDatabase(t){await this.#t.createEntities(t)}async createEntityRelationInLocalDatabase(t){await this.#t.createEntityRelation(t)}async createEntityRelationsInLocalDatabase(t){await this.#t.createEntityRelations(t)}async updateEntityByKey(t,e){const a=await this.#t.getEntityByKey(t);if(!a)throw new Error(`Entity with key ${t} not found`);const i=y(a,e),s=p(i);return await this.#e?.updateEntity({...s,id:a.id,createdAt:a.createdAt||""})}async deleteEntityByKey(t){const e=await this.#e?.deleteEntity(t);return await this.#s(t),e}async deleteEntitiesInLocalDatabase(t){await this.#t.deleteEntities(t)}async getEntityRelationById(t){return await this.#e?.sync(),await this.#t.getEntityRelationById(t)}async getEntitiesRelations(t={}){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntitiesRelations(t);return o({data:e,params:t,totalCount:a,nameTransformationsFromDatabase:l,hasMore:i})}async createEntityRelation(t){return this.#e?.createEntityRelation(t)}async createEntitiesRelations(t){const e=this.#e;return e?await c(t,u,async a=>e.createEntityRelation(a).then(i=>({status:"ok",resource:i})).catch(i=>({key:a.sourceKey,status:"error",error:i}))):(r.warn("No remote database found"),[])}async updateEntityRelation(t,e){const a=await this.#t.getEntityRelationById(t);if(!a)throw new Error(`Entity relation with id ${t} not found`);const i=y(a,e),s=f(i);return this.#e?.createEntityRelation(s)}async deleteEntityRelation(t){let e=await this.#e?.deleteEntityRelation(t);return e||(e=await this.#t.deleteEntityRelation(t)),e}async deleteEntityRelationsInLocalDatabase(t){await this.#t.deleteEntityRelations(t)}async getEntitiesWithRelations(t={}){await this.#e?.sync();const{items:e,total:a,hasMore:i}=await this.#t.getEntitiesWithRelations(t);return o({data:e,params:t,totalCount:a,hasMore:i})}async getEntityWithRelationsByKey(t,e={}){return this.#t.getEntityWithRelationsByKey(t,e)}async getRelatedEntities(t,e={}){await this.#e?.sync();const{items:a,total:i,hasMore:s}=await this.#t.getRelatedEntities(t,e);return o({data:a,params:e,totalCount:i,nameTransformationsFromDatabase:l,hasMore:s})}async#s(t){await this.#e?.deleteEntitiesRelations({op:"OR",conditions:[{field:"source_key",operator:"equal",value:t},{field:"target_key",operator:"equal",value:t}]})}async listEntityRevisions(t,e){return await this.#e?.sync(),this.#t.listEntityRevisions(t,e)}}export{n as CatalogEntitiesService};
@@ -22,6 +22,10 @@ export declare class CatalogEntitiesLocalReadRepository {
22
22
  attachDatabase(databasePath: string): Promise<void>;
23
23
  getEntities(paginationParams?: PaginationParams): Promise<ListResult<EntityReadModelSchema>>;
24
24
  listEntityRevisions(entityKey: string, version?: string | null): Promise<Pick<EntityReadModelSchema, 'version' | 'revision' | 'isCurrent' | 'createdAt' | 'updatedAt' | 'isDefaultVersion'>[]>;
25
+ getEntitiesCountByTypes(): Promise<{
26
+ type: string;
27
+ count: number;
28
+ }[]>;
25
29
  getEntityByKey(key: string): Promise<EntityReadModelSchema | null>;
26
30
  getEntitiesRelations(paginationParams?: PaginationParams): Promise<ListResult<EntityRelationReadModelSchema>>;
27
31
  getEntityRelationById(id: string): Promise<EntityRelationReadModelSchema | null>;
@@ -1,4 +1,4 @@
1
- import{and as o,eq as r,ne as M,notExists as N,or as B,sql as e}from"drizzle-orm";import{unionAll as k}from"drizzle-orm/sqlite-core";import{asc as Y}from"drizzle-orm";import{logger as X}from"../../../../../tools/notifiers/logger.js";import{isObject as G}from"../../../../../../utils/guards/is-object.js";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{applyFilter as Q,getFirstFilterFieldValue as x}from"../../../../../providers/database/pagination/filter.js";import{createBffRelatedEntity as z}from"../../mappers/create-bff-related-entity.js";import{createBffEntity as V}from"../../mappers/create-bff-entity.js";import{FIELDS_TO_SELECT_FOR_ENTITY as c,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as _,createEntityFieldsForSelect as j,createEntityRelationFieldsForSelect as Z,createQualifiedEntityFieldsForSelect as K,createQualifiedEntityFieldsForSelectWithAliases as ee}from"../utils.js";import{createEntityReadModel as P}from"../../mappers/create-entity-read-model.js";import{createEntityRelation as J}from"../../mappers/create-entity-relation.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";class fe{#e;#t=void 0;constructor(t){this.#e=t}async attachDatabase(t){this.#t!==t&&(this.#t=t,await this.#e.client.run(e`ATTACH DATABASE ${t} AS remote`))}async getEntities(t={}){const s=this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0)),n=this.#e.client.select(c).from(s.as("combined_entities")),l=this.#e.client.select(c).from(s.as("combined_entities")).$dynamic(),E=S(l,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),u=this.#e.client.$count(E),d=n.$dynamic(),m=t.limit||10,y=S(d,{...t,limit:m+1}),[f,h]=await Promise.all([y.run(),u]),T=f.rows,g=T.length>m;return{items:T.slice(0,m).map(w=>P(w)).filter(w=>w!==null),hasMore:g,total:h}}async listEntityRevisions(t,s){const n=[r(i.key,t),...s?[r(i.version,s)]:[]],l=this.#t?k(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 = ${t}`,s?e`version = ${s}`:void 0)),this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).where(o(...n,N(this.#e.client.select({version:e.raw("version")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.version = ${i.version}`,e`remote.revision = ${i.revision}`)))))):this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).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(l.as("combined_revisions")).orderBy(e.raw("is_current DESC"),e.raw("updated_at DESC"),e.raw("created_at DESC")).run()).rows.map(u=>({version:u.version||null,revision:u.revision||null,isCurrent:u.is_current!==null?!!u.is_current:!1,createdAt:u.created_at||null,updatedAt:u.updated_at||null,isDefaultVersion:u.is_default_version!==null?!!u.is_default_version:!1}))}async getEntityByKey(t){const l=(await(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(o(r(i.key,t),r(e.raw("is_current"),1))),this.#e.client.select(c).from(i).where(o(r(i.key,t),r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(o(r(i.key,t),r(i.isCurrent,!0)))).run()).rows[0];return l?P(l):null}async getEntitiesRelations(t={}){const s=this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a),n=this.#e.client.select(_).from(s.as("combined_entities_relations")).$dynamic(),l=this.#e.client.select(_).from(s.as("combined_entities_relations")).$dynamic(),E=S(l,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),u=this.#e.client.$count(E),d=t.limit||10,m=S(n,{...t,limit:d+1}),[y,f]=await Promise.all([m.run(),u]),h=y.rows,T=h.length>d;return{items:h.slice(0,d).map(g=>J(g)).filter(g=>g!==null),hasMore:T,total:f}}async getEntityRelationById(t){const l=(await(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`).where(r(a.id,t)),this.#e.client.select(_).from(a).where(o(r(a.id,t),N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.id = ${a.id}`))))):this.#e.client.select(_).from(a).where(r(a.id,t))).run()).rows[0];return l?J(l):null}async getEntitiesWithRelations(t={}){const n=(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0))).as("e"),E=(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a)).as("combined_relations"),d=(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0))).as("combined_target_entities"),m=this.#e.client.with(n,E,d).select({...j("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(n).as("entities_with_relations"),y={...c,domains:m.domains,owners:m.owners},f=this.#e.client.with(m).select(y).from(m).$dynamic(),h=this.#e.client.with(m).select(y).from(m).$dynamic(),{whereCondition:T}=Q(f,t.filter);T&&f.where(T);const{whereCondition:g}=Q(h,t.filter);g&&h.where(g);try{const w=S(h,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),I=this.#e.client.$count(w),R=t.limit||10,L=S(f,{...t,limit:R+1}),[$,p]=await Promise.all([L.run(),I]),v=$.rows,D=v.length>R;return{items:v.slice(0,R).map(C=>V(C)).filter(C=>C!==null),hasMore:D,total:p}}catch(w){return X.error("Error getting entities with relations:",w),{items:[],hasMore:!1,total:0}}}#i(t){return G(t)?t.field==="version"||t.field==="revision":Array.isArray(t)?t.some(s=>this.#i(s)):!1}async getEntityWithRelationsByKey(t,s={}){const n=this.#i(s.filter),l=n?[]:[r(i.isCurrent,!0)],E=n?[e`remote.version = ${i.version}`,e`remote.revision = ${i.revision}`]:[e`remote.is_current = 1`],u=this.#e.client.select(c).from(e`remote.entities`),d=n?u.where(r(e.raw("key"),t)):u.where(o(r(e.raw("key"),t),r(e.raw("is_current"),1))),m=this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,...E)),y=this.#e.client.select(c).from(i).where(o(r(i.key,t),...l,N(m))),f=this.#e.client.select(c).from(i),h=n?f.where(r(i.key,t)):f.where(o(r(i.key,t),r(i.isCurrent,!0))),g=(this.#t?k(d,y):h).as("e"),I=(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a)).as("combined_relations"),R=this.#e.client.select(c).from(e`remote.entities`),L=n?R:R.where(r(e.raw("is_current"),1)),$=this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,...E)),p=this.#e.client.select(c).from(i),v=p.where(o(...l,N($))),D=n?p:p.where(r(i.isCurrent,!0)),H=(this.#t?k(L,v):D).as("combined_target_entities"),b=this.#e.client.with(g,I,H).select({...j("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(g).as("entities_with_relations_by_key"),U={...c,domains:b.domains,owners:b.owners},A=this.#e.client.with(b).select(U).from(b).$dynamic();A.where(r(e.raw("key"),t));const{whereCondition:F}=Q(A,s.filter);F&&A.where(F),A.limit(1);const W=await A.run();if(W.rows.length===0)return null;const O=W.rows[0];return V(O)}async getRelatedEntities(t,s={}){const n=Z("","relation_id"),l=x(s.filter,"version"),E=x(s.filter,"revision"),u=[B(r(a.sourceKey,t),r(a.targetKey,t))],d=typeof l=="string"?B(o(r(a.sourceKey,t),r(a.sourceVersion,l)),o(r(a.targetKey,t),r(a.targetVersion,l))):void 0,m=typeof E=="string"?B(o(r(a.sourceKey,t),r(a.sourceRevision,E)),o(r(a.targetKey,t),r(a.targetRevision,E))):void 0,y=[...u,d,m].filter(O=>O!==void 0),h=(this.#t?k(this.#e.client.select(n).from(e`remote.entities_relations`).where(o(...y)),this.#e.client.select(n).from(a).where(o(...y,N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(o(e`remote.source_key = ${a.sourceKey}`,e`remote.target_key = ${a.targetKey}`,e`remote.source_to_target_relation = ${a.sourceToTargetRelation}`)))))):this.#e.client.select(n).from(a).where(o(...y))).as("combined_relations"),T=j("","entity_id"),w=(this.#t?k(this.#e.client.select(T).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(T).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(T).from(i).where(r(i.isCurrent,!0))).as("combined_target_entities"),I=ee("combined_target_entities"),R=Object.values(K("combined_target_entities")),L={...I,relation_type:e`
1
+ import{and as o,count as Y,eq as r,ne as M,notExists as N,or as B,sql as e}from"drizzle-orm";import{unionAll as k}from"drizzle-orm/sqlite-core";import{asc as G}from"drizzle-orm";import{logger as X}from"../../../../../tools/notifiers/logger.js";import{isObject as z}from"../../../../../../utils/guards/is-object.js";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{applyFilter as Q,getFirstFilterFieldValue as x}from"../../../../../providers/database/pagination/filter.js";import{createBffRelatedEntity as Z}from"../../mappers/create-bff-related-entity.js";import{createBffEntity as V}from"../../mappers/create-bff-entity.js";import{FIELDS_TO_SELECT_FOR_ENTITY as c,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as _,createEntityFieldsForSelect as j,createEntityRelationFieldsForSelect as K,createQualifiedEntityFieldsForSelect as ee,createQualifiedEntityFieldsForSelectWithAliases as te}from"../utils.js";import{createEntityReadModel as P}from"../../mappers/create-entity-read-model.js";import{createEntityRelation as J}from"../../mappers/create-entity-relation.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";class we{#e;#t=void 0;constructor(t){this.#e=t}async attachDatabase(t){this.#t!==t&&(this.#t=t,await this.#e.client.run(e`ATTACH DATABASE ${t} AS remote`))}async getEntities(t={}){const s=this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0)),n=this.#e.client.select(c).from(s.as("combined_entities")),l=this.#e.client.select(c).from(s.as("combined_entities")).$dynamic(),E=S(l,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),u=this.#e.client.$count(E),d=n.$dynamic(),m=t.limit||10,y=S(d,{...t,limit:m+1}),[f,h]=await Promise.all([y.run(),u]),T=f.rows,g=T.length>m;return{items:T.slice(0,m).map(w=>P(w)).filter(w=>w!==null),hasMore:g,total:h}}async listEntityRevisions(t,s){const n=[r(i.key,t),...s?[r(i.version,s)]:[]],l=this.#t?k(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 = ${t}`,s?e`version = ${s}`:void 0)),this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).where(o(...n,N(this.#e.client.select({version:e.raw("version")}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.version = ${i.version}`,e`remote.revision = ${i.revision}`)))))):this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).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(l.as("combined_revisions")).orderBy(e.raw("is_current DESC"),e.raw("updated_at DESC"),e.raw("created_at DESC")).run()).rows.map(u=>({version:u.version||null,revision:u.revision||null,isCurrent:u.is_current!==null?!!u.is_current:!1,createdAt:u.created_at||null,updatedAt:u.updated_at||null,isDefaultVersion:u.is_default_version!==null?!!u.is_default_version:!1}))}async getEntitiesCountByTypes(){return this.#e.client.select({type:i.type,count:Y()}).from(i).groupBy(i.type)}async getEntityByKey(t){const l=(await(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(o(r(i.key,t),r(e.raw("is_current"),1))),this.#e.client.select(c).from(i).where(o(r(i.key,t),r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(o(r(i.key,t),r(i.isCurrent,!0)))).run()).rows[0];return l?P(l):null}async getEntitiesRelations(t={}){const s=this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a),n=this.#e.client.select(_).from(s.as("combined_entities_relations")).$dynamic(),l=this.#e.client.select(_).from(s.as("combined_entities_relations")).$dynamic(),E=S(l,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),u=this.#e.client.$count(E),d=t.limit||10,m=S(n,{...t,limit:d+1}),[y,f]=await Promise.all([m.run(),u]),h=y.rows,T=h.length>d;return{items:h.slice(0,d).map(g=>J(g)).filter(g=>g!==null),hasMore:T,total:f}}async getEntityRelationById(t){const l=(await(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`).where(r(a.id,t)),this.#e.client.select(_).from(a).where(o(r(a.id,t),N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.id = ${a.id}`))))):this.#e.client.select(_).from(a).where(r(a.id,t))).run()).rows[0];return l?J(l):null}async getEntitiesWithRelations(t={}){const n=(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0))).as("e"),E=(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a)).as("combined_relations"),d=(this.#t?k(this.#e.client.select(c).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(c).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(c).from(i).where(r(i.isCurrent,!0))).as("combined_target_entities"),m=this.#e.client.with(n,E,d).select({...j("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(n).as("entities_with_relations"),y={...c,domains:m.domains,owners:m.owners},f=this.#e.client.with(m).select(y).from(m).$dynamic(),h=this.#e.client.with(m).select(y).from(m).$dynamic(),{whereCondition:T}=Q(f,t.filter);T&&f.where(T);const{whereCondition:g}=Q(h,t.filter);g&&h.where(g);try{const w=S(h,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),I=this.#e.client.$count(w),R=t.limit||10,L=S(f,{...t,limit:R+1}),[$,p]=await Promise.all([L.run(),I]),v=$.rows,D=v.length>R;return{items:v.slice(0,R).map(C=>V(C)).filter(C=>C!==null),hasMore:D,total:p}}catch(w){return X.error("Error getting entities with relations:",w),{items:[],hasMore:!1,total:0}}}#i(t){return z(t)?t.field==="version"||t.field==="revision":Array.isArray(t)?t.some(s=>this.#i(s)):!1}async getEntityWithRelationsByKey(t,s={}){const n=this.#i(s.filter),l=n?[]:[r(i.isCurrent,!0)],E=n?[e`remote.version = ${i.version}`,e`remote.revision = ${i.revision}`]:[e`remote.is_current = 1`],u=this.#e.client.select(c).from(e`remote.entities`),d=n?u.where(r(e.raw("key"),t)):u.where(o(r(e.raw("key"),t),r(e.raw("is_current"),1))),m=this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,...E)),y=this.#e.client.select(c).from(i).where(o(r(i.key,t),...l,N(m))),f=this.#e.client.select(c).from(i),h=n?f.where(r(i.key,t)):f.where(o(r(i.key,t),r(i.isCurrent,!0))),g=(this.#t?k(d,y):h).as("e"),I=(this.#t?k(this.#e.client.select(_).from(e`remote.entities_relations`),this.#e.client.select(_).from(a).where(N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${a.sourceKey}`)))):this.#e.client.select(_).from(a)).as("combined_relations"),R=this.#e.client.select(c).from(e`remote.entities`),L=n?R:R.where(r(e.raw("is_current"),1)),$=this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,...E)),p=this.#e.client.select(c).from(i),v=p.where(o(...l,N($))),D=n?p:p.where(r(i.isCurrent,!0)),H=(this.#t?k(L,v):D).as("combined_target_entities"),b=this.#e.client.with(g,I,H).select({...j("e"),domains:this.#r("e").as("domains"),owners:this.#s("e").as("owners")}).from(g).as("entities_with_relations_by_key"),U={...c,domains:b.domains,owners:b.owners},A=this.#e.client.with(b).select(U).from(b).$dynamic();A.where(r(e.raw("key"),t));const{whereCondition:F}=Q(A,s.filter);F&&A.where(F),A.limit(1);const W=await A.run();if(W.rows.length===0)return null;const O=W.rows[0];return V(O)}async getRelatedEntities(t,s={}){const n=K("","relation_id"),l=x(s.filter,"version"),E=x(s.filter,"revision"),u=[B(r(a.sourceKey,t),r(a.targetKey,t))],d=typeof l=="string"?B(o(r(a.sourceKey,t),r(a.sourceVersion,l)),o(r(a.targetKey,t),r(a.targetVersion,l))):void 0,m=typeof E=="string"?B(o(r(a.sourceKey,t),r(a.sourceRevision,E)),o(r(a.targetKey,t),r(a.targetRevision,E))):void 0,y=[...u,d,m].filter(O=>O!==void 0),h=(this.#t?k(this.#e.client.select(n).from(e`remote.entities_relations`).where(o(...y)),this.#e.client.select(n).from(a).where(o(...y,N(this.#e.client.select({id:_.id}).from(e`remote.entities_relations as remote`).where(o(e`remote.source_key = ${a.sourceKey}`,e`remote.target_key = ${a.targetKey}`,e`remote.source_to_target_relation = ${a.sourceToTargetRelation}`)))))):this.#e.client.select(n).from(a).where(o(...y))).as("combined_relations"),T=j("","entity_id"),w=(this.#t?k(this.#e.client.select(T).from(e`remote.entities`).where(r(e.raw("is_current"),1)),this.#e.client.select(T).from(i).where(o(r(i.isCurrent,!0),N(this.#e.client.select({id:c.id}).from(e`remote.entities as remote`).where(o(e`remote.key = ${i.key}`,e`remote.is_current = 1`)))))):this.#e.client.select(T).from(i).where(r(i.isCurrent,!0))).as("combined_target_entities"),I=te("combined_target_entities"),R=Object.values(ee("combined_target_entities")),L={...I,relation_type:e`
2
2
  CASE
3
3
  WHEN COUNT(CASE WHEN combined_target_entities.key = combined_relations.source_key THEN 1 END) > 0
4
4
  THEN MIN(CASE WHEN combined_target_entities.key = combined_relations.source_key THEN combined_relations.source_to_target_relation END)
@@ -10,7 +10,7 @@ import{and as o,eq as r,ne as M,notExists as N,or as B,sql as e}from"drizzle-orm
10
10
  THEN 'source'
11
11
  ELSE 'target'
12
12
  END
13
- `.as("relation_role")},$=this.#e.client.with(h,w).select(L).from(h).innerJoin(w,B(r(e.raw("combined_relations.source_key"),e.raw("combined_target_entities.key")),r(e.raw("combined_relations.target_key"),e.raw("combined_target_entities.key")))).where(M(e.raw("combined_target_entities.key"),t)).groupBy(...R).having(M(e.raw("MIN(combined_target_entities.key)"),t)).orderBy(Y(e.raw("relation_role"))).$dynamic(),p=this.#e.client.with(h,w).select(I).from(h).innerJoin(w,B(r(e.raw("combined_relations.source_key"),e.raw("combined_target_entities.key")),r(e.raw("combined_relations.target_key"),e.raw("combined_target_entities.key")))).where(M(e.raw("combined_target_entities.key"),t)).groupBy(...R).having(M(e.raw("MIN(combined_target_entities.key)"),t)).$dynamic(),v=S(p,{...s,limit:void 0,skip:void 0,after:void 0,before:void 0}),D=this.#e.client.$count(v),C=s.limit||10,H={...s,limit:C+1},b=S($,H),[U,A]=await Promise.all([b.run(),D]),F=U.rows,W=F.length>C;return{items:F.slice(0,C).map(O=>z(O)).filter(O=>O!==null),hasMore:W,total:A}}async getCatalogFilters({entitiesTypes:t=[],emptyFilters:s=[]}){if(!s.length)return{};try{return await this.#n(t),(s.includes("domains")||s.includes("owners"))&&await this.#o(),await this.#a(s)}catch(n){return console.error("Error fetching catalog filters:",n),{}}finally{await this.#l()}}async#n(t){if(this.#t?await this.#e.client.run(e`
13
+ `.as("relation_role")},$=this.#e.client.with(h,w).select(L).from(h).innerJoin(w,B(r(e.raw("combined_relations.source_key"),e.raw("combined_target_entities.key")),r(e.raw("combined_relations.target_key"),e.raw("combined_target_entities.key")))).where(M(e.raw("combined_target_entities.key"),t)).groupBy(...R).having(M(e.raw("MIN(combined_target_entities.key)"),t)).orderBy(G(e.raw("relation_role"))).$dynamic(),p=this.#e.client.with(h,w).select(I).from(h).innerJoin(w,B(r(e.raw("combined_relations.source_key"),e.raw("combined_target_entities.key")),r(e.raw("combined_relations.target_key"),e.raw("combined_target_entities.key")))).where(M(e.raw("combined_target_entities.key"),t)).groupBy(...R).having(M(e.raw("MIN(combined_target_entities.key)"),t)).$dynamic(),v=S(p,{...s,limit:void 0,skip:void 0,after:void 0,before:void 0}),D=this.#e.client.$count(v),C=s.limit||10,H={...s,limit:C+1},b=S($,H),[U,A]=await Promise.all([b.run(),D]),F=U.rows,W=F.length>C;return{items:F.slice(0,C).map(O=>Z(O)).filter(O=>O!==null),hasMore:W,total:A}}async getCatalogFilters({entitiesTypes:t=[],emptyFilters:s=[]}){if(!s.length)return{};try{return await this.#n(t),(s.includes("domains")||s.includes("owners"))&&await this.#o(),await this.#a(s)}catch(n){return console.error("Error fetching catalog filters:",n),{}}finally{await this.#l()}}async#n(t){if(this.#t?await this.#e.client.run(e`
14
14
  CREATE TEMP TABLE IF NOT EXISTS temp_combined_entities AS
15
15
  SELECT
16
16
  e.key,
@@ -121,7 +121,7 @@ import{and as o,eq as r,ne as M,notExists as N,or as B,sql as e}from"drizzle-orm
121
121
  INNER JOIN temp_combined_entities tce ON tce.key = owner_key
122
122
  WHERE owner_key IS NOT NULL
123
123
  GROUP BY owner_key
124
- `);for(const d of l)await this.#c(d,s);if(n.length===0)return s;const E=n.join(" UNION ALL "),u=await this.#e.client.run(e.raw(E));if(u?.rows)for(const d of u.rows){const m=d.filter_name,y=d.value,f=Number(d.count)||0;s[m]||(s[m]=[]),y&&s[m].push({value:y,count:f})}return s}async#c(t,s){const n=t.substring(9),l=`$.${te(n)}`,E=await this.#e.client.run(e.raw(`
124
+ `);for(const d of l)await this.#c(d,s);if(n.length===0)return s;const E=n.join(" UNION ALL "),u=await this.#e.client.run(e.raw(E));if(u?.rows)for(const d of u.rows){const m=d.filter_name,y=d.value,f=Number(d.count)||0;s[m]||(s[m]=[]),y&&s[m].push({value:y,count:f})}return s}async#c(t,s){const n=t.substring(9),l=`$.${ie(n)}`,E=await this.#e.client.run(e.raw(`
125
125
  SELECT json_extract(metadata, '${l}') as value, COUNT(*) as count
126
126
  FROM temp_filtered_entities
127
127
  WHERE metadata IS NOT NULL
@@ -223,4 +223,4 @@ import{and as o,eq as r,ne as M,notExists as N,or as B,sql as e}from"drizzle-orm
223
223
  ),
224
224
  json_array()
225
225
  )
226
- `}}function te(q){return q.replace(/[^a-zA-Z0-9._-]/g,"")}export{fe as CatalogEntitiesLocalReadRepository};
226
+ `}}function ie(q){return q.replace(/[^a-zA-Z0-9._-]/g,"")}export{we as CatalogEntitiesLocalReadRepository};
@@ -14,6 +14,10 @@ export declare class CatalogEntitiesLocalRepository extends BaseRepository {
14
14
  attachDatabase(databasePath: string): Promise<void>;
15
15
  getEntities(paginationParams?: PaginationParams): Promise<import("./catalog-entities-local-read-repository.js").ListResult<import("../../../schemas/read-model-schemas.js").EntityReadModelSchema>>;
16
16
  getEntityByKey(key: string): Promise<import("../../../schemas/read-model-schemas.js").EntityReadModelSchema | null>;
17
+ getEntitiesCountByTypes(): Promise<{
18
+ type: string;
19
+ count: number;
20
+ }[]>;
17
21
  getEntitiesRelations(paginationParams?: PaginationParams): Promise<import("./catalog-entities-local-read-repository.js").ListResult<{
18
22
  createdAt?: string | null | undefined;
19
23
  updatedAt?: string | null | undefined;
@@ -1 +1 @@
1
- import{promiseMapLimit as n}from"../../../../../utils/async/promise-map-limit.js";import{CatalogEntitiesLocalReadRepository as r}from"./catalog-entities-local-read-repository.js";import{CatalogEntitiesLocalWriteRepository as o}from"./catalog-entities-local-write-repository.js";import{createEntityRelationDbRecordFromDto as y}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{BaseRepository as l}from"../../../../../providers/database/base-repository.js";import{LocalDatabaseInitializationStrategy as h}from"../../../../../providers/database/database-initialization-strategy.js";import{CATALOG_DATABASE_MIGRATIONS_FOLDER as E,CATALOG_LOCAL_DATABASE_FOLDER as c,CATALOG_LOCAL_DATABASE_NAME as d}from"../../consts.js";import{hasOptionsChanged as R}from"../../../utils/has-options-changed.js";const a=50;class i extends l{static#i;static#n;#t;#e;#a={};constructor(t){super(t),this.#t=new r(this.databaseClient),this.#e=new o(this.databaseClient,this.organizationId,this.projectId)}get transactionsManager(){return this.databaseClient.transactionsManager}getEntitySources(){return this.#a}static async getInstance(t){const e=R(i.#n,t);if(!i.#i||e){const s=await new h().initialize({databaseName:d,additionalFolder:c,migrationsFolder:E,...t});i.#i=new i(s),i.#n=t}return i.#i}async attachDatabase(t){await this.#t.attachDatabase(t)}getEntities(t={}){return this.#t.getEntities(t)}getEntityByKey(t){return this.#t.getEntityByKey(t)}getEntitiesRelations(t={}){return this.#t.getEntitiesRelations(t)}getEntityRelationById(t){return this.#t.getEntityRelationById(t)}getEntitiesWithRelations(t={}){return this.#t.getEntitiesWithRelations(t)}getEntityWithRelationsByKey(t,e={}){return this.#t.getEntityWithRelationsByKey(t,e)}getRelatedEntities(t,e={}){return this.#t.getRelatedEntities(t,e)}createEntity(t){return t.isRootEntity&&(this.#a[t.sourceFile]=t.entity.key),this.#e.createEntity(t)}async createEntities(t){await n(t,a,async e=>this.createEntity(e))}createEntityRelation(t){const e=y(t,this.organizationId,this.projectId);return this.#e.createEntityRelation(e)}async createEntityRelations(t){await n(t,a,async e=>this.createEntityRelation(e))}deleteEntity(t){return this.#e.deleteEntity(t)}deleteEntities(t){return this.#e.deleteEntities(t)}deleteEntityRelation(t){return this.#e.deleteEntityRelation(t)}deleteEntityRelations(t){return this.#e.deleteEntityRelations(t)}getCatalogFilters(t){return this.#t.getCatalogFilters(t)}listEntityRevisions(t,e){return this.#t.listEntityRevisions(t,e)}}export{i as CatalogEntitiesLocalRepository};
1
+ import{promiseMapLimit as n}from"../../../../../utils/async/promise-map-limit.js";import{CatalogEntitiesLocalReadRepository as r}from"./catalog-entities-local-read-repository.js";import{CatalogEntitiesLocalWriteRepository as o}from"./catalog-entities-local-write-repository.js";import{createEntityRelationDbRecordFromDto as y}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{BaseRepository as l}from"../../../../../providers/database/base-repository.js";import{LocalDatabaseInitializationStrategy as h}from"../../../../../providers/database/database-initialization-strategy.js";import{CATALOG_DATABASE_MIGRATIONS_FOLDER as E,CATALOG_LOCAL_DATABASE_FOLDER as c,CATALOG_LOCAL_DATABASE_NAME as d}from"../../consts.js";import{hasOptionsChanged as R}from"../../../utils/has-options-changed.js";const s=50;class i extends l{static#i;static#n;#t;#e;#s={};constructor(t){super(t),this.#t=new r(this.databaseClient),this.#e=new o(this.databaseClient,this.organizationId,this.projectId)}get transactionsManager(){return this.databaseClient.transactionsManager}getEntitySources(){return this.#s}static async getInstance(t){const e=R(i.#n,t);if(!i.#i||e){const a=await new h().initialize({databaseName:d,additionalFolder:c,migrationsFolder:E,...t});i.#i=new i(a),i.#n=t}return i.#i}async attachDatabase(t){await this.#t.attachDatabase(t)}getEntities(t={}){return this.#t.getEntities(t)}getEntityByKey(t){return this.#t.getEntityByKey(t)}getEntitiesCountByTypes(){return this.#t.getEntitiesCountByTypes()}getEntitiesRelations(t={}){return this.#t.getEntitiesRelations(t)}getEntityRelationById(t){return this.#t.getEntityRelationById(t)}getEntitiesWithRelations(t={}){return this.#t.getEntitiesWithRelations(t)}getEntityWithRelationsByKey(t,e={}){return this.#t.getEntityWithRelationsByKey(t,e)}getRelatedEntities(t,e={}){return this.#t.getRelatedEntities(t,e)}createEntity(t){return t.isRootEntity&&(this.#s[t.sourceFile]=t.entity.key),this.#e.createEntity(t)}async createEntities(t){await n(t,s,async e=>this.createEntity(e))}createEntityRelation(t){const e=y(t,this.organizationId,this.projectId);return this.#e.createEntityRelation(e)}async createEntityRelations(t){await n(t,s,async e=>this.createEntityRelation(e))}deleteEntity(t){return this.#e.deleteEntity(t)}deleteEntities(t){return this.#e.deleteEntities(t)}deleteEntityRelation(t){return this.#e.deleteEntityRelation(t)}deleteEntityRelations(t){return this.#e.deleteEntityRelations(t)}getCatalogFilters(t){return this.#t.getCatalogFilters(t)}listEntityRevisions(t,e){return this.#t.listEntityRevisions(t,e)}}export{i as CatalogEntitiesLocalRepository};
@@ -8,6 +8,7 @@ export declare class CatalogEntitiesRemoteRepository extends BaseRepository {
8
8
  #private;
9
9
  get transactionsManager(): import("../../../../../providers/database/transactions-manager.js").TransactionsManager;
10
10
  constructor(initializationResult: DatabaseInitializationResult);
11
+ sync(): Promise<void>;
11
12
  static getInstance(options: RepositoryInstanceOptions): Promise<CatalogEntitiesRemoteRepository | undefined>;
12
13
  createEntity(entity: EntityDtoSchema): Promise<EntityReadModelSchema | null>;
13
14
  updateEntity(entity: EntityDtoSchema & {
@@ -1 +1 @@
1
- import{eq as E}from"drizzle-orm";import{convertFilterToWhereCondition as m}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as g}from"../../../../../utils/async/promise-map-limit.js";import{logger as r}from"../../../../../tools/notifiers/logger.js";import{SQLD_REMOTE_DATABASE_FOLDER as h,SQLD_REMOTE_DATABASE_MIGRATIONS_FOLDER as A,SQLD_REMOTE_DATABASE_NAME as T}from"../../../../../constants/sqld-remote-database.js";import{createEntityDbRecord as y}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as f}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as D}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as n}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{BaseRepository as R}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionsManager as _}from"../../../../../providers/database/database-connections-manager.js";import{RemoteDatabaseInitializationStrategy as b}from"../../../../../providers/database/database-initialization-strategy.js";const w=15;class a extends R{static#e;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t)}static async getInstance(t){if(!a.#e){if(!process.env.SQLD_REMOTE_DATABASE_URL||!process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN){r.warn("SQLD_REMOTE_DATABASE_URL and SQLD_REMOTE_DATABASE_AUTH_TOKEN env variables not set - remote database will not be initialized");return}try{const e=await _.getConnection({config:{...t,databaseName:T,additionalFolder:h,migrationsFolder:A,syncUrl:process.env.SQLD_REMOTE_DATABASE_URL,authToken:process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN},strategy:new b});if(!e){r.warn("Remote database connection failed"),a.#e=void 0;return}a.#e=new a(e)}catch{a.#e=void 0;return}}return a.#e}async createEntity(t){try{r.info(`Adding entity ${t.key} to remote database`);const e=y({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:l,source:d,...s}=e,o=await this.databaseClient.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source],set:s}).returning();return o.length?(t.relations&&await this.createEntityRelations(t.relations.map(c=>({...c,sourceKey:t.key,targetKey:c.key}))),f(o[0])):null}catch(e){throw r.error("Error adding entity",e),e}}async updateEntity(t){try{r.info(`Updating entity ${t.key} in remote database`);const e=y({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:l,source:d,...s}=e,o=await this.databaseClient.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source],set:s}).returning();return o.length?f(o[0]):null}catch(e){return r.error("Error updating entity",e),null}}async deleteEntity(t){try{return await this.databaseClient.client.delete(i).where(E(i.key,t)),t}catch(e){return r.error("Error deleting entity",e),null}}async createEntityRelations(t){return await g(t,w,async e=>this.createEntityRelation(e))}async createEntityRelation(t){if(!t)return null;try{const e=D(t,this.organizationId,this.projectId),{sourceKey:l,targetKey:d,sourceVersion:s,targetVersion:o,sourceRevision:c,targetRevision:S,...p}=e,u=await this.databaseClient.client.insert(n).values(e).onConflictDoUpdate({target:[n.sourceKey,n.targetKey,n.sourceVersion,n.targetVersion,n.sourceRevision,n.targetRevision],set:p}).returning();return u.length?u[0]:null}catch(e){throw r.error("Error creating entity relation",e),e}}async deleteEntityRelation(t){try{return await this.databaseClient.client.delete(n).where(E(n.id,t)),t}catch(e){return r.error("Error deleting entity relation",e),null}}async deleteEntitiesRelations(t){try{const e=m(t);return e?(await this.databaseClient.client.delete(n).where(e),!0):!1}catch(e){return r.error("Error deleting entities relations",e),!1}}}export{a as CatalogEntitiesRemoteRepository};
1
+ import{eq as _}from"drizzle-orm";import{convertFilterToWhereCondition as p}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as g}from"../../../../../utils/async/promise-map-limit.js";import{logger as n}from"../../../../../tools/notifiers/logger.js";import{SQLD_REMOTE_DATABASE_FOLDER as f,SQLD_REMOTE_DATABASE_MIGRATIONS_FOLDER as A,SQLD_REMOTE_DATABASE_NAME as T}from"../../../../../constants/sqld-remote-database.js";import{telemetryTraceStep as i}from"../../../../../telemetry/helpers/trace-step.js";import{createEntityDbRecord as E}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as m}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as w}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{entitiesTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{BaseRepository as D}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionsManager as b}from"../../../../../providers/database/database-connections-manager.js";import{RemoteDatabaseInitializationStrategy as R}from"../../../../../providers/database/database-initialization-strategy.js";const S=15;class s extends D{static#t;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t)}async sync(){return i("catalog_entities.remote_repository.sync",async()=>{await this.#e(),await this.databaseClient.sync()})}static async getInstance(t){return await i("catalog_entities.remote_repository.get_instance",async e=>{if(!s.#t){if(!process.env.SQLD_REMOTE_DATABASE_URL||!process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN){n.warn("SQLD_REMOTE_DATABASE_URL and SQLD_REMOTE_DATABASE_AUTH_TOKEN env variables not set - remote database will not be initialized"),e?.error(new Error("SQLD_REMOTE_DATABASE_URL and SQLD_REMOTE_DATABASE_AUTH_TOKEN env variables not set - remote database will not be initialized"));return}try{const o=await b.getConnection({config:{...t,databaseName:T,additionalFolder:f,migrationsFolder:A,syncUrl:process.env.SQLD_REMOTE_DATABASE_URL,authToken:process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN},strategy:new R});if(!o){n.warn("Remote database connection failed!"),e?.error(new Error("Remote database connection failed!")),s.#t=void 0;return}s.#t=new s(o)}catch(o){s.#t=void 0,e?.error(o);return}}return s.#t})}async createEntity(t){return i("catalog_entities.remote_repository.create_entity",async()=>{await this.#e();try{n.info(`Adding entity ${t.key} to remote database`);const e=E({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,...l}=e,c=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:l}).returning();return c.length?(t.relations&&await this.createEntityRelations(t.relations.map(d=>({...d,sourceKey:t.key,targetKey:d.key}))),m(c[0])):null}catch(e){throw n.error("Error adding entity",e),e}})}async updateEntity(t){return i("catalog_entities.remote_repository.update_entity",async()=>{await this.#e();try{n.info(`Updating entity ${t.key} in remote database`);const e=E({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,...l}=e,c=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:l}).returning();return c.length?m(c[0]):null}catch(e){return n.error("Error updating entity",e),null}})}async deleteEntity(t){return i("catalog_entities.remote_repository.delete_entity",async()=>{await this.#e();try{return await this.databaseClient.client.delete(r).where(_(r.key,t)),t}catch(e){return n.error("Error deleting entity",e),null}})}async createEntityRelations(t){return i("catalog_entities.remote_repository.create_entity_relations",async()=>(await this.#e(),await g(t,S,async e=>this.createEntityRelation(e))))}async createEntityRelation(t){return i("catalog_entities.remote_repository.create_entity_relation",async()=>{if(await this.#e(),!t)return null;try{const e=w(t,this.organizationId,this.projectId),{sourceKey:o,targetKey:u,sourceVersion:l,targetVersion:c,sourceRevision:d,targetRevision:v,...h}=e,y=await this.databaseClient.client.insert(a).values(e).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision],set:h}).returning();return y.length?y[0]:null}catch(e){throw n.error("Error creating entity relation",e),e}})}async deleteEntityRelation(t){return i("catalog_entities.remote_repository.delete_entity_relation",async()=>{await this.#e();try{return await this.databaseClient.client.delete(a).where(_(a.id,t)),t}catch(e){return n.error("Error deleting entity relation",e),null}})}async deleteEntitiesRelations(t){return i("catalog_entities.remote_repository.delete_entities_relations",async()=>{await this.#e();try{const e=p(t);return e?(await this.databaseClient.client.delete(a).where(e),!0):!1}catch(e){return n.error("Error deleting entities relations",e),!1}})}#e(){return i("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{s as CatalogEntitiesRemoteRepository};
@@ -1,6 +1,7 @@
1
1
  import type { BundledDefinition } from '../../../../arazzo-docs/arazzo-doc-loader.js';
2
2
  import type { EntityFileSchema } from '@redocly/config';
3
- import { BaseApiEntitiesExtractor, type BaseApiEntitiesExtractorParams } from './base.js';
3
+ import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
4
+ import { BaseApiEntitiesExtractor } from './base.js';
4
5
  type Params = BaseApiEntitiesExtractorParams;
5
6
  export declare class ArazzoEntitiesExtractor extends BaseApiEntitiesExtractor<BundledDefinition> {
6
7
  #private;
@@ -1 +1 @@
1
- import h from"node:path";import{removeLeadingSlash as u}from"@redocly/theme/core/utils";import{toKebabCase as p}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as y}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as d}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as g}from"./base.js";import{resolveEntityVersion as w}from"../../../utils/resolve-entity-version.js";const m=15;class A extends g{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t){const o=u(t.realRelativePath),a=t.document.info.title,c=o.replace(/\.[^.]+$/,""),e=p(c.replace(/[\\/]/g,"-")),r=t.document["x-redocly-catalog-key"],n=typeof r=="string"&&r.trim()?p(r.trim()):e,l=t.document.info.version,s=w(l,t.realRelativePath);if(!s.success)throw new Error(`Arazzo "${a}" in file "${t.realRelativePath}" has conflicting versions: spec version "${s.fileVersion}" differs from folder version "${s.folderVersion}". Entity will not be created.`);return{type:this.type,key:n,title:a,summary:t.document.info.description?d(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:o},version:s.version}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t){const o=new Set;if(!this.#t(t))return this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`),o;const a=this.mapApiDescriptionToEntity(t);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:a,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0}),o.add(a.key),await this.#e(t,a.key,a.version,o);const c=t.document.sourceDescriptions||[];return await y(c,m,async e=>{if(!(e.type!=="openapi"||!e.url))try{const r=this.resolveSourceDescriptionUrl(e.url,t.realRelativePath);if(!r){!e.url.startsWith("http://")&&!e.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${e.url}`);return}const n=await this.context.cache.load(r,"load-oas");if(!(n.data&&Array.isArray(n.data)&&n.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${r}`);return}const s=n.data[0],i=p(u(s.realRelativePath).replace(/\.[^.]+$/,"").replace(/[\\/]/g,"-"));await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a.key,type:"relatesTo",targetKey:i,fileHash:t.hash}),await this.#r(t,e.name,s,a.key,i,a.version)}catch(r){this.context.logger.warn(`Failed to create relation to OpenAPI source "${e.url}": ${r instanceof Error?r.message:"Unknown error"}`)}}),o}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,o,a,c)=>{try{const e=t.document.components?.inputs,r=e?Object.entries(e):[],n=[];for(const[l,s]of r)n.push(async()=>{const i=await this.#a({schemaName:l,schema:s,description:t,parentKey:o,parentVersion:a});c.add(i),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o,type:"uses",targetKey:i,fileHash:t.hash,sourceVersion:a,targetVersion:a})});if(n.length===0)return;await y(n,m,l=>l())}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:o,description:a,parentKey:c,parentVersion:e})=>{const r={type:"data-schema",key:`${c}-${p(t)}`,title:t,summary:o.description||o.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:e};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:r,sourceFile:a.realRelativePath,fileHash:a.hash}),r.key};#r=async(t,o,a,c,e,r)=>{const n=t.document.workflows||[];if(n.length===0)return;const l=new Set;for(const s of n)for(const i of s.steps||[]){if(!i.operationId)continue;const f=i.operationId.startsWith(`${o}.`)?i.operationId.substring(`${o}.`.length):i.operationId;f&&l.add(f)}l.size!==0&&await y(Array.from(l),m,async s=>{try{const i=`${e}-${p(s)}`;await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:c,type:"uses",targetKey:i,fileHash:t.hash,sourceVersion:r,targetVersion:r})}catch(i){this.context.logger.warn(`Failed to create relation to operation "${s}": ${i instanceof Error?i.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,o){try{const a=t.trim(),c=a.startsWith("@")?a.slice(1):a,[e]=c.split("#");if(e.startsWith("http://")||e.startsWith("https://"))return null;if(e.startsWith("/"))return u(h.posix.normalize(e));const r=h.posix.dirname(o);return e.startsWith(r+"/")?h.posix.normalize(e):h.posix.normalize(h.posix.join(r,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{A as ArazzoEntitiesExtractor};
1
+ import h from"node:path";import{removeLeadingSlash as u}from"@redocly/theme/core/utils";import{toKebabCase as p}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as y}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as d}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{resolveEntityVersion as g}from"../../../utils/resolve-entity-version.js";import{BaseApiEntitiesExtractor as w}from"./base.js";const m=15;class A extends w{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t){const o=u(t.realRelativePath),a=t.document.info.title,c=o.replace(/\.[^.]+$/,""),e=p(c.replace(/[\\/]/g,"-")),r=t.document["x-redocly-catalog-key"],n=typeof r=="string"&&r.trim()?p(r.trim()):e,l=t.document.info.version,s=g(l,t.realRelativePath);if(!s.success)throw new Error(`Arazzo "${a}" in file "${t.realRelativePath}" has conflicting versions: spec version "${s.fileVersion}" differs from folder version "${s.folderVersion}". Entity will not be created.`);return{type:this.type,key:n,title:a,summary:t.document.info.description?d(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:o},version:s.version}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t){const o=new Set;if(!this.#t(t))return this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`),o;const a=this.mapApiDescriptionToEntity(t);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:a,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0}),o.add(a.key),await this.#e(t,a.key,a.version,o);const c=t.document.sourceDescriptions||[];return await y(c,m,async e=>{if(!(e.type!=="openapi"||!e.url))try{const r=this.resolveSourceDescriptionUrl(e.url,t.realRelativePath);if(!r){!e.url.startsWith("http://")&&!e.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${e.url}`);return}const n=await this.context.cache.load(r,"load-oas");if(!(n.data&&Array.isArray(n.data)&&n.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${r}`);return}const s=n.data[0],i=p(u(s.realRelativePath).replace(/\.[^.]+$/,"").replace(/[\\/]/g,"-"));await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a.key,type:"relatesTo",targetKey:i,fileHash:t.hash}),await this.#r(t,e.name,s,a.key,i,a.version)}catch(r){this.context.logger.warn(`Failed to create relation to OpenAPI source "${e.url}": ${r instanceof Error?r.message:"Unknown error"}`)}}),o}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,o,a,c)=>{try{const e=t.document.components?.inputs,r=e?Object.entries(e):[],n=[];for(const[l,s]of r)n.push(async()=>{const i=await this.#a({schemaName:l,schema:s,description:t,parentKey:o,parentVersion:a});c.add(i),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o,type:"uses",targetKey:i,fileHash:t.hash,sourceVersion:a,targetVersion:a})});if(n.length===0)return;await y(n,m,l=>l())}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:o,description:a,parentKey:c,parentVersion:e})=>{const r={type:"data-schema",key:`${c}-${p(t)}`,title:t,summary:o.description||o.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:e};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:r,sourceFile:a.realRelativePath,fileHash:a.hash}),r.key};#r=async(t,o,a,c,e,r)=>{const n=t.document.workflows||[];if(n.length===0)return;const l=new Set;for(const s of n)for(const i of s.steps||[]){if(!i.operationId)continue;const f=i.operationId.startsWith(`${o}.`)?i.operationId.substring(`${o}.`.length):i.operationId;f&&l.add(f)}l.size!==0&&await y(Array.from(l),m,async s=>{try{const i=`${e}-${p(s)}`;await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:c,type:"uses",targetKey:i,fileHash:t.hash,sourceVersion:r,targetVersion:r})}catch(i){this.context.logger.warn(`Failed to create relation to operation "${s}": ${i instanceof Error?i.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,o){try{const a=t.trim(),c=a.startsWith("@")?a.slice(1):a,[e]=c.split("#");if(e.startsWith("http://")||e.startsWith("https://"))return null;if(e.startsWith("/"))return u(h.posix.normalize(e));const r=h.posix.dirname(o);return e.startsWith(r+"/")?h.posix.normalize(e):h.posix.normalize(h.posix.join(r,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{A as ArazzoEntitiesExtractor};
@@ -1,6 +1,7 @@
1
1
  import type { BundledDefinition } from '../../../../asyncapi-docs/asyncapi-doc-loader';
2
2
  import type { EntityFileSchema } from '@redocly/config';
3
- import { BaseApiEntitiesExtractor, type BaseApiEntitiesExtractorParams } from './base.js';
3
+ import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
4
+ import { BaseApiEntitiesExtractor } from './base.js';
4
5
  type Params = BaseApiEntitiesExtractorParams;
5
6
  export declare class AsyncApiEntitiesExtractor extends BaseApiEntitiesExtractor<BundledDefinition> {
6
7
  #private;
@@ -1,19 +1,10 @@
1
1
  import type { FileInfo, LifecycleContext, ProcessContentActions } from '../../../../../types';
2
2
  import type { CatalogEntitiesService } from '../../../database/catalog-entities-service.js';
3
3
  import type { EntityFileSchema } from '@redocly/config';
4
- import type { ApiDescriptionMetadataSchema } from '@redocly/config';
5
4
  import type { BaseEntitiesExtractor } from '../base';
6
5
  import type { FileType } from '../../../../../persistence/file-hashes/types.js';
7
6
  import type { HashManager } from '../../../utils/hash-manager.js';
8
- type SpecType = Exclude<ApiDescriptionMetadataSchema['specType'], 'jsonschema' | 'avro' | 'zod' | 'protobuf'>;
9
- export type BaseApiEntitiesExtractorParams = {
10
- actions: ProcessContentActions;
11
- context: LifecycleContext;
12
- catalogEntitiesService: CatalogEntitiesService;
13
- fileHashManager: HashManager;
14
- fileType: FileType;
15
- shouldCalculateEntities?: boolean;
16
- };
7
+ import type { BaseApiEntitiesExtractorParams, SpecType } from '../../../types/extractors.js';
17
8
  export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition extends Pick<FileInfo, 'realRelativePath' | 'relativePath' | 'isVirtual' | 'hash'>> implements BaseEntitiesExtractor {
18
9
  #private;
19
10
  protected type: "api-description";
@@ -30,5 +21,4 @@ export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition exte
30
21
  protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition): EntityFileSchema;
31
22
  protected abstract processApiDescription(definition: BundledApiDefinition): Promise<Set<string>>;
32
23
  }
33
- export {};
34
24
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- import{FileHashStatus as a}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as l}from"../../../../../utils/async/promise-map-limit.js";const r=3;class u{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),await l(t,r,async e=>{try{if(e.isVirtual||!e.hash)return;if(!((await this.fileHashManager.getByPath(e.realRelativePath))?.hash!==e.hash||this.#e||process.env.FORCE_CATALOG_CACHE_REVALIDATE==="true")){await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,a.UP_TO_DATE);return}const s=await this.processApiDescription(e);await this.#i(s,e.realRelativePath),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,a.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({limit:200,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:a.OUTDATED}]})};#i=async(t,e)=>{t.size!==0&&await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({op:"AND",conditions:[{field:"key",operator:"in",value:Array.from(t),modifier:"not"},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]})}}export{u as BaseApiEntitiesExtractor};
1
+ import{FileHashStatus as a}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as r}from"../../../../../utils/async/promise-map-limit.js";import{catalogDataCollector as s}from"../../../utils/catalog-data-collector.js";const o=3;class p{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&&s.addExtractor(this.specType),await r(t,o,async e=>{try{if(e.isVirtual||!e.hash)return;if(!((await this.fileHashManager.getByPath(e.realRelativePath))?.hash!==e.hash||this.#e||process.env.FORCE_CATALOG_CACHE_REVALIDATE==="true")){s.increaseSkippedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,a.UP_TO_DATE);return}const l=await this.processApiDescription(e);await this.#i(l,e.realRelativePath),s.increaseProcessedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,a.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({limit:200,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:a.OUTDATED}]})};#i=async(t,e)=>{t.size!==0&&await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({op:"AND",conditions:[{field:"key",operator:"in",value:Array.from(t),modifier:"not"},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]})}}export{p as BaseApiEntitiesExtractor};
@@ -1,7 +1,8 @@
1
1
  import type { GraphQLSchema } from 'graphql';
2
2
  import type { EntityFileSchema } from '@redocly/config';
3
3
  import type { FileInfo } from '../../../../../types';
4
- import { BaseApiEntitiesExtractor, type BaseApiEntitiesExtractorParams } from './base.js';
4
+ import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
5
+ import { BaseApiEntitiesExtractor } from './base.js';
5
6
  type GraphqlBundledDefinition = Omit<Pick<FileInfo, 'realRelativePath' | 'relativePath' | 'isVirtual' | 'hash'>, 'hash'> & {
6
7
  hash: string;
7
8
  schema: GraphQLSchema;
@@ -1,3 +1,3 @@
1
- import{buildSchema as v,isObjectType as m,isScalarType as R,isEnumType as I,isInterfaceType as T,isUnionType as d,isInputObjectType as w,getNamedType as y,printType as $}from"graphql";import{removeLeadingSlash as O}from"@redocly/theme/core/utils";import{toKebabCase as f}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as D}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as u}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as S}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as L}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as F}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as A}from"./base.js";import{resolveEntityVersion as j}from"../../../utils/resolve-entity-version.js";const E=15,b=15,N=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class Q extends A{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of await this.context.fs.scan(/(\.gql|\.graphql)$/))try{if(e.includes("@l10n")||await this.context.isPathIgnored(e))continue;const a=await this.context.cache.load(e,"graphql-doc");if(!a.data)continue;const{content:s,metadata:o}=a.data,r=v(s),l=L(s);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:l,schema:r,content:s,metadata:o})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t){const e=O(t.realRelativePath),a=t.relativePath.replace(/\.(gql|graphql)$/,""),s=this.#s(a.split("/").pop()||"GraphQL Schema"),o=e.replace(/\.(gql|graphql)$/,""),r=f(o.replace(/[\\/]/g,"-")),l=this.#c(t.metadata?.tags),c=t.metadata?.["x-redocly-catalog-key"],i=typeof c=="string"&&c.trim()?f(c.trim()):r,n=j(null,t.realRelativePath),p=n.success?n.version:null;return{type:this.type,key:i,title:s,summary:t.metadata?.description||null,tags:l.concat("graphql"),metadata:{specType:this.specType,descriptionFile:e},version:p}}async processApiDescription(t){const e=new Set,{schema:a}=t;if(!a)return e;const s=this.mapApiDescriptionToEntity(t);return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:s,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0}),e.add(s.key),await Promise.all([this.#a(t,s.key,s.version,e),this.#y(t,s.key,s.version,e)]),e}#a=async(t,e,a,s)=>{const{schema:o}=t,r=o.getTypeMap(),l=this.#r(o),c=Object.entries(r).filter(([n])=>!n.startsWith("__")&&!N.has(n)&&!l.has(n));if(c.length===0)return;const i=await S(c,b,async([n,p])=>{const h=await this.#l({typeName:n,type:p,description:t,parentKey:e,parentVersion:a});s.add(h),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"uses",targetKey:h,fileHash:t.hash,sourceVersion:a,targetVersion:a})},this.#t);i.count.failed>0&&this.#t.warn(`Schema processing completed with ${i.count.failed} failures out of ${c.length} types for ${t.realRelativePath}`),await this.#h({description:t,descriptionUniqueKey:e,userTypes:c})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&D(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${f(t)}`;#n=t=>m(t)?"object":T(t)?"interface":d(t)?"union":I(t)?"enum":w(t)?"input":R(t)?"scalar":"unknown";#r=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const s=t.getMutationType();s&&e.add(s.name);const o=t.getSubscriptionType();return o&&e.add(o.name),e};#i(t){const e=[],a=t.getQueryType();if(a){const r=a.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"QUERY",rootTypeName:a.name})}const s=t.getMutationType();if(s){const r=s.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"MUTATION",rootTypeName:s.name})}const o=t.getSubscriptionType();if(o){const r=o.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"SUBSCRIBE",rootTypeName:o.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const r of t.args){const l=y(r.type);l&&!l.name.startsWith("__")&&a.push(this.#e(l.name,e))}const s=[],o=y(t.type);return o&&!o.name.startsWith("__")&&s.push(this.#e(o.name,e)),{inputTypes:a,returnTypes:s}};#c=t=>{if(Array.isArray(t))return t.map(e=>String(e)).map(e=>e.trim()).filter(e=>e.length>0);if(typeof t=="string"){const e=t.trim();return e?[e]:[]}return[]};#l=async({typeName:t,type:e,description:a,parentKey:s,parentVersion:o})=>{const r=this.#e(t,s),l=e.description??null,c=this.#n(e),i={type:"data-schema",key:r,title:t,summary:l,tags:["graphql"],metadata:{specType:this.specType,typeKind:c,sdl:this.#p(e,a.schema)},version:o};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:i,sourceFile:a.realRelativePath,fileHash:a.hash}),i.key};#p=(t,e)=>{const a=new Set,s=[],o=new Set(["String","ID","Int","Float","Boolean"]),r=i=>{if(!i)return;const n=i.name;if(n.startsWith("__")||o.has(n)||a.has(n))return;const p=e.getType(n);p&&(a.add(n),s.push(p))};for(r(t);s.length>0;){const i=s.pop();if(m(i)){for(const p of i.getInterfaces?.()??[])r(p);const n=i.getFields();for(const p of Object.values(n)){r(y(p.type));for(const h of p.args??[])r(y(h.type))}}else if(T(i)){const n=i.getFields();for(const p of Object.values(n))r(y(p.type))}else if(d(i))for(const n of i.getTypes())r(n);else if(w(i)){const n=i.getFields();for(const p of Object.values(n))r(y(p.type))}}const l=[t.name,...[...a].filter(i=>i!==t.name)],c=[];for(const i of l){const n=e.getType(i);n&&c.push($(n))}return c.join(`
1
+ import{buildSchema as v,isObjectType as m,isScalarType as R,isEnumType as I,isInterfaceType as T,isUnionType as d,isInputObjectType as w,getNamedType as y,printType as $}from"graphql";import{removeLeadingSlash as O}from"@redocly/theme/core/utils";import{toKebabCase as f}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as D}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as u}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as S}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as L}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as F}from"../../../../markdown/markdoc/helpers/remove-markdoc-tags.js";import{resolveEntityVersion as A}from"../../../utils/resolve-entity-version.js";import{BaseApiEntitiesExtractor as j}from"./base.js";const E=15,b=15,N=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class Q extends j{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of await this.context.fs.scan(/(\.gql|\.graphql)$/))try{if(e.includes("@l10n")||await this.context.isPathIgnored(e))continue;const a=await this.context.cache.load(e,"graphql-doc");if(!a.data)continue;const{content:s,metadata:o}=a.data,r=v(s),l=L(s);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:l,schema:r,content:s,metadata:o})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t){const e=O(t.realRelativePath),a=t.relativePath.replace(/\.(gql|graphql)$/,""),s=this.#s(a.split("/").pop()||"GraphQL Schema"),o=e.replace(/\.(gql|graphql)$/,""),r=f(o.replace(/[\\/]/g,"-")),l=this.#c(t.metadata?.tags),c=t.metadata?.["x-redocly-catalog-key"],i=typeof c=="string"&&c.trim()?f(c.trim()):r,n=A(null,t.realRelativePath),p=n.success?n.version:null;return{type:this.type,key:i,title:s,summary:t.metadata?.description||null,tags:l.concat("graphql"),metadata:{specType:this.specType,descriptionFile:e},version:p}}async processApiDescription(t){const e=new Set,{schema:a}=t;if(!a)return e;const s=this.mapApiDescriptionToEntity(t);return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:s,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0}),e.add(s.key),await Promise.all([this.#a(t,s.key,s.version,e),this.#y(t,s.key,s.version,e)]),e}#a=async(t,e,a,s)=>{const{schema:o}=t,r=o.getTypeMap(),l=this.#r(o),c=Object.entries(r).filter(([n])=>!n.startsWith("__")&&!N.has(n)&&!l.has(n));if(c.length===0)return;const i=await S(c,b,async([n,p])=>{const h=await this.#l({typeName:n,type:p,description:t,parentKey:e,parentVersion:a});s.add(h),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"uses",targetKey:h,fileHash:t.hash,sourceVersion:a,targetVersion:a})},this.#t);i.count.failed>0&&this.#t.warn(`Schema processing completed with ${i.count.failed} failures out of ${c.length} types for ${t.realRelativePath}`),await this.#h({description:t,descriptionUniqueKey:e,userTypes:c})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&D(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${f(t)}`;#n=t=>m(t)?"object":T(t)?"interface":d(t)?"union":I(t)?"enum":w(t)?"input":R(t)?"scalar":"unknown";#r=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const s=t.getMutationType();s&&e.add(s.name);const o=t.getSubscriptionType();return o&&e.add(o.name),e};#i(t){const e=[],a=t.getQueryType();if(a){const r=a.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"QUERY",rootTypeName:a.name})}const s=t.getMutationType();if(s){const r=s.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"MUTATION",rootTypeName:s.name})}const o=t.getSubscriptionType();if(o){const r=o.getFields();for(const[l,c]of Object.entries(r))e.push({fieldName:l,field:c,operationType:"SUBSCRIBE",rootTypeName:o.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const r of t.args){const l=y(r.type);l&&!l.name.startsWith("__")&&a.push(this.#e(l.name,e))}const s=[],o=y(t.type);return o&&!o.name.startsWith("__")&&s.push(this.#e(o.name,e)),{inputTypes:a,returnTypes:s}};#c=t=>{if(Array.isArray(t))return t.map(e=>String(e)).map(e=>e.trim()).filter(e=>e.length>0);if(typeof t=="string"){const e=t.trim();return e?[e]:[]}return[]};#l=async({typeName:t,type:e,description:a,parentKey:s,parentVersion:o})=>{const r=this.#e(t,s),l=e.description??null,c=this.#n(e),i={type:"data-schema",key:r,title:t,summary:l,tags:["graphql"],metadata:{specType:this.specType,typeKind:c,sdl:this.#p(e,a.schema)},version:o};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:i,sourceFile:a.realRelativePath,fileHash:a.hash}),i.key};#p=(t,e)=>{const a=new Set,s=[],o=new Set(["String","ID","Int","Float","Boolean"]),r=i=>{if(!i)return;const n=i.name;if(n.startsWith("__")||o.has(n)||a.has(n))return;const p=e.getType(n);p&&(a.add(n),s.push(p))};for(r(t);s.length>0;){const i=s.pop();if(m(i)){for(const p of i.getInterfaces?.()??[])r(p);const n=i.getFields();for(const p of Object.values(n)){r(y(p.type));for(const h of p.args??[])r(y(h.type))}}else if(T(i)){const n=i.getFields();for(const p of Object.values(n))r(y(p.type))}else if(d(i))for(const n of i.getTypes())r(n);else if(w(i)){const n=i.getFields();for(const p of Object.values(n))r(y(p.type))}}const l=[t.name,...[...a].filter(i=>i!==t.name)],c=[];for(const i of l){const n=e.getType(i);n&&c.push($(n))}return c.join(`
2
2
 
3
3
  `)};#h=async({description:t,descriptionUniqueKey:e,userTypes:a})=>{const s=a.filter(([,o])=>m(o));s.length!==0&&await u(s,b,async([o,r])=>{const c=r.getInterfaces?.()??[];if(!c.length)return;const i=this.#e(o,e);await u([...c],5,async n=>{const p=this.#e(n.name,e);try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:i,type:"implements",targetKey:p,fileHash:t.hash})}catch(h){this.#t.warn(`Failed to create 'implements' relation ${i} -> ${p}: ${h instanceof Error?h.message:"Unknown error"}`)}})})};#y=async(t,e,a,s)=>{const{schema:o}=t,r=this.#i(o);if(r.length===0)return;const c=(await S(r,E,async({fieldName:i,field:n,operationType:p,rootTypeName:h})=>{const g=await this.#f(i,n,p,h,t,e,a);g&&s.add(g)},this.#t)).count.failed;c>0&&this.#t.warn(`Operation extraction completed with ${c} failures out of ${r.length} operations for ${e}`)};#f=async(t,e,a,s,o,r,l)=>{const{inputTypes:c,returnTypes:i}=this.#o(e,r),n=await this.#m({fieldName:t,field:e,operationType:a,rootTypeName:s,inputTypes:c,returnTypes:i,description:o,descriptionUniqueKey:r,descriptionVersion:l});return await this.#u({apiOperationKey:n,inputTypes:c,returnTypes:i,descriptionUniqueKey:r,description:o,descriptionVersion:l}),n??null};#m=async({fieldName:t,field:e,operationType:a,rootTypeName:s,inputTypes:o,returnTypes:r,description:l,descriptionUniqueKey:c,descriptionVersion:i})=>{const n=t,p=`${c}-${f(`${a.toLowerCase()}-${t}`)}`,h={type:"api-operation",key:p,title:n,summary:e.description?F(e.description):null,tags:["graphql"],metadata:{method:a,path:`${s}.${t}`,payload:o,responses:r},version:i};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:h,sourceFile:l.realRelativePath,fileHash:l.hash}),p};#u=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:s,description:o,descriptionVersion:r})=>{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:"partOf",targetKey:s,fileHash:o.hash,sourceVersion:r,targetVersion:r});const l=[...new Set(e)],c=[...new Set(a)],i=[...l.map(n=>({key:n,relationType:"uses"})),...c.map(n=>({key:n,relationType:"returns"}))];await u(i,E,async({key:n,relationType:p})=>{try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:p,targetKey:n,fileHash:o.hash,sourceVersion:r,targetVersion:r})}catch(h){this.#t.warn(`Failed to create relation between operation ${t} and type ${n} (${p}): ${h instanceof Error?h.message:"Unknown error"}`)}})}}export{Q as GraphqlEntitiesExtractor};
@@ -1,6 +1,7 @@
1
1
  import type { BundledDefinition } from '../../../../openapi-docs/load-definition';
2
2
  import type { EntityFileSchema } from '@redocly/config';
3
- import { BaseApiEntitiesExtractor, type BaseApiEntitiesExtractorParams } from './base.js';
3
+ import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
4
+ import { BaseApiEntitiesExtractor } from './base.js';
4
5
  export declare class OpenApiEntitiesExtractor extends BaseApiEntitiesExtractor<BundledDefinition> {
5
6
  #private;
6
7
  constructor(params: BaseApiEntitiesExtractorParams);
@@ -1 +1 @@
1
- import{CATALOG_ENTITIES_FILES_REGEX as l,ENTITY_SCHEMA_EXCLUDED_FOLDERS as E}from"../../../../constants/plugins/catalog-entities.js";import{FileHashStatus as c,FileType as a}from"../../../../persistence/file-hashes/types.js";import{promiseMapLimit as f}from"../../../../utils/async/promise-map-limit.js";import{extractFileContent as u}from"../../entities/extract-entities-content.js";import{resolveEntityVersion as d}from"../../utils/resolve-entity-version.js";import{parseAndValidateEntities as h}from"../../entities/validate-entity.js";const g=15;class _{#e;#t;#i;#s;#r;constructor({fileHashManager:t,context:e,catalogEntitiesService:i,catalogConfig:r,shouldCalculateEntities:o}){this.#e=t,this.#t=e,this.#i=i,this.#s=r,this.#r=o}async extract(t){try{if(t&&this.#o(t)){await this.#n(t);return}await this.#e.markAllAsOutdated(a.ENTITY_DEFINITION);const i=(await this.#t.fs.scan(l)).filter(({relativePath:r})=>this.#o(r));await f(i,g,async({relativePath:r})=>{await this.#n(r)}),await this.#E()}catch(e){this.#t.logger.error("Error extracting entities.",e)}}#o=t=>!!(t.match(l)&&!E.some(e=>t.includes(e)));#n=async t=>{try{const e=await u(t,this.#t);if(!e){this.#t.logger.warn(`Error extracting content from ${t}.`);return}const i=await this.#e.computeFileHash(e);if(!((await this.#e.getByPath(t))?.hash!==i||this.#r||process.env.FORCE_CATALOG_CACHE_REVALIDATE==="true")){await this.#e.upsert(a.ENTITY_DEFINITION,t,i,c.UP_TO_DATE);return}const s=this.#a(e.entities,t);if(!s)return;const n=await this.#c(s,t,i);await this.#l(n,t),await this.#e.upsert(a.ENTITY_DEFINITION,t,i,c.UP_TO_DATE)}catch(e){this.#t.logger.warn(`Error processing file "${t}". ${e instanceof Error?e.message:String(e)}.`)}};#a=(t,e)=>{try{return h(t,this.#s)}catch(i){return this.#t.logger.warn(`Error validating entities in "${e}". ${i instanceof Error?i.message:String(i)}.`),null}};#c=async(t,e,i)=>{const r=new Set;for(const o of t)try{const s=d(o.version,e);if(!s.success){this.#t.logger.warn(`Entity "${o.key}" in file "${e}" has conflicting versions: file version "${s.fileVersion}" differs from folder version "${s.folderVersion}". Entity will not be created.`);continue}const n={...o,version:s.version};await this.#i.createEntityInLocalDatabase({entity:n,sourceFile:e,fileHash:i}),o.key&&r.add(o.key)}catch(s){const n=o.key??"unknown";this.#t.logger.warn(`Error processing entity "${n}" from "${e}". ${s instanceof Error?s.message:String(s)}.`)}return r};#l=async(t,e)=>{t.size!==0&&await this.#i.deleteEntitiesInLocalDatabase({op:"AND",conditions:[{field:"key",operator:"in",value:Array.from(t),modifier:"not"},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]})};#E=async()=>{const t=await this.#e.getAllOutdated(a.ENTITY_DEFINITION);if(!t||t.length===0)return;const e=await this.#i.getEntities({limit:200,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.#i.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:e.items.map(({key:i})=>i)}),await this.#e.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:a.ENTITY_DEFINITION},{field:"status",operator:"equal",value:c.OUTDATED}]}))}}export{_ as FsEntitiesExtractor};
1
+ import{CATALOG_ENTITIES_FILES_REGEX as f,ENTITY_SCHEMA_EXCLUDED_FOLDERS as E}from"../../../../constants/plugins/catalog-entities.js";import{FileHashStatus as c,FileType as a}from"../../../../persistence/file-hashes/types.js";import{promiseMapLimit as u}from"../../../../utils/async/promise-map-limit.js";import{extractFileContent as d}from"../../entities/extract-entities-content.js";import{resolveEntityVersion as h}from"../../utils/resolve-entity-version.js";import{parseAndValidateEntities as g}from"../../entities/validate-entity.js";import{catalogDataCollector as l}from"../../utils/catalog-data-collector.js";const m=15;class D{#e;#t;#i;#r;#s;constructor({fileHashManager:t,context:e,catalogEntitiesService:i,catalogConfig:s,shouldCalculateEntities:o}){this.#e=t,this.#t=e,this.#i=i,this.#r=s,this.#s=o}async extract(t){try{if(t&&this.#o(t)){await this.#n(t);return}await this.#e.markAllAsOutdated(a.ENTITY_DEFINITION);const i=(await this.#t.fs.scan(f)).filter(({relativePath:s})=>this.#o(s));i.length&&l.addExtractor("fs"),await u(i,m,async({relativePath:s})=>{await this.#n(s)}),await this.#f()}catch(e){this.#t.logger.error("Error extracting entities.",e)}}#o=t=>!!(t.match(f)&&!E.some(e=>t.includes(e)));#n=async t=>{try{const e=await d(t,this.#t);if(!e){this.#t.logger.warn(`Error extracting content from ${t}.`);return}const i=await this.#e.computeFileHash(e);if(!((await this.#e.getByPath(t))?.hash!==i||this.#s||process.env.FORCE_CATALOG_CACHE_REVALIDATE==="true")){l.increaseSkippedFilesCount(),await this.#e.upsert(a.ENTITY_DEFINITION,t,i,c.UP_TO_DATE);return}const r=this.#a(e.entities,t);if(!r)return;const n=await this.#c(r,t,i);await this.#l(n,t),l.increaseProcessedFilesCount(),await this.#e.upsert(a.ENTITY_DEFINITION,t,i,c.UP_TO_DATE)}catch(e){this.#t.logger.warn(`Error processing file "${t}". ${e instanceof Error?e.message:String(e)}.`)}};#a=(t,e)=>{try{return g(t,this.#r)}catch(i){return this.#t.logger.warn(`Error validating entities in "${e}". ${i instanceof Error?i.message:String(i)}.`),null}};#c=async(t,e,i)=>{const s=new Set;for(const o of t)try{const r=h(o.version,e);if(!r.success){this.#t.logger.warn(`Entity "${o.key}" in file "${e}" has conflicting versions: file version "${r.fileVersion}" differs from folder version "${r.folderVersion}". Entity will not be created.`);continue}const n={...o,version:r.version};await this.#i.createEntityInLocalDatabase({entity:n,sourceFile:e,fileHash:i}),o.key&&s.add(o.key)}catch(r){const n=o.key??"unknown";this.#t.logger.warn(`Error processing entity "${n}" from "${e}". ${r instanceof Error?r.message:String(r)}.`)}return s};#l=async(t,e)=>{t.size!==0&&await this.#i.deleteEntitiesInLocalDatabase({op:"AND",conditions:[{field:"key",operator:"in",value:Array.from(t),modifier:"not"},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]})};#f=async()=>{const t=await this.#e.getAllOutdated(a.ENTITY_DEFINITION);if(!t||t.length===0)return;const e=await this.#i.getEntities({limit:200,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.#i.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:e.items.map(({key:i})=>i)}),await this.#e.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:a.ENTITY_DEFINITION},{field:"status",operator:"equal",value:c.OUTDATED}]}))}}export{D as FsEntitiesExtractor};
@@ -1 +1 @@
1
- import{FileType as n}from"../../persistence/file-hashes/types.js";import{telemetryTraceStep as O}from"../../../cli/telemetry/helpers/trace-step.js";import{CATALOG_BASE_SLUG as l,CATALOG_FILTERS_CACHE_NAMESPACE as D,ENTITIES_MAP_GLOBAL_DATA_KEY as P}from"../../constants/plugins/catalog-entities.js";import{CacheService as v}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as m}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as y}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as h}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as L}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as N}from"../../persistence/file-hashes/services/file-hashes-service.js";import{CatalogEntitiesService as w}from"./database/catalog-entities-service.js";import{ArazzoEntitiesExtractor as R}from"./extensions/extractors/api-description/arazzo-entities-extractor.js";import{FsEntitiesExtractor as b}from"./extensions/extractors/fs-entities-extractor.js";import{HashManager as G}from"./utils/hash-manager.js";import{OpenApiEntitiesExtractor as x}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const H="catalog-entity-template",M="catalog-entity";let g=!0;async function F(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(e,t){await O("build.plugin.catalog_entities",async E=>{if(process.env.NEW_CATALOG_ENABLED!=="true")return;const f=await t.getConfig(),a=y(f.entitiesCatalog);if(E?.setAttribute("config",JSON.stringify(a)),!a.show)return;const{logger:o}=t,u=process.env.NODE_ENV==="development"||process.env.REDOCLY_LOCAL_DEV==="true",i=g&&u,r=await w.getInstance({baseDbDir:e.serverOutDir,removeExisting:i,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),A=await N.getInstance({baseDbDir:e.serverOutDir}),s=new G(A),T=[new b({fileHashManager:s,context:t,catalogEntitiesService:r,catalogConfig:a,shouldCalculateEntities:i}),new x({actions:e,context:t,catalogEntitiesService:r,fileHashManager:s,fileType:n.OPENAPI_DESCRIPTION,shouldCalculateEntities:i}),new h({actions:e,context:t,catalogEntitiesService:r,fileHashManager:s,fileType:n.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:i}),new L({actions:e,context:t,catalogEntitiesService:r,fileHashManager:s,fileType:n.GRAPHQL_DESCRIPTION,shouldCalculateEntities:i}),new R({actions:e,context:t,catalogEntitiesService:r,fileHashManager:s,fileType:n.ARAZZO_DESCRIPTION,shouldCalculateEntities:i})];o.info("Starting entities extractors...");const C=o.startTiming();await r.transaction(async()=>{await Promise.all(T.map(async p=>p.extract()))});const S=r.getEntitySources();e.setGlobalData({[P]:S}),await(await v.getInstance({baseDbDir:e.serverOutDir})).deleteByNamespace(D),o.infoTime(C,"Entities extractors finished");const _=e.registerServerPropsGetter(M,m("../get-server-props.js")),d=e.createTemplate(H,m("../template/index.js"));e.addRoute({duplicateInAllLocales:!0,slug:l,fsPath:"",templateId:d,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[_],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:a}})});const[c]=Object.entries(a.catalogs??{}).find(([p,I])=>!I?.hide)||[];c&&e.addRedirect(l,{type:302,to:`${l}/${c}`}),o.info("Catalog Entities plugin finished"),g=!1})}}}var ee=F;export{F as catalogEntitiesPlugin,ee as default};
1
+ import{FileType as c}from"../../persistence/file-hashes/types.js";import{telemetryTraceStep as _}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as P}from"./utils/catalog-data-collector.js";import{CATALOG_BASE_SLUG as p,CATALOG_FILTERS_CACHE_NAMESPACE as I,ENTITIES_MAP_GLOBAL_DATA_KEY as v}from"../../constants/plugins/catalog-entities.js";import{CacheService as h}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as E}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as N}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as b}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as L}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as w}from"../../persistence/file-hashes/services/file-hashes-service.js";import{CatalogEntitiesService as R}from"./database/catalog-entities-service.js";import{ArazzoEntitiesExtractor as G}from"./extensions/extractors/api-description/arazzo-entities-extractor.js";import{FsEntitiesExtractor as x}from"./extensions/extractors/fs-entities-extractor.js";import{HashManager as F}from"./utils/hash-manager.js";import{OpenApiEntitiesExtractor as B}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const H="catalog-entity-template",M="catalog-entity";let u=!0;async function Y(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,i){await _("build.plugin.catalog_entities",async r=>{if(process.env.NEW_CATALOG_ENABLED!=="true")return;const f=await i.getConfig(),s=N(f.entitiesCatalog);if(r?.setAttribute("config",JSON.stringify(s)),!s.show)return;const{logger:l}=i,A=process.env.NODE_ENV==="development"||process.env.REDOCLY_LOCAL_DEV==="true",a=u&&A,e=await R.getInstance({baseDbDir:t.serverOutDir,removeExisting:a,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),C=await w.getInstance({baseDbDir:t.serverOutDir}),o=new F(C),T=[new x({fileHashManager:o,context:i,catalogEntitiesService:e,catalogConfig:s,shouldCalculateEntities:a}),new B({actions:t,context:i,catalogEntitiesService:e,fileHashManager:o,fileType:c.OPENAPI_DESCRIPTION,shouldCalculateEntities:a}),new b({actions:t,context:i,catalogEntitiesService:e,fileHashManager:o,fileType:c.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:a}),new L({actions:t,context:i,catalogEntitiesService:e,fileHashManager:o,fileType:c.GRAPHQL_DESCRIPTION,shouldCalculateEntities:a}),new G({actions:t,context:i,catalogEntitiesService:e,fileHashManager:o,fileType:c.ARAZZO_DESCRIPTION,shouldCalculateEntities:a})];l.info("Starting entities extractors...");const y=l.startTiming();await e.transaction(async()=>{await Promise.all(T.map(async m=>m.extract()))});const d=e.getEntitySources();t.setGlobalData({[v]:d}),await(await h.getInstance({baseDbDir:t.serverOutDir})).deleteByNamespace(I),l.infoTime(y,"Entities extractors finished");const S=t.registerServerPropsGetter(M,E("../get-server-props.js")),D=t.createTemplate(H,E("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:p,fsPath:"",templateId:D,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[S],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:s}})});const[g]=Object.entries(s.catalogs??{}).find(([m,O])=>!O?.hide)||[];g&&t.addRedirect(p,{type:302,to:`${p}/${g}`});const n=await P.getCatalogEntitiesData(e);r?.setAttribute("totalEntities",n.totalEntitiesCount),r?.setAttribute("entitiesCountByType",JSON.stringify(n.countOfEntitiesByType)),r?.setAttribute("totalFilesSkippedByHash",n.totalFilesSkippedByHash),r?.setAttribute("totalProcessedFiles",n.totalProcessedFiles),r?.setAttribute("extractors",n.extractors),l.info("Catalog Entities plugin finished"),u=!1})}}}var rt=Y;export{Y as catalogEntitiesPlugin,rt as default};
@@ -0,0 +1,16 @@
1
+ import type { ApiDescriptionMetadataSchema } from '@redocly/config';
2
+ import type { ProcessContentActions } from '../../../types/plugins/common';
3
+ import type { LifecycleContext } from '../../../types/plugins/common';
4
+ import type { CatalogEntitiesService } from '../database/catalog-entities-service.js';
5
+ import type { FileType } from '../../../persistence/file-hashes/types.js';
6
+ import type { HashManager } from '../utils/hash-manager.js';
7
+ export type SpecType = Exclude<ApiDescriptionMetadataSchema['specType'], 'jsonschema' | 'avro' | 'zod' | 'protobuf'>;
8
+ export type BaseApiEntitiesExtractorParams = {
9
+ actions: ProcessContentActions;
10
+ context: LifecycleContext;
11
+ catalogEntitiesService: CatalogEntitiesService;
12
+ fileHashManager: HashManager;
13
+ fileType: FileType;
14
+ shouldCalculateEntities?: boolean;
15
+ };
16
+ //# sourceMappingURL=extractors.d.ts.map
@@ -0,0 +1,20 @@
1
+ import type { SpecType } from '../types/extractors';
2
+ import type { CatalogEntitiesService } from '../database/catalog-entities-service';
3
+ type Extractor = SpecType | 'fs';
4
+ type CountOfEntitiesByType = Record<string, number>;
5
+ export declare class CatalogDataCollector {
6
+ #private;
7
+ addExtractor(extractor: Extractor): void;
8
+ increaseSkippedFilesCount(): void;
9
+ increaseProcessedFilesCount(): void;
10
+ getCatalogEntitiesData(catalogEntitiesService: CatalogEntitiesService): Promise<{
11
+ totalEntitiesCount: number | "error";
12
+ countOfEntitiesByType: "error" | CountOfEntitiesByType;
13
+ extractors: Extractor[];
14
+ totalFilesSkippedByHash: number;
15
+ totalProcessedFiles: number;
16
+ }>;
17
+ }
18
+ export declare const catalogDataCollector: CatalogDataCollector;
19
+ export {};
20
+ //# sourceMappingURL=catalog-data-collector.d.ts.map
@@ -0,0 +1 @@
1
+ const i="error";class a{#t=new Set;#e;#s;#i=0;#o=0;addExtractor(t){this.#t.add(t)}increaseSkippedFilesCount(){this.#i++}increaseProcessedFilesCount(){this.#o++}async getCatalogEntitiesData(t){this.#e=this.#n(t),this.#s=this.#a(t);const[s,e]=await Promise.allSettled([this.#e,this.#s]);return{totalEntitiesCount:s.status==="fulfilled"?s.value:i,countOfEntitiesByType:e.status==="fulfilled"?e.value:i,extractors:Array.from(this.#t),totalFilesSkippedByHash:this.#i,totalProcessedFiles:this.#o}}async#n(t){return(await t.getEntities({})).page.total}async#a(t){return(await t.getEntitiesCountByTypes()).reduce((e,{type:o,count:n})=>(e[o]=n,e),{})}}const l=new a;export{a as CatalogDataCollector,l as catalogDataCollector};
@@ -21,4 +21,13 @@ export type SearchOptions = {
21
21
  searchableFields: string[];
22
22
  value: string;
23
23
  };
24
+ export type PaginationParamsInput = {
25
+ after?: string;
26
+ before?: string;
27
+ sort?: string;
28
+ filter?: string;
29
+ search?: string;
30
+ limit?: string | number;
31
+ skip?: string | number;
32
+ };
24
33
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- import{CatalogEntitiesService as o}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as c}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_FROM_DATABASE as m}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";const l=["id","key","title","type","summary","source","sourceFile","createdAt","updatedAt"];function g(r){return async e=>{const a=await o.getInstance({baseDbDir:r.serverOutDir});try{const t=e.req.param("entityKey");if(!t)return e.json({message:"Entity key is required"},400);const i=e.req.query(),s=c(l,m).parse(i),n=await a.getRelatedEntities(t,s);return e.json(n)}catch(t){return console.error(t),e.json({message:t.message},500)}}}export{g as bffCatalogRelatedEntitiesHandler};
1
+ import{telemetryTraceStep as n}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as m}from"../../../../constants/common.js";import{ALLOWED_CATALOG_QUERY_PARAMS as l}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as u}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as y}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as d}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_FROM_DATABASE as c}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";const f=["id","key","title","type","summary","source","sourceFile","createdAt","updatedAt"],g=async({catalogEntitiesService:i,ctx:e})=>n("catalog_entities.bff.related_entities.get_related_entities",async r=>{try{const t=e.req.param(m);if(!t)return r?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400);r?.setAttribute("pathParams",JSON.stringify({entityKey:t}));const a=e.req.query();r?.setAttribute("queryParams",JSON.stringify(u(a,l)));const o=d(f,c).parse(a),s=await i.getRelatedEntities(t,o);return r?.setAttribute("relatedEntitiesCount",s.items.length),e.json(s)}catch(t){return console.error(t),r?.error(t),e.json({message:t.message},500)}});function q(i){return async e=>n("catalog_entities.bff.related_entities",async r=>{r?.setAttribute("method",e.req.method);const t=await y.getInstance({baseDbDir:i.serverOutDir});return g({catalogEntitiesService:t,ctx:e})})}export{q as bffCatalogRelatedEntitiesHandler};
@@ -0,0 +1,4 @@
1
+ import type { Handler } from 'hono';
2
+ import type { Store } from '../../../store.js';
3
+ export declare function bffCatalogRevisionsHandler(store: Store): Handler;
4
+ //# sourceMappingURL=bff-catalog-revisions.d.ts.map
@@ -0,0 +1 @@
1
+ import{telemetryTraceStep as a}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as y}from"../../../../constants/common.js";import{CatalogEntitiesService as g}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";function l(n){return async t=>a("catalog_entities.bff.revisions.get_entity_revisions",async e=>{const o=await g.getInstance({baseDbDir:n.serverOutDir}),i=t.req.param(y);if(!i)return e?.error(new Error("Missing entityKey")),t.json({message:"Missing entityKey"},400);e?.setAttribute("pathParams",JSON.stringify({entityKey:i}));const r=t.req.query("version")??null;e?.setAttribute("queryParams",JSON.stringify({version:r}));const s=await o.listEntityRevisions(i,r);return e?.setAttribute("totalRevisions",s.length),t.json({items:s})})}export{l as bffCatalogRevisionsHandler};
@@ -1,5 +1,4 @@
1
1
  import type { Handler } from 'hono';
2
2
  import type { Store } from '../../../store.js';
3
3
  export declare function bffCatalogHandler(store: Store): Handler;
4
- export declare function bffCatalogRevisionsHandler(store: Store): Handler;
5
4
  //# sourceMappingURL=bff-catalog.d.ts.map
@@ -1 +1 @@
1
- import{CatalogEntitiesService as o}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as y}from"../../../providers/database/pagination/schemas.js";const c=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","version","revision","createdAt","updatedAt","domains","owners"];function f(a){return async t=>{const n=await o.getInstance({baseDbDir:a.serverOutDir}),e=t.req.param("entityKey");if(!e){const u=t.req.query(),l=y(c).parse(u),m=await n.getEntitiesWithRelations(l);return t.json(m)}const i=t.req.query(),s=y(c).parse(i),r=await n.getEntityWithRelationsByKey(e,s);return r?t.json(r):t.json({message:"Entity not found"},404)}}function p(a){return async t=>{const n=await o.getInstance({baseDbDir:a.serverOutDir}),e=t.req.param("entityKey");if(!e)return t.json({message:"Missing entityKey"},400);const i=t.req.query("version")??null,s=await n.listEntityRevisions(e,i);return t.json({items:s})}}export{f as bffCatalogHandler,p as bffCatalogRevisionsHandler};
1
+ import{telemetryTraceStep as o}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as u}from"../../../../constants/common.js";import{ALLOWED_CATALOG_QUERY_PARAMS as g}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as f}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as c}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as y}from"../../../providers/database/pagination/schemas.js";const m=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","version","revision","createdAt","updatedAt","domains","owners"],l=async({catalogEntitiesService:i,ctx:t})=>o("catalog_entities.bff.get_entities",async e=>{const r=t.req.query();e?.setAttribute("queryParams",JSON.stringify(f(r,g)));const n=y(m).parse(r),a=await i.getEntitiesWithRelations(n);return e?.setAttribute("entitiesCount",a.items.length),t.json(a)}),d=async({catalogEntitiesService:i,ctx:t})=>o("catalog_entities.bff.get_entity",async e=>{const r=t.req.param(u);if(!r)return e?.error(new Error("Entity key is required")),t.json({message:"Entity key is required"},400);const n=t.req.query();e?.setAttribute("queryParams",JSON.stringify(n)),e?.setAttribute("pathParams",JSON.stringify({entityKey:r}));const a=y(m).parse(n),s=await i.getEntityWithRelationsByKey(r,a);return s?(e?.setAttribute("entity",JSON.stringify(s)),t.json(s)):(e?.error(new Error("Entity not found")),t.json({message:"Entity not found"},404))});function _(i){return async t=>o("catalog_entities.bff",async e=>{e?.setAttribute("method",t.req.method);const r=await c.getInstance({baseDbDir:i.serverOutDir});return t.req.param("entityKey")?d({catalogEntitiesService:r,ctx:t}):l({catalogEntitiesService:r,ctx:t})})}export{_ as bffCatalogHandler};
@@ -1 +1 @@
1
- import{entitiesRelationsDtoSchema as d,entityRelationDtoSchema as c}from"../../../plugins/catalog-entities/schemas/dto-schemas.js";import{CatalogEntitiesService as g}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as m}from"../../../providers/database/pagination/schemas.js";import{createValidator as l}from"../../../plugins/catalog-entities/utils/ajv-validator.js";import{ENTITY_RELATION_TO_DATABASE as y}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{CacheService as u}from"../../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as E}from"../../../constants/plugins/catalog-entities.js";const R=l(c,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"}),f=l(d,{errorPrefix:"Entities relations validation failed:",dataVar:"relation"}),p=["id","organizationId","projectId","sourceKey","targetKey","sourceId","targetId","type","createdAt","updatedAt"],s=async a=>{await(await u.getInstance({baseDbDir:a})).deleteByNamespace(E)},j=async(a,e)=>{const n=e.req.param("entityRelationId");if(!n)return e.json({message:"Entity relation id is required"},400);const r=await a.getEntityRelationById(n);return r?e.json(r):e.json({message:"Entity relation not found"},404)},I=async(a,e)=>{try{const n=e.req.query(),r=m(p,y).parse(n),t=await a.getEntitiesRelations(r);return e.json(t)}catch(n){return console.error(n),e.json({message:"Failed to get entities relations"},500)}},w=async(a,e,n)=>{const r=e.get("logger");try{const t=await e.req.json(),i=R(t),o=await a.createEntityRelation(i);return o?(s(n),e.json(o)):e.json({message:"Failed to create entity relation"},500)}catch(t){return r.error(t),t instanceof Error&&t.message.includes("validation failed")?e.json({message:t.message},400):e.json({message:"Failed to create entity relation"},500)}},h=async(a,e,n)=>{const r=e.get("logger");try{const t=await e.req.json(),i=f(t),o=await a.createEntitiesRelations(i);return o.length?(s(n),e.json(o,207)):e.json({message:"Failed to create entity relations"},500)}catch(t){return r.error(t),t instanceof Error&&t.message.includes("validation failed")?e.json({message:t.message},400):e.json({message:"Failed to create entity relations"},500)}},q=async(a,e,n)=>{const r=e.get("logger"),t=e.req.param("entityRelationId");if(!t)return e.json({message:"Entity relation id is required"},400);try{const i=await e.req.json(),o=await a.updateEntityRelation(t,i);return o?(s(n),e.json(o)):e.json({message:"Failed to update entity"},500)}catch(i){return r.error(i),i instanceof Error&&i.message.includes("validation failed")?e.json({message:i.message},400):e.json({message:i.message},500)}},v=async(a,e,n)=>{const r=e.req.param("entityRelationId");return r?(await a.deleteEntityRelation(r),s(n),new Response(null,{status:204})):e.json({message:"Entity relation id is required"},400)},T={GET:I,POST:w,PUT:h},A={GET:j,DELETE:v,PATCH:q};function _(a){return async e=>{const n=await g.getInstance({baseDbDir:a.serverOutDir}),r=e.req.method,t=e.req.param("entityRelationId")?A:T;return t[r]?await t[r](n,e,a.serverOutDir):e.json({message:"Method not allowed"},405)}}export{_ as catalogRelationsHandler};
1
+ import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_RELATION_ID as d}from"../../../../constants/common.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as c,ALLOWED_CATALOG_QUERY_PARAMS as E}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as f}from"../../../../utils/object/allowlist-object.js";import{entitiesRelationsDtoSchema as R,entityRelationDtoSchema as A}from"../../../plugins/catalog-entities/schemas/dto-schemas.js";import{CatalogEntitiesService as _}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as w}from"../../../providers/database/pagination/schemas.js";import{createValidator as y}from"../../../plugins/catalog-entities/utils/ajv-validator.js";import{ENTITY_RELATION_TO_DATABASE as b}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{CacheService as h}from"../../../persistence/cache/services/cache-service.js";const j=y(A,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"}),O=y(R,{errorPrefix:"Entities relations validation failed:",dataVar:"relation"}),q=["id","organizationId","projectId","sourceKey","targetKey","sourceId","targetId","type","createdAt","updatedAt"],u=async a=>{await(await h.getInstance({baseDbDir:a})).deleteByNamespace(c)},T=async({catalogEntitiesService:a,ctx:e})=>l("catalog_entities.relations.get_entity_relation",async n=>{const t=e.req.param(d);if(!t)return n?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);n?.setAttribute("pathParams",JSON.stringify({entityRelationId:t}));const i=await a.getEntityRelationById(t);return i?(n?.setAttribute("entityRelation",JSON.stringify(i)),e.json(i)):(n?.error(new Error("Entity relation not found")),e.json({message:"Entity relation not found"},404))}),p=async({catalogEntitiesService:a,ctx:e})=>l("catalog_entities.relations.get_entities_relations",async n=>{try{const t=e.req.query();n?.setAttribute("queryParams",JSON.stringify(f(t,E)));const i=w(q,b).parse(t),r=await a.getEntitiesRelations(i);return n?.setAttribute("entitiesRelationsCount",r.items.length),e.json(r)}catch(t){return console.error(t),n?.error(new Error("Failed to get entities relations")),e.json({message:"Failed to get entities relations"},500)}}),I=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.create_entity_relation",async t=>{const i=e.get("logger");try{const r=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(r));const o=j(r),s=await a.createEntityRelation(o);return s?(u(n),t?.setAttribute("entityRelation",JSON.stringify(s)),e.json(s)):(t?.error(new Error("Failed to create entity relation")),e.json({message:"Failed to create entity relation"},500))}catch(r){return i.error(r),r instanceof Error&&r.message.includes("validation failed")?(t?.error(new Error(r.message)),e.json({message:r.message},400)):(t?.error(r),e.json({message:"Failed to create entity relation"},500))}}),N=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.bulk_upsert_entities_relations",async t=>{const i=e.get("logger");try{const r=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(r));const o=O(r),s=await a.createEntitiesRelations(o);if(!s.length)return t?.error(new Error("Failed to create entity relations")),e.json({message:"Failed to create entity relations"},500);u(n);const g=s.filter(m=>m.status==="ok");return t?.setAttribute("totalSuccess",g.length),t?.setAttribute("totalFailed",s.length-g.length),e.json(s,207)}catch(r){return i.error(r),r instanceof Error&&r.message.includes("validation failed")?(t?.error(new Error(r.message)),e.json({message:r.message},400)):(t?.error(r),e.json({message:"Failed to create entity relations"},500))}}),P=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.update_entity_relation",async t=>{const i=e.get("logger"),r=e.req.param(d);if(!r)return t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);t?.setAttribute("pathParams",JSON.stringify({entityRelationId:r}));try{const o=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(o));const s=await a.updateEntityRelation(r,o);return s?(u(n),t?.setAttribute("entityRelation",JSON.stringify(s)),e.json(s)):(t?.error(new Error("Failed to update entity relation")),e.json({message:"Failed to update entity relation"},500))}catch(o){return i.error(o),o instanceof Error&&o.message.includes("validation failed")?(t?.error(new Error(o.message)),e.json({message:o.message},400)):(t?.error(o),e.json({message:o.message},500))}}),D=async({catalogEntitiesService:a,ctx:e,serverOutDir:n})=>l("catalog_entities.relations.delete_entity_relation",async t=>{const i=e.req.param(d);return i?(t?.setAttribute("pathParams",JSON.stringify({entityRelationId:i})),await a.deleteEntityRelation(i),u(n),new Response(null,{status:204})):(t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400))}),v={GET:p,POST:I,PUT:N},F={GET:T,DELETE:D,PATCH:P};function U(a){return async e=>l("catalog_entities.relations",async n=>{n?.setAttribute("method",e.req.method);const t=await _.getInstance({baseDbDir:a.serverOutDir}),i=e.req.method,r=e.req.param(d)?F:v;return r[i]?await r[i]({catalogEntitiesService:t,ctx:e,serverOutDir:a.serverOutDir}):(n?.error(new Error("Method not allowed")),e.json({message:"Method not allowed"},405))})}export{U as catalogRelationsHandler};
@@ -1 +1 @@
1
- import{getCompleteCatalogConfig as l}from"../../../plugins/catalog-entities/get-complete-catalog-config.js";import{parseAndValidateEntities as m,parseAndValidateEntity as d}from"../../../plugins/catalog-entities/entities/validate-entity.js";import{CatalogEntitiesService as u}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as E}from"../../../providers/database/pagination/schemas.js";import{createEntityRelationDtoFromFileSchema as p}from"../../../plugins/catalog-entities/database/mappers/create-entity-relation-dto-from-file-schema.js";import{CacheService as f}from"../../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as j}from"../../../constants/plugins/catalog-entities.js";const w=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"],y=async n=>{await(await f.getInstance({baseDbDir:n})).deleteByNamespace(j)},h=async(n,e)=>{const i=e.get("logger");try{const a=e.req.query(),r=E(w).parse(a),t=await n.getEntities(r);return e.json(t)}catch(a){return i.error(a),e.json({message:"Failed to get entities"},500)}},C=async(n,e)=>{const i=e.req.param("entityKey");if(!i)return e.json({message:"Entity key is required"},400);const a=await n.getEntityByKey(i);return a?e.json(a):e.json({message:"Entity not found"},404)},q=async(n,e,i,a)=>{const r=e.get("logger");try{const t=await e.req.json(),s=d(t,i),o=await n.createEntity(s),c=s.relations?.map(g=>p(s.key,g));return await n.createEntitiesRelations(c??[]),o?(y(a),e.json(o)):e.json({message:"Failed to create entity"},500)}catch(t){return r.error(t),t instanceof Error&&t.message.includes("validation failed")?e.json({message:t.message},400):e.json({message:"Failed to create entity"},500)}},F=async(n,e,i,a)=>{const r=e.get("logger");try{const t=await e.req.json(),s=m(t,i),o=await n.createEntities(s);return o.length?(y(a),e.json(o,207)):e.json({message:"Failed to create entities"},500)}catch(t){return r.error(t),t instanceof Error&&t.message.includes("validation failed")?e.json({message:t.message},400):e.json({message:"Failed to create entities"},500)}},v=async(n,e,i,a)=>{const r=e.get("logger"),t=e.req.param("entityKey");if(!t)return e.json({message:"Entity key is required"},400);try{const s=await e.req.json(),o=await n.updateEntityByKey(t,s);return o?(y(a),e.json(o)):e.json({message:"Failed to update entity"},500)}catch(s){return r.error(s),s instanceof Error&&s.message.includes("validation failed")?e.json({message:s.message},400):e.json({message:s.message},500)}},A=async(n,e,i,a)=>{const r=e.req.param("entityKey");return r?(await n.deleteEntityByKey(r),y(a),new Response(null,{status:204})):e.json({message:"Entity key is required"},400)},K={GET:h,POST:q,PUT:F},b={GET:C,DELETE:A,PATCH:v};function B(n){return async e=>{const i=await u.getInstance({baseDbDir:n.serverOutDir}),a=e.req.method,r=e.req.param("entityKey")?b:K,t=l(n.config.entitiesCatalog);return r[a]?await r[a](i,e,t,n.serverOutDir):e.json({message:"Method not allowed"},405)}}export{B as catalogHandler};
1
+ import{getCompleteCatalogConfig as c}from"../../../plugins/catalog-entities/get-complete-catalog-config.js";import{parseAndValidateEntities as E,parseAndValidateEntity as f}from"../../../plugins/catalog-entities/entities/validate-entity.js";import{telemetryTraceStep as g}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as A,ALLOWED_CATALOG_QUERY_PARAMS as w}from"../../../constants/plugins/catalog-entities.js";import{CATALOG_ENTITY_KEY as u}from"../../../../constants/common.js";import{allowlistObject as b}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as h}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as j}from"../../../providers/database/pagination/schemas.js";import{createEntityRelationDtoFromFileSchema as _}from"../../../plugins/catalog-entities/database/mappers/create-entity-relation-dto-from-file-schema.js";import{CacheService as q}from"../../../persistence/cache/services/cache-service.js";const p=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"],m=async s=>{await(await q.getInstance({baseDbDir:s})).deleteByNamespace(A)},O=async({catalogEntitiesService:s,ctx:e})=>g("catalog_entities.get_entities",async i=>{const n=e.get("logger");try{const r=e.req.query();i?.setAttribute("queryParams",JSON.stringify(b(r,w)));const o=j(p).parse(r),t=await s.getEntities(o);return i?.setAttribute("entitiesCount",t.items.length),e.json(t)}catch(r){return n.error(r),i?.error(r),e.json({message:"Failed to get entities"},500)}}),C=async({catalogEntitiesService:s,ctx:e})=>g("catalog_entities.get_entity",async i=>{const n=e.req.param(u);if(!n)return i?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400);i?.setAttribute("pathParams",JSON.stringify({entityKey:n}));const r=await s.getEntityByKey(n);return r?(i?.setAttribute("entity",JSON.stringify(r)),e.json(r)):(i?.error(new Error("Entity not found")),e.json({message:"Entity not found"},404))}),F=async({catalogEntitiesService:s,ctx:e,catalogConfig:i,serverOutDir:n})=>g("catalog_entities.create_entity",async r=>{const o=e.get("logger");try{const t=await e.req.json();r?.setAttribute("requestBody",JSON.stringify(t));const a=f(t,i),y=await s.createEntity(a),l=a.relations?.map(d=>_(a.key,d));return await s.createEntitiesRelations(l??[]),y?(m(n),r?.setAttribute("entity",JSON.stringify(y)),e.json(y)):(r?.error(new Error("Failed to create entity")),e.json({message:"Failed to create entity"},500))}catch(t){return o.error(t),t instanceof Error&&t.message.includes("validation failed")?(r?.error(new Error(t.message)),e.json({message:t.message},400)):(r?.error(t),e.json({message:"Failed to create entity"},500))}}),P=async({catalogEntitiesService:s,ctx:e,catalogConfig:i,serverOutDir:n})=>g("catalog_entities.bulk_upsert_entities",async r=>{const o=e.get("logger");try{const t=await e.req.json();r?.setAttribute("requestBody",JSON.stringify(t));const a=E(t,i),y=await s.createEntities(a);if(!y.length)return r?.error(new Error("Failed to create entities")),e.json({message:"Failed to create entities"},500);m(n);const l=y.filter(d=>d.status==="ok");return r?.setAttribute("totalSuccess",l.length),r?.setAttribute("totalFailed",y.length-l.length),e.json(y,207)}catch(t){return o.error(t),t instanceof Error&&t.message.includes("validation failed")?(r?.error(new Error(t.message)),e.json({message:t.message},400)):(r?.error(t),e.json({message:"Failed to create entities"},500))}}),N=async({catalogEntitiesService:s,ctx:e,serverOutDir:i})=>g("catalog_entities.update_entity",async n=>{const r=e.get("logger"),o=e.req.param(u);if(!o)return n?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400);n?.setAttribute("pathParams",JSON.stringify({entityKey:o}));try{const t=await e.req.json();n?.setAttribute("requestBody",JSON.stringify(t));const a=await s.updateEntityByKey(o,t);return a?(m(i),n?.setAttribute("entity",JSON.stringify(a)),e.json(a)):(n?.error(new Error("Failed to update entity")),e.json({message:"Failed to update entity"},500))}catch(t){return r.error(t),t instanceof Error&&t.message.includes("validation failed")?(n?.error(new Error(t.message)),e.json({message:t.message},400)):(n?.error(t),e.json({message:t.message},500))}}),T=async({catalogEntitiesService:s,ctx:e,serverOutDir:i})=>g("catalog_entities.delete_entity",async n=>{const r=e.req.param(u);return r?(n?.setAttribute("pathParams",JSON.stringify({entityKey:r})),await s.deleteEntityByKey(r),m(i),new Response(null,{status:204})):(n?.error(new Error("Entity key is required")),e.json({message:"Entity key is required"},400))}),k={GET:O,POST:F,PUT:P},v={GET:C,DELETE:T,PATCH:N};function U(s){return async e=>g("catalog_entities",async i=>{const n=await h.getInstance({baseDbDir:s.serverOutDir}),r=e.req.method;i?.setAttribute("method",r);const o=e.req.param(u)?v:k,t=c(s.config.entitiesCatalog),a=o[r];return a?await a({catalogEntitiesService:n,ctx:e,catalogConfig:t,serverOutDir:s.serverOutDir}):(i?.error(new Error("Method not allowed")),e.json({message:"Method not allowed"},405))})}export{U as catalogHandler};
@@ -1 +1 @@
1
- import{serveStatic as s}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as f}from"@redocly/theme/core/utils";import{ServerRoutes as i}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as R}from"../../constants/common.js";import{authMiddleware as c}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as S}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as P,oidcCallbackHandler as r,logoutHandler as T,idpLoginHandler as h,redoclyLoginCallbackHandler as N,samlCallbackHandler as D,redoclyTokenLoginHandler as M,inviteHandler as B}from"./auth.js";import{appDataHandler as U}from"./app-data.js";import{searchFacetsHandler as G,searchHandler as w}from"./search.js";import{dynamicRouteHandler as F}from"./dynamic-route.js";import{pageDataHandler as K,sharedPageDataHandler as y}from"./page-data.js";import{pathPrefixRedirectHandler as k}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as E,resolvePathHandler as o,resolvePathsHandler as v,resolveSlugHandler as p}from"./resolve-route.js";import{feedbackHandler as Y}from"./feedback.js";import{loggerMiddleware as b}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as V}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as x}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as z}from"./otel/otel.js";import{healthCheckHandler as Z}from"./health.js";import{askAiHandler as $}from"./ask-ai.js";import{replayOauth2RedirectCallbackHandler as q}from"./replay-oauth2-redirect.js";import{mcpOAuthProtectedResourceHandler as W,mcpOAuthAuthorizationServerHandler as j,mcpDynamicClientRegistrationHandler as J,mcpAuthorizationHandler as Q,mcpTokenPortalHandler as X,mcpCallbackHandler as _}from"./mcp-oauth.js";import{corsMiddleware as O}from"../middleware/corsMiddleware.js";import{installApiRoutes as u}from"./api-routes/api-routes.js";import{cookieMiddleware as aa}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ea}from"../routes/static-content.js";import{infoHandler as C}from"./info.js";import{catalogHandler as ia}from"./catalog/catalog.js";import{catalogRelationsHandler as la}from"./catalog/catalog-relations.js";import{bffCatalogHandler as ta,bffCatalogRevisionsHandler as ma}from"./catalog/bff-catalog.js";import{bffCatalogRelatedEntitiesHandler as na}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as L}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as Aa}from"../middleware/telemetry-middleware.js";import{errorHandler as da}from"./error.js";function $a(a,l,t){const{resolveRouteData:n,readStaticAsset:A}=t;a.use("*",x()),a.use("*",aa()),a.use("*",S(l)),a.use("*",c(l)),a.use("*",b()),a.use("*",V(l)),a.use("*",Aa()),a.use(e("*"),s({root:`./${R}`,getContent:(m,H)=>ea(m,H,l,A),rewriteRequestPath:m=>f(m)})),a.use(e(i.FEEDBACK),O({allowMethods:["POST"]})),a.use(e(i.ASK_AI),O({allowMethods:["POST"]})),a.use("*",Ta(l));const d=g(l);a.use(e(i.INFO),C()),process.env.NEW_CATALOG_ENABLED==="true"&&(a.use(e(i.CATALOG_ENTITIES),L({secureMethods:["POST","PUT","DELETE","PATCH"]})),a.use(e(i.CATALOG_ENTITIES_RELATIONS),L({secureMethods:["POST","PUT","DELETE","PATCH"]})),a.use(e(i.CATALOG_ENTITIES),ia(l)),a.use(e(i.CATALOG_ENTITIES_RELATIONS),la(l)),a.get(e(i.BFF_CATALOG_ENTITIES),ta(l)),a.get(e(i.BFF_CATALOG_RELATED_ENTITIES),na(l)),a.get(e(i.BFF_CATALOG_REVISIONS),ma(l))),a.get(e(i.SHARED_PAGE_DATA),y(l)),a.get(e(i.PAGE_DATA),K(l,n)),a.get(e(i.APP_DATA),U(l)),a.post(e(i.SEARCH),d,w(l)),a.post(e(i.SEARCH_FACETS),d,G(l)),a.post(e(i.AUTHORIZATION),P),a.post(e(i.LOGOUT),T(l)),a.get(e(i.LOGOUT),T(l)),a.get(e(i.OIDC_CALLBACK),r(l)),a.get(e(i.REDOCLY_TOKEN_LOGIN),M(l)),a.get(e(i.REDOCLY_LOGIN_CALLBACK),N()),a.get(e(i.IDP_LOGIN),h(l)),a.post(e(i.SAML_CALLBACK),D(l)),a.get(e(i.INVITE),B(l)),a.get(e(i.HEALTH),Z),a.get(e(i.MCP_OAUTH_PROTECTED_RESOURCE),W()),a.get(e(i.MCP_OAUTH_AUTHORIZATION_SERVER),j()),a.post(e(i.MCP_DYNAMIC_CLIENT_REGISTRATION),J()),a.get(e(i.MCP_AUTHORIZATION),Q()),a.post(e(i.MCP_TOKEN_PORTAL),X()),a.get(e(i.MCP_CALLBACK),_()),a.get(e(`${i.MCP_CALLBACK}/*`),_()),I(a,l),u(a,l),a.post(e(i.FEEDBACK),Y(l)),a.post(e(i.RESOLVE_ROUTE_BY_PATH),o(l)),a.post(e(i.RESOLVE_ROUTES_BY_PATHS),v(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),p(l)),a.post(e(i.ASK_AI),$(l)),a.get(e(i.GET_ROUTES_BY_LINE),E(l)),a.post(e(i.OTEL_TRACES),z),a.get(e(i.REPLAY_OAUTH2_CALLBACK),q),a.all(e("/*"),F(l,n,A)),a.get("*",k),a.onError(da)}function Ta(a){return async(l,t)=>{await a.waitForPluginsLifecycle(),await t()}}function qa(a,l){a.get(e(i.INFO),C()),a.post(e(i.RESOLVE_ROUTE_BY_PATH),o(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),p(l)),a.get(e(i.GET_ROUTES_BY_LINE),E(l))}export{qa as installDevRoutes,$a as installProdRoutes,Ta as waitForPluginsLifecycle};
1
+ import{serveStatic as f}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as s}from"@redocly/theme/core/utils";import{ServerRoutes as i}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as R}from"../../constants/common.js";import{authMiddleware as c}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as S}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as P,oidcCallbackHandler as r,logoutHandler as T,idpLoginHandler as h,redoclyLoginCallbackHandler as N,samlCallbackHandler as D,redoclyTokenLoginHandler as M,inviteHandler as B}from"./auth.js";import{appDataHandler as U}from"./app-data.js";import{searchFacetsHandler as G,searchHandler as w}from"./search.js";import{dynamicRouteHandler as F}from"./dynamic-route.js";import{pageDataHandler as K,sharedPageDataHandler as y}from"./page-data.js";import{pathPrefixRedirectHandler as k}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as E,resolvePathHandler as o,resolvePathsHandler as v,resolveSlugHandler as p}from"./resolve-route.js";import{feedbackHandler as Y}from"./feedback.js";import{loggerMiddleware as b}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as V}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as x}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as z}from"./otel/otel.js";import{healthCheckHandler as Z}from"./health.js";import{askAiHandler as $}from"./ask-ai.js";import{replayOauth2RedirectCallbackHandler as q}from"./replay-oauth2-redirect.js";import{mcpOAuthProtectedResourceHandler as W,mcpOAuthAuthorizationServerHandler as j,mcpDynamicClientRegistrationHandler as J,mcpAuthorizationHandler as Q,mcpTokenPortalHandler as X,mcpCallbackHandler as _}from"./mcp-oauth.js";import{corsMiddleware as O}from"../middleware/corsMiddleware.js";import{installApiRoutes as u}from"./api-routes/api-routes.js";import{cookieMiddleware as aa}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ea}from"../routes/static-content.js";import{infoHandler as C}from"./info.js";import{catalogHandler as ia}from"./catalog/catalog.js";import{catalogRelationsHandler as la}from"./catalog/catalog-relations.js";import{bffCatalogHandler as ma}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as ta}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as na}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as L}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as Aa}from"../middleware/telemetry-middleware.js";import{errorHandler as da}from"./error.js";function qa(a,l,m){const{resolveRouteData:n,readStaticAsset:A}=m;a.use("*",x()),a.use("*",aa()),a.use("*",S(l)),a.use("*",c(l)),a.use("*",b()),a.use("*",V(l)),a.use("*",Aa()),a.use(e("*"),f({root:`./${R}`,getContent:(t,H)=>ea(t,H,l,A),rewriteRequestPath:t=>s(t)})),a.use(e(i.FEEDBACK),O({allowMethods:["POST"]})),a.use(e(i.ASK_AI),O({allowMethods:["POST"]})),a.use("*",Ta(l));const d=g(l);a.use(e(i.INFO),C()),process.env.NEW_CATALOG_ENABLED==="true"&&(a.use(e(i.CATALOG_ENTITIES),L({secureMethods:["POST","PUT","DELETE","PATCH"]})),a.use(e(i.CATALOG_ENTITIES_RELATIONS),L({secureMethods:["POST","PUT","DELETE","PATCH"]})),a.use(e(i.CATALOG_ENTITIES),ia(l)),a.use(e(i.CATALOG_ENTITIES_RELATIONS),la(l)),a.get(e(i.BFF_CATALOG_ENTITIES),ma(l)),a.get(e(i.BFF_CATALOG_RELATED_ENTITIES),na(l)),a.get(e(i.BFF_CATALOG_REVISIONS),ta(l))),a.get(e(i.SHARED_PAGE_DATA),y(l)),a.get(e(i.PAGE_DATA),K(l,n)),a.get(e(i.APP_DATA),U(l)),a.post(e(i.SEARCH),d,w(l)),a.post(e(i.SEARCH_FACETS),d,G(l)),a.post(e(i.AUTHORIZATION),P),a.post(e(i.LOGOUT),T(l)),a.get(e(i.LOGOUT),T(l)),a.get(e(i.OIDC_CALLBACK),r(l)),a.get(e(i.REDOCLY_TOKEN_LOGIN),M(l)),a.get(e(i.REDOCLY_LOGIN_CALLBACK),N()),a.get(e(i.IDP_LOGIN),h(l)),a.post(e(i.SAML_CALLBACK),D(l)),a.get(e(i.INVITE),B(l)),a.get(e(i.HEALTH),Z),a.get(e(i.MCP_OAUTH_PROTECTED_RESOURCE),W()),a.get(e(i.MCP_OAUTH_AUTHORIZATION_SERVER),j()),a.post(e(i.MCP_DYNAMIC_CLIENT_REGISTRATION),J()),a.get(e(i.MCP_AUTHORIZATION),Q()),a.post(e(i.MCP_TOKEN_PORTAL),X()),a.get(e(i.MCP_CALLBACK),_()),a.get(e(`${i.MCP_CALLBACK}/*`),_()),I(a,l),u(a,l),a.post(e(i.FEEDBACK),Y(l)),a.post(e(i.RESOLVE_ROUTE_BY_PATH),o(l)),a.post(e(i.RESOLVE_ROUTES_BY_PATHS),v(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),p(l)),a.post(e(i.ASK_AI),$(l)),a.get(e(i.GET_ROUTES_BY_LINE),E(l)),a.post(e(i.OTEL_TRACES),z),a.get(e(i.REPLAY_OAUTH2_CALLBACK),q),a.all(e("/*"),F(l,n,A)),a.get("*",k),a.onError(da)}function Ta(a){return async(l,m)=>{await a.waitForPluginsLifecycle(),await m()}}function Wa(a,l){a.get(e(i.INFO),C()),a.post(e(i.RESOLVE_ROUTE_BY_PATH),o(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),p(l)),a.get(e(i.GET_ROUTES_BY_LINE),E(l))}export{Wa as installDevRoutes,qa as installProdRoutes,Ta as waitForPluginsLifecycle};
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Allows a subset of keys from an object.
3
+ *
4
+ * @param object - The object to allow.
5
+ * @param allowedKeys - The keys to allow.
6
+ * @returns A new object with the allowed keys.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const object = { a: 1, b: 2, c: 3 };
11
+ * const allowedObject = allowlistObject(object, ['a', 'c']);
12
+ * // { a: 1, c: 3 }
13
+ * ```
14
+ */
15
+ export declare function allowlistObject<T extends Record<string, unknown>, K extends keyof T>(object: T, allowedKeys: readonly K[]): Pick<T, K>;
16
+ //# sourceMappingURL=allowlist-object.d.ts.map
@@ -0,0 +1 @@
1
+ function i(e,t){return Object.fromEntries(Object.entries(e).filter(([r])=>t.includes(r)))}export{i as allowlistObject};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/revel",
3
- "version": "0.128.0-next.5",
3
+ "version": "0.128.0-next.6",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -92,14 +92,14 @@
92
92
  "xml-crypto": "6.0.1",
93
93
  "xpath": "0.0.34",
94
94
  "yaml-ast-parser": "0.0.43",
95
- "@redocly/asyncapi-docs": "1.5.0-next.5",
95
+ "@redocly/asyncapi-docs": "1.5.0-next.6",
96
96
  "@redocly/config": "0.40.0",
97
97
  "@redocly/graphql-docs": "1.5.0-next.1",
98
- "@redocly/openapi-docs": "3.16.0-next.5",
98
+ "@redocly/openapi-docs": "3.16.0-next.6",
99
99
  "@redocly/portal-legacy-ui": "0.11.0-next.0",
100
- "@redocly/portal-plugin-mock-server": "0.13.0-next.5",
101
- "@redocly/realm-asyncapi-sdk": "0.6.0-next.0",
102
- "@redocly/theme": "0.60.0-next.4"
100
+ "@redocly/portal-plugin-mock-server": "0.13.0-next.6",
101
+ "@redocly/realm-asyncapi-sdk": "0.6.0-next.1",
102
+ "@redocly/theme": "0.60.0-next.5"
103
103
  },
104
104
  "peerDependencies": {
105
105
  "react": "^19.1.0",