@redocly/reef 0.132.0-next.0 → 0.132.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/client/App.js +1 -1
  3. package/dist/client/TestProvider.js +1 -1
  4. package/dist/client/app/hooks/catalog/useCatalogSort.d.ts +3 -4
  5. package/dist/client/app/hooks/catalog/useFetchCatalogEntities.js +1 -1
  6. package/dist/client/app/hooks/catalog/useFetchCatalogEntitiesRelations.js +1 -1
  7. package/dist/client/app/hooks/index.d.ts +1 -0
  8. package/dist/client/app/hooks/index.js +1 -1
  9. package/dist/client/app/hooks/markdown/useMarkdocRenderer.d.ts +3 -0
  10. package/dist/client/app/hooks/markdown/useMarkdocRenderer.js +1 -0
  11. package/dist/client/app/hooks/useBanner.d.ts +3 -5
  12. package/dist/client/app/hooks/useBanner.js +1 -1
  13. package/dist/client/app/hooks/utils/match-banner-target.d.ts +2 -2
  14. package/dist/client/app/hooks/utils/match-banner-target.js +1 -1
  15. package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
  16. package/dist/client/app/markdoc/custom-components/ExcalidrawRenderer.d.ts +8 -0
  17. package/dist/client/app/markdoc/custom-components/ExcalidrawRenderer.js +14 -0
  18. package/dist/client/app/markdoc/custom-components/index.d.ts +1 -0
  19. package/dist/client/app/markdoc/custom-components/index.js +1 -1
  20. package/dist/client/app/utils/loadAndNavigate.js +1 -1
  21. package/dist/client/app/utils/scroll-to-anchor.d.ts +3 -0
  22. package/dist/client/app/utils/scroll-to-anchor.js +1 -0
  23. package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
  24. package/dist/constants/common.js +1 -1
  25. package/dist/markdoc/nodes/fence/index.js +1 -1
  26. package/dist/markdoc/tags/excalidraw.d.ts +3 -0
  27. package/dist/markdoc/tags/excalidraw.js +1 -0
  28. package/dist/markdoc/tags/index.d.ts +4 -0
  29. package/dist/markdoc/tags/index.js +1 -1
  30. package/dist/server/config/env-schema.d.ts +3 -0
  31. package/dist/server/config/env-schemas/auth.d.ts +3 -0
  32. package/dist/server/config/env-schemas/auth.js +1 -1
  33. package/dist/server/fs/fast-mtime.js +3 -3
  34. package/dist/server/plugins/api-functions/helpers/parse-route-fs-path-for-hono.js +1 -1
  35. package/dist/server/plugins/api-functions/index.js +1 -1
  36. package/dist/server/plugins/arazzo-docs/index.js +1 -1
  37. package/dist/server/plugins/asyncapi-docs/get-server-props.js +1 -1
  38. package/dist/server/plugins/asyncapi-docs/index.js +1 -1
  39. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.js +3 -3
  40. package/dist/server/plugins/catalog-entities/database/mappers/create-bff-related-entity.js +1 -1
  41. package/dist/server/plugins/catalog-entities/database/mappers/field-transformations.d.ts +2 -2
  42. package/dist/server/plugins/catalog-entities/database/mappers/field-transformations.js +1 -1
  43. package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.d.ts +1 -0
  44. package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.js +8 -8
  45. package/dist/server/plugins/catalog-entities/database/repositories/utils.d.ts +4 -0
  46. package/dist/server/plugins/catalog-entities/database/repositories/utils.js +1 -1
  47. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  48. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
  49. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +13 -1
  50. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  51. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
  52. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  53. package/dist/server/plugins/catalog-entities/get-server-props.js +1 -1
  54. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  55. package/dist/server/plugins/catalog-entities/schemas/database-schemas.d.ts +6 -6
  56. package/dist/server/plugins/catalog-entities/schemas/database-schemas.js +1 -1
  57. package/dist/server/plugins/config-parser/index.js +1 -1
  58. package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
  59. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.d.ts +1 -0
  60. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  61. package/dist/server/plugins/default-theme/index.js +1 -1
  62. package/dist/server/plugins/dev-onboarding/index.js +1 -1
  63. package/dist/server/plugins/enforce-login/index.d.ts +3 -0
  64. package/dist/server/plugins/enforce-login/index.js +1 -0
  65. package/dist/server/plugins/graphql-docs/spec-download.api.js +1 -1
  66. package/dist/server/plugins/lifecycle.js +2 -2
  67. package/dist/server/plugins/markdown/compiler.d.ts +1 -1
  68. package/dist/server/plugins/markdown/compiler.js +1 -1
  69. package/dist/server/plugins/markdown/get-server-props.js +1 -1
  70. package/dist/server/plugins/markdown/index.js +1 -1
  71. package/dist/server/plugins/markdown/markdoc/partials.js +1 -1
  72. package/dist/server/plugins/markdown/markdown-static-data-loader.js +1 -1
  73. package/dist/server/plugins/markdown/search/get-ai-search-documents.js +10 -10
  74. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  75. package/dist/server/plugins/openapi-docs/get-server-props.js +1 -1
  76. package/dist/server/plugins/openapi-docs/index.js +1 -1
  77. package/dist/server/plugins/openapi-docs/load-definition.js +3 -3
  78. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +32 -32
  79. package/dist/server/plugins/openapi-docs/spec-download.api.js +1 -1
  80. package/dist/server/plugins/scorecard-classic/compute-scorecard.js +4 -4
  81. package/dist/server/plugins/scorecard-classic/loaders/scorecard-config.js +1 -1
  82. package/dist/server/plugins/scorecard-classic/loaders/scorecard.js +1 -1
  83. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -1
  84. package/dist/server/plugins/search/documents/search-documents.js +1 -1
  85. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  86. package/dist/server/plugins/search/index.js +1 -1
  87. package/dist/server/plugins/search/llmstxt/index.d.ts +0 -1
  88. package/dist/server/plugins/search/llmstxt/index.js +4 -4
  89. package/dist/server/plugins/sso/index.js +1 -1
  90. package/dist/server/plugins/utils.d.ts +4 -0
  91. package/dist/server/plugins/utils.js +1 -1
  92. package/dist/server/ssr/index.js +1 -1
  93. package/dist/server/store.d.ts +2 -3
  94. package/dist/server/store.js +1 -1
  95. package/dist/server/tools/notifiers/terminal-manager.js +5 -5
  96. package/dist/server/types/plugins/common.d.ts +4 -4
  97. package/dist/server/types/plugins/markdown.d.ts +7 -1
  98. package/dist/server/utils/llmstxt/get-llms-txt-md-path-by-slug.d.ts +19 -0
  99. package/dist/server/utils/llmstxt/get-llms-txt-md-path-by-slug.js +1 -0
  100. package/dist/server/utils/rbac/is-rbac-scope-items.d.ts +3 -0
  101. package/dist/server/utils/rbac/is-rbac-scope-items.js +1 -0
  102. package/dist/server/utils/rbac.js +1 -1
  103. package/dist/server/utils/search/highlight-text-for-search.d.ts +2 -0
  104. package/dist/server/utils/search/highlight-text-for-search.js +1 -0
  105. package/dist/server/web-server/routes/api-routes/api-routes.js +1 -1
  106. package/dist/server/web-server/routes/app-data.js +1 -1
  107. package/dist/server/web-server/routes/ask-ai.js +1 -1
  108. package/dist/server/web-server/routes/auth.d.ts +2 -1
  109. package/dist/server/web-server/routes/auth.js +1 -1
  110. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  111. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  112. package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.js +1 -1
  113. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  114. package/dist/server/web-server/routes/feedback.js +1 -1
  115. package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.js +1 -1
  116. package/dist/server/web-server/routes/page-data.js +1 -1
  117. package/dist/server/web-server/routes/search.js +1 -1
  118. package/dist/server/web-server/routes/static-content.js +1 -1
  119. package/package.json +11 -10
  120. package/dist/server/web-server/routes/helpers/get-md-asset-pathname.d.ts +0 -2
  121. package/dist/server/web-server/routes/helpers/get-md-asset-pathname.js +0 -1
@@ -1 +1 @@
1
- import{logger as i}from"../../../../tools/notifiers/logger.js";import{relatedEntityDatabaseSchema as y,relatedEntityQueryRowDatabaseSchema as s}from"../../schemas/database-schemas.js";import{validateWithResult as u}from"../../utils/ajv-validator.js";import{readString as t}from"../../utils/read-string.js";function o(e){return!e.id||!e.type||!e.key||!e.title?(i.warn(`Invalid database bff catalog related entity: missing required fields (id: ${e.id}, type: ${e.type}, key: ${e.key}, title: ${e.title})`),null):{id:e.id,type:e.type,key:e.key,title:e.title,summary:e.summary,source:e.source,sourceFile:e.sourceFile,relationRole:e.relationRole,relationType:e.relationType,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata,version:e.version,...e.revision!==null&&{revision:e.revision}}}function l(e){if(e){if(typeof e=="string")try{return e?JSON.parse(e):void 0}catch{return}if(typeof e=="object"&&e!==null)return e}}function p(e){return typeof e=="string"||e===null||typeof e=="object"&&e!==null&&!Array.isArray(e)?e:null}function m(e){const a=t(e.source_to_target_relation)??t(e.target_to_source_relation)??t(e.relationType)??t(e.relation_type)??t(e.relationName)??t(e.relation_name)??"";return{id:t(e.id)??"",type:t(e.type)??"",key:t(e.key)??"",title:t(e.title)??"",summary:t(e.summary,!0)??null,source:t(e.source)??"",source_file:t(e.source_file,!0)??t(e.sourceFile,!0)??null,direction:t(e.direction)??"",relation_field:a,created_at:t(e.created_at,!0)??null,updated_at:t(e.updated_at,!0)??null,metadata:p(e.metadata),version:t(e.version,!0)??null,revision:t(e.revision,!0)??null}}function k(e){const a=u(y,e);if(!a.success)return i.warn(`Invalid database bff catalog related entity, error: ${a.error}`),null;const r=a.data||{};return o({id:r.id,type:r.type,key:r.key,title:r.title,summary:r.summary||null,source:r.source,sourceFile:r.source_file||null,relationRole:r.relation_role||"source",relationType:r.relation_type||"",createdAt:r.created_at||null,updatedAt:r.updated_at||null,metadata:l(r.metadata),version:r.version||null,revision:null})}function R(e){const a=m(e),r=u(s,a);if(!r.success)return i.warn(`Invalid database bff catalog related entity query row (key: ${a.key||"unknown"}), error: ${r.error}`),null;const n=r.data||{},c=n.direction==="outgoing"?"source":"target",d=n.relation_field.replace("reverse:","");return o({id:n.id,type:n.type,key:n.key,title:n.title,summary:n.summary??null,source:n.source,sourceFile:n.source_file??null,relationRole:c,relationType:d,createdAt:n.created_at??null,updatedAt:n.updated_at??null,metadata:l(n.metadata),version:n.version??null,revision:n.revision??null})}export{k as createBffRelatedEntity,R as createBffRelatedEntityFromQueryRow};
1
+ import{logger as i}from"../../../../tools/notifiers/logger.js";import{relatedEntityDatabaseSchema as y,relatedEntityQueryRowDatabaseSchema as s}from"../../schemas/database-schemas.js";import{validateWithResult as o}from"../../utils/ajv-validator.js";import{readString as t}from"../../utils/read-string.js";function u(e){return!e.id||!e.type||!e.key||!e.title?(i.warn(`Invalid database bff catalog related entity: missing required fields (id: ${e.id}, type: ${e.type}, key: ${e.key}, title: ${e.title})`),null):{id:e.id,type:e.type,key:e.key,title:e.title,summary:e.summary,source:e.source,sourceFile:e.sourceFile,relationRole:e.relationRole,relationType:e.relationType,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata,version:e.version,...e.revision!==null&&{revision:e.revision}}}function l(e){if(e){if(typeof e=="string")try{return e?JSON.parse(e):void 0}catch{return}if(typeof e=="object"&&e!==null)return e}}function p(e){return typeof e=="string"||e===null||typeof e=="object"&&e!==null&&!Array.isArray(e)?e:null}function m(e){const a=t(e.source_to_target_relation)??t(e.target_to_source_relation)??t(e.relationType)??t(e.relation_type)??t(e.relationName)??t(e.relation_name)??"";return{id:t(e.id)??"",type:t(e.type)??"",key:t(e.key)??"",title:t(e.title)??"",summary:t(e.summary,!0)??null,source:t(e.source)??"",source_file:t(e.source_file,!0)??t(e.sourceFile,!0)??null,direction:t(e.direction)??"",relation_field:a,created_at:t(e.created_at,!0)??"",updated_at:t(e.updated_at,!0)??"",metadata:p(e.metadata),version:t(e.version,!0)??null,revision:t(e.revision,!0)??null}}function k(e){const a=o(y,e);if(!a.success)return i.warn(`Invalid database bff catalog related entity, error: ${a.error}`),null;const r=a.data||{};return u({id:r.id,type:r.type,key:r.key,title:r.title,summary:r.summary||null,source:r.source,sourceFile:r.source_file||null,relationRole:r.relation_role||"source",relationType:r.relation_type||"",createdAt:r.created_at,updatedAt:r.updated_at,metadata:l(r.metadata),version:r.version||null,revision:null})}function R(e){const a=m(e),r=o(s,a);if(!r.success)return i.warn(`Invalid database bff catalog related entity query row (key: ${a.key||"unknown"}), error: ${r.error}`),null;const n=r.data||{},c=n.direction==="outgoing"?"source":"target",d=n.relation_field.replace("reverse:","");return u({id:n.id,type:n.type,key:n.key,title:n.title,summary:n.summary??null,source:n.source,sourceFile:n.source_file??null,relationRole:c,relationType:d,createdAt:n.created_at,updatedAt:n.updated_at,metadata:l(n.metadata),version:n.version??null,revision:n.revision??null})}export{k as createBffRelatedEntity,R as createBffRelatedEntityFromQueryRow};
@@ -1,7 +1,7 @@
1
1
  export declare const ENTITY_RELATION_TO_DATABASE: {
2
- readonly type: "source_to_target_relation";
2
+ readonly relation_type: "source_to_target_relation";
3
3
  };
4
4
  export declare const ENTITY_RELATION_FROM_DATABASE: {
5
- readonly source_to_target_relation: "type";
5
+ readonly source_to_target_relation: "relationType";
6
6
  };
7
7
  //# sourceMappingURL=field-transformations.d.ts.map
@@ -1 +1 @@
1
- const t={type:"source_to_target_relation"},_={source_to_target_relation:"type"};export{_ as ENTITY_RELATION_FROM_DATABASE,t as ENTITY_RELATION_TO_DATABASE};
1
+ const t={relation_type:"source_to_target_relation"},_={source_to_target_relation:"relationType"};export{_ as ENTITY_RELATION_FROM_DATABASE,t as ENTITY_RELATION_TO_DATABASE};
@@ -28,6 +28,7 @@ export declare function createMergedEntityFieldsForSelect(remoteAlias?: string,
28
28
  revision: SQL<unknown>;
29
29
  hash: SQL<unknown>;
30
30
  isCurrent: SQL<unknown>;
31
+ isDefaultVersion: SQL<unknown>;
31
32
  isDeleted: SQL<unknown>;
32
33
  scorecardsStatus: SQL<unknown>;
33
34
  };
