@redocly/realm 0.133.0-next.1 → 0.133.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 (243) hide show
  1. package/CHANGELOG.md +45 -2
  2. package/dist/server/constants/plugins/catalog-entities.d.ts +2 -0
  3. package/dist/server/constants/plugins/catalog-entities.js +1 -1
  4. package/dist/server/persistence/cache/mappers/create-cache-db-record.d.ts +1 -1
  5. package/dist/server/persistence/cache/mappers/create-cache-read-model.d.ts +1 -1
  6. package/dist/server/persistence/cache/repositories/{cache-local-repository.d.ts → cache-repository.d.ts} +3 -3
  7. package/dist/server/persistence/cache/repositories/cache-repository.js +1 -0
  8. package/dist/server/persistence/cache/services/cache-service.d.ts +2 -2
  9. package/dist/server/persistence/cache/services/cache-service.js +1 -1
  10. package/dist/server/persistence/file-hashes/mappers/create-file-hash-db-record.d.ts +1 -1
  11. package/dist/server/persistence/file-hashes/mappers/create-file-hash-read-model.d.ts +2 -2
  12. package/dist/server/persistence/file-hashes/mappers/create-file-hash-read-model.js +1 -1
  13. package/dist/server/persistence/file-hashes/repositories/{file-hashes-local-read-repository.d.ts → file-hashes-read-repository.d.ts} +3 -7
  14. package/dist/server/persistence/file-hashes/repositories/file-hashes-read-repository.js +1 -0
  15. package/dist/server/persistence/file-hashes/repositories/{file-hashes-local-repository.d.ts → file-hashes-repository.d.ts} +4 -3
  16. package/dist/server/persistence/file-hashes/repositories/file-hashes-repository.js +1 -0
  17. package/dist/server/persistence/file-hashes/repositories/{file-hashes-local-write-repository.d.ts → file-hashes-write-repository.d.ts} +2 -2
  18. package/dist/server/persistence/file-hashes/repositories/file-hashes-write-repository.js +1 -0
  19. package/dist/server/persistence/file-hashes/services/file-hashes-service.d.ts +3 -5
  20. package/dist/server/persistence/file-hashes/services/file-hashes-service.js +1 -1
  21. package/dist/server/persistence/kv/mappers/create-kv-db-record.d.ts +1 -1
  22. package/dist/server/persistence/kv/mappers/create-kv-list-entry.d.ts +1 -1
  23. package/dist/server/persistence/kv/mappers/create-kv-value.d.ts +1 -1
  24. package/dist/server/persistence/kv/repositories/{kv-remote-repository.d.ts → kv-repository.d.ts} +3 -3
  25. package/dist/server/persistence/kv/repositories/kv-repository.js +2 -0
  26. package/dist/server/persistence/kv/services/kv-service.d.ts +2 -2
  27. package/dist/server/persistence/kv/services/kv-service.js +1 -1
  28. package/dist/server/plugins/catalog-entities/database/catalog-entities-publisher.d.ts +6 -0
  29. package/dist/server/plugins/catalog-entities/database/catalog-entities-publisher.js +12 -0
  30. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +29 -66
  31. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
  32. package/dist/server/plugins/catalog-entities/database/consts.d.ts +45 -0
  33. package/dist/server/plugins/catalog-entities/database/consts.js +1 -0
  34. package/dist/server/plugins/catalog-entities/database/mappers/create-bff-entity.d.ts +1 -2
  35. package/dist/server/plugins/catalog-entities/database/mappers/create-bff-entity.js +1 -1
  36. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.d.ts +1 -1
  37. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-db-record.d.ts +1 -1
  38. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-read-model.d.ts +1 -3
  39. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-read-model.js +1 -1
  40. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-db-record-from-dto.d.ts +1 -1
  41. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-db-record-from-file-schema.d.ts +1 -1
  42. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-read-model.d.ts +3 -3
  43. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-read-model.js +1 -1
  44. package/dist/server/plugins/catalog-entities/database/repositories/{local/catalog-entities-bff-repository.d.ts → bffEntities/bff-entities-read-repository.d.ts} +4 -4
  45. package/dist/server/plugins/catalog-entities/database/repositories/bffEntities/bff-entities-read-repository.js +131 -0
  46. package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.d.ts +26 -0
  47. package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.js +1 -0
  48. package/dist/server/plugins/catalog-entities/database/repositories/common/filters-repository.d.ts +8 -0
  49. package/dist/server/plugins/catalog-entities/database/repositories/common/filters-repository.js +82 -0
  50. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +7 -7
  51. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -1
  52. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +1 -1
  53. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-read-repository.d.ts +27 -0
  54. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-read-repository.js +1 -0
  55. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.d.ts +27 -0
  56. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -0
  57. package/dist/server/plugins/catalog-entities/database/repositories/entityAttributes/entity-attributes-write-repository.d.ts +12 -0
  58. package/dist/server/plugins/catalog-entities/database/repositories/entityAttributes/entity-attributes-write-repository.js +1 -0
  59. package/dist/server/plugins/catalog-entities/database/repositories/{local/catalog-entities-relations-repository.d.ts → relations/relations-read-repository.d.ts} +7 -4
  60. package/dist/server/plugins/catalog-entities/database/repositories/relations/relations-read-repository.js +1 -0
  61. package/dist/server/plugins/catalog-entities/database/repositories/relations/relations-write-repository.d.ts +28 -0
  62. package/dist/server/plugins/catalog-entities/database/repositories/relations/relations-write-repository.js +1 -0
  63. package/dist/server/plugins/catalog-entities/database/repositories/types.d.ts +39 -0
  64. package/dist/server/plugins/catalog-entities/database/repositories/types.js +0 -0
  65. package/dist/server/plugins/catalog-entities/database/types.d.ts +26 -0
  66. package/dist/server/plugins/catalog-entities/database/types.js +0 -0
  67. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  68. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.d.ts +2 -2
  69. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
  70. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +2 -2
  71. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  72. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.d.ts +2 -2
  73. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
  74. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.d.ts +2 -2
  75. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  76. package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
  77. package/dist/server/plugins/catalog-entities/get-server-props.js +1 -1
  78. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  79. package/dist/server/plugins/catalog-entities/schemas/database-schemas.d.ts +38 -36
  80. package/dist/server/plugins/catalog-entities/schemas/database-schemas.js +1 -1
  81. package/dist/server/plugins/catalog-entities/schemas/dto-schemas.d.ts +1 -3
  82. package/dist/server/plugins/catalog-entities/schemas/read-model-schemas.d.ts +3 -1
  83. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.d.ts +15 -0
  84. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.js +1 -1
  85. package/dist/server/plugins/catalog-entities/utils/hash-manager.d.ts +1 -0
  86. package/dist/server/plugins/catalog-entities/utils/hash-manager.js +1 -1
  87. package/dist/server/plugins/catalog-entities/utils/rbac-config-hash-cache.d.ts +18 -0
  88. package/dist/server/plugins/catalog-entities/utils/rbac-config-hash-cache.js +1 -0
  89. package/dist/server/plugins/entitlements/index.js +1 -1
  90. package/dist/server/plugins/entitlements/utils/get-billed-catalog-build-pages-count.d.ts +0 -1
  91. package/dist/server/plugins/entitlements/utils/get-billed-catalog-build-pages-count.js +1 -1
  92. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  93. package/dist/server/plugins/mcp/types.d.ts +5 -0
  94. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +1 -0
  95. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  96. package/dist/server/plugins/scorecards/database/repositories/{local/scorecards-config-local-repository.d.ts → scorecards-config-repository.d.ts} +4 -4
  97. package/dist/server/plugins/scorecards/database/repositories/scorecards-config-repository.js +1 -0
  98. package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -1
  99. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -1
  100. package/dist/server/providers/database/base-repository.js +2 -2
  101. package/dist/server/providers/database/client.d.ts +1 -1
  102. package/dist/server/providers/database/client.js +1 -1
  103. package/dist/server/providers/database/constants.d.ts +4 -9
  104. package/dist/server/providers/database/constants.js +1 -1
  105. package/dist/server/providers/database/copy-migrations.js +1 -1
  106. package/dist/server/providers/database/database-connection-factory.d.ts +2 -2
  107. package/dist/server/providers/database/database-connection-factory.js +1 -1
  108. package/dist/server/providers/database/database-connections-manager.d.ts +3 -8
  109. package/dist/server/providers/database/database-connections-manager.js +1 -1
  110. package/dist/server/providers/database/database-preconnect-service.js +1 -1
  111. package/dist/server/providers/database/databases/sqlite-db/drizzle.config.d.ts +12 -0
  112. package/dist/server/providers/database/databases/sqlite-db/drizzle.config.js +1 -0
  113. package/dist/server/providers/database/databases/sqlite-db/migrations/0009_add-missing-local-tables.sql +41 -0
  114. package/dist/server/providers/database/databases/sqlite-db/migrations/0010_add-last-seen-run-id-to-entities-tables.sql +4 -0
  115. package/dist/server/providers/database/databases/sqlite-db/migrations/0011_update-entities-relations-index.sql +2 -0
  116. package/dist/server/providers/database/databases/sqlite-db/migrations/meta/0009_snapshot.json +1141 -0
  117. package/dist/server/providers/database/databases/sqlite-db/migrations/meta/0010_snapshot.json +1165 -0
  118. package/dist/server/providers/database/databases/sqlite-db/migrations/meta/0011_snapshot.json +1165 -0
  119. package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/_journal.json +21 -0
  120. package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-relations-table.d.ts +19 -0
  121. package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-relations-table.js +1 -1
  122. package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-table.d.ts +19 -0
  123. package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-table.js +1 -1
  124. package/dist/server/providers/database/pagination/limit.d.ts +5 -0
  125. package/dist/server/providers/database/pagination/limit.js +1 -1
  126. package/dist/server/providers/database/transient-sqld-error.d.ts +14 -0
  127. package/dist/server/providers/database/transient-sqld-error.js +1 -0
  128. package/dist/server/providers/database/types.d.ts +6 -6
  129. package/dist/server/providers/database/utils/get-first-row.d.ts +19 -0
  130. package/dist/server/providers/database/utils/get-first-row.js +1 -0
  131. package/dist/server/store.d.ts +1 -0
  132. package/dist/server/store.js +1 -1
  133. package/dist/server/types/plugins/common.d.ts +1 -0
  134. package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
  135. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  136. package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +0 -147
  137. package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.js +1 -1
  138. package/dist/server/web-server/routes/catalog/helpers/upsert-pages-stats.js +1 -1
  139. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entities.d.ts +1 -2
  140. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity-update-data.d.ts +1 -2
  141. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity.d.ts +1 -2
  142. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entities-relations.d.ts +1 -1
  143. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation-update-data.d.ts +1 -1
  144. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation.d.ts +1 -1
  145. package/dist/server/workers/mcp-tool-worker-pool.d.ts +1 -0
  146. package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
  147. package/dist/server/workers/mcp-tool-worker.js +1 -1
  148. package/dist/server/workers/types.d.ts +5 -1
  149. package/package.json +9 -9
  150. package/dist/server/persistence/cache/repositories/cache-local-repository.js +0 -1
  151. package/dist/server/persistence/file-hashes/repositories/file-hashes-local-read-repository.js +0 -1
  152. package/dist/server/persistence/file-hashes/repositories/file-hashes-local-repository.js +0 -1
  153. package/dist/server/persistence/file-hashes/repositories/file-hashes-local-write-repository.js +0 -1
  154. package/dist/server/persistence/file-hashes/repositories/utils.d.ts +0 -10
  155. package/dist/server/persistence/file-hashes/repositories/utils.js +0 -1
  156. package/dist/server/persistence/kv/repositories/kv-remote-repository.js +0 -2
  157. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +0 -123
  158. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +0 -98
  159. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +0 -145
  160. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +0 -100
  161. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +0 -1
  162. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.d.ts +0 -43
  163. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +0 -1
  164. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.js +0 -1
  165. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +0 -20
  166. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +0 -1
  167. package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.js +0 -1
  168. package/dist/server/providers/database/database-initialization-strategy.d.ts +0 -17
  169. package/dist/server/providers/database/database-initialization-strategy.js +0 -1
  170. package/dist/server/providers/database/databases/catalog-sqlite/drizzle.config.d.ts +0 -11
  171. package/dist/server/providers/database/databases/catalog-sqlite/drizzle.config.js +0 -1
  172. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0001_catalog-versions-and-revisions.sql +0 -20
  173. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0002_add-scorecards-status.sql +0 -1
  174. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0003_catalog_versions_and_revisions_relations.sql +0 -46
  175. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0004_normalize_relation_types.sql +0 -147
  176. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0005_catalog-relations-constraint-fix.sql +0 -2
  177. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0006_add-catalog-entitities-attributes-table.sql +0 -11
  178. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0001_snapshot.json +0 -378
  179. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0002_snapshot.json +0 -385
  180. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0003_snapshot.json +0 -392
  181. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0004_snapshot.json +0 -392
  182. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0005_snapshot.json +0 -393
  183. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0006_snapshot.json +0 -458
  184. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/_journal.json +0 -55
  185. package/dist/server/providers/database/databases/main-sqlite/drizzle.config.d.ts +0 -10
  186. package/dist/server/providers/database/databases/main-sqlite/drizzle.config.js +0 -1
  187. package/dist/server/providers/database/databases/main-sqlite/migrations/0000_initial_migration.sql +0 -11
  188. package/dist/server/providers/database/databases/main-sqlite/migrations/0001_update_file_hashes_file_type_values.sql +0 -10
  189. package/dist/server/providers/database/databases/main-sqlite/migrations/0002_cache-table.sql +0 -11
  190. package/dist/server/providers/database/databases/main-sqlite/migrations/0003_file-path-added.sql +0 -6
  191. package/dist/server/providers/database/databases/main-sqlite/migrations/0004_add-scorecards-tables.sql +0 -10
  192. package/dist/server/providers/database/databases/main-sqlite/migrations/0005_recreate-scorecards-config.sql +0 -25
  193. package/dist/server/providers/database/databases/main-sqlite/migrations/0006_change-scorecards-config-timestamps-field-types.sql +0 -19
  194. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0000_snapshot.json +0 -82
  195. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0001_snapshot.json +0 -82
  196. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0002_snapshot.json +0 -146
  197. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0003_snapshot.json +0 -153
  198. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0004_snapshot.json +0 -221
  199. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0005_snapshot.json +0 -263
  200. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0006_snapshot.json +0 -261
  201. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/_journal.json +0 -55
  202. package/dist/server/providers/database/databases/sqld-sqlite/drizzle.config.d.ts +0 -14
  203. package/dist/server/providers/database/databases/sqld-sqlite/drizzle.config.js +0 -1
  204. package/dist/server/providers/database/databases/sqld-sqlite/migrations/0000_initial_migration.sql +0 -46
  205. package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/0000_snapshot.json +0 -307
  206. /package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/migrations/0000_initial_migration.sql +0 -0
  207. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0001_add_kv_table.sql +0 -0
  208. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0002_catalog-versions-and-revisions.sql +0 -0
  209. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0003_add-scorecards-tables.sql +0 -0
  210. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0004_add-scorecards-status.sql +0 -0
  211. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0005_recreate-scorecards-tables.sql +0 -0
  212. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0006_catalog-versions-and-revisions-relations.sql +0 -0
  213. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0007_catalog-relations-constraint-fix.sql +0 -0
  214. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/0008_add-catalog-entitities-attributes-table.sql +0 -0
  215. /package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/migrations/meta/0000_snapshot.json +0 -0
  216. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0001_snapshot.json +0 -0
  217. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0002_snapshot.json +0 -0
  218. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0003_snapshot.json +0 -0
  219. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0004_snapshot.json +0 -0
  220. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0005_snapshot.json +0 -0
  221. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0006_snapshot.json +0 -0
  222. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0007_snapshot.json +0 -0
  223. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/migrations/meta/0008_snapshot.json +0 -0
  224. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/cache-table.d.ts +0 -0
  225. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/cache-table.js +0 -0
  226. /package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-attributes-table.d.ts +0 -0
  227. /package/dist/server/providers/database/databases/{catalog-sqlite → sqlite-db}/schemas/entities-attributes-table.js +0 -0
  228. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/file-hashes-table.d.ts +0 -0
  229. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/file-hashes-table.js +0 -0
  230. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/kv-table.d.ts +0 -0
  231. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/kv-table.js +0 -0
  232. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/scorecards-config-table.d.ts +0 -0
  233. /package/dist/server/providers/database/databases/{main-sqlite → sqlite-db}/schemas/scorecards-config-table.js +0 -0
  234. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-evaluation-runs-table.d.ts +0 -0
  235. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-evaluation-runs-table.js +0 -0
  236. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-level-results-table.d.ts +0 -0
  237. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-level-results-table.js +0 -0
  238. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-levels-rules-results-table.d.ts +0 -0
  239. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-levels-rules-results-table.js +0 -0
  240. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-results-table.d.ts +0 -0
  241. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-results-table.js +0 -0
  242. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-rule-results-table.d.ts +0 -0
  243. /package/dist/server/providers/database/databases/{sqld-sqlite → sqlite-db}/schemas/scorecards-rule-results-table.js +0 -0
