@redocly/revel-reef 0.130.0-next.6 → 0.130.0-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -5
- package/dist/cli/telemetry/index.d.ts +1 -1
- package/dist/client/browser-entry.js +3 -3
- package/dist/constants/common.d.ts +2 -1
- package/dist/constants/common.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/persistence/kv/repositories/kv-remote-repository.js +2 -2
- package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +5 -6
- package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-db-record.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +27 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +36 -0
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +30 -23
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +3 -2
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +23 -12
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +6 -4
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.d.ts +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +2 -5
- package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.d.ts +34 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.js +13 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.d.ts +23 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js +1 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.d.ts +78 -0
- package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.js +34 -0
- package/dist/server/plugins/catalog-entities/entities/validate-entity.d.ts +3 -1
- package/dist/server/plugins/catalog-entities/entities/validate-entity.js +1 -1
- package/dist/server/plugins/catalog-entities/plugin.js +1 -1
- package/dist/server/plugins/catalog-entities/schemas/dto-schemas.d.ts +3 -1
- package/dist/server/plugins/catalog-entities/utils/ajv-validator.js +1 -1
- package/dist/server/plugins/scorecard-classic/loaders/scorecard-config.js +1 -1
- package/dist/server/plugins/scorecards/database/scorecards-config-service.d.ts +1 -1
- package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -1
- package/dist/server/plugins/scorecards/workers/run-scorecards-worker.js +1 -1
- package/dist/server/plugins/scorecards/workers/scorecards.d.ts +1 -14
- package/dist/server/plugins/scorecards/workers/scorecards.js +1 -1
- package/dist/server/providers/database/pagination/entities-to-filter.d.ts +15 -0
- package/dist/server/providers/database/pagination/entities-to-filter.js +1 -0
- package/dist/server/providers/database/pagination/utils/index.d.ts +4 -0
- package/dist/server/providers/database/pagination/utils/index.js +1 -1
- package/dist/server/providers/database/pagination/utils/is-nested-condition.d.ts +16 -0
- package/dist/server/providers/database/pagination/utils/is-nested-condition.js +1 -0
- package/dist/server/providers/database/pagination/utils/is-simple-condition.d.ts +18 -0
- package/dist/server/providers/database/pagination/utils/is-simple-condition.js +1 -0
- package/dist/server/providers/database/pagination/utils/map-operator.d.ts +10 -0
- package/dist/server/providers/database/pagination/utils/map-operator.js +1 -0
- package/dist/server/providers/database/pagination/utils/transform-condition.d.ts +12 -0
- package/dist/server/providers/database/pagination/utils/transform-condition.js +1 -0
- package/dist/server/types/plugins/scorecards.d.ts +30 -0
- package/dist/server/types/plugins/scorecards.js +0 -0
- package/dist/server/web-server/routes/catalog/catalog.js +1 -1
- package/dist/server/workers/types.d.ts +1 -1
- package/package.json +11 -14
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import{and as
|
|
1
|
+
import{and as c,count as v,eq as u,isNotNull as D,notExists as y,or as $,sql as e}from"drizzle-orm";import{unionAll as f}from"drizzle-orm/sqlite-core";import{logger as F}from"../../../../../tools/notifiers/logger.js";import{VERSION_NOT_SPECIFIED as A}from"@redocly/theme/core/constants";import{applyPagination as S}from"../../../../../providers/database/pagination/index.js";import{applyFilter as B}from"../../../../../providers/database/pagination/filter.js";import{FIELDS_TO_SELECT_FOR_ENTITY as _,FIELDS_TO_SELECT_FOR_ENTITY_RELATION as m}from"../utils.js";import{createEntityReadModel as k}from"../../mappers/create-entity-read-model.js";import{createEntityRelation as C}from"../../mappers/create-entity-relation.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as E}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{CatalogEntitiesRelationsRepository as I}from"./catalog-entities-relations-repository.js";import{CatalogEntitiesBffRepository as g}from"./catalog-entities-bff-repository.js";import{createMergedEntityFieldsForSelect as b}from"../utils/create-merged-entity-fields-for-select.js";import{buildSemanticVersionSortExpr as L}from"../utils/semantic-version-sort.js";import{normalizeRevisionFlags as M}from"../utils/normalize-revision-flags.js";class te{#e;#t=void 0;#i;#r;constructor(t){this.#e=t,this.#i=new I(this.#e,this.#t||""),this.#r=new g(this.#e,this.#t||"")}async attachDatabase(t){this.#t!==t&&(this.#t=t,await this.#e.client.run(e`ATTACH DATABASE ${t} AS remote`),this.#i=new I(this.#e,t),this.#r=new g(this.#e,t))}async getEntities(t={}){const r=this.#t?f(this.#e.client.select(_).from(e`remote.entities`).where(y(this.#e.client.select({id:_.id}).from(i).where(c(e`${i.key} = remote.entities.key`,e`${i.version} = remote.entities.version`,e`${i.revision} = remote.entities.revision`)))),this.#e.client.select(_).from(i).where(y(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as r`).where(c(e`r.key = ${i.key}`,e`r.version = ${i.version}`,e`r.revision = ${i.revision}`)))),this.#e.client.select(b("r","l")).from(e`remote.entities as r`).innerJoin(e`entities as l`,e`l.key = r.key AND l.version = r.version AND l.revision = r.revision`)):this.#e.client.select(_).from(i),s=this.#e.client.select(_).from(r.as("combined_entities")),n=this.#e.client.select(_).from(r.as("combined_entities")).$dynamic(),d=S(n,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),l=this.#e.client.$count(d),a=s.$dynamic(),o=t.limit||10,h=S(a,{...t,limit:o+1}),[N,p]=await Promise.all([h.run(),l]),w=N.rows,T=w.length>o;return{items:w.slice(0,o).map(R=>k(R)).filter(R=>R!==null),hasMore:T,total:p}}async getEntityKeysAndVersionsBySourceFile(t){const r=this.#t?f(this.#e.client.select({keyVersion:e`key || ':' || COALESCE(version, ${A})`.as("keyVersion")}).from(e`remote.entities`).where(c(e`source_file = ${t}`,e`source = 'file'`,e`key IS NOT NULL`)),this.#e.client.select({keyVersion:e`${i.key} || ':' || COALESCE(${i.version}, ${A})`.as("keyVersion")}).from(i).where(c(u(i.sourceFile,t),u(i.source,"file"),e`${i.key} IS NOT NULL`,y(this.#e.client.select({key:e.raw("key")}).from(e`remote.entities as remote`).where(e`remote.key = ${i.key}`))))):this.#e.client.select({keyVersion:e`${i.key} || ':' || COALESCE(${i.version}, ${A})`.as("keyVersion")}).from(i).where(c(u(i.sourceFile,t),u(i.source,"file"),D(i.key))),s=await this.#e.client.selectDistinct({keyVersion:e`combined_keys_versions.keyVersion`}).from(r.as("combined_keys_versions")).run();return new Set(s.rows.map(n=>n.keyVersion))}async listEntityRevisions(t,r){const s=[u(i.key,t),u(i.isDeleted,!1),...r?[u(i.version,r)]:[]],n={version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")},d=this.#t?f(this.#e.client.select(n).from(e`remote.entities`).where(c(e`key = ${t}`,e`is_deleted = 0`,r?e`version = ${r}`:void 0,y(this.#e.client.select({id:e.raw("id")}).from(i).where(c(e`${i.key} = remote.entities.key`,e`${i.version} = remote.entities.version`,e`${i.revision} = remote.entities.revision`))))),this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).where(c(...s,y(this.#e.client.select({id:e.raw("id")}).from(e`remote.entities as r`).where(c(e`r.key = ${i.key}`,e`r.version = ${i.version}`,e`r.revision = ${i.revision}`))))),this.#e.client.select({version:e.raw("r.version AS version"),revision:e.raw("r.revision AS revision"),isCurrent:e.raw("MAX(r.is_current, l.is_current) AS is_current"),createdAt:e.raw("MIN(r.created_at, l.created_at) AS created_at"),updatedAt:e.raw("MAX(r.updated_at, l.updated_at) AS updated_at"),isDefaultVersion:e.raw("MAX(r.is_default_version, l.is_default_version) AS is_default_version")}).from(e`remote.entities as r`).innerJoin(e`entities as l`,e`l.key = r.key AND l.version = r.version AND l.revision = r.revision`).where(c(e`r.key = ${t}`,e`r.is_deleted = 0`,e`l.is_deleted = 0`,r?e`r.version = ${r}`:void 0))):this.#e.client.select({version:i.version,revision:i.revision,isCurrent:i.isCurrent,createdAt:i.createdAt,updatedAt:i.updatedAt,isDefaultVersion:i.isDefaultVersion}).from(i).where(c(...s)),a=(await this.#e.client.select({version:e.raw("version"),revision:e.raw("revision"),isCurrent:e.raw("is_current"),createdAt:e.raw("created_at"),updatedAt:e.raw("updated_at"),isDefaultVersion:e.raw("is_default_version")}).from(d.as("combined_revisions")).orderBy(e`${L("version")} DESC`,e.raw("revision DESC")).run()).rows.map(o=>({version:o.version||null,revision:o.revision??"",isCurrent:o.is_current!==null?!!o.is_current:!1,createdAt:o.created_at||null,updatedAt:o.updated_at||null,isDefaultVersion:o.is_default_version!==null?!!o.is_default_version:!1}));return M(a),a}async getEntitiesCountByTypes(){if(this.#t){const t=e`
|
|
2
|
+
SELECT key, type, version,
|
|
3
|
+
ROW_NUMBER() OVER (
|
|
4
|
+
PARTITION BY key
|
|
5
|
+
ORDER BY ${L("version")} DESC
|
|
6
|
+
) as rn
|
|
7
|
+
FROM (
|
|
8
|
+
SELECT key, type, version FROM remote.entities WHERE is_current = 1 AND is_deleted = 0
|
|
9
|
+
UNION ALL
|
|
10
|
+
SELECT key, type, version FROM entities WHERE is_current = 1 AND is_deleted = 0
|
|
11
|
+
)
|
|
12
|
+
`;return this.#e.client.select({type:e`type`,count:v()}).from(e`(SELECT * FROM (${t}) WHERE rn = 1) as highest_version_entities`).groupBy(e`type`)}return this.#e.client.select({type:i.type,count:v()}).from(i).where(c(u(i.isCurrent,!0),u(i.isDeleted,!1))).groupBy(i.type)}async getEntityById(t){const n=(await(this.#t?f(this.#e.client.select(_).from(e`remote.entities`).where(e`id = ${t}`),this.#e.client.select(_).from(i).where(u(i.id,t))):this.#e.client.select(_).from(i).where(u(i.id,t))).run()).rows[0];return n?k(n):null}async getOutdatedEntities(t){const r=this.#t?f(this.#e.client.select(_).from(e`remote.entities`),this.#e.client.select(_).from(i).where(y(this.#e.client.select({id:_.id}).from(e`remote.entities as remote`).where(e`remote.key = ${i.key}`)))):this.#e.client.select(_).from(i),s=this.#e.client.select(_).from(r.as("combined_entities")).$dynamic(),{whereCondition:n}=B(s,t),d=$(e`combined_entities.scorecards_status = 'OUTDATED'`,e`combined_entities.scorecards_status IS NULL`),l=n?c(n,d):d;return(await s.where(l).run()).rows.map(o=>k(o)).filter(o=>o!==null)}async getEntitiesRelations(t={}){const r=this.#t?f(this.#e.client.select(m).from(e`remote.entities_relations`),this.#e.client.select(m).from(E).where(y(this.#e.client.select({id:m.id}).from(e`remote.entities_relations as remote`).where(e`remote.source_key = ${E.sourceKey}`)))):this.#e.client.select(m).from(E),s=this.#e.client.select(m).from(r.as("combined_entities_relations")).$dynamic(),n=this.#e.client.select(m).from(r.as("combined_entities_relations")).$dynamic(),d=S(n,{...t,limit:void 0,skip:void 0,after:void 0,before:void 0}),l=this.#e.client.$count(d),a=t.limit||10,o=S(s,{...t,limit:a+1}),[h,N]=await Promise.all([o.run(),l]),p=h.rows,w=p.length>a;return{items:p.slice(0,a).map(T=>C(T)).filter(T=>T!==null),hasMore:w,total:N}}async getEntityRelationById(t){const n=(await(this.#t?f(this.#e.client.select(m).from(e`remote.entities_relations`).where(u(E.id,t)),this.#e.client.select(m).from(E).where(c(u(E.id,t),y(this.#e.client.select({id:m.id}).from(e`remote.entities_relations as remote`).where(e`remote.id = ${E.id}`))))):this.#e.client.select(m).from(E).where(u(E.id,t))).run()).rows[0];return n?C(n):null}async getEntitiesWithRelations(t={},r){return this.#r.getEntitiesWithRelations(t,r)}async getEntityWithRelationsByKey(t,r,s){return this.#r.getEntityWithRelationsByKey(t,r,s)}async getRelationsForEntity(t,r,s){return this.#i.getRelationsForEntity(t,r,s)}async getRelatedEntities(t,r={}){return this.#i.getRelatedEntities(t,r)}async getCatalogFilters({entitiesTypes:t=[],emptyFilters:r=[]}){if(!r.length)return{};try{return await this.#s(t),(r.includes("domains")||r.includes("owners"))&&await this.#n(),await this.#o(r)}catch(s){return console.error("Error fetching catalog filters:",s),{}}finally{await this.#l()}}async#s(t){if(this.#t?await this.#e.client.run(e`
|
|
2
13
|
CREATE TEMP TABLE IF NOT EXISTS temp_combined_entities AS
|
|
3
14
|
SELECT
|
|
4
15
|
e.key,
|
|
@@ -25,10 +36,10 @@ import{and as l,count as L,eq as n,isNotNull as v,notExists as y,or as D,sql as
|
|
|
25
36
|
metadata
|
|
26
37
|
FROM entities
|
|
27
38
|
WHERE is_current = 1
|
|
28
|
-
`),
|
|
39
|
+
`),t.length){const r=t.map(s=>`'${s.replace(/'/g,"''")}'`).join(",");await this.#e.client.run(e.raw(`
|
|
29
40
|
CREATE TEMP TABLE IF NOT EXISTS temp_filtered_entities AS
|
|
30
41
|
SELECT * FROM temp_combined_entities
|
|
31
|
-
WHERE type IN (${
|
|
42
|
+
WHERE type IN (${r})
|
|
32
43
|
`))}else await this.#e.client.run(e`
|
|
33
44
|
CREATE TEMP TABLE IF NOT EXISTS temp_filtered_entities AS
|
|
34
45
|
SELECT * FROM temp_combined_entities
|
|
@@ -64,12 +75,12 @@ import{and as l,count as L,eq as n,isNotNull as v,notExists as y,or as D,sql as
|
|
|
64
75
|
CREATE INDEX IF NOT EXISTS idx_temp_rel_target ON temp_combined_relations(target_key)
|
|
65
76
|
`),await this.#e.client.run(e`
|
|
66
77
|
CREATE INDEX IF NOT EXISTS idx_temp_rel_relation ON temp_combined_relations(source_to_target_relation)
|
|
67
|
-
`)}async#o(
|
|
78
|
+
`)}async#o(t){const r={},s=[],n=t.filter(a=>a.startsWith("metadata."));t.includes("type")&&s.push(`
|
|
68
79
|
SELECT 'type' as filter_name, type as value, COUNT(*) as count
|
|
69
80
|
FROM temp_filtered_entities
|
|
70
81
|
WHERE type IS NOT NULL
|
|
71
82
|
GROUP BY type
|
|
72
|
-
`),
|
|
83
|
+
`),t.includes("tags")&&s.push(`
|
|
73
84
|
SELECT 'tags' as filter_name, tag.value as value, COUNT(DISTINCT tfe.key) as count
|
|
74
85
|
FROM temp_filtered_entities tfe,
|
|
75
86
|
json_each(COALESCE(tfe.tags, json_array())) as tag
|
|
@@ -78,7 +89,7 @@ import{and as l,count as L,eq as n,isNotNull as v,notExists as y,or as D,sql as
|
|
|
78
89
|
AND tag.value IS NOT NULL
|
|
79
90
|
AND tag.value != ''
|
|
80
91
|
GROUP BY tag.value
|
|
81
|
-
`),
|
|
92
|
+
`),t.includes("domains")&&s.push(`
|
|
82
93
|
SELECT 'domains' as filter_name, tcr.source_key as value, COUNT(DISTINCT tfe.key) as count
|
|
83
94
|
FROM temp_combined_relations tcr
|
|
84
95
|
INNER JOIN temp_filtered_entities tfe ON tfe.key = tcr.target_key
|
|
@@ -86,7 +97,7 @@ import{and as l,count as L,eq as n,isNotNull as v,notExists as y,or as D,sql as
|
|
|
86
97
|
WHERE tce.type = 'domain'
|
|
87
98
|
AND tcr.source_to_target_relation = 'hasParts'
|
|
88
99
|
GROUP BY tcr.source_key
|
|
89
|
-
`),
|
|
100
|
+
`),t.includes("owners")&&s.push(`
|
|
90
101
|
SELECT 'owners' as filter_name, owner_key as value, COUNT(DISTINCT entity_key) as count
|
|
91
102
|
FROM (
|
|
92
103
|
SELECT
|
|
@@ -106,12 +117,12 @@ import{and as l,count as L,eq as n,isNotNull as v,notExists as y,or as D,sql as
|
|
|
106
117
|
INNER JOIN temp_combined_entities tce ON tce.key = owner_key
|
|
107
118
|
WHERE owner_key IS NOT NULL
|
|
108
119
|
GROUP BY owner_key
|
|
109
|
-
`);for(const
|
|
110
|
-
SELECT json_extract(metadata, '${
|
|
120
|
+
`);for(const a of n)await this.#a(a,r);if(s.length===0)return r;const d=s.join(" UNION ALL "),l=await this.#e.client.run(e.raw(d));if(l?.rows)for(const a of l.rows){const o=a.filter_name,h=a.value,N=Number(a.count)||0;r[o]||(r[o]=[]),h&&r[o].push({value:h,count:N})}return r}async#a(t,r){const s=t.substring(9),n=`$.${U(s)}`,d=await this.#e.client.run(e.raw(`
|
|
121
|
+
SELECT json_extract(metadata, '${n}') as value, COUNT(*) as count
|
|
111
122
|
FROM temp_filtered_entities
|
|
112
123
|
WHERE metadata IS NOT NULL
|
|
113
124
|
AND metadata != ''
|
|
114
|
-
AND json_extract(metadata, '${
|
|
115
|
-
AND json_extract(metadata, '${
|
|
125
|
+
AND json_extract(metadata, '${n}') IS NOT NULL
|
|
126
|
+
AND json_extract(metadata, '${n}') != ''
|
|
116
127
|
GROUP BY value
|
|
117
|
-
`));
|
|
128
|
+
`));d?.rows&&(r[t]=d.rows.map(l=>({value:l.value,count:Number(l.count)||0})).filter(l=>l.value))}async#l(){try{await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_filtered_entities`),await this.#e.client.run(e`DROP TABLE IF EXISTS temp_combined_relations`)}catch(t){F.error("Error cleaning up temp tables:",t)}}}function U(O){return O.replace(/[^a-zA-Z0-9._-]/g,"")}export{te as CatalogEntitiesLocalReadRepository};
|
|
@@ -5,6 +5,7 @@ import type { ScorecardsStatus } from '../../../../../plugins/catalog-entities/e
|
|
|
5
5
|
import type { DatabaseConnection, RepositoryInstanceOptions } from '../../../../../providers/database/types.js';
|
|
6
6
|
import type { CatalogFiltersParams } from './catalog-entities-local-read-repository.js';
|
|
7
7
|
import type { SidebarConnectedEntity } from '@redocly/theme/core/types';
|
|
8
|
+
import type { EntityReadModelSchema } from '../../../../../plugins/catalog-entities/schemas/read-model-schemas.js';
|
|
8
9
|
import { BaseRepository } from '../../../../../providers/database/base-repository.js';
|
|
9
10
|
import { type CreateEntityParams, type CreateEntityResult } from './catalog-entities-local-write-repository.js';
|
|
10
11
|
export declare class CatalogEntitiesLocalRepository extends BaseRepository {
|
|
@@ -14,8 +15,8 @@ export declare class CatalogEntitiesLocalRepository extends BaseRepository {
|
|
|
14
15
|
getEntitySources(): Record<string, SidebarConnectedEntity>;
|
|
15
16
|
static getInstance(options: RepositoryInstanceOptions): Promise<CatalogEntitiesLocalRepository>;
|
|
16
17
|
attachDatabase(databasePath: string): Promise<void>;
|
|
17
|
-
getEntities(paginationParams?: PaginationParams): Promise<import("./catalog-entities-local-read-repository.js").ListResult<
|
|
18
|
-
|
|
18
|
+
getEntities(paginationParams?: PaginationParams): Promise<import("./catalog-entities-local-read-repository.js").ListResult<EntityReadModelSchema>>;
|
|
19
|
+
getEntityById(id: string): Promise<EntityReadModelSchema | null>;
|
|
19
20
|
getEntityKeysAndVersionsBySourceFile(sourceFile: string): Promise<Set<string>>;
|
|
20
21
|
getEntitiesCountByTypes(): Promise<{
|
|
21
22
|
type: string;
|
|
@@ -87,9 +88,10 @@ export declare class CatalogEntitiesLocalRepository extends BaseRepository {
|
|
|
87
88
|
deleteEntityRelation(id: string): Promise<string | null>;
|
|
88
89
|
deleteEntityRelations(filter: Filter): Promise<boolean>;
|
|
89
90
|
getCatalogFilters(params: CatalogFiltersParams): Promise<Record<string, import("./catalog-entities-local-read-repository.js").FilterOption[]>>;
|
|
90
|
-
listEntityRevisions(entityKey: string, version?: string | null): Promise<import("
|
|
91
|
+
listEntityRevisions(entityKey: string, version?: string | null): Promise<import("../../../../../plugins/catalog-entities/schemas/read-model-schemas.js").EntityRevisionSummary[]>;
|
|
91
92
|
updateEntityScorecardsStatus(entityId: string, status: ScorecardsStatus): Promise<boolean>;
|
|
92
93
|
updateEntityScorecardsStatusIfCalculating(entityId: string, status: Extract<ScorecardsStatus, 'UP_TO_DATE' | 'OUTDATED'>): Promise<boolean>;
|
|
93
|
-
|
|
94
|
+
getOutdatedEntities(filter?: Filter): Promise<EntityReadModelSchema[]>;
|
|
95
|
+
setEntitiesAsOutdated(filter: Filter): Promise<void>;
|
|
94
96
|
}
|
|
95
97
|
//# sourceMappingURL=catalog-entities-local-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{promiseMapLimit as o}from"../../../../../utils/async/promise-map-limit.js";import{logger as R}from"../../../../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as f}from"../../../../../providers/database/database-connection-factory.js";import{BaseRepository as p}from"../../../../../providers/database/base-repository.js";import{CatalogEntitiesLocalReadRepository as m}from"./catalog-entities-local-read-repository.js";import{CatalogEntitiesLocalWriteRepository as w}from"./catalog-entities-local-write-repository.js";import{createEntityRelationDbRecordFromDto as
|
|
1
|
+
import{promiseMapLimit as o}from"../../../../../utils/async/promise-map-limit.js";import{logger as R}from"../../../../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as f}from"../../../../../providers/database/database-connection-factory.js";import{BaseRepository as p}from"../../../../../providers/database/base-repository.js";import{CatalogEntitiesLocalReadRepository as m}from"./catalog-entities-local-read-repository.js";import{CatalogEntitiesLocalWriteRepository as w}from"./catalog-entities-local-write-repository.js";import{createEntityRelationDbRecordFromDto as g}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{hasOptionsChanged as I}from"../../../utils/has-options-changed.js";const l=50;class s extends p{static#i;static#n;#t;#e;#s={};constructor(t){super(t),this.#t=new m(this.databaseClient),this.#e=new w(this.databaseClient,this.organizationId,this.projectId)}get transactionsManager(){return this.databaseClient.transactionsManager}getEntitySources(){return this.#s}static async getInstance(t){const e=I(s.#n,t);if(!s.#i||e){const n=await f.create("catalog-local",t);if(!n)throw new Error("Failed to create db connection for catalog entities local repository");s.#i=new s(n),s.#n=t}return s.#i}async attachDatabase(t){await this.#t.attachDatabase(t)}getEntities(t={}){return this.#t.getEntities(t)}getEntityById(t){return this.#t.getEntityById(t)}getEntityKeysAndVersionsBySourceFile(t){return this.#t.getEntityKeysAndVersionsBySourceFile(t)}getEntitiesCountByTypes(){return this.#t.getEntitiesCountByTypes()}getEntitiesRelations(t={}){return this.#t.getEntitiesRelations(t)}getEntityRelationById(t){return this.#t.getEntityRelationById(t)}getEntitiesWithRelations(t={},e){return this.#t.getEntitiesWithRelations(t,e)}getEntityWithRelationsByKey(t,e,n){return this.#t.getEntityWithRelationsByKey(t,e,n)}getRelatedEntities(t,e={}){return this.#t.getRelatedEntities(t,e)}createEntity(t){return t.isRootEntity&&(this.#s[t.sourceFile]={key:t.entity.key,version:t.entity.version??void 0}),this.#e.createEntity(t)}async createEntities(t){await o(t,l,async e=>this.createEntity(e))}createEntityRelation(t){const e=g(t,this.organizationId,this.projectId);return this.#e.upsertEntityRelation(e)}async createEntityRelations(t){await o(t,l,async e=>this.createEntityRelation(e))}deleteEntity(t){return this.#e.deleteEntity(t)}async softDeleteEntities({filter:t,revision:e,fileHash:n}){const c=await this.getEntities({filter:t}),i=await this.#e.softDeleteEntities(c.items,e,n);await this.softDeleteEntitiesRelations(i,e)}async softDeleteEntitiesRelations(t,e){try{const n=t.filter(i=>i.result==="created");if(n.length===0)return!0;const c=await o(n,l,async i=>(await this.#t.getRelationsForEntity(i.entityKey,i.entityVersion,e)).map(r=>{if(!r)return null;const y=r.direction,a=r.sourceToTargetRelation,u=r.targetKey,d=y==="outgoing"?i.entityKey:u,h=y==="outgoing"?u:i.entityKey,E=y==="outgoing"?a:a.startsWith("reverse:")?a.slice(8):a;return!E||!d||!h?null:g({type:E,sourceKey:d,targetKey:h,sourceVersion:i.entityVersion,targetVersion:i.entityVersion,sourceRevision:e,targetRevision:e,isDeleted:!0},this.organizationId,this.projectId)}).filter(r=>r!==null));return await o(c.flat(),l,async i=>this.#e.upsertEntityRelation(i)),!0}catch(n){return R.error("Error soft deleting entity relations",n),!1}}deleteEntities(t){return this.#e.deleteEntities(t)}deleteEntityRelation(t){return this.#e.deleteEntityRelation(t)}deleteEntityRelations(t){return this.#e.deleteEntityRelations(t)}getCatalogFilters(t){return this.#t.getCatalogFilters(t)}listEntityRevisions(t,e){return this.#t.listEntityRevisions(t,e)}updateEntityScorecardsStatus(t,e){return this.#e.updateEntityScorecardsStatus(t,e)}updateEntityScorecardsStatusIfCalculating(t,e){return this.#e.updateEntityScorecardsStatusIfCalculating(t,e)}getOutdatedEntities(t){return this.#t.getOutdatedEntities(t)}async setEntitiesAsOutdated(t){await this.#e.setEntitiesAsOutdated(t)}}export{s as CatalogEntitiesLocalRepository};
|
|
@@ -38,5 +38,6 @@ export declare class CatalogEntitiesLocalWriteRepository {
|
|
|
38
38
|
upsertEntityRelation(entityRelation: DatabaseEntityRelationDto): Promise<DatabaseEntityRelation | null>;
|
|
39
39
|
updateEntityScorecardsStatus(entityId: string, status: ScorecardsStatus): Promise<boolean>;
|
|
40
40
|
updateEntityScorecardsStatusIfCalculating(entityId: string, status: Extract<ScorecardsStatus, 'UP_TO_DATE' | 'OUTDATED'>): Promise<boolean>;
|
|
41
|
+
setEntitiesAsOutdated(filter: Filter): Promise<void>;
|
|
41
42
|
}
|
|
42
43
|
//# sourceMappingURL=catalog-entities-local-write-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{and as
|
|
1
|
+
import{and as m,eq as c,isNull as v,or as A,sql as N}from"drizzle-orm";import{logger as u}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as F}from"../../../../../utils/crypto/sha1.js";import{isWebView as b}from"../../../../../../utils/env/is-web-view.js";import{VERSION_NOT_SPECIFIED as O}from"@redocly/theme/core/constants";import{entitiesAttributesTable as D}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js";import{createEntityDbRecord as U}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as I}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as C}from"../../../../../providers/database/pagination/filter.js";import{createEntityAttributesDbRecord as z}from"../../mappers/create-entity-attributes-db-record.js";import{RevisionRepository as P}from"../common/revision-repository.js";import{VersionRepository as j}from"../common/version-repository.js";const w=15;class re{#e;#t;#r;#i;#s;constructor(e,t,s){this.#e=e,this.#t=t,this.#r=s,this.#i=new P(e),this.#s=new j(e)}async createEntity({entity:e,fileHash:t,sourceFile:s,revision:a=new Date().toISOString(),isRootEntity:o=!1,isDeleted:n=!1,rbacTeams:y=[]}){try{const{relations:l=[],...f}=e,p=F(JSON.stringify(f)),d=e.version??O,g=await this.#i.shouldSkipRevisionCreation(e.key,d,p,o,n);if(await this.#o({entityKey:e.key,rbacTeams:y}),g)return{result:"skipped",entityKey:e.key};const h=await this.#i.shouldSetNewCurrentRevision({key:e.key,version:d,revision:a}),R=U({entity:{...e,revision:a,hash:p,isCurrent:h,isDefaultVersion:h,isDeleted:n,version:d},sourceFile:s,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:t}),{key:V,source:L,...K}=R;if(h&&(await this.#i.markAllRevisionsAsNotCurrent(V),await this.#s.markAllVersionsAsNotDefault(V)),b())return await this.#n(R,l),{result:"created",entityKey:e.key,entityRevision:a,entityVersion:d};const S=this.#e.client.insert(r).values(R).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:K}),T=l?.length&&l.length>0?this.#e.client.insert(i).values(l.map(k=>I({relation:k,sourceFile:s,fileHash:t,sourceKey:e.key,sourceVersion:d,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation]}).run():Promise.resolve();return await E([S,T],w,async k=>k),{result:"created",entityKey:e.key,entityRevision:a,entityVersion:d}}catch(l){return u.error("Error adding entity",l),{result:"error",entityKey:e.key}}}async deleteEntity(e){try{return await this.#e.client.delete(r).where(c(r.key,e)),e}catch(t){return u.error("Error deleting entity",t),null}}async deleteEntities(e){try{const t=C(e);if(!t)return!1;const s=await this.#e.client.delete(r).where(t).returning({key:r.key,source:r.source,isCurrent:r.isCurrent,isDefaultVersion:r.isDefaultVersion,version:r.version});if(s.length===0)return!0;const a=s.reduce((o,n)=>((n.isCurrent||n.isDefaultVersion)&&o.add(n.key),o),new Set);if(a.size===0)return!0;await E(Array.from(a),w,async o=>this.#i.ensureDefaultAndCurrentRevisionForKey(o));for(const o of s)await this.#e.client.delete(i).where(A(m(c(i.sourceKey,o.key),...o.version?[c(i.sourceVersion,o.version)]:[v(i.sourceVersion)]),m(c(i.targetKey,o.key),...o.version?[c(i.targetVersion,o.version)]:[v(i.targetVersion)])));return!0}catch(t){return u.error("Error deleting entities",t),!1}}async deleteEntityRelation(e){try{return await this.#e.client.delete(i).where(c(i.id,e)),e}catch{return null}}async softDeleteEntities(e,t,s){try{const a=e.map(n=>{const y={type:n.type,key:n.key,title:n.title,summary:n.summary??void 0,tags:n.tags??void 0,metadata:n.metadata??void 0,git:n.git??void 0,contact:n.contact??void 0,links:n.links??void 0,version:n.version??void 0};return this.createEntity({entity:y,revision:t,sourceFile:n.sourceFile??"",fileHash:s,isDeleted:!0})});return await E(a,w,async n=>n)}catch(a){return u.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(e){try{const t=C(e);return t?(await this.#e.client.delete(i).where(t),!0):!1}catch(t){return u.error("Error deleting entity relations",t),!1}}async upsertEntityRelation(e){if(!e)return null;try{const{sourceKey:t,targetKey:s,sourceVersion:a,targetVersion:o,sourceRevision:n,targetRevision:y,...l}=e,f=await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation],set:l}).returning();return f?.length?f[0]:null}catch(t){return u.error("Error creating entity relation",t),null}}async#n(e,t){const{key:s,source:a,version:o,isDefaultVersion:n,...y}=e,p=(await this.#e.client.select({id:r.id}).from(r).where(m(c(r.key,s),c(r.source,a??"file"),o?c(r.version,o):v(r.version))).limit(1).run()).rows.length>0?this.#e.client.update(r).set(y).where(m(c(r.key,s),c(r.source,a??"file"),o?c(r.version,o):v(r.version))).run():this.#e.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:y}).run(),d=t?.map(g=>{const h=I({relation:g,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(i).values(h).onConflictDoUpdate({target:[i.sourceKey,i.targetKey,i.sourceVersion,i.targetVersion,i.sourceRevision,i.targetRevision,i.sourceToTargetRelation],set:h}).run()})??[];await E([p,...d],w,async g=>g)}async updateEntityScorecardsStatus(e,t){try{return(await this.#e.client.update(r).set({scorecardsStatus:t}).where(c(r.id,e)).returning()).length>0}catch(s){return u.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(e,t){try{return(await this.#e.client.update(r).set({scorecardsStatus:t}).where(N`${r.id} = ${e} AND ${r.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return u.error("Error updating entity scorecards status if calculating",s),!1}}async#o({entityKey:e,rbacTeams:t}){try{await this.#e.client.insert(D).values(z({rbacTeams:t,entityKey:e,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[D.entityKey],set:{rbacTeams:JSON.stringify(t)}}).run()}catch(s){u.error("Error saving entity attributes",s)}}async setEntitiesAsOutdated(e){try{const t=C(e);await this.#e.client.update(r).set({scorecardsStatus:"OUTDATED"}).where(t)}catch(t){u.error("Error updating entities as outdated",t)}}}export{re as CatalogEntitiesLocalWriteRepository};
|
|
@@ -11,11 +11,8 @@ export declare class CatalogEntitiesRemoteRepository extends BaseRepository {
|
|
|
11
11
|
sync(): Promise<void>;
|
|
12
12
|
static getInstance(options: RepositoryInstanceOptions): Promise<CatalogEntitiesRemoteRepository | null>;
|
|
13
13
|
createEntity(entity: EntityDtoSchema): Promise<EntityReadModelSchema | null>;
|
|
14
|
-
updateEntity(
|
|
15
|
-
|
|
16
|
-
createdAt?: string;
|
|
17
|
-
}): Promise<EntityReadModelSchema | null>;
|
|
18
|
-
deleteEntity(entityKey: string): Promise<string | null>;
|
|
14
|
+
updateEntity(incomingEntity: Partial<EntityDtoSchema>, entityToBeUpdated: EntityReadModelSchema): Promise<EntityReadModelSchema | null>;
|
|
15
|
+
deleteEntity(id: string): Promise<string | null>;
|
|
19
16
|
createEntityRelations(relations: EntityRelationDtoSchema[]): Promise<(DatabaseEntityRelation | null)[]>;
|
|
20
17
|
createEntityRelation(entityRelation: EntityRelationDtoSchema): Promise<DatabaseEntityRelation | null>;
|
|
21
18
|
deleteEntityRelation(id: string): Promise<string | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{eq as
|
|
1
|
+
import{and as f,eq as n,ne as C,or as w,sql as p}from"drizzle-orm";import{convertFilterToWhereCondition as D}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as V}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as E}from"../../../../../utils/crypto/sha1.js";import{logger as a}from"../../../../../tools/notifiers/logger.js";import{entitiesTable as i}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{telemetryTraceStep as c}from"../../../../../telemetry/helpers/trace-step.js";import{BaseRepository as A}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as I}from"../../../../../providers/database/database-connection-factory.js";import{entitiesRelationsTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{VERSION_NOT_SPECIFIED as b}from"@redocly/theme/core/constants";import{createEntityDbRecord as _}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as k}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as O}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{RevisionRepository as K}from"../common/revision-repository.js";import{VersionRepository as F}from"../common/version-repository.js";const S=15;class h extends A{static#r;#t;#i;#n=!1;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t),this.#t=new K(t.client),this.#i=new F(t.client)}async sync(){if(!this.#n&&this.isNonRemoteDatabaseMode()){a.warn("Catalog entities database is currently operating in local mode: not connected to the remote database. All changes and data will only persist locally and will not be synced remotely."),this.#n=!0;return}return c("catalog_entities.remote_repository.sync",async()=>{await this.#e(),await this.databaseClient.sync()})}static async getInstance(t){return await c("catalog_entities.remote_repository.get_instance",async e=>{if(!h.#r)try{const o=await I.create("sqld-remote",t);if(!o)return a.error("Failed to create db connection for catalog entities remote repository"),e?.error(new Error("Failed to create db connection for catalog entities remote repository")),h.#r=null,null;h.#r=new h(o)}catch(o){return a.error("Error creating db connection for catalog entities remote repository",o),e?.error(o),h.#r=null,null}return h.#r})}async createEntity(t){return c("catalog_entities.remote_repository.create_entity",async()=>{await this.#e();try{a.info(`Adding entity ${t.key} to remote database`);const{relations:e=[],...o}=t,l=E(JSON.stringify(o)),s=t.version??b,y=t.revision??new Date().toISOString();if(await this.#t.shouldSkipRevisionCreation(t.key,s,l))throw new Error("Entity validation failed: entity already exists");const d=await this.#t.shouldSetNewCurrentRevision({key:t.key,version:s,revision:y}),u=_({entity:{...t,revision:y,hash:l,isCurrent:d,isDefaultVersion:d,version:s},organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:m,source:L,...N}=u;d&&(await this.#t.markAllRevisionsAsNotCurrent(m),await this.#i.markAllVersionsAsNotDefault(m));const v=await this.databaseClient.client.insert(i).values(u).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:N}).returning();return v.length?(e&&await this.createEntityRelations(e.map(R=>({...R,sourceKey:t.key,targetKey:R.key}))),k(v[0])):null}catch(e){throw a.error("Error adding entity",e),e}})}async updateEntity(t,e){return c("catalog_entities.remote_repository.update_entity",async()=>{await this.#e();try{a.info(`Updating entity ${e.key} in remote database`);const o=await this.#t.shouldSetNewCurrentRevision({key:e.key,version:t.version??e.version??b,revision:e.revision});o&&(await this.#t.markAllRevisionsAsNotCurrent(e.key),await this.#i.markAllVersionsAsNotDefault(e.key));const l=_({entity:{...e,...t,hash:E(JSON.stringify({...e,...t})),isCurrent:o,isDefaultVersion:o,createdAt:e.createdAt??void 0},organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:s,source:y,scorecardsStatus:g,...d}=l,u=await this.databaseClient.client.insert(i).values(l).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...d,scorecardsStatus:p`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return u.length?k(u[0]):null}catch(o){return a.error("Error updating entity",o),null}})}async deleteEntity(t){return c("catalog_entities.remote_repository.delete_entity",async()=>{await this.#e();try{const e=await this.databaseClient.client.select().from(i).where(n(i.id,t)).get();return e?(await this.#o(e),await this.databaseClient.client.delete(i).where(n(i.id,t)),e&&this.#t.ensureDefaultAndCurrentRevisionForKey(e.key),t):null}catch(e){return a.error("Error deleting entity",e),null}})}async createEntityRelations(t){return c("catalog_entities.remote_repository.create_entity_relations",async()=>(await this.#e(),await V(t,S,async e=>this.createEntityRelation(e))))}async createEntityRelation(t){return c("catalog_entities.remote_repository.create_entity_relation",async()=>{if(await this.#e(),!t)return null;try{const e=O(t,this.organizationId,this.projectId),{sourceKey:o,targetKey:l,sourceVersion:s,targetVersion:y,sourceRevision:g,targetRevision:d,...u}=e,m=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.sourceKey,r.targetKey,r.sourceVersion,r.targetVersion,r.sourceRevision,r.targetRevision,r.sourceToTargetRelation],set:u}).returning();return m.length?m[0]:null}catch(e){throw a.error("Error creating entity relation",e),e}})}async deleteEntityRelation(t){return c("catalog_entities.remote_repository.delete_entity_relation",async()=>{await this.#e();try{return await this.databaseClient.client.delete(r).where(n(r.id,t)),t}catch(e){return a.error("Error deleting entity relation",e),null}})}async deleteEntitiesRelations(t){return c("catalog_entities.remote_repository.delete_entities_relations",async()=>{await this.#e();try{const e=D(t);return e?(await this.databaseClient.client.delete(r).where(e),!0):!1}catch(e){return a.error("Error deleting entities relations",e),!1}})}async#o(t){const{key:e,version:o,revision:l}=t,s=o??"",y=l??"";if(((await this.databaseClient.client.select({count:p`COUNT(*)`}).from(i).where(f(n(i.key,e),C(i.id,t.id))).get())?.count??0)===0){await this.databaseClient.client.delete(r).where(w(n(r.sourceKey,e),n(r.targetKey,e)));return}if(((await this.databaseClient.client.select({count:p`COUNT(*)`}).from(i).where(f(n(i.key,e),n(i.version,s),C(i.id,t.id))).get())?.count??0)===0){await this.databaseClient.client.delete(r).where(w(f(n(r.sourceKey,e),n(r.sourceVersion,s)),f(n(r.targetKey,e),n(r.targetVersion,s))));return}await this.databaseClient.client.delete(r).where(w(f(n(r.sourceKey,e),n(r.sourceVersion,s),n(r.sourceRevision,y)),f(n(r.targetKey,e),n(r.targetVersion,s),n(r.targetRevision,y))))}#e(){return c("catalog_entities.remote_repository.db_health",async t=>{if(this.databaseClient.dbClient.$client.closed){const e=new Error("The remote database connection is closed!");throw t?.error(e),e}})}}export{h as CatalogEntitiesRemoteRepository};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* Creates merged entity fields for SELECT when joining remote and local entities.
|
|
4
|
+
* JSON fields (metadata, git, contact, links, tags) are merged using json_patch.
|
|
5
|
+
* Simple fields prefer the newer value based on updated_at.
|
|
6
|
+
* @param remoteAlias - Alias for remote table (default: 'r')
|
|
7
|
+
* @param localAlias - Alias for local table (default: 'l')
|
|
8
|
+
*/
|
|
9
|
+
export declare function createMergedEntityFieldsForSelect(remoteAlias?: string, localAlias?: string): {
|
|
10
|
+
id: SQL<unknown>;
|
|
11
|
+
organizationId: SQL<unknown>;
|
|
12
|
+
projectId: SQL<unknown>;
|
|
13
|
+
key: SQL<unknown>;
|
|
14
|
+
type: SQL<unknown>;
|
|
15
|
+
title: SQL<unknown>;
|
|
16
|
+
summary: SQL<unknown>;
|
|
17
|
+
tags: SQL<unknown>;
|
|
18
|
+
metadata: SQL<unknown>;
|
|
19
|
+
git: SQL<unknown>;
|
|
20
|
+
contact: SQL<unknown>;
|
|
21
|
+
links: SQL<unknown>;
|
|
22
|
+
createdAt: SQL<unknown>;
|
|
23
|
+
updatedAt: SQL<unknown>;
|
|
24
|
+
source: SQL<unknown>;
|
|
25
|
+
sourceFile: SQL<unknown>;
|
|
26
|
+
fileHash: SQL<unknown>;
|
|
27
|
+
version: SQL<unknown>;
|
|
28
|
+
revision: SQL<unknown>;
|
|
29
|
+
hash: SQL<unknown>;
|
|
30
|
+
isCurrent: SQL<unknown>;
|
|
31
|
+
isDeleted: SQL<unknown>;
|
|
32
|
+
scorecardsStatus: SQL<unknown>;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=create-merged-entity-fields-for-select.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{sql as u}from"drizzle-orm";function p(t="r",d="l"){return{id:$("id","id",t,d),organizationId:$("organization_id","organization_id",t,d),projectId:$("project_id","project_id",t,d),key:u.raw(`${t}.key AS key`),type:$("type","type",t,d),title:$("title","title",t,d),summary:$("summary","summary",t,d),tags:_("tags","tags",t,d),metadata:_("metadata","metadata",t,d),git:_("git","git",t,d),contact:_("contact","contact",t,d),links:_("links","links",t,d),createdAt:u.raw(`MIN(${t}.created_at, ${d}.created_at) AS created_at`),updatedAt:u.raw(`MAX(${t}.updated_at, ${d}.updated_at) AS updated_at`),source:$("source","source",t,d),sourceFile:$("source_file","source_file",t,d),fileHash:$("file_hash","file_hash",t,d),version:u.raw(`${t}.version AS version`),revision:u.raw(`${t}.revision AS revision`),hash:$("hash","hash",t,d),isCurrent:$("is_current","is_current",t,d),isDeleted:$("is_deleted","is_deleted",t,d),scorecardsStatus:$("scorecards_status","scorecards_status",t,d)}}function _(t,d,n="r",r="l"){return u.raw(`
|
|
2
|
+
CASE
|
|
3
|
+
WHEN ${n}.${t} IS NULL THEN ${r}.${t}
|
|
4
|
+
WHEN ${r}.${t} IS NULL THEN ${n}.${t}
|
|
5
|
+
WHEN ${n}.updated_at >= ${r}.updated_at THEN json_patch(${r}.${t}, ${n}.${t})
|
|
6
|
+
ELSE json_patch(${n}.${t}, ${r}.${t})
|
|
7
|
+
END AS ${d}
|
|
8
|
+
`)}function $(t,d,n="r",r="l"){return u.raw(`
|
|
9
|
+
CASE
|
|
10
|
+
WHEN ${n}.updated_at >= ${r}.updated_at THEN COALESCE(${n}.${t}, ${r}.${t})
|
|
11
|
+
ELSE COALESCE(${r}.${t}, ${n}.${t})
|
|
12
|
+
END AS ${d}
|
|
13
|
+
`)}export{p as createMergedEntityFieldsForSelect};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a revision with flags that can be normalized.
|
|
3
|
+
*/
|
|
4
|
+
export type RevisionWithFlags = {
|
|
5
|
+
version: string | null;
|
|
6
|
+
revision: string;
|
|
7
|
+
isCurrent: boolean;
|
|
8
|
+
isDefaultVersion: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes revision flags to ensure only one revision is marked as current/default.
|
|
12
|
+
*
|
|
13
|
+
* When multiple revisions are flagged (isCurrent or isDefaultVersion), the one with
|
|
14
|
+
* the highest semantic version wins. If versions are equal, the highest revision string wins.
|
|
15
|
+
* All other flagged revisions have their flags reset to false.
|
|
16
|
+
*
|
|
17
|
+
* Note: In this system, isCurrent and isDefaultVersion are coupled - if a revision
|
|
18
|
+
* is current, it is also the default version.
|
|
19
|
+
*
|
|
20
|
+
* @param revisions - Array of revisions to normalize (mutated in place)
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeRevisionFlags<T extends RevisionWithFlags>(revisions: T[]): void;
|
|
23
|
+
//# sourceMappingURL=normalize-revision-flags.d.ts.map
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{VERSION_NOT_SPECIFIED as t}from"@redocly/theme/core/constants";import{compareVersionsDescending as f}from"../../../utils/version-compare.js";function s(n){return!n||n===t}function c(n,i){const e=s(n.version),r=s(i.version);if(e&&!r)return 1;if(!e&&r)return-1;const o=f(n.version??"",i.version??"");return o!==0?o:(i.revision??"").localeCompare(n.revision??"")}function a(n){const i=n.filter(e=>e.isCurrent||e.isDefaultVersion);if(!(i.length<=1)){i.sort(c);for(let e=1;e<i.length;e++)i[e].isCurrent=!1,i[e].isDefaultVersion=!1}}export{a as normalizeRevisionFlags};
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { SQL } from 'drizzle-orm';
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* SEMANTIC VERSION SORTING IN SQLITE
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* SQLite lacks native semantic version comparison, so we convert versions
|
|
8
|
+
* into sortable strings. The key insight is that string comparison uses
|
|
9
|
+
* ASCII/Unicode ordering, so we can control sort order through prefixes
|
|
10
|
+
* and zero-padding.
|
|
11
|
+
*
|
|
12
|
+
* ## Sort Strategy (for descending order)
|
|
13
|
+
*
|
|
14
|
+
* We transform versions into strings that sort correctly when compared lexicographically:
|
|
15
|
+
*
|
|
16
|
+
* | Version Type | Transformation | Example Result |
|
|
17
|
+
* |----------------------|-------------------------------------|-------------------------|
|
|
18
|
+
* | not_specified_version| Prefix with '!' | '!not_specified' |
|
|
19
|
+
* | null/empty | Padded zeros | '0000000000.0000...' |
|
|
20
|
+
* | Numeric (1.2.3) | Zero-padded to 10 digits per part | '0000000001.0000000002.0000000003' |
|
|
21
|
+
* | Text (latest) | Prefix with 'Z' | 'ZZZZZZZZZZ.latest' |
|
|
22
|
+
*
|
|
23
|
+
* ASCII ordering ensures: '!' < '0' < 'Z', giving us:
|
|
24
|
+
* latest > 10.0.0 > 3.1 > 1 > null > not_specified_version
|
|
25
|
+
*
|
|
26
|
+
* ## Why Zero-Padding?
|
|
27
|
+
*
|
|
28
|
+
* Without padding, string comparison fails for multi-digit numbers:
|
|
29
|
+
* '9' > '10' (wrong!) vs '0000000009' < '0000000010' (correct!)
|
|
30
|
+
*
|
|
31
|
+
* We use 10 digits to support versions up to 9,999,999,999 per component.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Builds SQL expression for semantic version sorting in SQLite.
|
|
35
|
+
* Handles versions like: 1, 1.0, 1.0.0, 10.2.3, latest, etc.
|
|
36
|
+
*
|
|
37
|
+
* @param versionColumn - The column name or expression containing the version
|
|
38
|
+
* @returns SQL expression that can be used in ORDER BY for descending version sort
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```sql
|
|
42
|
+
* ORDER BY ${buildSemanticVersionSortExpr('version')} DESC
|
|
43
|
+
* -- Sorts: latest, 10.0.0, 3.1, 3, 2.0.1, 1, not_specified_version
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildSemanticVersionSortExpr(versionColumn: string): SQL;
|
|
47
|
+
/**
|
|
48
|
+
* ============================================================================
|
|
49
|
+
* VERSION COMPARISON FILTER
|
|
50
|
+
* ============================================================================
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* Builds a SQL condition that checks no higher semantic version exists
|
|
54
|
+
* for the same key in either local or remote database.
|
|
55
|
+
*
|
|
56
|
+
* This is used to find the "current" version of an entity when multiple
|
|
57
|
+
* versions exist across local and remote databases.
|
|
58
|
+
*
|
|
59
|
+
* ## Logic
|
|
60
|
+
*
|
|
61
|
+
* Returns TRUE if there is NO other entity with the same key that has:
|
|
62
|
+
* 1. A higher semantic version, OR
|
|
63
|
+
* 2. The same version but a higher revision number
|
|
64
|
+
*
|
|
65
|
+
* ## Example
|
|
66
|
+
*
|
|
67
|
+
* Given entities with key='my-api':
|
|
68
|
+
* - Local: version='1.0.0', revision=1
|
|
69
|
+
* - Remote: version='1.0.0', revision=2 ← This one wins (same version, higher revision)
|
|
70
|
+
* - Remote: version='2.0.0', revision=1 ← This one wins (higher version)
|
|
71
|
+
*
|
|
72
|
+
* @param keyExpr - SQL expression for the entity's key (e.g., 'entities.key')
|
|
73
|
+
* @param versionExpr - SQL expression for the entity's version (e.g., 'entities.version')
|
|
74
|
+
* @param revisionExpr - SQL expression for the entity's revision (e.g., 'entities.revision')
|
|
75
|
+
* @returns SQL expression that evaluates to TRUE if this is the highest version
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildNoHigherVersionExistsFilter(keyExpr: string, versionExpr: string, revisionExpr: string): SQL;
|
|
78
|
+
//# sourceMappingURL=semantic-version-sort.d.ts.map
|
package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import{sql as o}from"drizzle-orm";const $="not_specified_version";function h(e){return o.raw(`
|
|
2
|
+
CASE
|
|
3
|
+
${s(e)}
|
|
4
|
+
${S(e)}
|
|
5
|
+
${a(e)}
|
|
6
|
+
${E(e)}
|
|
7
|
+
END
|
|
8
|
+
`)}function s(e){return`WHEN ${e} = '${$}' THEN '!not_specified'`}function S(e){return`WHEN ${e} IS NULL OR ${e} = '' THEN '0000000000.0000000000.0000000000'`}function a(e){return`WHEN ${e} GLOB '*[^0-9.]*' THEN 'ZZZZZZZZZZ.' || ${e}`}function E(e){return`ELSE ${c(e)}`}function c(e){const r=u(e),i=N(e),t=T(e);return`PRINTF('%010d.%010d.%010d', ${r}, ${i}, ${t})`}function u(e){const r=`${e} || '.0.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${r}, 1, INSTR(${r}, '.') - 1), ''), '0') AS INTEGER)`}function N(e){const r=`${e} || '.0.0'`,i=`SUBSTR(${r}, INSTR(${r}, '.') + 1) || '.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${i}, 1, INSTR(${i}, '.') - 1), ''), '0') AS INTEGER)`}function T(e){const r=`${e} || '.0.0'`,i=`SUBSTR(${r}, INSTR(${r}, '.') + 1) || '.0'`,t=`SUBSTR(${i}, INSTR(${i}, '.') + 1) || '.0'`;return`CAST(COALESCE(NULLIF(SUBSTR(${t}, 1, INSTR(${t}, '.') - 1), ''), '0') AS INTEGER)`}function d(e){return`
|
|
9
|
+
CASE
|
|
10
|
+
${s(e)}
|
|
11
|
+
${S(e)}
|
|
12
|
+
${a(e)}
|
|
13
|
+
${E(e)}
|
|
14
|
+
END
|
|
15
|
+
`}function l(e,r,i){const t=d("higher_version.version"),n=d(r);return o.raw(`
|
|
16
|
+
NOT EXISTS (
|
|
17
|
+
SELECT 1 FROM (
|
|
18
|
+
-- Combine all current, non-deleted entities from both databases
|
|
19
|
+
SELECT key, version, revision FROM remote.entities WHERE is_current = 1 AND is_deleted = 0
|
|
20
|
+
UNION ALL
|
|
21
|
+
SELECT key, version, revision FROM entities WHERE is_current = 1 AND is_deleted = 0
|
|
22
|
+
) higher_version
|
|
23
|
+
WHERE higher_version.key = ${e}
|
|
24
|
+
AND (
|
|
25
|
+
-- Case 1: Another entity has a strictly higher version
|
|
26
|
+
(${t}) > (${n})
|
|
27
|
+
OR (
|
|
28
|
+
-- Case 2: Same version, but another entity has a higher revision
|
|
29
|
+
(${t}) = (${n})
|
|
30
|
+
AND higher_version.revision > ${i}
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
`)}export{l as buildNoHigherVersionExistsFilter,h as buildSemanticVersionSortExpr};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type EntityRelationFileSchema, type EntityBaseFileSchema } from '@redocly/config';
|
|
2
2
|
import type { EntitiesCatalogConfig } from '@redocly/config';
|
|
3
|
+
import type { EntityDtoSchema } from '../schemas/dto-schemas.js';
|
|
3
4
|
export declare function validateEntityRelation(relation: unknown): asserts relation is EntityRelationFileSchema;
|
|
4
5
|
export declare function parseAndValidateEntity(entity: unknown, catalogConfig: EntitiesCatalogConfig): EntityBaseFileSchema;
|
|
5
|
-
export declare function
|
|
6
|
+
export declare function parseAndValidateEntityUpdate(entity: unknown, catalogConfig: EntitiesCatalogConfig, entityType: string): Partial<EntityDtoSchema>;
|
|
7
|
+
export declare function parseAndValidateEntities(entities: unknown[], catalogConfig: EntitiesCatalogConfig): EntityDtoSchema[];
|
|
6
8
|
//# sourceMappingURL=validate-entity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{entityFileSchema as
|
|
1
|
+
import{entityFileSchema as o,entityRelationFileSchema as y,entityBaseProperties as s}from"@redocly/config";import{createValidator as a}from"../utils/ajv-validator.js";const d=a(y,{errorPrefix:"Entity relation validation failed:",dataVar:"relation"});function f(e){d(e)}function u(e,i){const t=p(i);return a(t,{errorPrefix:"Entity validation failed:",dataVar:"entity"})(e)}function E(e,i,t){const r=c(i,t);return a(r,{errorPrefix:"Entity validation failed:",dataVar:"entity"})(e)}function V(e,i){const t={type:"array",items:p(i)};return a(t,{errorPrefix:"Entity validation failed:",dataVar:"entity"})(e)}function p(e){const i=Object.entries(e.entityTypes??{}).map(([t,r])=>({type:"object",properties:{...s,type:{const:t},metadata:{additionalProperties:!0,...r.metadataSchema},revision:{type:"string"}},required:["key","title","type"],additionalProperties:!1}));return{type:"object",discriminator:{propertyName:"type"},oneOf:[...o.oneOf.map(t=>({...t,properties:{...t.properties,revision:{type:"string"}}})),...i]}}function c(e,i){const t=o.oneOf.find(r=>r.properties.type.const===i);if(!t){const r=Object.keys(e.entityTypes??{}).find(n=>n===i);if(!r)throw new Error(`Entity type: ${i} not found`);return{type:"object",properties:{...s,type:{const:r},metadata:{additionalProperties:!0,...e.entityTypes?.[r].metadataSchema},revision:{type:"string"}},additionalProperties:!1}}return{properties:{...t.properties,revision:{type:"string"}},additionalProperties:!1}}export{V as parseAndValidateEntities,u as parseAndValidateEntity,E as parseAndValidateEntityUpdate,f as validateEntityRelation};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FileType as u}from"../../persistence/file-hashes/types.js";import{deepEqual as O}from"../../../utils/object/deep-equal.js";import{telemetryTraceStep as P}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as I}from"./utils/catalog-data-collector.js";import{CATALOG_BASE_SLUG as m,CATALOG_FILTERS_CACHE_NAMESPACE as _,ENTITIES_MAP_GLOBAL_DATA_KEY as b}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 C}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as w}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as N}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as R}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 d=!0,A;async function Y(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const i=await e.getConfig(),r=C(i.entitiesCatalog);if(!r.show)return;const{logger:o}=e,n=t.registerServerPropsGetter(M,f("../get-server-props.js")),p=t.createTemplate(B,f("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:m,fsPath:"",templateId:p,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[n],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[
|
|
1
|
+
import{FileType as u}from"../../persistence/file-hashes/types.js";import{deepEqual as O}from"../../../utils/object/deep-equal.js";import{telemetryTraceStep as P}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as I}from"./utils/catalog-data-collector.js";import{CATALOG_BASE_SLUG as m,CATALOG_FILTERS_CACHE_NAMESPACE as _,ENTITIES_MAP_GLOBAL_DATA_KEY as b}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 C}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as w}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as N}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as R}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 d=!0,A;async function Y(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const i=await e.getConfig(),r=C(i.entitiesCatalog);if(!r.show)return;const{logger:o}=e,n=t.registerServerPropsGetter(M,f("../get-server-props.js")),p=t.createTemplate(B,f("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:m,fsPath:"",templateId:p,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[n],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[l]=Object.entries(r.catalogs??{}).find(([E,s])=>!s?.hide)||[];l&&t.addRedirect(m,{type:302,to:`${m}/${l}`}),o.info("Catalog Entities plugin finished")},async afterRoutesCreated(t,e){await P("build.plugin.catalog_entities",async i=>{const r=await e.getConfig(),o=C(r.entitiesCatalog);if(i?.setAttribute("config",JSON.stringify(o)),!o.show)return;const{logger:n}=e,p=process.env.NODE_ENV==="development"||process.env.REDOCLY_LOCAL_DEV==="true",l=d&&p,E=!O(A,r.rbac);A=r.rbac;const s=l||E,a=await L.getInstance({baseDbDir:t.serverOutDir,removeExisting:l,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),T=await R.getInstance({baseDbDir:t.serverOutDir}),c=new F(T),y=[new x({fileHashManager:c,context:e,catalogEntitiesService:a,catalogConfig:o,shouldCalculateEntities:s}),new H({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:u.OPENAPI_DESCRIPTION,shouldCalculateEntities:s}),new w({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:u.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:s}),new N({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:u.GRAPHQL_DESCRIPTION,shouldCalculateEntities:s}),new G({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:u.ARAZZO_DESCRIPTION,shouldCalculateEntities:s})];n.info("Starting entities extractors...");const h=n.startTiming();await a.transaction(async()=>{await Promise.all(y.map(async D=>D.extract()))});const S=a.getEntitySources();t.setGlobalData({[b]:S}),await(await v.getInstance({baseDbDir:t.serverOutDir})).deleteByNamespace(_),n.infoTime(h,"Entities extractors finished");const g=await I.getCatalogEntitiesData(a);i?.setAttribute("totalEntities",g.totalEntitiesCount),i?.setAttribute("entitiesCountByType",JSON.stringify(g.countOfEntitiesByType)),i?.setAttribute("totalFilesSkippedByHash",g.totalFilesSkippedByHash),i?.setAttribute("totalProcessedFiles",g.totalProcessedFiles),i?.setAttribute("extractors",g.extractors),d=!1})}}}var rt=Y;export{Y as catalogEntitiesPlugin,rt as default};
|
|
@@ -100,6 +100,8 @@ export declare const entitiesRelationsDtoSchema: {
|
|
|
100
100
|
};
|
|
101
101
|
export type EntityRelationDtoSchema = FromSchema<typeof entityRelationDtoSchema>;
|
|
102
102
|
export type EntitiesRelationsDtoSchema = FromSchema<typeof entitiesRelationsDtoSchema>;
|
|
103
|
-
export type EntityDtoSchema = EntityBaseFileSchema
|
|
103
|
+
export type EntityDtoSchema = EntityBaseFileSchema & {
|
|
104
|
+
revision?: string;
|
|
105
|
+
};
|
|
104
106
|
export type EntityAttributesDtoSchema = FromSchema<typeof entityAttributesDtoSchema>;
|
|
105
107
|
//# sourceMappingURL=dto-schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import u from"@redocly/ajv";const o=new u({coerceTypes:!0,removeAdditional:!0,discriminator:!0,allErrors:!0});o.addKeyword({keyword:"nodeTypeName",schemaType:"string"}),o.addFormat("uri",{type:"string",validate:e=>{try{return new URL(e),!0}catch{return!1}}}),o.addFormat("email",{type:"string",validate:e=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)});function f(e,t){const{errorPrefix:a,dataVar:n="data"}=t??{},r=o.compile(e);return function(i){if(!r(i)){const c=r.errors?.length?r.errors.map(s=>{const l=s.instancePath.replaceAll("/",".");return`'${n}${l}' ${s.message}`}).join(", "):"unknown error",d=a?`${a} `:"";throw new Error(`${d}${c}`)}return i}}function h(e,t){const a=o.compile(e),n=a(t);return{success:n,data:n?t:void 0,error:n?void 0:a.errors?.map(r=>`${r.instancePath} ${r.message}`).join(", ")}}export{f as createValidator,h as validateWithResult};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"node:path";import{createConfig as m,loadIgnoreConfig as u}from"@redocly/openapi-core";import{ruleTypes as p}from"@redocly/config";import{ExternalResolver as C}from"../../../fs/utils/external-ref-resolver.js";import{deepMerge as d}from"../../../../utils/object/deep-merge.js";import{CONFIG_FILE_NAME as v}from"../../../../constants/common.js";import{getScorecardConfig as w}from"../get-scorecard-config.js";async function N(i,r){const e=await r.getConfig(),n=w(e),t=n.levels??[],o=l.join(r.fs.cwd,v),f=new C(r.fs),s=await u(o,f),c=await a(t,e.plugins,o,s),g=await y(n.targets,t,e.plugins,o,s);return{levelsConfig:t,configs:c,targets:g}}async function a(i,r=[],e,n){const t={};for(const o of i)t[o.name]=await m({...o,plugins:r},{configPath:e,ignore:n});return t}async function y(i,r,e=[],n,t){return i?Promise.all(i?.filter(o=>!!o.rules).map(async o=>{const f=r.map(s=>({...s,...L(s,o.rules)}));return{...o,configs:await a(f,e,n,t)}})||[]):[]}function L(i,r){return p.reduce((e,n)=>(e[n]=d(i[n]??{},r??{}),e),{})}export{N as scorecardConfigLoader};
|