@@ -1,13 +1,13 @@
1
- import{sql as u}from"drizzle-orm";function p(t="r",d="l"){return{id:$("id","id",t,d),organizationId:$("organization_id","organization_id",t,d),projectId:$("project_id","project_id",t,d),key:u.raw(`${t}.key AS key`),type:$("type","type",t,d),title:$("title","title",t,d),summary:$("summary","summary",t,d),tags:_("tags","tags",t,d),metadata:_("metadata","metadata",t,d),git:_("git","git",t,d),contact:_("contact","contact",t,d),links:_("links","links",t,d),createdAt:u.raw(`MIN(${t}.created_at, ${d}.created_at) AS created_at`),updatedAt:u.raw(`MAX(${t}.updated_at, ${d}.updated_at) AS updated_at`),source:$("source","source",t,d),sourceFile:$("source_file","source_file",t,d),fileHash:$("file_hash","file_hash",t,d),version:u.raw(`${t}.version AS version`),revision:u.raw(`${t}.revision AS revision`),hash:$("hash","hash",t,d),isCurrent:$("is_current","is_current",t,d),isDeleted:$("is_deleted","is_deleted",t,d),scorecardsStatus:$("scorecards_status","scorecards_status",t,d)}}function _(t,d,n="r",r="l"){return u.raw(`
1
+ import{sql as u}from"drizzle-orm";function p(t="r",d="l"){return{id:n("id","id",t,d),organizationId:n("organization_id","organization_id",t,d),projectId:n("project_id","project_id",t,d),key:u.raw(`${t}.key AS key`),type:n("type","type",t,d),title:n("title","title",t,d),summary:n("summary","summary",t,d),tags:_("tags","tags",t,d),metadata:_("metadata","metadata",t,d),git:_("git","git",t,d),contact:_("contact","contact",t,d),links:_("links","links",t,d),createdAt:u.raw(`MIN(${t}.created_at, ${d}.created_at) AS created_at`),updatedAt:u.raw(`MAX(${t}.updated_at, ${d}.updated_at) AS updated_at`),source:n("source","source",t,d),sourceFile:n("source_file","source_file",t,d),fileHash:n("file_hash","file_hash",t,d),version:u.raw(`${t}.version AS version`),revision:u.raw(`${t}.revision AS revision`),hash:n("hash","hash",t,d),isCurrent:n("is_current","is_current",t,d),isDefaultVersion:n("is_default_version","is_default_version",t,d),isDeleted:n("is_deleted","is_deleted",t,d),scorecardsStatus:n("scorecards_status","scorecards_status",t,d)}}function _(t,d,$="r",r="l"){return u.raw(`
2
2
  CASE
3
- WHEN ${n}.${t} IS NULL THEN ${r}.${t}
4
- WHEN ${r}.${t} IS NULL THEN ${n}.${t}
5
- WHEN ${n}.updated_at >= ${r}.updated_at THEN json_patch(${r}.${t}, ${n}.${t})
6
- ELSE json_patch(${n}.${t}, ${r}.${t})
3
+ WHEN ${$}.${t} IS NULL THEN ${r}.${t}
4
+ WHEN ${r}.${t} IS NULL THEN ${$}.${t}
5
+ WHEN ${$}.updated_at >= ${r}.updated_at THEN json_patch(${r}.${t}, ${$}.${t})
6
+ ELSE json_patch(${$}.${t}, ${r}.${t})
7
7
  END AS ${d}
8
- `)}function $(t,d,n="r",r="l"){return u.raw(`
8
+ `)}function n(t,d,$="r",r="l"){return u.raw(`
9
9
  CASE
10
- WHEN ${n}.updated_at >= ${r}.updated_at THEN COALESCE(${n}.${t}, ${r}.${t})
11
- ELSE COALESCE(${r}.${t}, ${n}.${t})
10
+ WHEN ${$}.updated_at >= ${r}.updated_at THEN COALESCE(${$}.${t}, ${r}.${t})
11
+ ELSE COALESCE(${r}.${t}, ${$}.${t})
12
12
  END AS ${d}
13
13
  `)}export{p as createMergedEntityFieldsForSelect};
@@ -20,6 +20,7 @@ export declare const createEntityFieldsForSelect: (tableAlias?: string, idAlias?
20
20
  revision: import("drizzle-orm").SQL<unknown>;
21
21
  hash: import("drizzle-orm").SQL<unknown>;
22
22
  isCurrent: import("drizzle-orm").SQL<unknown>;
23
+ isDefaultVersion: import("drizzle-orm").SQL<unknown>;
23
24
  isDeleted: import("drizzle-orm").SQL<unknown>;
24
25
  scorecardsStatus: import("drizzle-orm").SQL<unknown>;
25
26
  };
@@ -61,6 +62,7 @@ export declare const createQualifiedEntityFieldsForSelect: (tableAlias?: string)
61
62
  revision: import("drizzle-orm").SQL<unknown>;
62
63
  hash: import("drizzle-orm").SQL<unknown>;
63
64
  isCurrent: import("drizzle-orm").SQL<unknown>;
65
+ isDefaultVersion: import("drizzle-orm").SQL<unknown>;
64
66
  isDeleted: import("drizzle-orm").SQL<unknown>;
65
67
  };
66
68
  export declare const createQualifiedEntityFieldsForSelectWithAliases: (tableAlias?: string) => {
@@ -85,6 +87,7 @@ export declare const createQualifiedEntityFieldsForSelectWithAliases: (tableAlia
85
87
  revision: import("drizzle-orm").SQL.Aliased<unknown>;
86
88
  hash: import("drizzle-orm").SQL.Aliased<unknown>;
87
89
  isCurrent: import("drizzle-orm").SQL.Aliased<unknown>;
90
+ isDefaultVersion: import("drizzle-orm").SQL.Aliased<unknown>;
88
91
  isDeleted: import("drizzle-orm").SQL.Aliased<unknown>;
89
92
  };
90
93
  export declare const FIELDS_TO_SELECT_FOR_ENTITY: {
@@ -109,6 +112,7 @@ export declare const FIELDS_TO_SELECT_FOR_ENTITY: {
109
112
  revision: import("drizzle-orm").SQL<unknown>;
110
113
  hash: import("drizzle-orm").SQL<unknown>;
111
114
  isCurrent: import("drizzle-orm").SQL<unknown>;
115
+ isDefaultVersion: import("drizzle-orm").SQL<unknown>;
112
116
  isDeleted: import("drizzle-orm").SQL<unknown>;
113
117
  scorecardsStatus: import("drizzle-orm").SQL<unknown>;
114
118
  };
@@ -1 +1 @@
1
- import{sql as a}from"drizzle-orm";const i=(t="",r)=>{const e=t?`${t}.`:"";return{id:r?a.raw(e+"id").as(r):a.raw(e+"id"),organizationId:a.raw(e+"organization_id"),projectId:a.raw(e+"project_id"),key:a.raw(e+"key"),type:a.raw(e+"type"),title:a.raw(e+"title"),summary:a.raw(e+"summary"),tags:a.raw(e+"tags"),metadata:a.raw(e+"metadata"),git:a.raw(e+"git"),contact:a.raw(e+"contact"),links:a.raw(e+"links"),createdAt:a.raw(e+"created_at"),updatedAt:a.raw(e+"updated_at"),source:a.raw(e+"source"),sourceFile:a.raw(e+"source_file"),fileHash:a.raw(e+"file_hash"),version:a.raw(e+"version"),revision:a.raw(e+"revision"),hash:a.raw(e+"hash"),isCurrent:a.raw(e+"is_current"),isDeleted:a.raw(e+"is_deleted"),scorecardsStatus:a.raw(e+"scorecards_status")}},s=(t="",r)=>{const e=t?`${t}.`:"";return{id:r?a.raw(e+"id").as(r):a.raw(e+"id"),organizationId:a.raw(e+"organization_id"),projectId:a.raw(e+"project_id"),sourceKey:a.raw(e+"source_key"),sourceVersion:a.raw(e+"source_version"),sourceRevision:a.raw(e+"source_revision"),sourceToTargetRelation:a.raw(e+"source_to_target_relation"),targetKey:a.raw(e+"target_key"),targetVersion:a.raw(e+"target_version"),targetRevision:a.raw(e+"target_revision"),targetToSourceRelation:a.raw(e+"target_to_source_relation"),fileHash:a.raw(e+"file_hash"),createdAt:a.raw(e+"created_at"),updatedAt:a.raw(e+"updated_at")}},n=(t="")=>{const r=t?`${t}.`:"";return{id:a.raw(r+"entity_id"),organizationId:a.raw(r+"organization_id"),projectId:a.raw(r+"project_id"),key:a.raw(r+"key"),type:a.raw(r+"type"),title:a.raw(r+"title"),summary:a.raw(r+"summary"),tags:a.raw(r+"tags"),metadata:a.raw(r+"metadata"),git:a.raw(r+"git"),contact:a.raw(r+"contact"),links:a.raw(r+"links"),createdAt:a.raw(r+"created_at"),updatedAt:a.raw(r+"updated_at"),source:a.raw(r+"source"),sourceFile:a.raw(r+"source_file"),fileHash:a.raw(r+"file_hash"),version:a.raw(r+"version"),revision:a.raw(r+"revision"),hash:a.raw(r+"hash"),isCurrent:a.raw(r+"is_current"),isDeleted:a.raw(r+"is_deleted")}},w=(t="")=>{const r=t?`${t}.`:"";return{id:a.raw(r+"entity_id").as("id"),organizationId:a.raw(r+"organization_id").as("organization_id"),projectId:a.raw(r+"project_id").as("project_id"),key:a.raw(r+"key").as("key"),type:a.raw(r+"type").as("type"),title:a.raw(r+"title").as("title"),summary:a.raw(r+"summary").as("summary"),tags:a.raw(r+"tags").as("tags"),metadata:a.raw(r+"metadata").as("metadata"),git:a.raw(r+"git").as("git"),contact:a.raw(r+"contact").as("contact"),links:a.raw(r+"links").as("links"),createdAt:a.raw(r+"created_at").as("created_at"),updatedAt:a.raw(r+"updated_at").as("updated_at"),source:a.raw(r+"source").as("source"),sourceFile:a.raw(r+"source_file").as("source_file"),fileHash:a.raw(r+"file_hash").as("file_hash"),version:a.raw(r+"version").as("version"),revision:a.raw(r+"revision").as("revision"),hash:a.raw(r+"hash").as("hash"),isCurrent:a.raw(r+"is_current").as("is_current"),isDeleted:a.raw(r+"is_deleted").as("is_deleted")}},c=i(),d=s();export{c as FIELDS_TO_SELECT_FOR_ENTITY,d as FIELDS_TO_SELECT_FOR_ENTITY_RELATION,i as createEntityFieldsForSelect,s as createEntityRelationFieldsForSelect,n as createQualifiedEntityFieldsForSelect,w as createQualifiedEntityFieldsForSelectWithAliases};
1
+ import{sql as a}from"drizzle-orm";const i=(t="",r)=>{const e=t?`${t}.`:"";return{id:r?a.raw(e+"id").as(r):a.raw(e+"id"),organizationId:a.raw(e+"organization_id"),projectId:a.raw(e+"project_id"),key:a.raw(e+"key"),type:a.raw(e+"type"),title:a.raw(e+"title"),summary:a.raw(e+"summary"),tags:a.raw(e+"tags"),metadata:a.raw(e+"metadata"),git:a.raw(e+"git"),contact:a.raw(e+"contact"),links:a.raw(e+"links"),createdAt:a.raw(e+"created_at"),updatedAt:a.raw(e+"updated_at"),source:a.raw(e+"source"),sourceFile:a.raw(e+"source_file"),fileHash:a.raw(e+"file_hash"),version:a.raw(e+"version"),revision:a.raw(e+"revision"),hash:a.raw(e+"hash"),isCurrent:a.raw(e+"is_current"),isDefaultVersion:a.raw(e+"is_default_version"),isDeleted:a.raw(e+"is_deleted"),scorecardsStatus:a.raw(e+"scorecards_status")}},s=(t="",r)=>{const e=t?`${t}.`:"";return{id:r?a.raw(e+"id").as(r):a.raw(e+"id"),organizationId:a.raw(e+"organization_id"),projectId:a.raw(e+"project_id"),sourceKey:a.raw(e+"source_key"),sourceVersion:a.raw(e+"source_version"),sourceRevision:a.raw(e+"source_revision"),sourceToTargetRelation:a.raw(e+"source_to_target_relation"),targetKey:a.raw(e+"target_key"),targetVersion:a.raw(e+"target_version"),targetRevision:a.raw(e+"target_revision"),targetToSourceRelation:a.raw(e+"target_to_source_relation"),fileHash:a.raw(e+"file_hash"),createdAt:a.raw(e+"created_at"),updatedAt:a.raw(e+"updated_at")}},n=(t="")=>{const r=t?`${t}.`:"";return{id:a.raw(r+"entity_id"),organizationId:a.raw(r+"organization_id"),projectId:a.raw(r+"project_id"),key:a.raw(r+"key"),type:a.raw(r+"type"),title:a.raw(r+"title"),summary:a.raw(r+"summary"),tags:a.raw(r+"tags"),metadata:a.raw(r+"metadata"),git:a.raw(r+"git"),contact:a.raw(r+"contact"),links:a.raw(r+"links"),createdAt:a.raw(r+"created_at"),updatedAt:a.raw(r+"updated_at"),source:a.raw(r+"source"),sourceFile:a.raw(r+"source_file"),fileHash:a.raw(r+"file_hash"),version:a.raw(r+"version"),revision:a.raw(r+"revision"),hash:a.raw(r+"hash"),isCurrent:a.raw(r+"is_current"),isDefaultVersion:a.raw(r+"is_default_version"),isDeleted:a.raw(r+"is_deleted")}},w=(t="")=>{const r=t?`${t}.`:"";return{id:a.raw(r+"entity_id").as("id"),organizationId:a.raw(r+"organization_id").as("organization_id"),projectId:a.raw(r+"project_id").as("project_id"),key:a.raw(r+"key").as("key"),type:a.raw(r+"type").as("type"),title:a.raw(r+"title").as("title"),summary:a.raw(r+"summary").as("summary"),tags:a.raw(r+"tags").as("tags"),metadata:a.raw(r+"metadata").as("metadata"),git:a.raw(r+"git").as("git"),contact:a.raw(r+"contact").as("contact"),links:a.raw(r+"links").as("links"),createdAt:a.raw(r+"created_at").as("created_at"),updatedAt:a.raw(r+"updated_at").as("updated_at"),source:a.raw(r+"source").as("source"),sourceFile:a.raw(r+"source_file").as("source_file"),fileHash:a.raw(r+"file_hash").as("file_hash"),version:a.raw(r+"version").as("version"),revision:a.raw(r+"revision").as("revision"),hash:a.raw(r+"hash").as("hash"),isCurrent:a.raw(r+"is_current").as("is_current"),isDefaultVersion:a.raw(r+"is_default_version").as("is_default_version"),isDeleted:a.raw(r+"is_deleted").as("is_deleted")}},d=i(),c=s();export{d as FIELDS_TO_SELECT_FOR_ENTITY,c as FIELDS_TO_SELECT_FOR_ENTITY_RELATION,i as createEntityFieldsForSelect,s as createEntityRelationFieldsForSelect,n as createQualifiedEntityFieldsForSelect,w as createQualifiedEntityFieldsForSelectWithAliases};
@@ -1 +1 @@
1
- import y from"node:path";import{removeLeadingSlash as f}from"@redocly/theme/core/utils";import{toKebabCase as m}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as g}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";const d=15;class D extends E{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t,i){const a=f(t.realRelativePath),h=t.document.info.title,r=a.replace(/\.[^.]+$/,""),o=m(r.replace(/[\\/]/g,"-")),n=t.document["x-redocly-catalog-key"],e=typeof n=="string"&&n.trim()?m(n.trim()):o;return{type:this.type,key:e,title:h,summary:t.document.info.description?w(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a},version:i}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t,i,a,h){if(!this.#t(t)){this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`);return}const r=this.getRbacTeamsForDefinition(t.relativePath),o=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:o,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,revision:i,rbacTeams:r}),h.delete(`${o.key}:${a}`),await this.#e(t,o.key,o.version,a,i,h,r);const n=t.document.sourceDescriptions||[];await g(n,d,async e=>{if(!(e.type!=="openapi"||!e.url))try{const c=this.resolveSourceDescriptionUrl(e.url,t.realRelativePath);if(!c){!e.url.startsWith("http://")&&!e.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${e.url}`);return}const l=await this.context.cache.load(c,"load-oas");if(!(l.data&&Array.isArray(l.data)&&l.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${c}`);return}const p=l.data[0],u=m(f(p.realRelativePath).replace(/\.[^.]+$/,"").replace(/[\\/]/g,"-"));await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o.key,type:"relatesTo",targetKey:u,fileHash:t.hash}),await this.#r(t,e.name,p,o.key,u,o.version,i)}catch(c){this.context.logger.warn(`Failed to create relation to OpenAPI source "${e.url}": ${c instanceof Error?c.message:"Unknown error"}`)}})}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,i,a,h,r,o,n)=>{try{const e=t.document.components?.inputs,c=e?Object.entries(e):[],l=[];for(const[s,p]of c)l.push(async()=>{const u=await this.#a({schemaName:s,schema:p,description:t,parentKey:i,parentVersion:a,parentRevision:r,rbacTeams:n});o.delete(`${u.entityKey}:${h}`),u.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:i,type:"uses",targetKey:u.entityKey,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:r,targetRevision:r})});if(l.length===0)return;await g(l,d,s=>s())}catch(e){this.context.logger.warn(`Failed to create data schema entities for Arazzo description: ${e instanceof Error?e.message:"Unknown error"}`)}};#a=async({schemaName:t,schema:i,description:a,parentKey:h,parentVersion:r,parentRevision:o,rbacTeams:n})=>{const e={type:"data-schema",key:`${h}-${m(t)}`,title:t,summary:i.description||i.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:r};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:e,sourceFile:a.realRelativePath,fileHash:a.hash,revision:o,rbacTeams:n})};#r=async(t,i,a,h,r,o,n)=>{const e=t.document.workflows||[];if(e.length===0)return;const c=new Set;for(const l of e)for(const s of l.steps||[]){if(!s.operationId)continue;const p=s.operationId.startsWith(`${i}.`)?s.operationId.substring(`${i}.`.length):s.operationId;p&&c.add(p)}c.size!==0&&await g(Array.from(c),d,async l=>{try{const s=`${r}-${m(l)}`;await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:h,type:"uses",targetKey:s,fileHash:t.hash,sourceVersion:o,targetVersion:o,sourceRevision:n,targetRevision:n})}catch(s){this.context.logger.warn(`Failed to create relation to operation "${l}": ${s instanceof Error?s.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,i){try{const a=t.trim(),h=a.startsWith("@")?a.slice(1):a,[r]=h.split("#");if(r.startsWith("http://")||r.startsWith("https://"))return null;if(r.startsWith("/"))return f(y.posix.normalize(r));const o=y.posix.dirname(i);return r.startsWith(o+"/")?y.posix.normalize(r):y.posix.normalize(y.posix.join(o,r))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{D as ArazzoEntitiesExtractor};
1
+ import u from"node:path";import{removeLeadingSlash as g}from"@redocly/theme/core/utils";import{toKebabCase as d}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as v}from"./base.js";const f=15;class P extends v{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t,i){const a=g(t.realRelativePath),l=t.document.info.title,e=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:t.document["x-redocly-catalog-key"]});return{type:this.type,key:e,title:l,summary:t.document.info.description?w(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a},version:i}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t,i,a,l){if(!this.#t(t)){this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`);return}const e=this.getRbacTeamsForDefinition(t.relativePath),o=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:o,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,revision:i,rbacTeams:e}),l.delete(`${o.key}:${a}`),await this.#e(t,o.key,o.version,a,i,l,e);const h=t.document.sourceDescriptions||[];await m(h,f,async r=>{if(!(r.type!=="openapi"||!r.url))try{const n=this.resolveSourceDescriptionUrl(r.url,t.realRelativePath);if(!n){!r.url.startsWith("http://")&&!r.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${r.url}`);return}const c=await this.context.cache.load(n,"load-oas");if(!(c.data&&Array.isArray(c.data)&&c.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${n}`);return}const p=c.data[0],y=this.resolveEntityKey({realRelativePath:p.realRelativePath,customKey:p.definition["x-redocly-catalog-key"]});await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o.key,type:"relatesTo",targetKey:y,fileHash:t.hash}),await this.#r(t,r.name,p,o.key,y,o.version,i)}catch(n){this.context.logger.warn(`Failed to create relation to OpenAPI source "${r.url}": ${n instanceof Error?n.message:"Unknown error"}`)}})}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,i,a,l,e,o,h)=>{try{const r=t.document.components?.inputs,n=r?Object.entries(r):[],c=[];for(const[s,p]of n)c.push(async()=>{const y=await this.#a({schemaName:s,schema:p,description:t,parentKey:i,parentVersion:a,parentRevision:e,rbacTeams:h});o.delete(`${y.entityKey}:${l}`),y.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:i,type:"uses",targetKey:y.entityKey,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:e,targetRevision:e})});if(c.length===0)return;await m(c,f,s=>s())}catch(r){this.context.logger.warn(`Failed to create data schema entities for Arazzo description: ${r instanceof Error?r.message:"Unknown error"}`)}};#a=async({schemaName:t,schema:i,description:a,parentKey:l,parentVersion:e,parentRevision:o,rbacTeams:h})=>{const r={type:"data-schema",key:`${l}-${d(t)}`,title:t,summary:i.description||i.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,revision:o,rbacTeams:h})};#r=async(t,i,a,l,e,o,h)=>{const r=t.document.workflows||[];if(r.length===0)return;const n=new Set;for(const c of r)for(const s of c.steps||[]){if(!s.operationId)continue;const p=s.operationId.startsWith(`${i}.`)?s.operationId.substring(`${i}.`.length):s.operationId;p&&n.add(p)}n.size!==0&&await m(Array.from(n),f,async c=>{try{const s=`${e}-${d(c)}`;await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:l,type:"uses",targetKey:s,fileHash:t.hash,sourceVersion:o,targetVersion:o,sourceRevision:h,targetRevision:h})}catch(s){this.context.logger.warn(`Failed to create relation to operation "${c}": ${s instanceof Error?s.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,i){try{const a=t.trim(),l=a.startsWith("@")?a.slice(1):a,[e]=l.split("#");if(e.startsWith("http://")||e.startsWith("https://"))return null;if(e.startsWith("/"))return g(u.posix.normalize(e));const o=u.posix.dirname(i);return e.startsWith(o+"/")?u.posix.normalize(e):u.posix.normalize(u.posix.join(o,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{P as ArazzoEntitiesExtractor};
@@ -1 +1 @@
1
- import{removeLeadingSlash as d}from"@redocly/theme/core/utils";import{toKebabCase as m}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{removeMarkdocTags as R}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";import{extractPartsFromComponentsRef as f}from"../../../utils/extract-parts-from-components-ref.js";import{extractPartsFromChannelsMessageRef as w}from"../../../utils/extract-parts-from-channels-message-ref.js";const u=15;class N extends E{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,a){const s=d(e.realRelativePath),r=e.document.info.title,t=s.replace(/\.[^.]+$/,""),n=m(t.replace(/[\\/]/g,"-")),c=e.document["x-redocly-catalog-key"],o=typeof c=="string"&&c.trim()?m(c.trim()):n;return{type:this.type,key:o,title:r,summary:R(e.document.info.description),tags:e.document.info.tags?.map(i=>i.name),metadata:{specType:this.specType,descriptionFile:s},version:a}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,a,s,r){const t=this.getRbacTeamsForDefinition(e.relativePath),n=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:n,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,revision:a,rbacTeams:t}),r.delete(`${n.key}:${s}`);const c=this.#a(e),[o,i]=await Promise.allSettled([this.#s(e,n.key,n.version,s,a,r,t),this.#r(c,e,n.key,n.version,s,a,r,t)]);o.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",o.reason),i.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",i.reason)}#a=e=>{const a=e.documentWithReferences.operations;return a?Object.entries(a).map(([s,r])=>({operationName:s,operation:r})):[]};#s=async(e,a,s,r,t,n,c)=>{const o=e.document.components?.schemas;if(!o)return;const i=Object.entries(o);if(i.length===0)return;const l=await $(i,u,async([h,y])=>{const g=await this.#n({schemaName:h,schema:y,description:e,parentKey:a,parentVersion:s,parentRevision:t,rbacTeams:c});n.delete(`${g.entityKey}:${r}`),g.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:g.entityKey,fileHash:e.hash,sourceVersion:s,targetVersion:s,sourceRevision:t,targetRevision:t})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${i.length} schemas for ${e.realRelativePath}`)};#n=async({schemaName:e,schema:a,description:s,parentKey:r,parentVersion:t,parentRevision:n,rbacTeams:c})=>{const o=`${r}-${m(e)}`,i="title"in a?a.title??a.description:null,l=JSON.stringify(a),h={type:"data-schema",key:o,title:e,summary:i,tags:[],metadata:{specType:this.specType,schema:l},version:t};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:h,sourceFile:s.realRelativePath,fileHash:s.hash,revision:n,rbacTeams:c})};#r=async(e,a,s,r,t,n,c,o)=>{if(!e.length)return;const i=await $(e,u,async({operationName:l,operation:h})=>{const y=await this.#c(h,l,a,s,r,n,o);y&&c.delete(`${y}:${t}`)},this.context.logger);i.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${i.count.failed} failures out of ${e.length} operations for ${a.realRelativePath}`)};#c=async(e,a,s,r,t,n,c)=>{const o=await this.#o(e.messages??[],s,r),i=await this.#i(a,e,o,s,r,t,n,c);return i.result==="created"&&await this.#l({apiOperationKey:i.entityKey,operation:e,descriptionUniqueKey:r,description:s,descriptionVersion:t,parentRevision:n}),i.entityKey??null};#o=async(e,a,s)=>{if(!e||e.length===0)return[];const r=new Set;for(const t of e){let n=null;if("$ref"in t){const c=t.$ref.startsWith("#/channels/")?this.#e(t.$ref,a):t.$ref;if(c){const o=f(c);if(o?.componentName&&o.componentType==="messages"){const i=a.documentWithReferences.components?.messages[o.componentName];i?.payload&&"$ref"in i.payload&&i.payload.$ref&&(n=i.payload.$ref)}}}else t.payload&&"$ref"in t.payload&&t.payload.$ref&&(n=t.payload.$ref);if(n){const c=f(n);c?.componentName&&c.componentType==="schemas"&&r.add(`${s}-${m(c.componentName)}`)}}return Array.from(r)};#i=async(e,a,s,r,t,n,c,o)=>{const i={type:"api-operation",key:`${t}-${m(e)}`,title:a.title||e,summary:a.summary??"",tags:a.tags?.map(h=>h.name)??[],metadata:{method:a.action==="send"?"PUBLISH":"SUBSCRIBE",path:a.channel.address??"",payload:a.action==="receive"?s:[],responses:a.action==="send"?s:[]},version:n};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:i,sourceFile:r.realRelativePath,fileHash:r.hash,revision:c,rbacTeams:o})};#l=async({apiOperationKey:e,operation:a,descriptionUniqueKey:s,description:r,descriptionVersion:t,parentRevision:n})=>(await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"partOf",targetKey:s,fileHash:r.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),await this.#h(a,e,t,n),!Array.isArray(a.messages)||!a.messages?.length?[]:await this.#m(a.messages,e,r,s,t,n));#h=async(e,a,s,r)=>{e["x-catalog-relations"]?.length&&await p(e["x-catalog-relations"],u,async t=>{try{this.validateEntityRelationFileSchema(t),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:t.type,targetKey:t.key,sourceVersion:s,targetVersion:"",sourceRevision:r,targetRevision:""})}catch(n){this.context.logger.warn(`Error creating entity relation for operation ${a} based on custom property: ${n instanceof Error?n.message:"Unknown error"}`)}})};#m=async(e,a,s,r,t,n)=>e.length===0?[]:(await p(e,u,async o=>await this.#y(o,a,s,r,t,n)??"")).filter(o=>!!o);#y=async(e,a,s,r,t,n)=>"$ref"in e?this.#f(e,a,s,r,t,n):e.payload?this.#u(e,a,s,r,t,n):null;#f=async(e,a,s,r,t,n)=>{const c=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,s):e.$ref;if(!c)return null;const o=f(c);if(!o||!o.componentName||o.componentType!=="messages")return null;const i=s.documentWithReferences.components?.messages[o.componentName];return!i?.payload||!("$ref"in i.payload)||!i.payload.$ref?null:this.#t(i.payload.$ref,a,s,r,t,n)};#e=(e,a)=>{const s=w(e);if(!s||!s.channelName||!s.messageName)return null;const r=a.documentWithReferences.channels?.[s.channelName];if(!r?.messages)return null;const t=r.messages[s.messageName];return!t||!("$ref"in t)||typeof t.$ref!="string"||!t.$ref.startsWith("#/components/messages/")?null:t.$ref};#u=async(e,a,s,r,t,n)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,a,s,r,t,n);#t=async(e,a,s,r,t,n)=>{const c=f(e);if(!c||!c.componentName||c.componentType!=="schemas")return null;const o=`${r}-${m(c.componentName)}`;return await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:o,fileHash:s.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),o}}export{N as AsyncApiEntitiesExtractor};
1
+ import{removeLeadingSlash as d}from"@redocly/theme/core/utils";import{toKebabCase as y}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{removeMarkdocTags as R}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";import{extractPartsFromComponentsRef as f}from"../../../utils/extract-parts-from-components-ref.js";import{extractPartsFromChannelsMessageRef as w}from"../../../utils/extract-parts-from-channels-message-ref.js";const u=15;class N extends E{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,a){const s=d(e.realRelativePath),r=e.document.info.title,t=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.document["x-redocly-catalog-key"]});return{type:this.type,key:t,title:r,summary:R(e.document.info.description),tags:e.document.info.tags?.map(n=>n.name),metadata:{specType:this.specType,descriptionFile:s},version:a}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,a,s,r){const t=this.getRbacTeamsForDefinition(e.relativePath),n=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:n,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,revision:a,rbacTeams:t}),r.delete(`${n.key}:${s}`);const o=this.#a(e),[c,i]=await Promise.allSettled([this.#s(e,n.key,n.version,s,a,r,t),this.#r(o,e,n.key,n.version,s,a,r,t)]);c.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",c.reason),i.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",i.reason)}#a=e=>{const a=e.documentWithReferences.operations;return a?Object.entries(a).map(([s,r])=>({operationName:s,operation:r})):[]};#s=async(e,a,s,r,t,n,o)=>{const c=e.document.components?.schemas;if(!c)return;const i=Object.entries(c);if(i.length===0)return;const l=await $(i,u,async([h,m])=>{const g=await this.#n({schemaName:h,schema:m,description:e,parentKey:a,parentVersion:s,parentRevision:t,rbacTeams:o});n.delete(`${g.entityKey}:${r}`),g.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:g.entityKey,fileHash:e.hash,sourceVersion:s,targetVersion:s,sourceRevision:t,targetRevision:t})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${i.length} schemas for ${e.realRelativePath}`)};#n=async({schemaName:e,schema:a,description:s,parentKey:r,parentVersion:t,parentRevision:n,rbacTeams:o})=>{const c=`${r}-${y(e)}`,i="title"in a?a.title??a.description:null,l=JSON.stringify(a),h={type:"data-schema",key:c,title:e,summary:i,tags:[],metadata:{specType:this.specType,schema:l},version:t};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:h,sourceFile:s.realRelativePath,fileHash:s.hash,revision:n,rbacTeams:o})};#r=async(e,a,s,r,t,n,o,c)=>{if(!e.length)return;const i=await $(e,u,async({operationName:l,operation:h})=>{const m=await this.#c(h,l,a,s,r,n,c);m&&o.delete(`${m}:${t}`)},this.context.logger);i.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${i.count.failed} failures out of ${e.length} operations for ${a.realRelativePath}`)};#c=async(e,a,s,r,t,n,o)=>{const c=await this.#i(e.messages??[],s,r),i=await this.#o(a,e,c,s,r,t,n,o);return i.result==="created"&&await this.#l({apiOperationKey:i.entityKey,operation:e,descriptionUniqueKey:r,description:s,descriptionVersion:t,parentRevision:n}),i.entityKey??null};#i=async(e,a,s)=>{if(!e||e.length===0)return[];const r=new Set;for(const t of e){let n=null;if("$ref"in t){const o=t.$ref.startsWith("#/channels/")?this.#e(t.$ref,a):t.$ref;if(o){const c=f(o);if(c?.componentName&&c.componentType==="messages"){const i=a.documentWithReferences.components?.messages[c.componentName];i?.payload&&"$ref"in i.payload&&i.payload.$ref&&(n=i.payload.$ref)}}}else t.payload&&"$ref"in t.payload&&t.payload.$ref&&(n=t.payload.$ref);if(n){const o=f(n);o?.componentName&&o.componentType==="schemas"&&r.add(`${s}-${y(o.componentName)}`)}}return Array.from(r)};#o=async(e,a,s,r,t,n,o,c)=>{const i={type:"api-operation",key:`${t}-${y(e)}`,title:a.title||e,summary:a.summary??"",tags:a.tags?.map(h=>h.name)??[],metadata:{method:a.action==="send"?"PUBLISH":"SUBSCRIBE",path:a.channel.address??"",payload:a.action==="receive"?s:[],responses:a.action==="send"?s:[]},version:n};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:i,sourceFile:r.realRelativePath,fileHash:r.hash,revision:o,rbacTeams:c})};#l=async({apiOperationKey:e,operation:a,descriptionUniqueKey:s,description:r,descriptionVersion:t,parentRevision:n})=>(await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"partOf",targetKey:s,fileHash:r.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),await this.#h(a,e,t,n),!Array.isArray(a.messages)||!a.messages?.length?[]:await this.#m(a.messages,e,r,s,t,n));#h=async(e,a,s,r)=>{e["x-catalog-relations"]?.length&&await p(e["x-catalog-relations"],u,async t=>{try{this.validateEntityRelationFileSchema(t),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:t.type,targetKey:t.key,sourceVersion:s,targetVersion:"",sourceRevision:r,targetRevision:""})}catch(n){this.context.logger.warn(`Error creating entity relation for operation ${a} based on custom property: ${n instanceof Error?n.message:"Unknown error"}`)}})};#m=async(e,a,s,r,t,n)=>e.length===0?[]:(await p(e,u,async c=>await this.#y(c,a,s,r,t,n)??"")).filter(c=>!!c);#y=async(e,a,s,r,t,n)=>"$ref"in e?this.#f(e,a,s,r,t,n):e.payload?this.#u(e,a,s,r,t,n):null;#f=async(e,a,s,r,t,n)=>{const o=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,s):e.$ref;if(!o)return null;const c=f(o);if(!c||!c.componentName||c.componentType!=="messages")return null;const i=s.documentWithReferences.components?.messages[c.componentName];return!i?.payload||!("$ref"in i.payload)||!i.payload.$ref?null:this.#t(i.payload.$ref,a,s,r,t,n)};#e=(e,a)=>{const s=w(e);if(!s||!s.channelName||!s.messageName)return null;const r=a.documentWithReferences.channels?.[s.channelName];if(!r?.messages)return null;const t=r.messages[s.messageName];return!t||!("$ref"in t)||typeof t.$ref!="string"||!t.$ref.startsWith("#/components/messages/")?null:t.$ref};#u=async(e,a,s,r,t,n)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,a,s,r,t,n);#t=async(e,a,s,r,t,n)=>{const o=f(e);if(!o||!o.componentName||o.componentType!=="schemas")return null;const c=`${r}-${y(o.componentName)}`;return await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:a,type:"uses",targetKey:c,fileHash:s.hash,sourceVersion:t,targetVersion:t,sourceRevision:n,targetRevision:n}),c}}export{N as AsyncApiEntitiesExtractor};
@@ -19,8 +19,20 @@ export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition exte
19
19
  extract(): Promise<void>;