@@ -1,10 +1,11 @@
1
1
  import type { BffCatalogRelatedEntity } from '@redocly/theme/core/types';
2
2
  import type { DatabaseClient } from '../../../../../providers/database/client';
3
3
  import type { PaginationParams } from '../../../../../providers/database/pagination/schemas.js';
4
- import type { ListResult } from './catalog-entities-local-read-repository.js';
5
- export declare class CatalogEntitiesRelationsRepository {
4
+ import type { ListResult } from '../types.js';
5
+ import type { EntityRelationReadModelSchema } from '../../../schemas/read-model-schemas.js';
6
+ export declare class RelationsReadRepository {
6
7
  #private;
7
- constructor(db: DatabaseClient, attachedDatabasePath: string);
8
+ constructor(db: DatabaseClient);
8
9
  getRelationsForEntity(key: string, version?: string | null, revision?: string | null): Promise<{
9
10
  targetKey: string;
10
11
  targetRevision: string;
@@ -19,5 +20,7 @@ export declare class CatalogEntitiesRelationsRepository {
19
20
  excludedTypes?: string[];
20
21
  excludedEntities?: string[];
21
22
  }): Promise<ListResult<BffCatalogRelatedEntity>>;
23
+ getEntitiesRelations(paginationParams?: PaginationParams): Promise<ListResult<EntityRelationReadModelSchema>>;
24
+ getEntityRelationById(id: string): Promise<EntityRelationReadModelSchema | null>;
22
25
  }
23
- //# sourceMappingURL=catalog-entities-relations-repository.d.ts.map
26
+ //# sourceMappingURL=relations-read-repository.d.ts.map
@@ -0,0 +1 @@
1
+ import{and as $,desc as L,eq as R,sql as i}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as O}from"@redocly/theme/core/constants";import{entitiesTable as e}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{entitiesRelationsTable as t}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{entitiesAttributesTable as C}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-attributes-table.js";import{excludeFieldsFromFilter as W,getFirstFilterFieldValue as T}from"../../../../../providers/database/pagination/filter.js";import{applyPagination as g}from"../../../../../providers/database/pagination/index.js";import{getEffectivePaginationLimit as S}from"../../../../../providers/database/pagination/limit.js";import{createBffRelatedEntityFromQueryRow as H}from"../../mappers/create-bff-related-entity.js";import{mapEntityRelationRow as q}from"../../mappers/map-entity-relation-row.js";import{buildEntitiesExclusionFilter as Y}from"../utils/build-entities-exclusion-filter.js";import{buildRbacFilter as M}from"../utils/build-rbac-filter.js";import{FIELDS_TO_SELECT_FOR_ENTITY_RELATION as p}from"../utils.js";import{createEntityRelationReadModel as A}from"../../mappers/create-entity-relation-read-model.js";class oe{#e;constructor(r){this.#e=r}async getRelationsForEntity(r,n,u){const a=await this.#t(r,n,u);return a?(await this.#e.client.select().from(a).all()).map(c=>q(c)):[]}async getRelatedEntities({key:r,paginationParams:n,rbacTeams:u,excludedTypes:a,excludedEntities:d}){const c=T(n.filter,"version"),y=T(n.filter,"revision"),o=await this.#t(r,c,y);if(!o)return{items:[],total:0};const m=this.#e.client.select({relationType:o.relationName,direction:o.direction,key:e.key,revision:e.revision,id:e.id,type:e.type,title:e.title,summary:e.summary,tags:e.tags,metadata:e.metadata,createdAt:e.createdAt,updatedAt:e.updatedAt,source:e.source,sourceFile:e.sourceFile,version:e.version,isDeleted:e.isDeleted,isCurrent:e.isCurrent,rbacTeams:C.rbacTeams,dedupRn:i`ROW_NUMBER() OVER (PARTITION BY ${o.entityKey} ORDER BY ${o.priority} ASC, CASE WHEN ${o.entityRevision} = ${e.revision} THEN 1 ELSE 0 END DESC, CASE WHEN ${o.entityVersion} = ${e.version} THEN 1 ELSE 0 END DESC, ${e.isCurrent} DESC, ${e.revision} DESC)`.as("dedupRn")}).from(o).innerJoin(e,i`${o.entityKey} = ${e.key} AND (${o.entityRevision} = ${e.revision} OR ${o.entityRevision} = '' OR ${e.isCurrent} = 1) AND (${o.entityVersion} = ${e.version} OR ${o.entityVersion} = '' OR ${e.version} = ${O})`).leftJoin(C,R(e.key,C.entityKey)).as("unique_relations"),f=M(u,"unique_relations"),E=Y(a,d,"unique_relations");let s=i`${m.dedupRn} = 1 AND COALESCE(${m.isDeleted}, 0) = 0`;f&&(s=i`${s} AND ${f}`),E&&(s=i`${s} AND ${E}`);const l=this.#e.client.select().from(m).$dynamic(),V=this.#e.client.select().from(m).$dynamic(),F=W(n.filter,["version","revision"]),D={...n,filter:F,baseWhereCondition:s},w=g(V,{...D,limit:void 0,skip:void 0,after:void 0,before:void 0}),_=this.#e.client.$count(w),N=S(n),b=g(l,{...D,limit:N+1}),[B,K]=await Promise.all([b.all(),_]),h=B.filter(v=>v.id!=null).map(v=>H(v)).filter(v=>v!==null),I=h.slice(0,N),Q=h.length>N;return{items:I,hasMore:Q,total:K}}async getEntitiesRelations(r={}){const n=this.#e.client.select(p).from(t),u=this.#e.client.select(p).from(n.as("combined_entities_relations")).$dynamic(),a=this.#e.client.select(p).from(n.as("combined_entities_relations")).$dynamic(),d=g(a,{...r,limit:void 0,skip:void 0,after:void 0,before:void 0}),c=this.#e.client.$count(d),y=S(r),o=g(u,{...r,limit:y+1}),[m,f]=await Promise.all([o.all(),c]),E=m,s=E.length>y;return{items:E.slice(0,y).map(l=>A(l)).filter(l=>l!==null),hasMore:s,total:f}}async getEntityRelationById(r){const n=await this.#e.client.select(p).from(t).where(R(t.id,r)).get();return n?A(n):null}async#i(r,n){if(n){const c=await this.#e.client.select({version:e.version,revision:e.revision}).from(e).where($(R(e.key,r),R(e.version,n))).orderBy(L(e.revision)).limit(1).get();return c?{version:c.version||null,revision:c.revision||null}:null}const a=await this.#e.client.select({version:e.version,revision:e.revision}).from(e).where($(R(e.key,r),R(e.isCurrent,!0))).limit(1).get();return a?{version:a.version||null,revision:a.revision||null}:null}async#t(r,n,u){const a=u?{version:n||null,revision:u}:await this.#i(r,n||null),d=n||a?.version||null,c=u||a?.revision||null,y=!d||d===O,o=y?i`1 = 1`:i`(${t.sourceVersion} = ${d} OR ${t.sourceVersion} = '')`,m=y?i`1 = 1`:i`(${t.targetVersion} = ${d} OR ${t.targetVersion} = '')`,f=c?i`(${t.sourceRevision} <= ${c} OR ${t.sourceRevision} = '')`:i`1 = 0`,E=c?i`(${t.targetRevision} <= ${c} OR ${t.targetRevision} = '')`:i`1 = 0`,s=this.#e.client.select({entityKey:t.targetKey,entityRevision:t.targetRevision,entityVersion:t.targetVersion,relationName:t.sourceToTargetRelation,direction:i`'outgoing'`.as("direction"),priority:i`1`.as("priority"),isDeleted:t.isDeleted,rn:i`ROW_NUMBER() OVER (PARTITION BY ${t.targetKey}, ${t.sourceToTargetRelation} ORDER BY CASE WHEN ${t.sourceVersion} != '' THEN 1 ELSE 0 END DESC, ${t.sourceRevision} DESC)`.as("rn")}).from(t).where($(R(t.sourceKey,r),o,f)).as("outgoing_filtered"),l=this.#e.client.select({entityKey:t.sourceKey,entityRevision:t.sourceRevision,entityVersion:t.sourceVersion,relationName:t.targetToSourceRelation,direction:i`'incoming'`.as("direction"),priority:i`2`.as("priority"),isDeleted:t.isDeleted,rn:i`ROW_NUMBER() OVER (PARTITION BY ${t.sourceKey}, ${t.targetToSourceRelation} ORDER BY CASE WHEN ${t.targetVersion} != '' THEN 1 ELSE 0 END DESC, ${t.targetRevision} DESC)`.as("rn")}).from(t).where($(R(t.targetKey,r),m,E)).as("incoming_filtered");return this.#e.client.select({entityKey:s.entityKey,entityRevision:s.entityRevision,entityVersion:s.entityVersion,relationName:s.relationName,direction:s.direction,priority:s.priority}).from(s).where(i`${s.rn} = 1 AND COALESCE(${s.isDeleted}, 0) = 0`).unionAll(this.#e.client.select({entityKey:l.entityKey,entityRevision:l.entityRevision,entityVersion:l.entityVersion,relationName:l.relationName,direction:l.direction,priority:l.priority}).from(l).where(i`${l.rn} = 1 AND COALESCE(${l.isDeleted}, 0) = 0`)).as("all_relations")}}export{oe as RelationsReadRepository};
@@ -0,0 +1,28 @@
1
+ import type { DatabaseClient } from '../../../../../providers/database/client.js';
2
+ import type { DatabaseEntityRelation, DatabaseEntityRelationDto } from '../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js';
3
+ import type { Filter } from '../../../../../providers/database/pagination/types.js';
4
+ import type { EntityRelationDtoSchema } from '../../../schemas/dto-schemas.js';
5
+ import type { EntityRelationReadModelSchema } from '../../../schemas/read-model-schemas.js';
6
+ export declare class RelationsWriteRepository {
7
+ #private;
8
+ constructor(db: DatabaseClient, organizationId: string, projectId: string);
9
+ createEntityRelation(entityRelation: EntityRelationDtoSchema): Promise<EntityRelationReadModelSchema | null>;
10
+ createEntityRelations(relations: EntityRelationDtoSchema[]): Promise<(EntityRelationReadModelSchema | null)[]>;
11
+ upsertEntityRelation(entityRelation: DatabaseEntityRelationDto): Promise<DatabaseEntityRelation | null>;
12
+ deleteEntityRelation(id: string): Promise<string | null>;
13
+ deleteEntitiesRelations(filter: Filter): Promise<boolean>;
14
+ /**
15
+ * Deletes entity relations when an entity is removed.
16
+ * The deletion logic depends on what other revisions exist:
17
+ * - If this is the only revision of the key: remove all relations with this key (source or target)
18
+ * - If this is the only revision with given version: remove relations with key+version (any revision)
19
+ * - Always: remove relations with exact key+version+revision match
20
+ */
21
+ deleteEntityRelationsOnEntityRemoval(entity: {
22
+ id: string;
23
+ key: string;
24
+ version?: string | null;
25
+ revision?: string | null;
26
+ }): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=relations-write-repository.d.ts.map
@@ -0,0 +1 @@
1
+ import{and as a,eq as i,ne as m,or as h,sql as g}from"drizzle-orm";import{entitiesRelationsTable as t}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{logger as c}from"../../../../../tools/notifiers/logger.js";import{telemetryTraceStep as l}from"../../../../../telemetry/helpers/trace-step.js";import{entitiesTable as o}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{promiseMapLimit as f}from"../../../../../utils/async/promise-map-limit.js";import{convertFilterToWhereCondition as v}from"../../../../../providers/database/pagination/filter.js";import{createEntityRelationReadModel as w}from"../../mappers/create-entity-relation-read-model.js";import{createEntityRelationDbRecordFromDto as _}from"../../mappers/create-entity-relation-db-record-from-dto.js";const E=15;class k{#e;#t;#r;constructor(r,e,n){this.#e=r,this.#t=e,this.#r=n}async createEntityRelation(r){return l("catalog_entities.remote_repository.create_entity_relation",async()=>{if(!r)return null;try{const e=_(r,this.#t,this.#r),n=await this.upsertEntityRelation(e);return w(n)}catch(e){throw c.error("Error creating entity relation",e),e}})}async createEntityRelations(r){return l("catalog_entities.remote_repository.create_entity_relations",async()=>await f(r,E,async e=>this.createEntityRelation(e)))}async upsertEntityRelation(r){if(!r)return null;try{const{sourceKey:e,targetKey:n,sourceVersion:R,targetVersion:s,sourceRevision:y,targetRevision:p,...d}=r,u=await this.#e.client.insert(t).values(r).onConflictDoUpdate({target:[t.sourceKey,t.targetKey,t.sourceVersion,t.targetVersion,t.sourceRevision,t.targetRevision,t.sourceToTargetRelation],set:d}).returning();return u?.length?u[0]:null}catch(e){return c.error("Error creating entity relation",e),null}}async deleteEntityRelation(r){return l("catalog_entities.remote_repository.delete_entity_relation",async()=>{try{return await this.#e.client.delete(t).where(i(t.id,r)),r}catch(e){return c.error("Error deleting entity relation",e),null}})}async deleteEntitiesRelations(r){return l("catalog_entities.remote_repository.delete_entities_relations",async()=>{try{const e=v(r);return e?(await this.#e.client.delete(t).where(e),!0):!1}catch(e){return c.error("Error deleting entities relations",e),!1}})}async deleteEntityRelationsOnEntityRemoval(r){const{key:e,version:n,revision:R}=r,s=n??"",y=R??"";if(((await this.#e.client.select({count:g`COUNT(*)`}).from(o).where(a(i(o.key,e),m(o.id,r.id))).get())?.count??0)===0){await this.#e.client.delete(t).where(h(i(t.sourceKey,e),i(t.targetKey,e)));return}if(((await this.#e.client.select({count:g`COUNT(*)`}).from(o).where(a(i(o.key,e),i(o.version,s),m(o.id,r.id))).get())?.count??0)===0){await this.#e.client.delete(t).where(h(a(i(t.sourceKey,e),i(t.sourceVersion,s)),a(i(t.targetKey,e),i(t.targetVersion,s))));return}await this.#e.client.delete(t).where(h(a(i(t.sourceKey,e),i(t.sourceVersion,s),i(t.sourceRevision,y)),a(i(t.targetKey,e),i(t.targetVersion,s),i(t.targetRevision,y))))}}export{k as RelationsWriteRepository};
@@ -0,0 +1,39 @@
1
+ import type { EntityDtoSchema } from '../../schemas/dto-schemas';
2
+ import type { EntitySource } from '../../schemas/read-model-schemas';
3
+ export type ListResult<T> = {
4
+ items: T[];
5
+ hasMore?: boolean;
6
+ total: number;
7
+ };
8
+ export type CatalogFiltersParams = {
9
+ entitiesTypes?: string[];
10
+ emptyFilters?: string[];
11
+ rbacTeams?: string[];
12
+ excludedTypes?: string[];
13
+ excludedEntities?: string[];
14
+ };
15
+ export type FilterOption = {
16
+ value: string;
17
+ count: number;
18
+ };
19
+ export type CreateEntityParams = {
20
+ entity: EntityDtoSchema;
21
+ source: EntitySource;
22
+ revision?: string;
23
+ fileHash?: string;
24
+ sourceFile?: string;
25
+ rbacTeams?: string[];
26
+ isRootEntity?: boolean;
27
+ isDeleted?: boolean;
28
+ errorOnSkip?: boolean;
29
+ };
30
+ export type CreateEntityResult = {
31
+ result: 'created';
32
+ entityKey: string;
33
+ entityRevision: string;
34
+ entityVersion: string | null;
35
+ } | {
36
+ result: 'skipped' | 'error';
37
+ entityKey: string;
38
+ };
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,26 @@
1
+ import type { DatabaseConnectionFactory } from '../../../providers/database/database-connection-factory';
2
+ export type PublishCatalogEntitiesParams = {
3
+ baseDbDir: string;
4
+ chunkSize?: number;
5
+ changedSourceFiles?: string[];
6
+ removedSourceFiles?: string[];
7
+ };
8
+ export type PublishCatalogEntitiesRunResult = {
9
+ runId: string;
10
+ published: boolean;
11
+ };
12
+ export type PublishRowsResult = {
13
+ upserted: number;
14
+ skipped: number;
15
+ };
16
+ export type DatabaseConnection = NonNullable<Awaited<ReturnType<typeof DatabaseConnectionFactory.create>>>;
17
+ export type SourceFilesFilter = string[] | 'none';
18
+ export type BulkSyncResult<T> = Array<{
19
+ status: 'ok';
20
+ resource: T | null;
21
+ } | {
22
+ key: string;
23
+ status: 'error';
24
+ error: string;
25
+ }>;
26
+ //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
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
+ import y 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 A 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.createEntity({entity:{...o},revision:i,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:e,source:"file"}),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 s=this.resolveSourceDescriptionUrl(r.url,t.realRelativePath);if(!s){!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(s,"load-oas");if(!(c.data&&Array.isArray(c.data)&&c.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${s}`);return}const p=c.data[0],u=this.resolveEntityKey({realRelativePath:p.realRelativePath,customKey:p.definition["x-redocly-catalog-key"]});await this.catalogEntitiesService.createEntityRelation({sourceKey:o.key,type:"relatesTo",targetKey:u,sourceFile:t.realRelativePath,fileHash:t.hash}),await this.#r(t,r.name,p,o.key,u,o.version,i)}catch(s){this.context.logger.warn(`Failed to create relation to OpenAPI source "${r.url}": ${s instanceof Error?s.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,s=r?Object.entries(r):[],c=[];for(const[n,p]of s)c.push(async()=>{const u=await this.#a({schemaName:n,schema:p,description:t,parentKey:i,parentVersion:a,parentRevision:e,rbacTeams:h});o.delete(`${u?.key}:${l}`),u&&await this.catalogEntitiesService.createEntityRelation({sourceKey:i,type:"uses",targetKey:u.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:e,targetRevision:e})});if(c.length===0)return;await m(c,f,n=>n())}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};try{return await this.catalogEntitiesService.createEntity({entity:r,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:h,source:"file",revision:o})}catch(s){return this.context.logger.warn(`Failed to create data schema entity for ${t}: ${s instanceof Error?s.message:"Unknown error"}`),null}};#r=async(t,i,a,l,e,o,h)=>{const r=t.document.workflows||[];if(r.length===0)return;const s=new Set;for(const c of r)for(const n of c.steps||[]){if(!n.operationId)continue;const p=n.operationId.startsWith(`${i}.`)?n.operationId.substring(`${i}.`.length):n.operationId;p&&s.add(p)}s.size!==0&&await m(Array.from(s),f,async c=>{try{const n=`${e}-${d(c)}`;await this.catalogEntitiesService.createEntityRelation({sourceKey:l,type:"uses",targetKey:n,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:o,targetVersion:o,sourceRevision:h,targetRevision:h})}catch(n){this.context.logger.warn(`Failed to create relation to operation "${c}": ${n instanceof Error?n.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(y.posix.normalize(e));const o=y.posix.dirname(i);return e.startsWith(o+"/")?y.posix.normalize(e):y.posix.normalize(y.posix.join(o,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{A as ArazzoEntitiesExtractor};
@@ -1,12 +1,12 @@
1
1
  import type { BundledDefinition } from '../../../../asyncapi-docs/asyncapi-doc-loader';
2
- import type { EntityFileSchema } from '@redocly/config';
3
2
  import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
3
+ import type { EntityDtoSchema } from '../../../schemas/dto-schemas';
4
4
  import { BaseApiEntitiesExtractor } from './base.js';
5
5
  type Params = BaseApiEntitiesExtractorParams;
6
6
  export declare class AsyncApiEntitiesExtractor extends BaseApiEntitiesExtractor<BundledDefinition> {
7
7
  #private;
8
8
  constructor(params: Params);
9
- mapApiDescriptionToEntity(description: BundledDefinition, version: string): EntityFileSchema;
9
+ mapApiDescriptionToEntity(description: BundledDefinition, version: string): EntityDtoSchema;
10
10
  loadApiDescriptions(): Promise<BundledDefinition[]>;
11
11
  processApiDescription(description: BundledDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
12
12
  }
@@ -1 +1 @@
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};
1
+ import{removeLeadingSlash as R}from"@redocly/theme/core/utils";import{toKebabCase as f}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 d}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";import{extractPartsFromComponentsRef as y}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 M extends E{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,t){const a=R(e.realRelativePath),n=e.document.info.title,s=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.document["x-redocly-catalog-key"]});return{type:this.type,key:s,title:n,summary:d(e.document.info.description),tags:e.document.info.tags?.map(r=>r.name),metadata:{specType:this.specType,descriptionFile:a},version:t}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,t,a,n){const s=this.getRbacTeamsForDefinition(e.relativePath),r=this.mapApiDescriptionToEntity(e,a);await this.catalogEntitiesService.createEntity({entity:r,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,rbacTeams:s,source:"file"}),n.delete(`${r.key}:${a}`);const o=this.#a(e),[i,c]=await Promise.allSettled([this.#s(e,r.key,r.version,a,t,n,s),this.#n(o,e,r.key,r.version,a,t,n,s)]);i.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",i.reason),c.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",c.reason)}#a=e=>{const t=e.documentWithReferences.operations;return t?Object.entries(t).map(([a,n])=>({operationName:a,operation:n})):[]};#s=async(e,t,a,n,s,r,o)=>{const i=e.document.components?.schemas;if(!i)return;const c=Object.entries(i);if(c.length===0)return;const l=await $(c,u,async([m,h])=>{const g=await this.#r({schemaName:m,schema:h,description:e,parentKey:t,parentVersion:a,parentRevision:s,rbacTeams:o});r.delete(`${g?.key}:${n}`),g&&await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:g.key,sourceFile:e.realRelativePath,fileHash:e.hash,sourceVersion:a,targetVersion:a,sourceRevision:s,targetRevision:s})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${c.length} schemas for ${e.realRelativePath}`)};#r=async({schemaName:e,schema:t,description:a,parentKey:n,parentVersion:s,parentRevision:r,rbacTeams:o})=>{const i=`${n}-${f(e)}`,c="title"in t?t.title??t.description:null,l=JSON.stringify(t),m={type:"data-schema",key:i,title:e,summary:c,tags:[],metadata:{specType:this.specType,schema:l},version:s};try{return await this.catalogEntitiesService.createEntity({entity:m,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:o,source:"file",revision:r})}catch(h){return this.context.logger.warn(`Failed to create data schema entity for ${e}: ${h instanceof Error?h.message:"Unknown error"}`),null}};#n=async(e,t,a,n,s,r,o,i)=>{if(!e.length)return;const c=await $(e,u,async({operationName:l,operation:m})=>{const h=await this.#o(m,l,t,a,n,r,i);h&&o.delete(`${h}:${s}`)},this.context.logger);c.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${c.count.failed} failures out of ${e.length} operations for ${t.realRelativePath}`)};#o=async(e,t,a,n,s,r,o)=>{const i=await this.#i(e.messages??[],a,n),c=await this.#c(t,e,i,a,n,s,r,o);return c&&await this.#l({apiOperationKey:c.key,operation:e,descriptionUniqueKey:n,description:a,descriptionVersion:s,parentRevision:r}),c?.key??null};#i=async(e,t,a)=>{if(!e||e.length===0)return[];const n=new Set;for(const s of e){let r=null;if("$ref"in s){const o=s.$ref.startsWith("#/channels/")?this.#e(s.$ref,t):s.$ref;if(o){const i=y(o);if(i?.componentName&&i.componentType==="messages"){const c=t.documentWithReferences.components?.messages[i.componentName];c?.payload&&"$ref"in c.payload&&c.payload.$ref&&(r=c.payload.$ref)}}}else s.payload&&"$ref"in s.payload&&s.payload.$ref&&(r=s.payload.$ref);if(r){const o=y(r);o?.componentName&&o.componentType==="schemas"&&n.add(`${a}-${f(o.componentName)}`)}}return Array.from(n)};#c=async(e,t,a,n,s,r,o,i)=>{const c={type:"api-operation",key:`${s}-${f(e)}`,title:t.title||e,summary:t.summary??"",tags:t.tags?.map(l=>l.name)??[],metadata:{method:t.action==="send"?"PUBLISH":"SUBSCRIBE",path:t.channel.address??"",payload:t.action==="receive"?a:[],responses:t.action==="send"?a:[]},version:r};try{return await this.catalogEntitiesService.createEntity({entity:c,sourceFile:n.realRelativePath,fileHash:n.hash,rbacTeams:i,source:"file",revision:o})}catch(l){return this.context.logger.warn(`Failed to create API operation entity for ${e}: ${l instanceof Error?l.message:"Unknown error"}`),null}};#l=async({apiOperationKey:e,operation:t,descriptionUniqueKey:a,description:n,descriptionVersion:s,parentRevision:r})=>(await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:a,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r}),await this.#h(t,e,n,s,r),!Array.isArray(t.messages)||!t.messages?.length?[]:await this.#m(t.messages,e,n,a,s,r));#h=async(e,t,a,n,s)=>{e["x-catalog-relations"]?.length&&await p(e["x-catalog-relations"],u,async r=>{try{this.validateEntityRelationFileSchema(r),await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:r.type,targetKey:r.key,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:n,targetVersion:"",sourceRevision:s,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${t} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})};#m=async(e,t,a,n,s,r)=>e.length===0?[]:(await p(e,u,async i=>await this.#f(i,t,a,n,s,r)??"")).filter(i=>!!i);#f=async(e,t,a,n,s,r)=>"$ref"in e?this.#y(e,t,a,n,s,r):e.payload?this.#u(e,t,a,n,s,r):null;#y=async(e,t,a,n,s,r)=>{const o=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,a):e.$ref;if(!o)return null;const i=y(o);if(!i||!i.componentName||i.componentType!=="messages")return null;const c=a.documentWithReferences.components?.messages[i.componentName];return!c?.payload||!("$ref"in c.payload)||!c.payload.$ref?null:this.#t(c.payload.$ref,t,a,n,s,r)};#e=(e,t)=>{const a=w(e);if(!a||!a.channelName||!a.messageName)return null;const n=t.documentWithReferences.channels?.[a.channelName];if(!n?.messages)return null;const s=n.messages[a.messageName];return!s||!("$ref"in s)||typeof s.$ref!="string"||!s.$ref.startsWith("#/components/messages/")?null:s.$ref};#u=async(e,t,a,n,s,r)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,t,a,n,s,r);#t=async(e,t,a,n,s,r)=>{const o=y(e);if(!o||!o.componentName||o.componentType!=="schemas")return null;const i=`${n}-${f(o.componentName)}`;return await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:i,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r}),i}}export{M as AsyncApiEntitiesExtractor};
@@ -1,10 +1,10 @@
1
- import { type EntityFileSchema } from '@redocly/config';
2
1
  import type { AfterRoutesCreatedActions, FileInfo, LifecycleContext } from '../../../../../types';
3
2
  import type { CatalogEntitiesService } from '../../../database/catalog-entities-service.js';
4
3
  import type { BaseEntitiesExtractor } from '../base';
5
4
  import type { FileType } from '../../../../../persistence/file-hashes/types.js';
6
5
  import type { HashManager } from '../../../utils/hash-manager.js';
7
6
  import type { BaseApiEntitiesExtractorParams, SpecType } from '../../../types/extractors.js';
7
+ import type { EntityDtoSchema } from '../../../schemas/dto-schemas.js';
8
8
  export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition extends Pick<FileInfo, 'realRelativePath' | 'relativePath' | 'isVirtual' | 'hash'>> implements BaseEntitiesExtractor {
9
9
  #private;
10
10
  protected type: "api-description";
@@ -32,7 +32,7 @@ export declare abstract class BaseApiEntitiesExtractor<BundledApiDefinition exte
32
32
  extensionPattern?: RegExp;
33
33
  }): string;
34
34
  protected abstract loadApiDescriptions(): Promise<BundledApiDefinition[]>;
35
- protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string): EntityFileSchema;
35
+ protected abstract mapApiDescriptionToEntity(definition: BundledApiDefinition, version: string, revision?: string): EntityDtoSchema;
36
36
  protected abstract processApiDescription(definition: BundledApiDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
37
37
  }
38
38
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
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)){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&&(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)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
+ import{entityRelationFileSchema as P}from"@redocly/config";import{removeLeadingSlash as _}from"@redocly/theme/core/utils";import{toKebabCase as R}from"../../../../../../utils/string/to-kebab-case.js";import{FileHashStatus as g}from"../../../../../persistence/file-hashes/types.js";import{promiseMapLimit as w}from"../../../../../utils/async/promise-map-limit.js";import{OPERATORS as A}from"../../../../../providers/database/pagination/constants.js";import{VERSION_NOT_SPECIFIED as T}from"@redocly/theme/core/constants";import{getRbacTeamsListForResource as F}from"../../../../../utils/rbac.js";import{envConfig as u}from"../../../../../config/env-config.js";import{resolveEntityVersion as S}from"../../../utils/resolve-entity-version.js";import{catalogDataCollector as p}from"../../../utils/catalog-data-collector.js";import{createValidator as D}from"../../../utils/ajv-validator.js";const H=15,C=200,O=500;class z{type="api-description";specType;fileType;actions;context;catalogEntitiesService;fileHashManager;entitySources={};#e;constructor(i,e){this.specType=i,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 i=await this.loadApiDescriptions(),e=await this.fileHashManager.getStatusSnapshot(this.fileType);await this.fileHashManager.markAllAsOutdated(this.fileType),i.length&&p.addExtractor(this.specType);const a=this.#s(i),t={skipped:0,fileHashMissing:0,fileHashMismatch:0,shouldCalculateFlag:0,forceRevalidateFlag:0,previouslyUnconfirmed:0},o=[],r=new Set;await w(Array.from(a.values()),H,async c=>{for(const{description:s,version:l}of c)try{const n=s.hash;if(!n)continue;r.add(s.realRelativePath);const h=await this.fileHashManager.getByPath(s.realRelativePath),m=h?.hash!==n,v=e.get(s.realRelativePath),E=v!==void 0&&v!==g.UP_TO_DATE,f=this.#i({fileHashChanged:m,hasExistingHashRecord:!!h,previouslyUnconfirmed:E});if(!(f!==null)){t.skipped++,p.increaseSkippedFilesCount(),await this.fileHashManager.upsert(this.fileType,s.realRelativePath,n,g.UP_TO_DATE);continue}f&&t[f]++,f==="fileHashMismatch"&&h&&o.length<3&&o.push({path:s.realRelativePath,stored:h.hash,incoming:n});const d=await this.catalogEntitiesService.getEntityKeysAndVersionsBySourceFile(s.realRelativePath);await this.#a(d);const y=new Date().toISOString();await this.processApiDescription(s,y,l,d),(m||E||u.FORCE_CATALOG_CACHE_REVALIDATE)&&p.markSourceFileAsChanged(s.realRelativePath),await this.#r(d,s.realRelativePath,y,n),p.increaseProcessedFilesCount(),await this.fileHashManager.upsert(this.fileType,s.realRelativePath,n,g.OUTDATED),p.markFileHashPendingConfirmation({fileType:this.fileType,filePath:s.realRelativePath,hash:n})}catch(n){this.context.logger.warn(`Error extracting entities from ${this.specType} description: ${s.realRelativePath}`),this.context.logger.warn(n)}}),await this.#o(r)}#i({fileHashChanged:i,hasExistingHashRecord:e,previouslyUnconfirmed:a}){return i?e?"fileHashMismatch":"fileHashMissing":a?"previouslyUnconfirmed":this.#e?"shouldCalculateFlag":u.FORCE_CATALOG_CACHE_REVALIDATE?"forceRevalidateFlag":null}#a=async i=>{u.FORCE_CATALOG_CACHE_REVALIDATE&&(await this.catalogEntitiesService.deleteEntities({field:"key",operator:"in",value:Array.from(i).map(e=>e.split(":")[0])}),i.clear())};#t=async i=>{let e=0,a=0;for(;;){const t=await this.catalogEntitiesService.getEntities({paginationParams:{limit:O,filter:i}});if(!t||t.items.length===0)break;await this.catalogEntitiesService.deleteEntities({field:"id",operator:"in",value:t.items.map(({id:o})=>o)}),e+=t.items.length,a+=1}return{total:e,pages:a}};#s(i){const e=new Map;for(const a of i)if(!(a.isVirtual||!a.hash))try{const t=this.#n(a),o=this.mapApiDescriptionToEntity(a,t),r=e.get(o.key)??[];r.push({description:a,version:t}),e.set(o.key,r)}catch(t){this.context.logger.warn(`Error resolving entity key for ${this.specType} description (skipping): ${a.realRelativePath}`),this.context.logger.warn(t)}return e}#o=async i=>{const e=await this.fileHashManager.getAllOutdated(this.fileType);if(!e||e.length===0)return;const a=e.filter(({filePath:l})=>!i.has(l));if(a.length===0)return;a.forEach(({filePath:l})=>{p.markSourceFileAsRemoved(l)});const t=a.map(({filePath:l})=>l),{total:o,pages:r}=await this.#t({op:"AND",conditions:[{field:"source_file",operator:"in",value:t},{field:"is_current",operator:"equal",value:!0}]}),{total:c,pages:s}=await this.#t({field:"source_file",operator:"in",value:t});this.context.logger.info(`[${this.specType}] removed-files cleanup: files=${t.length} currentRevisionsDeleted=${o} currentPages=${r} orphanRevisionsDeleted=${c} orphanPages=${s} removedFiles=${t.slice(0,3).join(", ")}${t.length>3?`, +${t.length-3} more`:""}`)};#r=async(i,e,a,t)=>{if(i.size===0||u.FORCE_CATALOG_CACHE_REVALIDATE)return;const o=Array.from(i).map(r=>{const[c,s]=r.split(":");return{key:c,version:s}});for(let r=0;r<o.length;r+=C){const c=o.slice(r,r+C),s=Array.from(new Set(c.map(({key:n})=>n))),l=c.map(({key:n,version:h})=>({op:A.AND,conditions:[{field:"key",operator:"equal",value:n},{field:"version",operator:"equal",value:h}]}));await this.catalogEntitiesService.softDeleteEntitiesWithRelations({revision:a,fileHash:t,filter:{op:"AND",conditions:[{field:"key",operator:"in",value:s},{op:A.OR,conditions:l},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e},{field:"is_current",operator:"equal",value:!0}]}})}};#n(i){const e=i.document?.info?.version??i.definition?.info?.version??null,a=S(e,i.realRelativePath);return a.success?a.version??T:T}validateEntityRelationFileSchema(i){D(P,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"})(i)}getRbacTeamsForDefinition(i){const e=this.actions.getConfig().access?.rbac,a=this.actions.getRouteByFsPath(i);return F(a||{fsPath:i},e||{})}resolveEntityKey({realRelativePath:i,customKey:e,extensionPattern:a}){const t=this.#l(i,a);return typeof e=="string"&&e.trim()?R(e.trim()):t}#l(i,e){let t=_(i);for(;/^@[^/]+\//.test(t);)t=t.replace(/^@[^/]+\//,"");t=t.replace(/\/@[^/]+/g,"");const o=e?t.replace(e,""):t.replace(/\.[^.]+$/,"");return R(o.replace(/[\\/]/g,"-"))}}export{z as BaseApiEntitiesExtractor};
@@ -1,7 +1,7 @@
1
1
  import type { GraphQLSchema } from 'graphql';
2
- import type { EntityFileSchema } from '@redocly/config';
3
2
  import type { FileInfo } from '../../../../../types';
4
3
  import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
4
+ import type { EntityDtoSchema } from '../../../schemas/dto-schemas.js';
5
5
  import { BaseApiEntitiesExtractor } from './base.js';
6
6
  type GraphqlBundledDefinition = Omit<Pick<FileInfo, 'realRelativePath' | 'relativePath' | 'isVirtual' | 'hash'>, 'hash'> & {
7
7
  hash: string;
@@ -13,7 +13,7 @@ export declare class GraphqlEntitiesExtractor extends BaseApiEntitiesExtractor<G
13
13
  #private;
14
14
  constructor(params: BaseApiEntitiesExtractorParams);
15
15
  loadApiDescriptions(): Promise<GraphqlBundledDefinition[]>;
16
- mapApiDescriptionToEntity(description: GraphqlBundledDefinition, version: string): EntityFileSchema;
16
+ mapApiDescriptionToEntity(description: GraphqlBundledDefinition, version: string): EntityDtoSchema;
17
17
  processApiDescription(description: GraphqlBundledDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
18
18
  }
19
19
  export {};
@@ -1,3 +1,3 @@
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(`
1
+ import{buildSchema as O,isObjectType as g,isScalarType as I,isEnumType as P,isInterfaceType as w,isUnionType as E,isInputObjectType as S,getNamedType as u,printType as F}from"graphql";import{removeLeadingSlash as k}from"@redocly/theme/core/utils";import{toKebabCase as $}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 D}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as N}from"./base.js";const b=15,v=15,_=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class Q 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:n}=a.data,s=O(i),r=j(i);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:r,schema:s,content:i,metadata:n})}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=k(t.realRelativePath),i=t.relativePath.replace(/\.(gql|graphql)$/,""),n=this.#s(i.split("/").pop()||"GraphQL Schema"),s=this.#c(t.metadata?.tags),r=t.metadata?.["x-redocly-catalog-key"],h=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:typeof r=="string"?r:void 0,extensionPattern:/\.(gql|graphql)$/});return{type:this.type,key:h,title:n,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:n}=t;if(!n)return;const s=this.getRbacTeamsForDefinition(t.relativePath),r=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntity({entity:r,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:s,source:"file",revision:e}),i.delete(`${r.key}:${a}`),await Promise.all([this.#a(t,r.key,r.version,a,e,i,s),this.#f(t,r.key,r.version,a,e,i,s)])}#a=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=h.getTypeMap(),l=this.#n(h),o=Object.entries(c).filter(([f])=>!f.startsWith("__")&&!_.has(f)&&!l.has(f));if(o.length===0)return;const p=await R(o,v,async([f,m])=>{const y=await this.#l({typeName:f,type:m,description:t,parentKey:e,parentVersion:a,parentRevision:n,rbacTeams:r});s.delete(`${y?.key}:${i}`),y&&await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"uses",targetKey:y.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:n,targetRevision:n})},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:n})};#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}-${$(t)}`;#r=t=>g(t)?"object":w(t)?"interface":E(t)?"union":P(t)?"enum":S(t)?"input":I(t)?"scalar":"unknown";#n=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const i=t.getMutationType();i&&e.add(i.name);const n=t.getSubscriptionType();return n&&e.add(n.name),e};#i(t){const e=[],a=t.getQueryType();if(a){const s=a.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"QUERY",rootTypeName:a.name})}const i=t.getMutationType();if(i){const s=i.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"MUTATION",rootTypeName:i.name})}const n=t.getSubscriptionType();if(n){const s=n.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"SUBSCRIBE",rootTypeName:n.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const s of t.args){const r=u(s.type);r&&!r.name.startsWith("__")&&a.push(this.#e(r.name,e))}const i=[],n=u(t.type);return n&&!n.name.startsWith("__")&&i.push(this.#e(n.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:n,parentRevision:s,rbacTeams:r})=>{const h=this.#e(t,i),c=e.description??null,l=this.#r(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:n};try{return await this.catalogEntitiesService.createEntity({entity:o,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:r,source:"file",revision:s})}catch(p){return this.#t.warn(`Failed to create data schema entity for ${t}: ${p instanceof Error?p.message:"Unknown error"}`),null}};#h=(t,e)=>{const a=new Set,i=[],n=new Set(["String","ID","Int","Float","Boolean"]),s=c=>{if(!c)return;const l=c.name;if(l.startsWith("__")||n.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(w(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}else if(E(c))for(const l of c.getTypes())s(l);else if(S(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}}const r=[t.name,...[...a].filter(c=>c!==t.name)],h=[];for(const c of r){const l=e.getType(c);l&&h.push(F(l))}return h.join(`
2
2
 
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};
3
+ `)};#p=async({description:t,descriptionUniqueKey:e,userTypes:a,parentRevision:i})=>{const n=a.filter(([,s])=>g(s));n.length!==0&&await T(n,v,async([s,r])=>{const c=r.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.createEntityRelation({sourceKey:l,type:"implements",targetKey:p,sourceFile:t.realRelativePath,fileHash:t.hash,sourceRevision:i,targetRevision:i})}catch(f){this.#t.warn(`Failed to create 'implements' relation ${l} -> ${p}: ${f instanceof Error?f.message:"Unknown error"}`)}})})};#f=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=this.#i(h);if(c.length===0)return;const o=(await R(c,b,async({fieldName:p,field:f,operationType:m,rootTypeName:y})=>{const d=await this.#y(p,f,m,y,t,e,a,n,r);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}`)};#y=async(t,e,a,i,n,s,r,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:n,descriptionUniqueKey:s,descriptionVersion:r,parentRevision:h,rbacTeams:c});return p&&await this.#m({apiOperationKey:p.key,inputTypes:l,returnTypes:o,descriptionUniqueKey:s,description:n,descriptionVersion:r,parentRevision:h}),p?.key??null};#u=async({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:n,returnTypes:s,description:r,descriptionUniqueKey:h,descriptionVersion:c,parentRevision:l,rbacTeams:o})=>{const p=t,m={type:"api-operation",key:`${h}-${$(`${a.toLowerCase()}-${t}`)}`,title:p,summary:e.description?D(e.description):null,tags:["graphql"],metadata:{method:a,path:`${i}.${t}`,payload:n,responses:s},version:c};try{return await this.catalogEntitiesService.createEntity({entity:m,sourceFile:r.realRelativePath,fileHash:r.hash,rbacTeams:o,source:"file",revision:l})}catch(y){return this.#t.warn(`Failed to create API operation entity for ${p}: ${y instanceof Error?y.message:"Unknown error"}`),null}};#m=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:i,description:n,descriptionVersion:s,parentRevision:r})=>{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"partOf",targetKey:i,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r});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,b,async({key:o,relationType:p})=>{try{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:p,targetKey:o,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r})}catch(f){this.#t.warn(`Failed to create relation between operation ${t} and type ${o} (${p}): ${f instanceof Error?f.message:"Unknown error"}`)}})}}export{Q as GraphqlEntitiesExtractor};
@@ -1,12 +1,12 @@
1
- import { type EntityFileSchema } from '@redocly/config';
2
1
  import type { BundledDefinition } from '../../../../openapi-docs/load-definition';
3
2
  import type { BaseApiEntitiesExtractorParams } from '../../../types/extractors.js';
3
+ import type { EntityDtoSchema } from '../../../schemas/dto-schemas';
4
4
  import { BaseApiEntitiesExtractor } from './base.js';
5
5
  export declare class OpenApiEntitiesExtractor extends BaseApiEntitiesExtractor<BundledDefinition> {
6
6
  #private;
7
7
  constructor(params: BaseApiEntitiesExtractorParams);
8
8
  loadApiDescriptions(): Promise<BundledDefinition[]>;
9
- mapApiDescriptionToEntity(description: BundledDefinition, version: string): EntityFileSchema;
9
+ mapApiDescriptionToEntity(description: BundledDefinition, version: string): EntityDtoSchema;
10
10
  processApiDescription(description: BundledDefinition, revision: string, version: string, entitiesToRemoveFromFile: Set<string>): Promise<void>;
11
11
  }
12
12
  //# sourceMappingURL=openapi-entities-extractor.d.ts.map
@@ -1 +1 @@
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
+ import{REDOCLY_TEAMS_RBAC as $}from"@redocly/config";import{removeLeadingSlash as x}from"@redocly/theme/core/utils";import{toKebabCase as y}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as N}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 b}from"./base.js";import{OpenapiSchemaResolver as S}from"../../../utils/openapi-schema-resolver.js";import{extractPartsFromComponentsRef as k}from"../../../utils/extract-parts-from-components-ref.js";import{isValidTagName as v}from"../../../utils/is-valid-tag-name.js";const A=["get","post","put","delete","patch"],O=15,T=15;class _ extends b{#e;constructor(e){super("openapi",e),this.#e=e.context.logger}async loadApiDescriptions(){return await this.actions.loadOpenApiDefinitions(this.context)}mapApiDescriptionToEntity(e,n){const r=x(e.realRelativePath),s=e.definition.info.title,t=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.definition["x-redocly-catalog-key"]});return{type:this.type,key:t,title:s,summary:w(e.definition.info.description),tags:e.definition.tags?.filter(a=>a.name&&v(a.name)).map(a=>a.name),metadata:{specType:this.specType,descriptionFile:r},version:n}}async processApiDescription(e,n,r,s){if(S.clearSchemaCache(),!e?.definition?.paths)return;const t=this.getRbacTeamsForDefinition(e.relativePath),a=this.mapApiDescriptionToEntity(e,r);await this.catalogEntitiesService.createEntity({entity:a,sourceFile:e.realRelativePath,fileHash:e.hash,source:"file",isRootEntity:!0,rbacTeams:t,revision:n}),s.delete(`${a.key}:${r}`),await this.#s(e,a.key,a.version,r,n,s,t);const o=this.#r(e.definition.paths);if(o.length!==0){const c=(await N(o,O,async({operation:m,path:h,method:l})=>{if(!m.operationId)return;const f=await this.#n(m,h,l,e,a.key,a.version,n,t);f&&s.delete(`${f}:${r}`)},this.#e)).count.failed;c>0&&this.#e.warn(`Extraction completed with ${c} failures out of ${o.length} operations for ${a.key}`)}}#r(e){return Object.entries(e).flatMap(([n,r])=>A.filter(s=>r[s]).map(s=>{const t=r[s];if(!t)throw new Error(`Operation not found for method ${s} on path ${n}`);return{operation:t,path:n,method:s.toUpperCase()}}))}async#s(e,n,r,s,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([m,h])=>{const l=await this.#o({schemaName:m,schema:h,description:e,parentKey:n,parentVersion:r,parentRevision:t,rbacTeams:o});a.delete(`${l?.key}:${s}`),l&&await this.catalogEntitiesService.createEntityRelation({sourceKey:n,sourceVersion:r,sourceRevision:t,type:"uses",targetKey:l.key,targetVersion:r,targetRevision:t,sourceFile:e.realRelativePath,fileHash:e.hash})})}async#o({schemaName:e,schema:n,description:r,parentKey:s,parentVersion:t,parentRevision:a,rbacTeams:o}){const i=S.resolveSchemaRefs(n,r),c=JSON.stringify(i),m=i[$]?R(i[$]):o,h=R(i["x-rbac"]),l={type:"data-schema",key:`${s}-${y(e)}`,title:e,summary:i.description??i.title??null,tags:[],metadata:{specType:this.specType,schema:c},version:t};try{return await this.catalogEntitiesService.createEntity({entity:l,sourceFile:r.realRelativePath,fileHash:r.hash,rbacTeams:h.length?h:m,source:"file",revision:a})}catch(f){return this.#e.error(`Failed to create data schema entity for ${e}: ${f instanceof Error?f.message:"Unknown error"}`),null}}async#n(e,n,r,s,t,a,o,i){const c=await Promise.all([this.#h(e.requestBody??null,s),this.#m(e.responses??{},s)]),m=c[0].schemaNames,h=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=m.map(u=>`${t}-${y(u)}`),f=h.map(u=>`${t}-${y(u)}`),p=await this.#f({path:n,method:r,operation:e,requestBodySchemasKeys:l,responseSchemasKeys:f,description:s,parentKey:t,parentVersion:a,parentRevision:o,rbacTeams:i});return p&&await Promise.all([this.#i(m,e.operationId??"",s.realRelativePath,s.hash,t,a,o),this.#c(h,e.operationId??"",s.realRelativePath,s.hash,t,a,o),this.#p({apiOperationKey:p.key,operationRelations:e["x-catalog-relations"],descriptionUniqueKey:t,description:s,parentVersion:a,parentRevision:o})]),p?.key??null}async#i(e,n,r,s,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,r,s,t,a,o)}async#c(e,n,r,s,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,r,s,t,a,o)}#h(e,n){const r=[],s=[];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&&r.push(a.componentName)}if(e&&e.$ref){const t=this.#t(e.$ref);if(t?.componentType==="requestBodies"&&t.componentName){const a=n.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&&r.push(i.componentName)}}}}catch(t){s.push(`Failed to extract request body schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(r)],errors:s}}#m(e,n){const r=[],s=[];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&&r.push(o.componentName)}if(t&&t.$ref){const a=this.#t(t.$ref);if(a?.componentType==="responses"&&a.componentName){const o=n.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&&r.push(c.componentName)}}}}}catch(t){s.push(`Failed to extract response schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(r)],errors:s}}#t(e){try{return k(e)}catch{return{componentType:"",componentName:null}}}async#a(e,n,r,s,t,a,o){return e.length===0?[]:await E(e,T,async i=>await this.#l({operationId:n,schemaName:i,descriptionSourceFile:r,descriptionHash:s,parentKey:t,parentVersion:a,parentRevision:o}))}async#l({operationId:e,schemaName:n,descriptionSourceFile:r,descriptionHash:s,parentKey:t,parentVersion:a,parentRevision:o}){const i=`${t}-${y(n)}`;try{return await this.catalogEntitiesService.createEntityRelation({sourceKey:`${t}-${y(e)}`,type:"uses",targetKey:i,sourceFile:r,fileHash:s,sourceVersion:a,targetVersion:a,sourceRevision:o,targetRevision:o}),i}catch(c){throw this.#e.error(`Failed to create relation between operation ${e} and schema ${n}: ${c instanceof Error?c.message:"Unknown error"}`),c}}async#f({path:e,method:n,operation:r,requestBodySchemasKeys:s,responseSchemasKeys:t,description:a,parentKey:o,parentVersion:i,parentRevision:c,rbacTeams:m}){const h=`${r.operationId}`,l=`${o}-${y(h)}`,f=r[$]?R(r[$]):m,p=R(r["x-rbac"]),u={type:"api-operation",key:l,title:h,summary:w(r.summary),tags:r.tags?.filter(g=>v(g)),metadata:{path:e,method:n,payload:s,responses:t},version:i};try{return await this.catalogEntitiesService.createEntity({entity:u,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:p.length>0?p:f,source:"file",revision:c})}catch(g){return this.#e.error(`Failed to create API operation entity for ${h}: ${g instanceof Error?g.message:"Unknown error"}`),null}}async#p({apiOperationKey:e,operationRelations:n,descriptionUniqueKey:r,description:s,parentVersion:t,parentRevision:a}){try{await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:r,sourceFile:s.realRelativePath,fileHash:s.hash,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),await this.#y(e,s,n,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,n,r,s,t){r?.length&&await E(r,O,async a=>{try{this.validateEntityRelationFileSchema(a),await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:a.type,targetKey:a.key,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:"",sourceRevision:t,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${e} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})}}export{_ as OpenApiEntitiesExtractor};
@@ -1 +1 @@
1
- import{CATALOG_ENTITIES_FILES_REGEX as E,ENTITY_SCHEMA_EXCLUDED_FOLDERS as d}from"../../../../constants/plugins/catalog-entities.js";import{FileHashStatus as l,FileType as a}from"../../../../persistence/file-hashes/types.js";import{OPERATORS as u}from"../../../../providers/database/pagination/constants.js";import{promiseMapLimit as m}from"../../../../utils/async/promise-map-limit.js";import{VERSION_NOT_SPECIFIED as p}from"@redocly/theme/core/constants";import{parseEntities as h}from"../../../../web-server/routes/catalog/parsers/entities/parse-entities.js";import{envConfig as g}from"../../../../config/env-config.js";import{extractFileContent as y}from"../../entities/extract-file-content.js";import{resolveEntityVersion as I}from"../../utils/resolve-entity-version.js";import{catalogDataCollector as f}from"../../utils/catalog-data-collector.js";const T=15;class ${#t;#e;#i;#r;#s;constructor({fileHashManager:e,context:t,catalogEntitiesService:i,catalogConfig:o,shouldCalculateEntities:s}){this.#t=e,this.#e=t,this.#i=i,this.#r=o,this.#s=s}async extract(e){try{if(e&&this.#o(e)){await this.#n(e);return}await this.#t.markAllAsOutdated(a.ENTITY_DEFINITION);const i=this.#e.fs.scan(E).filter(({relativePath:o})=>this.#o(o));i.length&&f.addExtractor("fs"),await m(i,T,async({relativePath:o})=>{await this.#n(o)}),await this.#f()}catch(t){this.#e.logger.error("Error extracting entities.",t)}}#o=e=>!!(e.match(E)&&!d.some(t=>e.includes(t)));#n=async e=>{try{const t=await y(e,this.#e);if(!t){this.#e.logger.warn(`Error extracting content from ${e}.`);return}const i=await this.#t.computeFileHash(t);if(!((await this.#t.getByPath(e))?.hash!==i||this.#s||g.FORCE_CATALOG_CACHE_REVALIDATE)){f.increaseSkippedFilesCount(),await this.#t.upsert(a.ENTITY_DEFINITION,e,i,l.UP_TO_DATE);return}const r=this.#a(t.entities,e);if(!r)return;const n=await this.#i.getEntityKeysAndVersionsBySourceFile(e);await this.#c(r,e,i,n),await this.#l(n,e),f.increaseProcessedFilesCount(),await this.#t.upsert(a.ENTITY_DEFINITION,e,i,l.UP_TO_DATE)}catch(t){this.#e.logger.warn(`Error processing file "${e}". ${t instanceof Error?t.message:String(t)}.`)}};#a=(e,t)=>{try{return h(e,this.#r)}catch(i){return this.#e.logger.warn(`Error validating entities in "${t}". ${i instanceof Error?i.message:String(i)}.`),null}};#c=async(e,t,i,o)=>{for(const s of e)try{const r=I(s.version,t);if(!r.success){this.#e.logger.warn(`Entity "${s.key}" in file "${t}" has conflicting versions: file version "${r.fileVersion}" differs from folder version "${r.folderVersion}". Entity will not be created.`);continue}const n={...s,version:r.version};if(await this.#i.createEntityInLocalDatabase({entity:n,sourceFile:t,fileHash:i}),s.key){const c=r.version??p;o.delete(`${s.key}:${c}`)}}catch(r){const n=s.key??"unknown";this.#e.logger.warn(`Error processing entity "${n}" from "${t}". ${r instanceof Error?r.message:String(r)}.`)}};#l=async(e,t)=>{if(e.size===0)return;const i=Array.from(e).map(r=>{const[n,c]=r.split(":");return{key:n,version:c}}),o=Array.from(new Set(i.map(({key:r})=>r))),s=i.map(({key:r,version:n})=>({op:u.AND,conditions:[{field:"key",operator:"equal",value:r},{field:"version",operator:"equal",value:n}]}));await this.#i.deleteEntitiesInLocalDatabase({op:"AND",conditions:[{field:"key",operator:"in",value:o},{op:u.OR,conditions:s},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:t}]})};#f=async()=>{const e=await this.#t.getAllOutdated(a.ENTITY_DEFINITION);if(!e||e.length===0)return;const t=await this.#i.getEntities({paginationParams:{limit:1e3,filter:{op:"AND",conditions:[{field:"source_file",operator:"in",value:e.map(({filePath:i})=>i)},{field:"is_current",operator:"equal",value:!0}]}}});!t||t.items.length===0||(await this.#i.deleteEntitiesInLocalDatabase({field:"key",operator:"in",value:t.items.map(({key:i})=>i)}),await this.#t.deleteFileHashes({op:"AND",conditions:[{field:"file_type",operator:"equal",value:a.ENTITY_DEFINITION},{field:"status",operator:"equal",value:l.OUTDATED}]}))}}export{$ as FsEntitiesExtractor};
1
+ import{CATALOG_ENTITIES_FILES_REGEX as u,ENTITY_SCHEMA_EXCLUDED_FOLDERS as m}from"../../../../constants/plugins/catalog-entities.js";import{FileHashStatus as f,FileType as a}from"../../../../persistence/file-hashes/types.js";import{OPERATORS as d}from"../../../../providers/database/pagination/constants.js";import{promiseMapLimit as h}from"../../../../utils/async/promise-map-limit.js";import{VERSION_NOT_SPECIFIED as p}from"@redocly/theme/core/constants";import{parseEntities as g}from"../../../../web-server/routes/catalog/parsers/entities/parse-entities.js";import{envConfig as T}from"../../../../config/env-config.js";import{extractFileContent as y}from"../../entities/extract-file-content.js";import{resolveEntityVersion as I}from"../../utils/resolve-entity-version.js";import{catalogDataCollector as l}from"../../utils/catalog-data-collector.js";const F=15;class ${#t;#e;#i;#r;#o;#s=new Map;constructor({fileHashManager:t,context:e,catalogEntitiesService:s,catalogConfig:o,shouldCalculateEntities:r}){this.#t=t,this.#e=e,this.#i=s,this.#r=o,this.#o=r}async extract(t){try{if(t&&this.#n(t)){this.#s=await this.#t.getStatusSnapshot(a.ENTITY_DEFINITION),await this.#a(t);return}this.#s=await this.#t.getStatusSnapshot(a.ENTITY_DEFINITION),await this.#t.markAllAsOutdated(a.ENTITY_DEFINITION);const s=this.#e.fs.scan(u).filter(({relativePath:r})=>this.#n(r));s.length&&l.addExtractor("fs");const o=new Set;await h(s,F,async({relativePath:r})=>{o.add(r),await this.#a(r)}),await this.#E(o)}catch(e){this.#e.logger.error("Error extracting entities.",e)}}#n=t=>!!(t.match(u)&&!m.some(e=>t.includes(e)));#a=async t=>{try{const e=await y(t,this.#e);if(!e){this.#e.logger.warn(`Error extracting content from ${t}.`);return}const s=await this.#t.computeFileHash(e),o=await this.#t.getByPath(t),r=this.#s.get(t),i=r!==void 0&&r!==f.UP_TO_DATE;if(!(o?.hash!==s||i||this.#o||T.FORCE_CATALOG_CACHE_REVALIDATE)){l.increaseSkippedFilesCount(),await this.#t.upsert(a.ENTITY_DEFINITION,t,s,f.UP_TO_DATE);return}const c=this.#c(e.entities,t);if(!c)return;const E=await this.#i.getEntityKeysAndVersionsBySourceFile(t);await this.#l(c,t,s,E),l.markSourceFileAsChanged(t),await this.#f(E,t),l.increaseProcessedFilesCount(),await this.#t.upsert(a.ENTITY_DEFINITION,t,s,f.OUTDATED),l.markFileHashPendingConfirmation({fileType:a.ENTITY_DEFINITION,filePath:t,hash:s})}catch(e){this.#e.logger.warn(`Error processing file "${t}". ${e instanceof Error?e.message:String(e)}.`)}};#c=(t,e)=>{try{return g(t,this.#r)}catch(s){return this.#e.logger.warn(`Error validating entities in "${e}". ${s instanceof Error?s.message:String(s)}.`),null}};#l=async(t,e,s,o)=>{for(const r of t)try{const i=I(r.version,e);if(!i.success){this.#e.logger.warn(`Entity "${r.key}" in file "${e}" has conflicting versions: file version "${i.fileVersion}" differs from folder version "${i.folderVersion}". Entity will not be created.`);continue}const n={...r,version:i.version};if(await this.#i.createEntity({entity:n,sourceFile:e,fileHash:s,source:"file"}),r.key){const c=i.version??p;o.delete(`${r.key}:${c}`)}}catch(i){const n=r.key??"unknown";this.#e.logger.warn(`Error processing entity "${n}" from "${e}". ${i instanceof Error?i.message:String(i)}.`)}};#f=async(t,e)=>{if(t.size===0)return;const s=Array.from(t).map(i=>{const[n,c]=i.split(":");return{key:n,version:c}}),o=Array.from(new Set(s.map(({key:i})=>i))),r=s.map(({key:i,version:n})=>({op:d.AND,conditions:[{field:"key",operator:"equal",value:i},{field:"version",operator:"equal",value:n}]}));await this.#i.deleteEntities({op:"AND",conditions:[{field:"key",operator:"in",value:o},{op:d.OR,conditions:r},{field:"source",operator:"equal",value:"file"},{field:"source_file",operator:"equal",value:e}]})};#E=async t=>{const e=await this.#t.getAllOutdated(a.ENTITY_DEFINITION);if(!e||e.length===0)return;const s=e.filter(({filePath:i})=>!t.has(i));if(s.length===0)return;s.forEach(({filePath:i})=>{l.markSourceFileAsRemoved(i)});const o=500,r=s.map(({filePath:i})=>i);for(;;){const i=await this.#i.getEntities({paginationParams:{limit:o,filter:{op:"AND",conditions:[{field:"source_file",operator:"in",value:r},{field:"is_current",operator:"equal",value:!0}]}}});if(!i||i.items.length===0)break;await this.#i.deleteEntities({field:"key",operator:"in",value:i.items.map(({key:n})=>n)})}}}export{$ as FsEntitiesExtractor};
@@ -1 +1 @@
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
+ 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 it={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:i,catalogConfig:a,queries:t={},rbacTeams:o,excludedTypes:g,excludedEntities:u,initialViewMode:p})=>{const m=await w.getInstance({baseDbDir:i}),d=I.concat("domains","owners"),s=E(d).parse(t),y=a.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:i,queries:a,rbacTeams:t,excludedTypes:o,excludedEntities:g})=>{const u=await w.getInstance({baseDbDir:i});let p=null;const m=a?.revision;m&&V(m)&&(p=m);const d=a?.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(a),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:a?.search?_(a?.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 i=JSON.stringify({entitiesTypes:e.entitiesTypes.sort(),filtersConfig:e.filtersConfig,rbacTeams:e.rbacTeams,excludedTypes:e.excludedTypes,excludedEntities:e.excludedEntities});return D(i)},K=async({serverOutDir:e,entitiesTypes:i,filtersConfig:a,rbacTeams:t,excludedTypes:o,excludedEntities:g})=>{if(!a||a.length===0)return{};const u=x({entitiesTypes:i,filtersConfig:a,rbacTeams:t,excludedTypes:o,excludedEntities:g}),p=await P.getInstance({baseDbDir:e,databaseType:"local"}),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 a)!n.options||n.options.length===0?s.push(n.property):y.set(n.property,n.options);const C=await d.getCatalogFilters({entitiesTypes:i,emptyFilters:s,rbacTeams:t,excludedTypes:o,excludedEntities:g}),l={};for(const n of a){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:i,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:i},{variables:a},{serverOutDir:t,getRouteSharedDataByFsPath:o,getConfig:g})=>{const u=i?.catalogConfig||{};if(!e.params||!i?.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,a?.rbac.teams||[]),{catalogs:n,types:c,entities:b}=O({rbacConfig:C,currentRbacTeams:a?.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,i)=>Object.values(e.catalogs??{}).find(a=>a&&typeof a=="object"&&"slug"in a&&a.slug===i),j=(e,i,a)=>Object.values(e.catalogs??{}).filter(t=>!t?.hide&&!a.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)),B=(e,i)=>({op:"AND",conditions:[...e.length?[{field:"type",operator:"in",value:e}]:[],...i.length?[{field:"key",operator:"in",value:i,modifier:"not"}]:[]]}),H=(e,i,a)=>{let t=e;if(i!==void 0){const o={field:"version",operator:"equal",value:i};t=t?{op:A.AND,conditions:[t,o]}:o}if(a){const o={field:"revision",operator:"equal",value:a};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 m}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 p}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 k(){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:p,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[n],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[u]=Object.entries(r.catalogs??{}).find(([s,i])=>!i?.hide)||[];u&&t.addRedirect(p,{type:302,to:`${p}/${u}`},{trackOriginalSource:!1}),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,u=!I(d,r.access?.rbac);d=r.access?.rbac;const s=g||u,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:m.OPENAPI_DESCRIPTION,shouldCalculateEntities:s}),new w({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:m.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:s}),new R({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:m.GRAPHQL_DESCRIPTION,shouldCalculateEntities:s}),new G({actions:t,context:e,catalogEntitiesService:i,fileHashManager:l,fileType:m.ARAZZO_DESCRIPTION,shouldCalculateEntities:s})];n.info("Starting entities extractors...");const y=n.startTiming();await i.transaction(async()=>{await Promise.all(T.map(async h=>h.extract()))});const S=i.getEntitySources();t.setGlobalData({[_]:S}),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=k;export{k as catalogEntitiesPlugin,ot as default};
1
+ import{FileHashStatus as A,FileType as m}from"../../persistence/file-hashes/types.js";import{envConfig as N}from"../../config/env-config.js";import{CATALOG_BASE_SLUG as h}from"../../../constants/catalog-entities.js";import{telemetryTraceStep as H}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as f}from"./utils/catalog-data-collector.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as L,ENTITIES_MAP_GLOBAL_DATA_KEY as x}from"../../constants/plugins/catalog-entities.js";import{CacheService as G}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as b}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as y}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as B}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as M}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as k}from"../../persistence/file-hashes/services/file-hashes-service.js";import{CatalogEntitiesService as Y}from"./database/catalog-entities-service.js";import{CatalogEntitiesPublisher as j}from"./database/catalog-entities-publisher.js";import{ArazzoEntitiesExtractor as q}from"./extensions/extractors/api-description/arazzo-entities-extractor.js";import{FsEntitiesExtractor as z}from"./extensions/extractors/fs-entities-extractor.js";import{HashManager as U}from"./utils/hash-manager.js";import{RbacConfigHashCache as W}from"./utils/rbac-config-hash-cache.js";import{OpenApiEntitiesExtractor as J}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const Z="catalog-entity-template",$="catalog-entity";let D=!0;async function K(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const i=await e.getConfig(),r=y(i.entitiesCatalog);if(!r.show)return;const{logger:o}=e,a=t.registerServerPropsGetter($,b("../get-server-props.js")),g=t.createTemplate(Z,b("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:h,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[a],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[n]=Object.entries(r.catalogs??{}).find(([T,p])=>!p?.hide)||[];n&&t.addRedirect(h,{type:302,to:`${h}/${n}`},{trackOriginalSource:!1}),o.info("Catalog Entities plugin finished")},async afterRoutesCreated(t,e){await H("build.plugin.catalog_entities",async i=>{const r=await e.getConfig(),o=y(r.entitiesCatalog);if(i?.setAttribute("config",JSON.stringify(o)),!o.show)return;const{logger:a}=e;f.resetForRun();const g=D&&N.isDevelopMode,n=await G.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),T=new W(n),{rbacConfigChanged:p}=await T.syncAndDetectChange(r.access?.rbac??null),l=g||p,s=await Y.getInstance({baseDbDir:t.serverOutDir,removeExisting:g,databaseType:"local",runWithPragmaWalWriteOptimization:!0}),E=await k.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),c=new U(E),S=[new z({fileHashManager:c,context:e,catalogEntitiesService:s,catalogConfig:o,shouldCalculateEntities:l}),new J({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:m.OPENAPI_DESCRIPTION,shouldCalculateEntities:l}),new B({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:m.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:l}),new M({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:m.GRAPHQL_DESCRIPTION,shouldCalculateEntities:l}),new q({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:m.ARAZZO_DESCRIPTION,shouldCalculateEntities:l})];a.info("Starting entities extractors...");const P=a.startTiming();await s.transaction(async()=>{await Promise.all(S.map(async C=>C.extract()))});const O=s.getEntitySources();t.setGlobalData({[x]:O}),await n.deleteByNamespace(L),a.infoTime(P,"Entities extractors finished");const{changedSourceFiles:w,removedSourceFiles:d}=f.getPublishDelta(),v=a.startTiming(),I=await j.publishFromLocalToRemote(p?{baseDbDir:t.serverOutDir}:{baseDbDir:t.serverOutDir,changedSourceFiles:w,removedSourceFiles:d});a.infoTime(v,"Entities published to the database"),d.length&&await E.deleteFileHashes({op:"AND",conditions:[{field:"status",operator:"equal",value:A.OUTDATED},{field:"file_path",operator:"in",value:d}]});const _=f.getFileHashConfirmations();for(const{fileType:C,filePath:R,hash:F}of _)await E.upsertFileHash({fileType:C,filePath:R,hash:F,status:A.UP_TO_DATE});I||a.warn("Local catalog extraction completed, but publish to remote was skipped because remote connection is unavailable.");const u=await f.getCatalogEntitiesData(s);i?.setAttribute("totalEntities",u.totalEntitiesCount),i?.setAttribute("entitiesCountByType",JSON.stringify(u.countOfEntitiesByType)),i?.setAttribute("totalFilesSkippedByHash",u.totalFilesSkippedByHash),i?.setAttribute("totalProcessedFiles",u.totalProcessedFiles),i?.setAttribute("extractors",u.extractors),D=!1})}}}var dt=K;export{K as catalogEntitiesPlugin,dt as default};