20
20
  protected validateEntityRelationFileSchema(relation: unknown): void;
21
21
  protected getRbacTeamsForDefinition(relativePath: string): string[];
22
+ /**
23
+ * Resolves the entity key for an API description.
24
+ * Uses x-redocly-catalog-key if present and non-empty, otherwise derives a key from the file path.
25
+ * @param realRelativePath - The real relative path of the description file
26
+ * @param customKey - Optional custom key from x-redocly-catalog-key
27
+ * @param extensionPattern - Optional regex to strip file extension (default: any extension)
28
+ */
29
+ protected resolveEntityKey({ realRelativePath, customKey, extensionPattern, }: {
30
+ realRelativePath: string;
31
+ customKey?: string | null;
32
+ extensionPattern?: RegExp;
33
+ }): string;
22
34
  protected abstract loadApiDescriptions(): Promise<BundledApiDefinition[]>;
23
- protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string, rbacTeams: string[]): EntityFileSchema;
35
+ protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string): EntityFileSchema;
24
36
  protected abstract processApiDescription(definition: BundledApiDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
25
37
  }
26
38
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- import{entityRelationFileSchema as g}from"@redocly/config";import{FileHashStatus as c}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{OPERATORS as u}from"../../../../../providers/database/pagination/constants.js";import{VERSION_NOT_SPECIFIED as p}from"@redocly/theme/core/constants";import{getRbacTeamsListForResource as v}from"../../../../../utils/rbac.js";import{envConfig as h}from"../../../../../config/env-config.js";import{resolveEntityVersion as y}from"../../../utils/resolve-entity-version.js";import{catalogDataCollector as f}from"../../../utils/catalog-data-collector.js";import{createValidator as d}from"../../../utils/ajv-validator.js";const R=3;class x{type="api-description";specType;fileType;actions;context;catalogEntitiesService;fileHashManager;entitySources={};#e;constructor(t,e){this.specType=t,this.fileType=e.fileType,this.actions=e.actions,this.context=e.context,this.catalogEntitiesService=e.catalogEntitiesService,this.fileHashManager=e.fileHashManager,this.#e=e.shouldCalculateEntities??!1}async extract(){const t=await this.loadApiDescriptions();await this.fileHashManager.markAllAsOutdated(this.fileType),t.length&&f.addExtractor(this.specType),await m(t,R,async e=>{try{if(e.isVirtual||!e.hash)return;if(!((await this.fileHashManager.getByPath(e.realRelativePath))?.hash!==e.hash||this.#e||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")){f.increaseSkippedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,c.UP_TO_DATE);return}const a=await this.catalogEntitiesService.getEntityKeysAndVersionsBySourceFile(e.realRelativePath);h.FORCE_CATALOG_CACHE_REVALIDATE==="true"&&(await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:Array.from(a).map(o=>o.split(":")[0])}),a.clear());const s=new Date().toISOString(),n=this.#a(e);await this.processApiDescription(e,s,n,a),await this.#i(a,e.realRelativePath,s,e.hash),f.increaseProcessedFilesCount(),await this.fileHashManager.upsert(this.fileType,e.realRelativePath,e.hash,c.UP_TO_DATE)}catch(i){this.context.logger.warn(`Error extracting entities from ${this.specType} description: ${e.realRelativePath}`),this.context.logger.warn(i)}}),await this.#t()}#t=async()=>{const t=await this.fileHashManager.getAllOutdated(this.fileType);if(!t||t.length===0)return;const e=await this.catalogEntitiesService.getEntities({paginationParams:{limit:1e3,filter:{op:"AND",conditions:[{field:"source_file",operator:"in",value:t.map(({filePath:i})=>i)},{field:"is_current",operator:"equal",value:!0}]}}});e&&e.items.length>0&&await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:e.items.map(({key:i})=>i)}),await this.fileHashManager.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:this.fileType},{field:"status",operator:"equal",value:c.OUTDATED}]})};#i=async(t,e,i,r)=>{if(t.size===0||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")return;const a=Array.from(t).map(o=>{const[l,E]=o.split(":");return{key:l,version:E}}),s=Array.from(new Set(a.map(({key:o})=>o))),n=a.map(({key:o,version:l})=>({op:u.AND,conditions:[{field:"key",operator:"equal",value:o},{field:"version",operator:"equal",value:l}]}));await this.catalogEntitiesService.softDeleteEntitiesInLocalDatabase({revision:i,fileHash:r,filter:{op:"AND",conditions:[{field:"key",operator:"in",value:s},{op:u.OR,conditions:n},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]}})};#a(t){const e=t.document?.info?.version??t.definition?.info?.version??null,i=y(e,t.realRelativePath);return i.success?i.version??p:p}validateEntityRelationFileSchema(t){d(g,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"})(t)}getRbacTeamsForDefinition(t){const e=this.actions.getConfig().rbac,i=this.actions.getRouteByFsPath(t);return v(i||{fsPath:t},e||{})}}export{x as BaseApiEntitiesExtractor};
1
+ import{entityRelationFileSchema as m}from"@redocly/config";import{removeLeadingSlash as E}from"@redocly/theme/core/utils";import{toKebabCase as u}from"../../../../../../utils/string/to-kebab-case.js";import{FileHashStatus as c}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as v}from"../../../../../utils/async/promise-map-limit.js";import{OPERATORS as y}from"../../../../../providers/database/pagination/constants.js";import{VERSION_NOT_SPECIFIED as d}from"@redocly/theme/core/constants";import{getRbacTeamsListForResource as R}from"../../../../../utils/rbac.js";import{envConfig as h}from"../../../../../config/env-config.js";import{resolveEntityVersion as A}from"../../../utils/resolve-entity-version.js";import{catalogDataCollector as p}from"../../../utils/catalog-data-collector.js";import{createValidator as T}from"../../../utils/ajv-validator.js";const C=3;class M{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&&p.addExtractor(this.specType);const e=this.#t(t);await v(Array.from(e.values()),C,async a=>{for(const{description:i,version:r}of a)try{const o=i.hash;if(!o)continue;if(!((await this.fileHashManager.getByPath(i.realRelativePath))?.hash!==o||this.#e||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")){p.increaseSkippedFilesCount(),await this.fileHashManager.upsert(this.fileType,i.realRelativePath,o,c.UP_TO_DATE);continue}const s=await this.catalogEntitiesService.getEntityKeysAndVersionsBySourceFile(i.realRelativePath);h.FORCE_CATALOG_CACHE_REVALIDATE==="true"&&(await this.catalogEntitiesService.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:Array.from(s).map(g=>g.split(":")[0])}),s.clear());const l=new Date().toISOString();await this.processApiDescription(i,l,r,s),await this.#a(s,i.realRelativePath,l,o),p.increaseProcessedFilesCount(),await this.fileHashManager.upsert(this.fileType,i.realRelativePath,o,c.UP_TO_DATE)}catch(o){this.context.logger.warn(`Error extracting entities from ${this.specType} description: ${i.realRelativePath}`),this.context.logger.warn(o)}}),await this.#i()}#t(t){const e=new Map;for(const a of t)if(!(a.isVirtual||!a.hash))try{const i=this.#o(a),r=this.mapApiDescriptionToEntity(a,i),o=e.get(r.key)??[];o.push({description:a,version:i}),e.set(r.key,o)}catch(i){this.context.logger.warn(`Error resolving entity key for ${this.specType} description (skipping): ${a.realRelativePath}`),this.context.logger.warn(i)}return e}#i=async()=>{const t=await this.fileHashManager.getAllOutdated(this.fileType);if(!t||t.length===0)return;const e=await this.catalogEntitiesService.getEntities({paginationParams:{limit:1e3,filter:{op:"AND",conditions:[{field:"source_file",operator:"in",value:t.map(({filePath:a})=>a)},{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:a})=>a)}),await this.fileHashManager.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:this.fileType},{field:"status",operator:"equal",value:c.OUTDATED}]})};#a=async(t,e,a,i)=>{if(t.size===0||h.FORCE_CATALOG_CACHE_REVALIDATE==="true")return;const r=Array.from(t).map(n=>{const[s,l]=n.split(":");return{key:s,version:l}}),o=Array.from(new Set(r.map(({key:n})=>n))),f=r.map(({key:n,version:s})=>({op:y.AND,conditions:[{field:"key",operator:"equal",value:n},{field:"version",operator:"equal",value:s}]}));await this.catalogEntitiesService.softDeleteEntitiesInLocalDatabase({revision:a,fileHash:i,filter:{op:"AND",conditions:[{field:"key",operator:"in",value:o},{op:y.OR,conditions:f},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]}})};#o(t){const e=t.document?.info?.version??t.definition?.info?.version??null,a=A(e,t.realRelativePath);return a.success?a.version??d:d}validateEntityRelationFileSchema(t){T(m,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"})(t)}getRbacTeamsForDefinition(t){const e=this.actions.getConfig().access?.rbac,a=this.actions.getRouteByFsPath(t);return R(a||{fsPath:t},e||{})}resolveEntityKey({realRelativePath:t,customKey:e,extensionPattern:a}){const i=this.#r(t,a);return typeof e=="string"&&e.trim()?u(e.trim()):i}#r(t,e){let i=E(t);for(;/^@[^/]+\//.test(i);)i=i.replace(/^@[^/]+\//,"");i=i.replace(/\/@[^/]+/g,"");const r=e?i.replace(e,""):i.replace(/\.[^.]+$/,"");return u(r.replace(/[\\/]/g,"-"))}}export{M as BaseApiEntitiesExtractor};
@@ -1,3 +1,3 @@
1
- import{buildSchema as O,isObjectType as T,isScalarType as D,isEnumType as v,isInterfaceType as w,isUnionType as E,isInputObjectType as b,getNamedType as u,printType as L}from"graphql";import{removeLeadingSlash as A}from"@redocly/theme/core/utils";import{toKebabCase as g}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as j}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as d}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as K}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as F}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as N}from"./base.js";const R=15,I=15,P=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class U extends N{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of 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:i,metadata:r}=a.data,s=O(i),n=K(i);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:n,schema:s,content:i,metadata:r})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t,e){const a=A(t.realRelativePath),i=t.relativePath.replace(/\.(gql|graphql)$/,""),r=this.#s(i.split("/").pop()||"GraphQL Schema"),s=a.replace(/\.(gql|graphql)$/,""),n=g(s.replace(/[\\/]/g,"-")),p=this.#c(t.metadata?.tags),o=t.metadata?.["x-redocly-catalog-key"],l=typeof o=="string"&&o.trim()?g(o.trim()):n;return{type:this.type,key:l,title:r,summary:t.metadata?.description||null,tags:p.concat("graphql"),metadata:{specType:this.specType,descriptionFile:a},version:e}}async processApiDescription(t,e,a,i){const{schema:r}=t;if(!r)return;const s=this.getRbacTeamsForDefinition(t.relativePath),n=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:n,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,revision:e,rbacTeams:s}),i.delete(`${n.key}:${a}`),await Promise.all([this.#a(t,n.key,n.version,a,e,i,s),this.#y(t,n.key,n.version,a,e,i,s)])}#a=async(t,e,a,i,r,s,n)=>{const{schema:p}=t,o=p.getTypeMap(),l=this.#i(p),c=Object.entries(o).filter(([y])=>!y.startsWith("__")&&!P.has(y)&&!l.has(y));if(c.length===0)return;const h=await $(c,I,async([y,m])=>{const f=await this.#l({typeName:y,type:m,description:t,parentKey:e,parentVersion:a,parentRevision:r,rbacTeams:n});s.delete(`${f.entityKey}:${i}`),f.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"uses",targetKey:f.entityKey,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:r,targetRevision:r})},this.#t);h.count.failed>0&&this.#t.warn(`Schema processing completed with ${h.count.failed} failures out of ${c.length} types for ${t.realRelativePath}`),await this.#h({description:t,descriptionUniqueKey:e,userTypes:c,parentRevision:r})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&j(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${g(t)}`;#n=t=>T(t)?"object":w(t)?"interface":E(t)?"union":v(t)?"enum":b(t)?"input":D(t)?"scalar":"unknown";#i=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const i=t.getMutationType();i&&e.add(i.name);const r=t.getSubscriptionType();return r&&e.add(r.name),e};#r(t){const e=[],a=t.getQueryType();if(a){const s=a.getFields();for(const[n,p]of Object.entries(s))e.push({fieldName:n,field:p,operationType:"QUERY",rootTypeName:a.name})}const i=t.getMutationType();if(i){const s=i.getFields();for(const[n,p]of Object.entries(s))e.push({fieldName:n,field:p,operationType:"MUTATION",rootTypeName:i.name})}const r=t.getSubscriptionType();if(r){const s=r.getFields();for(const[n,p]of Object.entries(s))e.push({fieldName:n,field:p,operationType:"SUBSCRIBE",rootTypeName:r.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const s of t.args){const n=u(s.type);n&&!n.name.startsWith("__")&&a.push(this.#e(n.name,e))}const i=[],r=u(t.type);return r&&!r.name.startsWith("__")&&i.push(this.#e(r.name,e)),{inputTypes:a,returnTypes:i}};#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:i,parentVersion:r,parentRevision:s,rbacTeams:n})=>{const p=this.#e(t,i),o=e.description??null,l=this.#n(e),c={type:"data-schema",key:p,title:t,summary:o,tags:["graphql"],metadata:{specType:this.specType,typeKind:l,sdl:this.#p(e,a.schema)},version:r};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:c,sourceFile:a.realRelativePath,fileHash:a.hash,revision:s,rbacTeams:n})};#p=(t,e)=>{const a=new Set,i=[],r=new Set(["String","ID","Int","Float","Boolean"]),s=o=>{if(!o)return;const l=o.name;if(l.startsWith("__")||r.has(l)||a.has(l))return;const c=e.getType(l);c&&(a.add(l),i.push(c))};for(s(t);i.length>0;){const o=i.pop();if(T(o)){for(const c of o.getInterfaces?.()??[])s(c);const l=o.getFields();for(const c of Object.values(l)){s(u(c.type));for(const h of c.args??[])s(u(h.type))}}else if(w(o)){const l=o.getFields();for(const c of Object.values(l))s(u(c.type))}else if(E(o))for(const l of o.getTypes())s(l);else if(b(o)){const l=o.getFields();for(const c of Object.values(l))s(u(c.type))}}const n=[t.name,...[...a].filter(o=>o!==t.name)],p=[];for(const o of n){const l=e.getType(o);l&&p.push(L(l))}return p.join(`
1
+ import{buildSchema as O,isObjectType as g,isScalarType as v,isEnumType as D,isInterfaceType as S,isUnionType as w,isInputObjectType as E,getNamedType as u,printType as L}from"graphql";import{removeLeadingSlash as P}from"@redocly/theme/core/utils";import{toKebabCase as b}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as A}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as T}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as R}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as j}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as K}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as F}from"./base.js";const $=15,I=15,N=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class U extends F{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of 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:i,metadata:r}=a.data,s=O(i),n=j(i);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:n,schema:s,content:i,metadata:r})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t,e){const a=P(t.realRelativePath),i=t.relativePath.replace(/\.(gql|graphql)$/,""),r=this.#s(i.split("/").pop()||"GraphQL Schema"),s=this.#c(t.metadata?.tags),n=t.metadata?.["x-redocly-catalog-key"],h=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:typeof n=="string"?n:void 0,extensionPattern:/\.(gql|graphql)$/});return{type:this.type,key:h,title:r,summary:t.metadata?.description||null,tags:s.concat("graphql"),metadata:{specType:this.specType,descriptionFile:a},version:e}}async processApiDescription(t,e,a,i){const{schema:r}=t;if(!r)return;const s=this.getRbacTeamsForDefinition(t.relativePath),n=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:n,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,revision:e,rbacTeams:s}),i.delete(`${n.key}:${a}`),await Promise.all([this.#a(t,n.key,n.version,a,e,i,s),this.#y(t,n.key,n.version,a,e,i,s)])}#a=async(t,e,a,i,r,s,n)=>{const{schema:h}=t,c=h.getTypeMap(),l=this.#i(h),o=Object.entries(c).filter(([y])=>!y.startsWith("__")&&!N.has(y)&&!l.has(y));if(o.length===0)return;const p=await R(o,I,async([y,m])=>{const f=await this.#l({typeName:y,type:m,description:t,parentKey:e,parentVersion:a,parentRevision:r,rbacTeams:n});s.delete(`${f.entityKey}:${i}`),f.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"uses",targetKey:f.entityKey,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:r,targetRevision:r})},this.#t);p.count.failed>0&&this.#t.warn(`Schema processing completed with ${p.count.failed} failures out of ${o.length} types for ${t.realRelativePath}`),await this.#p({description:t,descriptionUniqueKey:e,userTypes:o,parentRevision:r})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&A(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${b(t)}`;#n=t=>g(t)?"object":S(t)?"interface":w(t)?"union":D(t)?"enum":E(t)?"input":v(t)?"scalar":"unknown";#i=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const i=t.getMutationType();i&&e.add(i.name);const r=t.getSubscriptionType();return r&&e.add(r.name),e};#r(t){const e=[],a=t.getQueryType();if(a){const s=a.getFields();for(const[n,h]of Object.entries(s))e.push({fieldName:n,field:h,operationType:"QUERY",rootTypeName:a.name})}const i=t.getMutationType();if(i){const s=i.getFields();for(const[n,h]of Object.entries(s))e.push({fieldName:n,field:h,operationType:"MUTATION",rootTypeName:i.name})}const r=t.getSubscriptionType();if(r){const s=r.getFields();for(const[n,h]of Object.entries(s))e.push({fieldName:n,field:h,operationType:"SUBSCRIBE",rootTypeName:r.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const s of t.args){const n=u(s.type);n&&!n.name.startsWith("__")&&a.push(this.#e(n.name,e))}const i=[],r=u(t.type);return r&&!r.name.startsWith("__")&&i.push(this.#e(r.name,e)),{inputTypes:a,returnTypes:i}};#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:i,parentVersion:r,parentRevision:s,rbacTeams:n})=>{const h=this.#e(t,i),c=e.description??null,l=this.#n(e),o={type:"data-schema",key:h,title:t,summary:c,tags:["graphql"],metadata:{specType:this.specType,typeKind:l,sdl:this.#h(e,a.schema)},version:r};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:o,sourceFile:a.realRelativePath,fileHash:a.hash,revision:s,rbacTeams:n})};#h=(t,e)=>{const a=new Set,i=[],r=new Set(["String","ID","Int","Float","Boolean"]),s=c=>{if(!c)return;const l=c.name;if(l.startsWith("__")||r.has(l)||a.has(l))return;const o=e.getType(l);o&&(a.add(l),i.push(o))};for(s(t);i.length>0;){const c=i.pop();if(g(c)){for(const o of c.getInterfaces?.()??[])s(o);const l=c.getFields();for(const o of Object.values(l)){s(u(o.type));for(const p of o.args??[])s(u(p.type))}}else if(S(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}else if(w(c))for(const l of c.getTypes())s(l);else if(E(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}}const n=[t.name,...[...a].filter(c=>c!==t.name)],h=[];for(const c of n){const l=e.getType(c);l&&h.push(L(l))}return h.join(`
2
2
 
3
- `)};#h=async({description:t,descriptionUniqueKey:e,userTypes:a,parentRevision:i})=>{const r=a.filter(([,s])=>T(s));r.length!==0&&await d(r,I,async([s,n])=>{const o=n.getInterfaces?.()??[];if(!o.length)return;const l=this.#e(s,e);await d([...o],5,async c=>{const h=this.#e(c.name,e);try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:l,type:"implements",targetKey:h,fileHash:t.hash,sourceRevision:i,targetRevision:i})}catch(y){this.#t.warn(`Failed to create 'implements' relation ${l} -> ${h}: ${y instanceof Error?y.message:"Unknown error"}`)}})})};#y=async(t,e,a,i,r,s,n)=>{const{schema:p}=t,o=this.#r(p);if(o.length===0)return;const c=(await $(o,R,async({fieldName:h,field:y,operationType:m,rootTypeName:f})=>{const S=await this.#f(h,y,m,f,t,e,a,r,n);S&&s.delete(`${S}:${i}`)},this.#t)).count.failed;c>0&&this.#t.warn(`Operation extraction completed with ${c} failures out of ${o.length} operations for ${e}`)};#f=async(t,e,a,i,r,s,n,p,o)=>{const{inputTypes:l,returnTypes:c}=this.#o(e,s),h=await this.#u({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:l,returnTypes:c,description:r,descriptionUniqueKey:s,descriptionVersion:n,parentRevision:p,rbacTeams:o});return h.result==="created"&&await this.#m({apiOperationKey:h.entityKey,inputTypes:l,returnTypes:c,descriptionUniqueKey:s,description:r,descriptionVersion:n,parentRevision:p}),h.entityKey??null};#u=async({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:r,returnTypes:s,description:n,descriptionUniqueKey:p,descriptionVersion:o,parentRevision:l,rbacTeams:c})=>{const h=t,m={type:"api-operation",key:`${p}-${g(`${a.toLowerCase()}-${t}`)}`,title:h,summary:e.description?F(e.description):null,tags:["graphql"],metadata:{method:a,path:`${i}.${t}`,payload:r,responses:s},version:o};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:m,sourceFile:n.realRelativePath,fileHash:n.hash,revision:l,rbacTeams:c})};#m=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:i,description:r,descriptionVersion:s,parentRevision:n})=>{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:"partOf",targetKey:i,fileHash:r.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n});const p=[...new Set(e)],o=[...new Set(a)],l=[...p.map(c=>({key:c,relationType:"uses"})),...o.map(c=>({key:c,relationType:"returns"}))];await d(l,R,async({key:c,relationType:h})=>{try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:h,targetKey:c,fileHash:r.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n})}catch(y){this.#t.warn(`Failed to create relation between operation ${t} and type ${c} (${h}): ${y instanceof Error?y.message:"Unknown error"}`)}})}}export{U as GraphqlEntitiesExtractor};
3
+ `)};#p=async({description:t,descriptionUniqueKey:e,userTypes:a,parentRevision:i})=>{const r=a.filter(([,s])=>g(s));r.length!==0&&await T(r,I,async([s,n])=>{const c=n.getInterfaces?.()??[];if(!c.length)return;const l=this.#e(s,e);await T([...c],5,async o=>{const p=this.#e(o.name,e);try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:l,type:"implements",targetKey:p,fileHash:t.hash,sourceRevision:i,targetRevision:i})}catch(y){this.#t.warn(`Failed to create 'implements' relation ${l} -> ${p}: ${y instanceof Error?y.message:"Unknown error"}`)}})})};#y=async(t,e,a,i,r,s,n)=>{const{schema:h}=t,c=this.#r(h);if(c.length===0)return;const o=(await R(c,$,async({fieldName:p,field:y,operationType:m,rootTypeName:f})=>{const d=await this.#f(p,y,m,f,t,e,a,r,n);d&&s.delete(`${d}:${i}`)},this.#t)).count.failed;o>0&&this.#t.warn(`Operation extraction completed with ${o} failures out of ${c.length} operations for ${e}`)};#f=async(t,e,a,i,r,s,n,h,c)=>{const{inputTypes:l,returnTypes:o}=this.#o(e,s),p=await this.#u({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:l,returnTypes:o,description:r,descriptionUniqueKey:s,descriptionVersion:n,parentRevision:h,rbacTeams:c});return p.result==="created"&&await this.#m({apiOperationKey:p.entityKey,inputTypes:l,returnTypes:o,descriptionUniqueKey:s,description:r,descriptionVersion:n,parentRevision:h}),p.entityKey??null};#u=async({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:r,returnTypes:s,description:n,descriptionUniqueKey:h,descriptionVersion:c,parentRevision:l,rbacTeams:o})=>{const p=t,m={type:"api-operation",key:`${h}-${b(`${a.toLowerCase()}-${t}`)}`,title:p,summary:e.description?K(e.description):null,tags:["graphql"],metadata:{method:a,path:`${i}.${t}`,payload:r,responses:s},version:c};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:m,sourceFile:n.realRelativePath,fileHash:n.hash,revision:l,rbacTeams:o})};#m=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:i,description:r,descriptionVersion:s,parentRevision:n})=>{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:"partOf",targetKey:i,fileHash:r.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n});const h=[...new Set(e)],c=[...new Set(a)],l=[...h.map(o=>({key:o,relationType:"uses"})),...c.map(o=>({key:o,relationType:"returns"}))];await T(l,$,async({key:o,relationType:p})=>{try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:t,type:p,targetKey:o,fileHash:r.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n})}catch(y){this.#t.warn(`Failed to create relation between operation ${t} and type ${o} (${p}): ${y instanceof Error?y.message:"Unknown error"}`)}})}}export{U as GraphqlEntitiesExtractor};
@@ -1 +1 @@
1
- import{REDOCLY_TEAMS_RBAC as $}from"@redocly/config";import{removeLeadingSlash as x}from"@redocly/theme/core/utils";import{toKebabCase as p}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as T}from"../../../../../utils/async/promise-map-limit-with-status.js";import{extractTeamsFromScopeItems as R}from"../../../../../utils/rbac.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as N}from"./base.js";import{OpenapiSchemaResolver as S}from"../../../utils/openapi-schema-resolver.js";import{extractPartsFromComponentsRef as v}from"../../../utils/extract-parts-from-components-ref.js";import{isValidTagName as O}from"../../../utils/is-valid-tag-name.js";const A=["get","post","put","delete","patch"],b=15,d=15;class _ extends N{#e;constructor(e){super("openapi",e),this.#e=e.context.logger}async loadApiDescriptions(){return await this.actions.loadOpenApiDefinitions(this.context)}mapApiDescriptionToEntity(e,o){const s=x(e.realRelativePath),n=e.definition.info.title,t=s.replace(/\.[^.]+$/,""),a=p(t.replace(/[\\/]/g,"-")),r=e.definition["x-redocly-catalog-key"],i=typeof r=="string"&&r.trim()?p(r.trim()):a;return{type:this.type,key:i,title:n,summary:w(e.definition.info.description),tags:e.definition.tags?.filter(c=>c.name&&O(c.name)).map(c=>c.name),metadata:{specType:this.specType,descriptionFile:s},version:o}}async processApiDescription(e,o,s,n){if(S.clearSchemaCache(),!e?.definition?.paths)return;const t=this.getRbacTeamsForDefinition(e.relativePath),a=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:a,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,revision:o,rbacTeams:t}),n.delete(`${a.key}:${s}`),await this.#n(e,a.key,a.version,s,o,n,t);const r=this.#s(e.definition.paths);if(r.length!==0){const c=(await T(r,b,async({operation:h,path:m,method:l})=>{if(!h.operationId)return;const f=await this.#r(h,m,l,e,a.key,a.version,o,t);f&&n.delete(`${f}:${s}`)},this.#e)).count.failed;c>0&&this.#e.warn(`Extraction completed with ${c} failures out of ${r.length} operations for ${a.key}`)}}#s(e){return Object.entries(e).flatMap(([o,s])=>A.filter(n=>s[n]).map(n=>{const t=s[n];if(!t)throw new Error(`Operation not found for method ${n} on path ${o}`);return{operation:t,path:o,method:n.toUpperCase()}}))}async#n(e,o,s,n,t,a,r){const i=e.definition.components?.schemas;if(!i)return;const c=Object.entries(i);c.length!==0&&await E(c,d,async([h,m])=>{const l=await this.#o({schemaName:h,schema:m,description:e,parentKey:o,parentVersion:s,parentRevision:t,rbacTeams:r});a.delete(`${l.entityKey}:${n}`),l.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:o,sourceVersion:s,sourceRevision:t,type:"uses",targetKey:l.entityKey,targetVersion:s,targetRevision:t,fileHash:e.hash})})}async#o({schemaName:e,schema:o,description:s,parentKey:n,parentVersion:t,parentRevision:a,rbacTeams:r}){const i=S.resolveSchemaRefs(o,s),c=JSON.stringify(i),h=i[$]?R(i[$]):r,m=R(i["x-rbac"]),l={type:"data-schema",key:`${n}-${p(e)}`,title:e,summary:i.description??i.title??null,tags:[],metadata:{specType:this.specType,schema:c},version:t};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:l,sourceFile:s.realRelativePath,fileHash:s.hash,revision:a,rbacTeams:m.length?m:h})}async#r(e,o,s,n,t,a,r,i){const c=await Promise.all([this.#m(e.requestBody??null,n),this.#h(e.responses??{},n)]),h=c[0].schemaNames,m=c[1].schemaNames;c[0].errors.length>0&&this.#e.warn(`Schema extraction errors for operation ${e.operationId}: ${c[0].errors.join(", ")}`),c[1].errors.length>0&&this.#e.warn(`Response schema extraction errors for operation ${e.operationId}: ${c[1].errors.join(", ")}`);const l=h.map(g=>`${t}-${p(g)}`),f=m.map(g=>`${t}-${p(g)}`),y=await this.#p({path:o,method:s,operation:e,requestBodySchemasKeys:l,responseSchemasKeys:f,description:n,parentKey:t,parentVersion:a,parentRevision:r,rbacTeams:i});return y.result==="created"&&await Promise.all([this.#i(h,e.operationId??"",n.hash,t,a,r),this.#c(m,e.operationId??"",n.hash,t,a,r),this.#f({apiOperationKey:y.entityKey,operationRelations:e["x-catalog-relations"],descriptionUniqueKey:t,description:n,parentVersion:a,parentRevision:r})]),y.entityKey??null}async#i(e,o,s,n,t,a){return e.length===0||!o?[]:await this.#a(e,o,s,n,t,a)}async#c(e,o,s,n,t,a){return e.length===0||!o?[]:await this.#a(e,o,s,n,t,a)}#m(e,o){const s=[],n=[];try{if(e&&"content"in e&&e.content)for(const t of Object.values(e.content)){if(!t.schema?.$ref)continue;const a=this.#t(t.schema.$ref);a?.componentType==="schemas"&&a.componentName&&s.push(a.componentName)}if(e&&e.$ref){const t=this.#t(e.$ref);if(t?.componentType==="requestBodies"&&t.componentName){const a=o.definition.components?.requestBodies?.[t.componentName];if(a&&"content"in a)for(const r of Object.values(a.content??{})){if(!r.schema?.$ref)continue;const i=this.#t(r.schema.$ref);i?.componentType==="schemas"&&i.componentName&&s.push(i.componentName)}}}}catch(t){n.push(`Failed to extract request body schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:n}}#h(e,o){const s=[],n=[];try{for(const t of Object.values(e)){if(t&&"content"in t&&t.content)for(const a of Object.values(t.content)){if(!a.schema?.$ref)continue;const r=this.#t(a.schema.$ref);r?.componentType==="schemas"&&r.componentName&&s.push(r.componentName)}if(t&&t.$ref){const a=this.#t(t.$ref);if(a?.componentType==="responses"&&a.componentName){const r=o.definition.components?.responses?.[a.componentName];if(r&&"content"in r)for(const i of Object.values(r.content??{})){if(!i.schema?.$ref)continue;const c=this.#t(i.schema.$ref);c?.componentType==="schemas"&&c.componentName&&s.push(c.componentName)}}}}}catch(t){n.push(`Failed to extract response schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:n}}#t(e){try{return v(e)}catch{return{componentType:"",componentName:null}}}async#a(e,o,s,n,t,a){return e.length===0?[]:await E(e,d,async r=>await this.#l({operationId:o,schemaName:r,descriptionHash:s,parentKey:n,parentVersion:t,parentRevision:a}))}async#l({operationId:e,schemaName:o,descriptionHash:s,parentKey:n,parentVersion:t,parentRevision:a}){const r=`${n}-${p(o)}`;try{return await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:`${n}-${p(e)}`,type:"uses",targetKey:r,fileHash:s,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),r}catch(i){throw this.#e.error(`Failed to create relation between operation ${e} and schema ${o}: ${i instanceof Error?i.message:"Unknown error"}`),i}}async#p({path:e,method:o,operation:s,requestBodySchemasKeys:n,responseSchemasKeys:t,description:a,parentKey:r,parentVersion:i,parentRevision:c,rbacTeams:h}){const m=`${s.operationId}`,l=`${r}-${p(m)}`,f=s[$]?R(s[$]):h,y=R(s["x-rbac"]),g={type:"api-operation",key:l,title:m,summary:w(s.summary),tags:s.tags?.filter(u=>O(u)),metadata:{path:e,method:o,payload:n,responses:t},version:i};try{return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:g,sourceFile:a.realRelativePath,fileHash:a.hash,revision:c,rbacTeams:y.length>0?y:f})}catch(u){throw this.#e.error(`Failed to create API operation entity for ${m}: ${u instanceof Error?u.message:"Unknown error"}`),u}}async#f({apiOperationKey:e,operationRelations:o,descriptionUniqueKey:s,description:n,parentVersion:t,parentRevision:a}){try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"partOf",targetKey:s,fileHash:n.hash,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),await this.#y(e,o,t,a)}catch(r){this.#e.error(`Failed to create API operation relations for ${e}: ${r instanceof Error?r.message:"Unknown error"}`)}}async#y(e,o,s,n){o?.length&&await E(o,b,async t=>{try{this.validateEntityRelationFileSchema(t),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:t.type,targetKey:t.key,sourceVersion:s,targetVersion:"",sourceRevision:n,targetRevision:""})}catch(a){this.context.logger.warn(`Error creating entity relation for operation ${e} based on custom property: ${a instanceof Error?a.message:"Unknown error"}`)}})}}export{_ as OpenApiEntitiesExtractor};
1
+ import{REDOCLY_TEAMS_RBAC as $}from"@redocly/config";import{removeLeadingSlash as d}from"@redocly/theme/core/utils";import{toKebabCase as u}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as v}from"../../../../../utils/async/promise-map-limit-with-status.js";import{extractTeamsFromScopeItems as R}from"../../../../../utils/rbac.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as x}from"./base.js";import{OpenapiSchemaResolver as S}from"../../../utils/openapi-schema-resolver.js";import{extractPartsFromComponentsRef as N}from"../../../utils/extract-parts-from-components-ref.js";import{isValidTagName as O}from"../../../utils/is-valid-tag-name.js";const A=["get","post","put","delete","patch"],b=15,T=15;class _ extends x{#e;constructor(e){super("openapi",e),this.#e=e.context.logger}async loadApiDescriptions(){return await this.actions.loadOpenApiDefinitions(this.context)}mapApiDescriptionToEntity(e,r){const s=d(e.realRelativePath),n=e.definition.info.title,t=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.definition["x-redocly-catalog-key"]});return{type:this.type,key:t,title:n,summary:w(e.definition.info.description),tags:e.definition.tags?.filter(a=>a.name&&O(a.name)).map(a=>a.name),metadata:{specType:this.specType,descriptionFile:s},version:r}}async processApiDescription(e,r,s,n){if(S.clearSchemaCache(),!e?.definition?.paths)return;const t=this.getRbacTeamsForDefinition(e.relativePath),a=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntityInLocalDatabase({entity:a,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,revision:r,rbacTeams:t}),n.delete(`${a.key}:${s}`),await this.#n(e,a.key,a.version,s,r,n,t);const o=this.#s(e.definition.paths);if(o.length!==0){const c=(await v(o,b,async({operation:h,path:m,method:l})=>{if(!h.operationId)return;const p=await this.#o(h,m,l,e,a.key,a.version,r,t);p&&n.delete(`${p}:${s}`)},this.#e)).count.failed;c>0&&this.#e.warn(`Extraction completed with ${c} failures out of ${o.length} operations for ${a.key}`)}}#s(e){return Object.entries(e).flatMap(([r,s])=>A.filter(n=>s[n]).map(n=>{const t=s[n];if(!t)throw new Error(`Operation not found for method ${n} on path ${r}`);return{operation:t,path:r,method:n.toUpperCase()}}))}async#n(e,r,s,n,t,a,o){const i=e.definition.components?.schemas;if(!i)return;const c=Object.entries(i);c.length!==0&&await E(c,T,async([h,m])=>{const l=await this.#r({schemaName:h,schema:m,description:e,parentKey:r,parentVersion:s,parentRevision:t,rbacTeams:o});a.delete(`${l.entityKey}:${n}`),l.result==="created"&&await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:r,sourceVersion:s,sourceRevision:t,type:"uses",targetKey:l.entityKey,targetVersion:s,targetRevision:t,fileHash:e.hash})})}async#r({schemaName:e,schema:r,description:s,parentKey:n,parentVersion:t,parentRevision:a,rbacTeams:o}){const i=S.resolveSchemaRefs(r,s),c=JSON.stringify(i),h=i[$]?R(i[$]):o,m=R(i["x-rbac"]),l={type:"data-schema",key:`${n}-${u(e)}`,title:e,summary:i.description??i.title??null,tags:[],metadata:{specType:this.specType,schema:c},version:t};return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:l,sourceFile:s.realRelativePath,fileHash:s.hash,revision:a,rbacTeams:m.length?m:h})}async#o(e,r,s,n,t,a,o,i){const c=await Promise.all([this.#m(e.requestBody??null,n),this.#h(e.responses??{},n)]),h=c[0].schemaNames,m=c[1].schemaNames;c[0].errors.length>0&&this.#e.warn(`Schema extraction errors for operation ${e.operationId}: ${c[0].errors.join(", ")}`),c[1].errors.length>0&&this.#e.warn(`Response schema extraction errors for operation ${e.operationId}: ${c[1].errors.join(", ")}`);const l=h.map(g=>`${t}-${u(g)}`),p=m.map(g=>`${t}-${u(g)}`),f=await this.#p({path:r,method:s,operation:e,requestBodySchemasKeys:l,responseSchemasKeys:p,description:n,parentKey:t,parentVersion:a,parentRevision:o,rbacTeams:i});return f.result==="created"&&await Promise.all([this.#i(h,e.operationId??"",n.hash,t,a,o),this.#c(m,e.operationId??"",n.hash,t,a,o),this.#f({apiOperationKey:f.entityKey,operationRelations:e["x-catalog-relations"],descriptionUniqueKey:t,description:n,parentVersion:a,parentRevision:o})]),f.entityKey??null}async#i(e,r,s,n,t,a){return e.length===0||!r?[]:await this.#a(e,r,s,n,t,a)}async#c(e,r,s,n,t,a){return e.length===0||!r?[]:await this.#a(e,r,s,n,t,a)}#m(e,r){const s=[],n=[];try{if(e&&"content"in e&&e.content)for(const t of Object.values(e.content)){if(!t.schema?.$ref)continue;const a=this.#t(t.schema.$ref);a?.componentType==="schemas"&&a.componentName&&s.push(a.componentName)}if(e&&e.$ref){const t=this.#t(e.$ref);if(t?.componentType==="requestBodies"&&t.componentName){const a=r.definition.components?.requestBodies?.[t.componentName];if(a&&"content"in a)for(const o of Object.values(a.content??{})){if(!o.schema?.$ref)continue;const i=this.#t(o.schema.$ref);i?.componentType==="schemas"&&i.componentName&&s.push(i.componentName)}}}}catch(t){n.push(`Failed to extract request body schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:n}}#h(e,r){const s=[],n=[];try{for(const t of Object.values(e)){if(t&&"content"in t&&t.content)for(const a of Object.values(t.content)){if(!a.schema?.$ref)continue;const o=this.#t(a.schema.$ref);o?.componentType==="schemas"&&o.componentName&&s.push(o.componentName)}if(t&&t.$ref){const a=this.#t(t.$ref);if(a?.componentType==="responses"&&a.componentName){const o=r.definition.components?.responses?.[a.componentName];if(o&&"content"in o)for(const i of Object.values(o.content??{})){if(!i.schema?.$ref)continue;const c=this.#t(i.schema.$ref);c?.componentType==="schemas"&&c.componentName&&s.push(c.componentName)}}}}}catch(t){n.push(`Failed to extract response schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:n}}#t(e){try{return N(e)}catch{return{componentType:"",componentName:null}}}async#a(e,r,s,n,t,a){return e.length===0?[]:await E(e,T,async o=>await this.#l({operationId:r,schemaName:o,descriptionHash:s,parentKey:n,parentVersion:t,parentRevision:a}))}async#l({operationId:e,schemaName:r,descriptionHash:s,parentKey:n,parentVersion:t,parentRevision:a}){const o=`${n}-${u(r)}`;try{return await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:`${n}-${u(e)}`,type:"uses",targetKey:o,fileHash:s,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),o}catch(i){throw this.#e.error(`Failed to create relation between operation ${e} and schema ${r}: ${i instanceof Error?i.message:"Unknown error"}`),i}}async#p({path:e,method:r,operation:s,requestBodySchemasKeys:n,responseSchemasKeys:t,description:a,parentKey:o,parentVersion:i,parentRevision:c,rbacTeams:h}){const m=`${s.operationId}`,l=`${o}-${u(m)}`,p=s[$]?R(s[$]):h,f=R(s["x-rbac"]),g={type:"api-operation",key:l,title:m,summary:w(s.summary),tags:s.tags?.filter(y=>O(y)),metadata:{path:e,method:r,payload:n,responses:t},version:i};try{return await this.catalogEntitiesService.createEntityInLocalDatabase({entity:g,sourceFile:a.realRelativePath,fileHash:a.hash,revision:c,rbacTeams:f.length>0?f:p})}catch(y){throw this.#e.error(`Failed to create API operation entity for ${m}: ${y instanceof Error?y.message:"Unknown error"}`),y}}async#f({apiOperationKey:e,operationRelations:r,descriptionUniqueKey:s,description:n,parentVersion:t,parentRevision:a}){try{await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:"partOf",targetKey:s,fileHash:n.hash,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),await this.#y(e,r,t,a)}catch(o){this.#e.error(`Failed to create API operation relations for ${e}: ${o instanceof Error?o.message:"Unknown error"}`)}}async#y(e,r,s,n){r?.length&&await E(r,b,async t=>{try{this.validateEntityRelationFileSchema(t),await this.catalogEntitiesService.createEntityRelationInLocalDatabase({sourceKey:e,type:t.type,targetKey:t.key,sourceVersion:s,targetVersion:"",sourceRevision:n,targetRevision:""})}catch(a){this.context.logger.warn(`Error creating entity relation for operation ${e} based on custom property: ${a instanceof Error?a.message:"Unknown error"}`)}})}}export{_ as OpenApiEntitiesExtractor};
@@ -1 +1 @@
1
- import{sha1 as I}from"../../utils/crypto/sha1.js";import{isValidSanitizedString as D}from"../../utils/validate-and-sanitize-string";import{CatalogEntitiesService as F}from"./database/catalog-entities-service.js";import{createPaginationParamsValidator as E}from"../../providers/database/pagination/schemas";import{parseSearch as R}from"../../providers/database/pagination/search";import{OPERATORS as w}from"../../providers/database/pagination/constants.js";import{CacheService as P}from"../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as A,CATALOG_FILTERS_CACHE_TTL_IN_SECONDS as N}from"../../constants/plugins/catalog-entities.js";import{isValidIsoDate as V}from"../../utils/is-valid-iso-date.js";import{expandTeamsForRead as _}from"../../utils";import{getNotAccessibleCatalogResources as L}from"./utils/get-not-accessible-catalog-resources.js";const st={all:"all",domains:"domain",services:"service",teams:"team",users:"user","api-descriptions":"api-description","data-schemas":"data-schema"},O={team:{field:"type",operator:"equal",value:"user"},"api-description":{field:"type",operator:"equal",value:"api-operation"}},M=async({entitiesTypes:e,serverOutDir:i,catalogConfig:s,queries:t={},rbacTeams:o,excludedTypes:p,excludedEntities:c})=>{const u=await F.getInstance({baseDbDir:i}),f=T.concat("domains","owners"),l=E(f).parse(t),n=s.excludes?.map(a=>a.key)??[],g=e.filter(a=>a!=="all"),m=j(g,n);return l.filter?l.filter={op:w.AND,conditions:[l.filter,m]}:l.filter=m,await u.getEntitiesWithRelations({paginationParams:{sort:[{field:"type",order:"ASC"},{field:"title",order:"ASC"}],limit:10,...l},rbacTeams:o,excludedTypes:p,excludedEntities:c})},k=async({entityKey:e,serverOutDir:i,queries:s,rbacTeams:t,excludedTypes:o,excludedEntities:p})=>{const c=await F.getInstance({baseDbDir:i});let u=null;const f=s?.revision;f&&V(f)&&(u=f);const l=s?.version;if(!D(l,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return null;const n=await c.getEntityWithRelationsByKey({entityKey:e,filter:{revision:u,version:l},rbacTeams:t,excludedTypes:o,excludedEntities:p});if(!n)return null;const g=n.type==="data-schema"?await c.getRelatedEntities({entityKey:e,paginationParams:{limit:1,filter:{field:"type",operator:"equal",value:"api-description"}}}).then(b=>b.items?.[0]??null):null,m=O[n.type]??void 0,d=B(m,l,u),y=E(T).parse(s),h=await c.getRelatedEntities({entityKey:e,paginationParams:{limit:10,sort:y.sort?.length?y.sort:[{field:"title",order:"ASC"}],filter:d,search:s?.search?R(s?.search,["key","type","title","summary"]):void 0},rbacTeams:t,excludedTypes:o,excludedEntities:p});return{status:"success",entity:n,relatedEntity:g,relations:h}},q=e=>{const i=JSON.stringify({entitiesTypes:e.entitiesTypes.sort(),filtersConfig:e.filtersConfig,rbacTeams:e.rbacTeams,excludedTypes:e.excludedTypes,excludedEntities:e.excludedEntities});return I(i)},x=async({serverOutDir:e,entitiesTypes:i,filtersConfig:s,rbacTeams:t,excludedTypes:o,excludedEntities:p})=>{if(!s||s.length===0)return{};const c=q({entitiesTypes:i,filtersConfig:s,rbacTeams:t,excludedTypes:o,excludedEntities:p}),u=await P.getInstance({baseDbDir:e}),f=await u.get({key:c,namespace:A});if(f)return f;const l=await F.getInstance({baseDbDir:e}),n=[],g=new Map;for(const a of s)!a.options||a.options.length===0?n.push(a.property):g.set(a.property,a.options);const m=await l.getCatalogFilters({entitiesTypes:i,emptyFilters:n,rbacTeams:t,excludedTypes:o,excludedEntities:p}),d={};for(const a of s){const y=g.get(a.property);if(!y){const r=m[a.property];d[a.property]=r&&r.length>0?r:[];continue}const b=(await l.getCatalogFilters({entitiesTypes:i,emptyFilters:[a.property],rbacTeams:t,excludedTypes:o,excludedEntities:p}))[a.property];if(!b){d[a.property]=[];continue}const S=new Map;for(const r of b){const C=r.value.toLowerCase().trim();S.set(C,{originalValue:r.value,count:r.count})}d[a.property]=y.map(r=>{const C=r.toLowerCase().trim(),v=S.get(C);return{value:v?.originalValue??r,count:v?.count??0}}).filter(r=>r.count>0).sort((r,C)=>r.value.localeCompare(C.value))}return await u.set({key:c,value:d,namespace:A,ttlInSeconds:N}),d},K=async(e,{props:i},{variables:s},{serverOutDir:t,getRouteSharedDataByFsPath:o,getConfig:p})=>{const c=i?.catalogConfig||{};if(!e.params||!i?.catalogConfig)return{status:"notFound"};const[u,f,l]=e.params;if(!u)return{status:"notFound"};const n=z(c,u),g=n?.includes?.map(C=>C.type)??[];if(!n||n.hide)return{status:"notFound"};const m=_(p().rbac||{},s?.rbac.teams||[]),{catalogs:d,types:a,entities:y}=L({rbacConfig:p().rbac||{},currentRbacTeams:s?.rbac.teams||[]});if(d.includes(u))return{status:"notFound"};if(!l&&f!=="entities"){const C=await x({entitiesTypes:g,serverOutDir:t,filtersConfig:n.filters,rbacTeams:m,excludedTypes:a,excludedEntities:y}),v=e.queries?.viewMode??"table";return{status:"success",catalogSwitcherItems:W(c,n,d),entitiesTypes:g,entities:await M({entitiesTypes:g,serverOutDir:t,catalogConfig:n,queries:e.queries,rbacTeams:m,excludedTypes:a,excludedEntities:y}),catalogConfig:n,filters:C,initialViewMode:v}}const h=await k({entityKey:l,serverOutDir:t,queries:e.queries,rbacTeams:m,excludedTypes:a,excludedEntities:y});if(!h)return{status:"notFound"};const b=h?.entity.sourceFile,S=h?.entity.type==="api-description",r=b&&S&&o(b)||{};return{status:"success",entity:h.entity,relatedEntity:h.relatedEntity,relations:h.relations,entitiesCatalogConfig:c,catalogConfig:n,sharedDataIds:r}},z=(e,i)=>Object.values(e.catalogs??{}).find(s=>s&&typeof s=="object"&&"slug"in s&&s.slug===i),W=(e,i,s)=>Object.values(e.catalogs??{}).filter(t=>!t?.hide&&!s.includes(t?.slug??"")).map(t=>({labelTranslationKey:t?.catalogSwitcherLabelTranslationKey??t?.slug??"",slug:t?.slug??"",selected:t?.slug===i.slug})).sort((t,o)=>t.slug.localeCompare(o.slug)),j=(e,i)=>({op:"AND",conditions:[...e.length?[{field:"type",operator:"in",value:e}]:[],...i.length?[{field:"key",operator:"in",value:i,modifier:"not"}]:[]]}),B=(e,i,s)=>{let t=e;if(i!==void 0){const o={field:"version",operator:"equal",value:i};t=t?{op:w.AND,conditions:[t,o]}:o}if(s){const o={field:"revision",operator:"equal",value:s};t=t?{op:w.AND,conditions:[t,o]}:o}return t},T=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"];var it=K;export{it as default};
1
+ import{sha1 as D}from"../../utils/crypto/sha1.js";import{isValidSanitizedString as R}from"../../utils/validate-and-sanitize-string";import{CatalogEntitiesService as w}from"./database/catalog-entities-service.js";import{createPaginationParamsValidator as E}from"../../providers/database/pagination/schemas";import{parseSearch as _}from"../../providers/database/pagination/search";import{OPERATORS as A}from"../../providers/database/pagination/constants.js";import{CacheService as P}from"../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as T,CATALOG_FILTERS_CACHE_TTL_IN_SECONDS as N}from"../../constants/plugins/catalog-entities.js";import{isValidIsoDate as V}from"../../utils/is-valid-iso-date.js";import{expandTeamsForRead as L}from"../../utils";import{getNotAccessibleCatalogResources as O}from"./utils/get-not-accessible-catalog-resources.js";const at={all:"all",domains:"domain",services:"service",teams:"team",users:"user","api-descriptions":"api-description","data-schemas":"data-schema"},M={team:{field:"type",operator:"equal",value:"user"},"api-description":{field:"type",operator:"equal",value:"api-operation"}},k=async({entitiesTypes:e,serverOutDir:a,catalogConfig:i,queries:t={},rbacTeams:o,excludedTypes:g,excludedEntities:u,initialViewMode:p})=>{const m=await w.getInstance({baseDbDir:a}),d=I.concat("domains","owners"),s=E(d).parse(t),y=i.excludes?.map(c=>c.key)??[],C=e.filter(c=>c!=="all"),l=B(C,y);return s.filter?s.filter={op:A.AND,conditions:[s.filter,l]}:s.filter=l,await m.getEntitiesWithRelations({paginationParams:{sort:p==="table"?[{field:"updated_at",order:"ASC"},{field:"id",order:"ASC"}]:[{field:"type",order:"ASC"},{field:"title",order:"ASC"},{field:"id",order:"ASC"}],limit:10,...s},rbacTeams:o,excludedTypes:g,excludedEntities:u})},q=async({entityKey:e,serverOutDir:a,queries:i,rbacTeams:t,excludedTypes:o,excludedEntities:g})=>{const u=await w.getInstance({baseDbDir:a});let p=null;const m=i?.revision;m&&V(m)&&(p=m);const d=i?.version;if(!R(d,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return null;const s=await u.getEntityWithRelationsByKey({entityKey:e,filter:{revision:p,version:d},rbacTeams:t,excludedTypes:o,excludedEntities:g});if(!s)return null;const y=s.type==="data-schema"?await u.getRelatedEntities({entityKey:e,paginationParams:{limit:1,filter:{field:"type",operator:"equal",value:"api-description"}}}).then(f=>f.items?.[0]??null):null,C=M[s.type]??void 0,l=H(C,d,p),c=E(I).parse(i),b=await u.getRelatedEntities({entityKey:e,paginationParams:{limit:10,sort:c.sort?.length?c.sort:[{field:"updated_at",order:"ASC"},{field:"id",order:"ASC"}],filter:l,search:i?.search?_(i?.search,["key","type","title","summary"]):void 0},rbacTeams:t,excludedTypes:o,excludedEntities:g});return{status:"success",entity:s,relatedEntity:y,relations:b}},x=e=>{const a=JSON.stringify({entitiesTypes:e.entitiesTypes.sort(),filtersConfig:e.filtersConfig,rbacTeams:e.rbacTeams,excludedTypes:e.excludedTypes,excludedEntities:e.excludedEntities});return D(a)},K=async({serverOutDir:e,entitiesTypes:a,filtersConfig:i,rbacTeams:t,excludedTypes:o,excludedEntities:g})=>{if(!i||i.length===0)return{};const u=x({entitiesTypes:a,filtersConfig:i,rbacTeams:t,excludedTypes:o,excludedEntities:g}),p=await P.getInstance({baseDbDir:e}),m=await p.get({key:u,namespace:T});if(m)return m;const d=await w.getInstance({baseDbDir:e}),s=[],y=new Map;for(const n of i)!n.options||n.options.length===0?s.push(n.property):y.set(n.property,n.options);const C=await d.getCatalogFilters({entitiesTypes:a,emptyFilters:s,rbacTeams:t,excludedTypes:o,excludedEntities:g}),l={};for(const n of i){const c=y.get(n.property);if(!c){const r=C[n.property];l[n.property]=r&&r.length>0?r:[];continue}const f=(await d.getCatalogFilters({entitiesTypes:a,emptyFilters:[n.property],rbacTeams:t,excludedTypes:o,excludedEntities:g}))[n.property];if(!f){l[n.property]=[];continue}const v=new Map;for(const r of f){const h=r.value.toLowerCase().trim();v.set(h,{originalValue:r.value,count:r.count})}l[n.property]=c.map(r=>{const h=r.toLowerCase().trim(),S=v.get(h);return{value:S?.originalValue??r,count:S?.count??0}}).filter(r=>r.count>0).sort((r,h)=>r.value.localeCompare(h.value))}return await p.set({key:u,value:l,namespace:T,ttlInSeconds:N}),l},z=async(e,{props:a},{variables:i},{serverOutDir:t,getRouteSharedDataByFsPath:o,getConfig:g})=>{const u=a?.catalogConfig||{};if(!e.params||!a?.catalogConfig)return{status:"notFound"};const[p,m,d]=e.params;if(!p)return{status:"notFound"};const s=W(u,p),y=s?.includes?.map(S=>S.type)??[];if(!s||s.hide)return{status:"notFound"};const C=g().access?.rbac||{},l=L(C,i?.rbac.teams||[]),{catalogs:n,types:c,entities:b}=O({rbacConfig:C,currentRbacTeams:i?.rbac.teams||[]});if(n.includes(p))return{status:"notFound"};if(!d&&m!=="entities"){const S=await K({entitiesTypes:y,serverOutDir:t,filtersConfig:s.filters,rbacTeams:l,excludedTypes:c,excludedEntities:b}),F=e.queries?.viewMode??"table";return{status:"success",catalogSwitcherItems:j(u,s,n),entitiesTypes:y,entities:await k({entitiesTypes:y,serverOutDir:t,catalogConfig:s,queries:e.queries,rbacTeams:l,excludedTypes:c,excludedEntities:b,initialViewMode:F}),catalogConfig:s,filters:S,initialViewMode:F}}const f=await q({entityKey:d,serverOutDir:t,queries:e.queries,rbacTeams:l,excludedTypes:c,excludedEntities:b});if(!f)return{status:"notFound"};const v=f?.entity.sourceFile,r=f?.entity.type==="api-description",h=v&&r&&o(v)||{};return{status:"success",entity:f.entity,relatedEntity:f.relatedEntity,relations:f.relations,entitiesCatalogConfig:u,catalogConfig:s,sharedDataIds:h}},W=(e,a)=>Object.values(e.catalogs??{}).find(i=>i&&typeof i=="object"&&"slug"in i&&i.slug===a),j=(e,a,i)=>Object.values(e.catalogs??{}).filter(t=>!t?.hide&&!i.includes(t?.slug??"")).map(t=>({labelTranslationKey:t?.catalogSwitcherLabelTranslationKey??t?.slug??"",slug:t?.slug??"",selected:t?.slug===a.slug})).sort((t,o)=>t.slug.localeCompare(o.slug)),B=(e,a)=>({op:"AND",conditions:[...e.length?[{field:"type",operator:"in",value:e}]:[],...a.length?[{field:"key",operator:"in",value:a,modifier:"not"}]:[]]}),H=(e,a,i)=>{let t=e;if(a!==void 0){const o={field:"version",operator:"equal",value:a};t=t?{op:A.AND,conditions:[t,o]}:o}if(i){const o={field:"revision",operator:"equal",value:i};t=t?{op:A.AND,conditions:[t,o]}:o}return t},I=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","source_file","created_at","updated_at"];var st=z;export{st as default};
@@ -1 +1 @@
1
- import{FileType as p}from"../../persistence/file-hashes/types.js";import{envConfig as P}from"../../config/env-config.js";import{deepEqual as I}from"../../../utils/object/deep-equal.js";import{CATALOG_BASE_SLUG as u}from"../../../constants/catalog-entities.js";import{telemetryTraceStep as D}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as O}from"./utils/catalog-data-collector.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as b,ENTITIES_MAP_GLOBAL_DATA_KEY as _}from"../../constants/plugins/catalog-entities.js";import{CacheService as v}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as f}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as E}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as w}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as R}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 L}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 H}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const B="catalog-entity-template",M="catalog-entity";let C=!0,d;async function Y(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const a=await e.getConfig(),r=E(a.entitiesCatalog);if(!r.show)return;const{logger:s}=e,n=t.registerServerPropsGetter(M,f("../get-server-props.js")),g=t.createTemplate(B,f("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:u,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[n],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[m]=Object.entries(r.catalogs??{}).find(([o,i])=>!i?.hide)||[];m&&t.addRedirect(u,{type:302,to:`${u}/${m}`}),s.info("Catalog Entities plugin finished")},async afterRoutesCreated(t,e){await D("build.plugin.catalog_entities",async a=>{const r=await e.getConfig(),s=E(r.entitiesCatalog);if(a?.setAttribute("config",JSON.stringify(s)),!s.show)return;const{logger:n}=e,g=C&&P.isDevelopMode,m=!I(d,r.rbac);d=r.rbac;const o=g||m,i=await L.getInstance({baseDbDir:t.serverOutDir,removeExisting:g,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),A=await N.getInstance({baseDbDir:t.serverOutDir}),l=new F(A),T=[new x({fileHashManager:l,context:e,catalogEntitiesService:i,catalogConfig:s,shouldCalculateEntities:o}),new H({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.OPENAPI_DESCRIPTION,shouldCalculateEntities:o}),new w({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:o}),new R({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.GRAPHQL_DESCRIPTION,shouldCalculateEntities:o}),new G({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.ARAZZO_DESCRIPTION,shouldCalculateEntities:o})];n.info("Starting entities extractors...");const y=n.startTiming();await i.transaction(async()=>{await Promise.all(T.map(async S=>S.extract()))});const h=i.getEntitySources();t.setGlobalData({[_]:h}),await(await v.getInstance({baseDbDir:t.serverOutDir})).deleteByNamespace(b),n.infoTime(y,"Entities extractors finished");const c=await O.getCatalogEntitiesData(i);a?.setAttribute("totalEntities",c.totalEntitiesCount),a?.setAttribute("entitiesCountByType",JSON.stringify(c.countOfEntitiesByType)),a?.setAttribute("totalFilesSkippedByHash",c.totalFilesSkippedByHash),a?.setAttribute("totalProcessedFiles",c.totalProcessedFiles),a?.setAttribute("extractors",c.extractors),C=!1})}}}var st=Y;export{Y as catalogEntitiesPlugin,st as default};
1
+ import{FileType as p}from"../../persistence/file-hashes/types.js";import{envConfig as P}from"../../config/env-config.js";import{deepEqual as I}from"../../../utils/object/deep-equal.js";import{CATALOG_BASE_SLUG as u}from"../../../constants/catalog-entities.js";import{telemetryTraceStep as D}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as O}from"./utils/catalog-data-collector.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as b,ENTITIES_MAP_GLOBAL_DATA_KEY as _}from"../../constants/plugins/catalog-entities.js";import{CacheService as v}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as f}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as E}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as w}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as R}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 L}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 H}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const B="catalog-entity-template",M="catalog-entity";let C=!0,d;async function Y(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const a=await e.getConfig(),r=E(a.entitiesCatalog);if(!r.show)return;const{logger:o}=e,n=t.registerServerPropsGetter(M,f("../get-server-props.js")),g=t.createTemplate(B,f("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:u,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[n],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[m]=Object.entries(r.catalogs??{}).find(([s,i])=>!i?.hide)||[];m&&t.addRedirect(u,{type:302,to:`${u}/${m}`}),o.info("Catalog Entities plugin finished")},async afterRoutesCreated(t,e){await D("build.plugin.catalog_entities",async a=>{const r=await e.getConfig(),o=E(r.entitiesCatalog);if(a?.setAttribute("config",JSON.stringify(o)),!o.show)return;const{logger:n}=e,g=C&&P.isDevelopMode,m=!I(d,r.access?.rbac);d=r.access?.rbac;const s=g||m,i=await L.getInstance({baseDbDir:t.serverOutDir,removeExisting:g,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),A=await N.getInstance({baseDbDir:t.serverOutDir}),l=new F(A),T=[new x({fileHashManager:l,context:e,catalogEntitiesService:i,catalogConfig:o,shouldCalculateEntities:s}),new H({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.OPENAPI_DESCRIPTION,shouldCalculateEntities:s}),new w({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:s}),new R({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.GRAPHQL_DESCRIPTION,shouldCalculateEntities:s}),new G({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:p.ARAZZO_DESCRIPTION,shouldCalculateEntities:s})];n.info("Starting entities extractors...");const y=n.startTiming();await i.transaction(async()=>{await Promise.all(T.map(async S=>S.extract()))});const h=i.getEntitySources();t.setGlobalData({[_]:h}),await(await v.getInstance({baseDbDir:t.serverOutDir})).deleteByNamespace(b),n.infoTime(y,"Entities extractors finished");const c=await O.getCatalogEntitiesData(i);a?.setAttribute("totalEntities",c.totalEntitiesCount),a?.setAttribute("entitiesCountByType",JSON.stringify(c.countOfEntitiesByType)),a?.setAttribute("totalFilesSkippedByHash",c.totalFilesSkippedByHash),a?.setAttribute("totalProcessedFiles",c.totalProcessedFiles),a?.setAttribute("extractors",c.extractors),C=!1})}}}var ot=Y;export{Y as catalogEntitiesPlugin,ot as default};
@@ -168,10 +168,10 @@ export declare const relatedEntityDatabaseSchema: {
168
168
  readonly type: readonly ["string", "null"];
169
169
  };
170
170
  readonly created_at: {
171
- readonly type: readonly ["string", "null"];
171
+ readonly type: readonly ["string"];
172
172
  };
173
173
  readonly updated_at: {
174
- readonly type: readonly ["string", "null"];
174
+ readonly type: readonly ["string"];
175
175
  };
176
176
  readonly metadata: {
177
177
  readonly type: readonly ["string", "null"];
@@ -180,7 +180,7 @@ export declare const relatedEntityDatabaseSchema: {
180
180
  readonly type: readonly ["string", "null"];
181
181
  };
182
182
  };
183
- readonly required: readonly ["id", "key", "title", "type", "source"];
183
+ readonly required: readonly ["id", "key", "title", "type", "source", "created_at", "updated_at"];
184
184
  readonly additionalProperties: false;
185
185
  };
186
186
  /**
@@ -217,10 +217,10 @@ export declare const relatedEntityQueryRowDatabaseSchema: {
217
217
  readonly type: readonly ["string", "null"];
218
218
  };
219
219
  readonly created_at: {
220
- readonly type: readonly ["string", "null"];
220
+ readonly type: readonly ["string"];
221
221
  };
222
222
  readonly updated_at: {
223
- readonly type: readonly ["string", "null"];
223
+ readonly type: readonly ["string"];
224
224
  };
225
225
  readonly metadata: {
226
226
  readonly type: readonly ["string", "object", "null"];
@@ -240,7 +240,7 @@ export declare const relatedEntityQueryRowDatabaseSchema: {
240
240
  readonly minLength: 1;
241
241
  };
242
242
  };
243
- readonly required: readonly ["id", "key", "title", "type", "source", "direction", "relation_field"];
243
+ readonly required: readonly ["id", "key", "title", "type", "source", "direction", "relation_field", "created_at", "updated_at"];
244
244
  readonly additionalProperties: false;
245
245
  };
246
246
  export type EntityRelationDto = FromSchema<typeof entityRelationDatabaseSchema>;
@@ -1 +1 @@
1
- import{ENTITY_RELATION_TYPES as t}from"@redocly/config";const i={type:"object",properties:{id:{type:"string"},organization_id:{type:"string"},project_id:{type:"string"},source_key:{type:"string"},source_id:{type:["string","null"]},source_version:{type:["string","null"]},source_revision:{type:["string","null"]},source_to_target_relation:{type:"string"},target_key:{type:"string"},target_id:{type:["string","null"]},target_version:{type:["string","null"]},target_revision:{type:["string","null"]},target_to_source_relation:{type:"string"},source_file:{type:["string","null"]},file_hash:{type:["string","null"]},created_at:{type:"string"},updated_at:{type:"string"}},required:["id","organization_id","project_id","source_key","source_to_target_relation","target_key","target_to_source_relation","created_at","updated_at"],additionalProperties:!1},n={type:"object",properties:{id:{type:"string"},organization_id:{type:"string"},project_id:{type:"string"},key:{type:"string"},type:{type:"string"},title:{type:"string"},summary:{type:["string","null"]},tags:{type:["string","null"]},metadata:{type:["string","null"]},git:{type:["string","null"]},contact:{type:["string","null"]},links:{type:["string","null"]},created_at:{type:"string"},updated_at:{type:"string"},source:{type:"string"},source_file:{type:["string","null"]},file_hash:{type:["string","null"]},version:{type:["string","null"]},revision:{type:["string","null"]},hash:{type:["string","null"]},is_current:{type:["boolean","null"]},is_default_version:{type:["boolean","null"]},is_deleted:{type:["boolean","null"]},rbac_teams:{type:["string","null"]}},required:["id","organization_id","project_id","key","type","title","created_at","updated_at","source"],additionalProperties:!1},r={type:"object",properties:{id:{type:"string"},key:{type:"string"},title:{type:"string"},type:{type:"string"},summary:{type:["string","null"]},source:{type:"string"},relation_role:{type:["string","null"]},relation_type:{type:["string","null"],enum:t},source_file:{type:["string","null"]},created_at:{type:["string","null"]},updated_at:{type:["string","null"]},metadata:{type:["string","null"]},version:{type:["string","null"]}},required:["id","key","title","type","source"],additionalProperties:!1},s={type:"object",properties:{id:{type:"string",minLength:1},key:{type:"string",minLength:1},title:{type:"string",minLength:1},type:{type:"string",minLength:1},summary:{type:["string","null"]},source:{type:"string",minLength:1},source_file:{type:["string","null"]},created_at:{type:["string","null"]},updated_at:{type:["string","null"]},metadata:{type:["string","object","null"]},version:{type:["string","null"]},revision:{type:["string","null"]},direction:{type:"string",enum:["outgoing","incoming"]},relation_field:{type:"string",minLength:1}},required:["id","key","title","type","source","direction","relation_field"],additionalProperties:!1};export{n as entityDatabaseSchema,i as entityRelationDatabaseSchema,r as relatedEntityDatabaseSchema,s as relatedEntityQueryRowDatabaseSchema};
1
+ import{ENTITY_RELATION_TYPES as t}from"@redocly/config";const i={type:"object",properties:{id:{type:"string"},organization_id:{type:"string"},project_id:{type:"string"},source_key:{type:"string"},source_id:{type:["string","null"]},source_version:{type:["string","null"]},source_revision:{type:["string","null"]},source_to_target_relation:{type:"string"},target_key:{type:"string"},target_id:{type:["string","null"]},target_version:{type:["string","null"]},target_revision:{type:["string","null"]},target_to_source_relation:{type:"string"},source_file:{type:["string","null"]},file_hash:{type:["string","null"]},created_at:{type:"string"},updated_at:{type:"string"}},required:["id","organization_id","project_id","source_key","source_to_target_relation","target_key","target_to_source_relation","created_at","updated_at"],additionalProperties:!1},r={type:"object",properties:{id:{type:"string"},organization_id:{type:"string"},project_id:{type:"string"},key:{type:"string"},type:{type:"string"},title:{type:"string"},summary:{type:["string","null"]},tags:{type:["string","null"]},metadata:{type:["string","null"]},git:{type:["string","null"]},contact:{type:["string","null"]},links:{type:["string","null"]},created_at:{type:"string"},updated_at:{type:"string"},source:{type:"string"},source_file:{type:["string","null"]},file_hash:{type:["string","null"]},version:{type:["string","null"]},revision:{type:["string","null"]},hash:{type:["string","null"]},is_current:{type:["boolean","null"]},is_default_version:{type:["boolean","null"]},is_deleted:{type:["boolean","null"]},rbac_teams:{type:["string","null"]}},required:["id","organization_id","project_id","key","type","title","created_at","updated_at","source"],additionalProperties:!1},n={type:"object",properties:{id:{type:"string"},key:{type:"string"},title:{type:"string"},type:{type:"string"},summary:{type:["string","null"]},source:{type:"string"},relation_role:{type:["string","null"]},relation_type:{type:["string","null"],enum:t},source_file:{type:["string","null"]},created_at:{type:["string"]},updated_at:{type:["string"]},metadata:{type:["string","null"]},version:{type:["string","null"]}},required:["id","key","title","type","source","created_at","updated_at"],additionalProperties:!1},s={type:"object",properties:{id:{type:"string",minLength:1},key:{type:"string",minLength:1},title:{type:"string",minLength:1},type:{type:"string",minLength:1},summary:{type:["string","null"]},source:{type:"string",minLength:1},source_file:{type:["string","null"]},created_at:{type:["string"]},updated_at:{type:["string"]},metadata:{type:["string","object","null"]},version:{type:["string","null"]},revision:{type:["string","null"]},direction:{type:"string",enum:["outgoing","incoming"]},relation_field:{type:"string",minLength:1}},required:["id","key","title","type","source","direction","relation_field","created_at","updated_at"],additionalProperties:!1};export{r as entityDatabaseSchema,i as entityRelationDatabaseSchema,n as relatedEntityDatabaseSchema,s as relatedEntityQueryRowDatabaseSchema};
@@ -1 +1 @@
1
- import R from"path";import{REDOCLY_ROUTE_RBAC as l,REDOCLY_TEAMS_RBAC as m}from"@redocly/config";import{deepMerge as C}from"../../../utils/object/deep-merge.js";import{buildWildcardRedirectsTree as S}from"../../utils/redirects/build-wildcard-redirects-tree.js";import{formatCustomScripts as g,formatCustomLinks as D}from"./format-custom-tags.js";import{applyL10nToRbacConfig as P,resolveDirectoryHashes as T}from"../../utils/rbac.js";import{copySeoAssets as v}from"./copy-seo-assets.js";import{normalizeRedirectSources as A}from"./normalize-redirect-sources.js";import{applyL10nToRedirects as L}from"./apply-l10n-to-redirects.js";import{DEFAULT_LOADERS as w}from"./loaders/index.js";import{resolveSearchFacets as O}from"./resolve-search-facets.js";import{telemetryTraceStep as E}from"../../../cli/telemetry/helpers/trace-step.js";async function H(){return{id:"Config Parser",loaders:w,async processContent(t,{getConfig:n,fs:i}){await E("build.plugin.config_parser",async o=>{const{contentDir:e,setGlobalConfig:a,setGlobalData:d}=t,r=await n(),c={outdir:t.outdir,contentDir:e},u=await g(r.scripts?.head,c),b=await D(r.links,c),y=await g(r.scripts?.body,c),f=C(r,{headScriptTags:u,linkTags:b,postBodyScriptTags:y});o?.setAttribute("config",JSON.stringify(f));const p=r.redirects?A(r.redirects):{},h=f.banner?.map(s=>typeof s=="object"&&s!==null&&s.rbac?{...s,[m]:s.rbac}:s);a({...f,banner:h,requiresLogin:!!r.requiresLogin,rbac:P(i,r.rbac||{}),directoryPaths:await T(i,r.rbac),seo:r.seo&&await v(r.seo,c.contentDir,c.outdir),redirects:L(p,r.l10n),wildcardRedirectsTree:S(p)}),O(r.search?.filters?.facets||[],t.getSearchFacets,t.setSearchFacets),d({removeAttribution:!!r.removeAttribution})})},async afterRoutesCreated(t){const n=t.getGlobalConfig("rbac"),i=t.getGlobalConfig("directoryPaths");if(!(!n||Object.keys(n).length===0))for(const o of t.getAllRoutes()){if(o.versions&&i)for(const e of o.versions){const a=i[e.folderId],r=a==="."||a==="/"?"":a;e[l]={slug:e.link,fsPath:R.posix.join(r,"@"+e.version,"index.md")}}o[l]||o[m]||(o[l]={slug:o.slug,fsPath:o.fsPath})}}}}export{H as configParserPlugin};
1
+ import A from"path";import{REDOCLY_ROUTE_RBAC as m,REDOCLY_TEAMS_RBAC as b}from"@redocly/config";import{deepMerge as v}from"../../../utils/object/deep-merge.js";import{buildWildcardRedirectsTree as P}from"../../utils/redirects/build-wildcard-redirects-tree.js";import{shaHexShort as S}from"../../utils/crypto/sha-hex-short.js";import{formatCustomScripts as u,formatCustomLinks as D}from"./format-custom-tags.js";import{applyL10nToRbacConfig as T,resolveDirectoryHashes as w}from"../../utils/rbac.js";import{copySeoAssets as L}from"./copy-seo-assets.js";import{normalizeRedirectSources as O}from"./normalize-redirect-sources.js";import{applyL10nToRedirects as k}from"./apply-l10n-to-redirects.js";import{DEFAULT_LOADERS as E}from"./loaders/index.js";import{resolveSearchFacets as G}from"./resolve-search-facets.js";import{telemetryTraceStep as _}from"../../../cli/telemetry/helpers/trace-step.js";import{transformMdAst as B}from"../markdown/runtime-transform.js";async function Q(){return{id:"Config Parser",loaders:E,async processContent(e,{getConfig:i,fs:t}){await _("build.plugin.config_parser",async o=>{const{contentDir:s,setGlobalConfig:a,setGlobalData:l}=e,r=await i(),n=r.access||{},p=T(t,n.rbac||{}),f={outdir:e.outdir,contentDir:s},y=await u(r.scripts?.head,f),h=await D(r.links,f),R=await u(r.scripts?.body,f),d=v(r,{headScriptTags:y,linkTags:h,postBodyScriptTags:R});o?.setAttribute("config",JSON.stringify(d));const g=r.redirects?O(r.redirects):{},C=d.banner?.map(c=>typeof c=="object"&&c!==null&&c.rbac?{...c,[b]:c.rbac}:c);a({...d,banner:C,access:{...n,requiresLogin:!!n.requiresLogin,rbac:p},directoryPaths:await w(t,n.rbac),seo:r.seo&&await L(r.seo,f.contentDir,f.outdir),redirects:k(g,r.l10n),wildcardRedirectsTree:P(g)}),G(r.search?.filters?.facets||[],e.getSearchFacets,e.setSearchFacets),l({removeAttribution:!!r.removeAttribution})})},async afterRoutesCreated(e,i){x(e);const t=e.getGlobalConfig("banner");if(Array.isArray(t)){const o=await Promise.all(t.map(async(s,a)=>{const{content:l,...r}=s,{ast:n}=await e.parseMarkdoc({input:{content:l,relativePath:"redocly.yaml"},context:i,resource:`redocly.yaml#banner${a}`}),{renderableAst:p}=await B(n,{variables:{},partials:{}},e.serverOutDir);return{...r,ast:p,hash:S(l)}}));e.setGlobalConfig({banner:o})}}}}function x(e){const i=e.getGlobalConfig("access")?.rbac,t=e.getGlobalConfig("directoryPaths");if(!(!i||Object.keys(i).length===0))for(const o of e.getAllRoutes()){if(o.versions&&t)for(const s of o.versions){const a=t[s.folderId],r=a==="."||a==="/"?"":a;s[m]={slug:s.link,fsPath:A.posix.join(r,"@"+s.version,"index.md")}}o[m]||o[b]||(o[m]={slug:o.slug,fsPath:o.fsPath})}}export{Q as configParserPlugin};
@@ -1 +1 @@
1
- import{redocConfigSchema as m,rootRedoclyConfigSchema as t}from"@redocly/config";import p from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{DEFAULT_SEARCH_ENGINE as A}from"../../../constants/plugins/search.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as v}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as y}from"../../../utils/rbac.js";import{RbacConfigLocation as g,validateRbacConfig as E}from"../../validate-rbac-config.js";const z=async(e,{fs:r},a)=>{const n=await h(e,r,a,async c=>e===f?S(r.cwd,c?.plugins||[]):void 0);n?.rbac&&(n.rbac=await y(n.rbac),E(n.rbac,e===f?g.RootRedoclyYaml:void 0)),(n?.l10n||n?.i18n)&&(n.l10n=L(n),n.i18n=void 0);const s=F(n||{},{markdown:{partialsFolders:(n?.markdown?.partialsFolders||[]).flatMap(c=>l(c,r))}});return R({...s,configPath:e,ignore:I(n?.ignore,r)})};async function S(e,r){const a=await v(e,r),n=a.map(i=>i.config.schema?i.lifecyclePlugin.id:""),s={};for(const i of a){const o=i.lifecyclePlugin?.id;i.config.schema&&o&&t.properties&&(s[o]=i.config.schema)}return{...t,properties:{...s,...t.properties,openapi:m},$id:t.$id+n.join("")}}function R(e){const r=C.instance();return r.canAccessFeature("apiFunctions")||(e.apiFunctions=void 0),r.canAccessFeature("products")||(e.products=void 0),r.canAccessFeature("breadcrumbs")||(e.breadcrumbs={hide:!0}),r.canAccessFeature("seo")||(e.seo=void 0),r.canAccessFeature("redirects")||(e.redirects={}),r.canAccessFeature("l10n")||(e.l10n=void 0),r.canAccessFeature("rbac")||(e.rbac=void 0),r.canAccessFeature("sso")||(e.sso=void 0),r.canAccessFeature("ssoDirect")||(e.ssoDirect=void 0),r.canAccessFeature("catalogClassic")||(e.catalog=void 0,e.catalogClassic=void 0),r.canAccessFeature("scorecard")||(e.scorecard=void 0,e.scorecardClassic=void 0),r.canAccessFeature("scorecards")||(e.scorecards=void 0),r.canAccessFeature("devOnboarding")||(e.developerOnboarding=void 0),r.canAccessFeature("analytics")||(e.analytics=void 0),r.canAccessFeature("removeAttribution")||(e.removeAttribution=void 0),r.canAccessFeature("mockServer")||(e.mockServer={off:!0}),r.canAccessFeature("advancedSearch")||e.search&&(e.search.engine=A),r.canAccessFeature("banner")||(e.banner=void 0),e}function I(e=[],r){return["static",...e].flatMap(a=>p(a)&&(a.startsWith("*")||a.startsWith(u)||a.startsWith("/"+u)||a.startsWith(d)||a.startsWith("/"+d))?a:l(a,r))}function L(e){return e.i18n&&b.warn("The `i18n` configuration is deprecated. Please use `l10n` instead."),e.l10n||e.i18n||{}}export{z as redoclyConfigLoader};
1
+ import{redocConfigSchema as m,rootRedoclyConfigSchema as t}from"@redocly/config";import p from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{DEFAULT_SEARCH_ENGINE as A}from"../../../constants/plugins/search.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as v}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as y}from"../../../utils/rbac.js";import{RbacConfigLocation as E,validateRbacConfig as S}from"../../validate-rbac-config.js";const z=async(e,{fs:r},a)=>{const s=await h(e,r,a,async n=>e===f?g(r.cwd,n?.plugins||[]):void 0);if(s?.access?.rbac){const n=await y(s.access.rbac);s.access.rbac=n,S(n,e===f?E.RootRedoclyYaml:void 0)}(s?.l10n||s?.i18n)&&(s.l10n=L(s),s.i18n=void 0);const i=F(s||{},{markdown:{partialsFolders:(s?.markdown?.partialsFolders||[]).flatMap(n=>l(n,r))}});return R({...i,configPath:e,ignore:I(s?.ignore,r)})};async function g(e,r){const a=await v(e,r),s=a.map(c=>c.config.schema?c.lifecyclePlugin.id:""),i={};for(const c of a){const o=c.lifecyclePlugin?.id;c.config.schema&&o&&t.properties&&(i[o]=c.config.schema)}return{...t,properties:{...i,...t.properties,openapi:m},$id:t.$id+s.join("")}}function R(e){const r=C.instance();return r.canAccessFeature("apiFunctions")||(e.apiFunctions=void 0),r.canAccessFeature("products")||(e.products=void 0),r.canAccessFeature("breadcrumbs")||(e.breadcrumbs={hide:!0}),r.canAccessFeature("seo")||(e.seo=void 0),r.canAccessFeature("redirects")||(e.redirects={}),r.canAccessFeature("l10n")||(e.l10n=void 0),r.canAccessFeature("rbac")||e.access&&(e.access.rbac=void 0),r.canAccessFeature("sso")||e.access&&(e.access.sso=void 0),r.canAccessFeature("ssoDirect")||(e.ssoDirect=void 0),r.canAccessFeature("catalogClassic")||(e.catalog=void 0,e.catalogClassic=void 0),r.canAccessFeature("scorecard")||(e.scorecard=void 0,e.scorecardClassic=void 0),r.canAccessFeature("scorecards")||(e.scorecards=void 0),r.canAccessFeature("devOnboarding")||(e.developerOnboarding=void 0),r.canAccessFeature("analytics")||(e.analytics=void 0),r.canAccessFeature("removeAttribution")||(e.removeAttribution=void 0),r.canAccessFeature("mockServer")||(e.mockServer={off:!0}),r.canAccessFeature("advancedSearch")||e.search&&(e.search.engine=A),r.canAccessFeature("banner")||(e.banner=void 0),e}function I(e=[],r){return["static",...e].flatMap(a=>p(a)&&(a.startsWith("*")||a.startsWith(u)||a.startsWith("/"+u)||a.startsWith(d)||a.startsWith("/"+d))?a:l(a,r))}function L(e){return e.i18n&&b.warn("The `i18n` configuration is deprecated. Please use `l10n` instead."),e.l10n||e.i18n||{}}export{z as redoclyConfigLoader};
@@ -2,4 +2,5 @@ import type { RedoclyConfig } from '@redocly/config';
2
2
  import type { JSONSchemaType } from '@redocly/ajv';
3
3
  import type { Fs } from '../../../../fs/fs.js';
4
4
  export declare function readAndValidateConfig<T extends Partial<RedoclyConfig>>(configPath: string, fs: Fs, reportError: (error: Error) => void, getValidationSchemaFn: (parsedConfig: T) => Promise<JSONSchemaType<T> | undefined>): Promise<T | undefined>;
5
+ export declare function ensureAccessBackwardsCompatibility<T extends Partial<RedoclyConfig>>(config: T): T;
5
6
  //# sourceMappingURL=read-and-validate-config.d.ts.map