@redocly/redoc 0.133.0-next.2 → 0.133.0-next.3

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # @redocly/redoc
2
2
 
3
+ ## 0.133.0-next.3
4
+
5
+ ### Minor Changes
6
+
7
+ - e2b2f2e27f3: Updated Markdown links to display a clearer underline with a thicker underline on hover for improved visibility and accessibility.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [e2b2f2e27f3]
12
+ - @redocly/theme@0.65.0-next.3
13
+ - @redocly/asyncapi-docs@1.10.0-next.3
14
+ - @redocly/graphql-docs@1.10.0-next.3
15
+ - @redocly/openapi-docs@3.21.0-next.3
16
+ - @redocly/portal-plugin-mock-server@0.18.0-next.3
17
+
3
18
  ## 0.133.0-next.2
4
19
 
5
20
  ### Minor Changes
@@ -1,12 +1,12 @@
1
- import{and as h,eq as g,inArray as R,isNotNull as A,isNull as E,ne as k,or as I,sql as S}from"drizzle-orm";import{ulid as N}from"ulid";import{logger as F}from"../../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as D}from"../../../providers/database/database-connection-factory.js";import{entitiesAttributesTable as m}from"../../../providers/database/databases/sqlite-db/schemas/entities-attributes-table.js";import{entitiesRelationsTable as u}from"../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{entitiesTable as d}from"../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{BATCH_TRANSIENT_RETRY as $,withTransientErrorRetry as L}from"../../../providers/database/transient-sqld-error.js";import{envConfig as O}from"../../../config/env-config.js";import{ATTRIBUTES_UPSERT_SET as U,DEFAULT_CHUNK_SIZE as B,ENTITIES_UPSERT_SET as K,MAX_BATCH_PAYLOAD_BYTES as M,MAX_LOGGED_DB_ERROR_LENGTH as b,MIN_RETRYABLE_BATCH_SIZE as H,RELATIONS_UPSERT_SET as x}from"./consts.js";class c{static async publishFromLocalToRemote(e){if(O.isDevelopMode)return!1;const{baseDbDir:t,chunkSize:s=B,changedSourceFiles:o=[],removedSourceFiles:n=[]}=e,a=N(),[i,r]=await Promise.all([D.create({baseDbDir:t,databaseType:"local"}),D.create({baseDbDir:t,databaseType:"remote"})]);if(!i||!r)return F.warn("Skipping entities remote sync: local or remote connection is unavailable"),!1;const l="changedSourceFiles"in e||"removedSourceFiles"in e,p=Array.from(new Set([...o,...n]));if(l&&p.length===0)return!0;const y=l?o.length?o:"none":void 0;try{return await c.#i({runId:a,chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#c({runId:a,chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#a({chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#l({runId:a,remoteConnection:r,sourceFilesFilter:l?p:void 0}),!0}catch(f){const w=c.#o(f);throw F.error(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Failed runId=${a}. ${w}`),new Error(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Failed runId=${a}. ${w}`,{cause:f instanceof Error?f:void 0})}}static#i(e){const{runId:t,localConnection:s,remoteConnection:o,sourceFilesFilter:n,chunkSize:a}=e,i=c.#e(n);return c.#t({chunkSize:a,sourceFilesFilter:n,selectRows:(r,l)=>s.client.client.select().from(d).where(h(g(d.source,"file"),i?R(d.sourceFile,i):void 0)).limit(l).offset(r).all(),decorateRow:r=>({...r,lastSeenRunId:t}),runUpsert:async r=>{await o.client.client.insert(d).values(r).onConflictDoUpdate({target:[d.key,d.source,d.revision,d.version],set:K}).run()},describeSkippedRow:r=>`entity key=${String(r.key)}`})}static#c(e){const{runId:t,localConnection:s,remoteConnection:o,sourceFilesFilter:n,chunkSize:a}=e,i=c.#e(n);return c.#t({chunkSize:a,sourceFilesFilter:n,selectRows:(r,l)=>s.client.client.select().from(u).where(h(A(u.sourceFile),i?R(u.sourceFile,i):void 0)).limit(l).offset(r).all(),decorateRow:r=>({...r,lastSeenRunId:t}),runUpsert:async r=>{await o.client.client.insert(u).values(r).onConflictDoUpdate({target:[u.sourceKey,u.targetKey,u.sourceVersion,u.targetVersion,u.sourceRevision,u.targetRevision,u.sourceToTargetRelation],set:x}).run()},describeSkippedRow:r=>{const l=r;return`relation sourceKey=${String(l.sourceKey)} targetKey=${String(l.targetKey)}`}})}static#a(e){const{localConnection:t,remoteConnection:s,sourceFilesFilter:o,chunkSize:n}=e,a=c.#e(o);return c.#t({chunkSize:n,sourceFilesFilter:o,selectRows:(i,r)=>t.client.client.select().from(m).where(a?S`EXISTS (
1
+ import{and as h,eq as g,inArray as R,isNotNull as A,isNull as E,ne as k,or as I,sql as S}from"drizzle-orm";import{ulid as $}from"ulid";import{logger as F}from"../../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as v}from"../../../providers/database/database-connection-factory.js";import{entitiesAttributesTable as m}from"../../../providers/database/databases/sqlite-db/schemas/entities-attributes-table.js";import{entitiesRelationsTable as u}from"../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{entitiesTable as d}from"../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{BATCH_TRANSIENT_RETRY as L,withTransientErrorRetry as O}from"../../../providers/database/transient-sqld-error.js";import{envConfig as D}from"../../../config/env-config.js";import{ATTRIBUTES_UPSERT_SET as U,DEFAULT_CHUNK_SIZE as B,ENTITIES_UPSERT_SET as K,MAX_BATCH_PAYLOAD_BYTES as M,MAX_LOGGED_DB_ERROR_LENGTH as b,MIN_RETRYABLE_BATCH_SIZE as H,RELATIONS_UPSERT_SET as x}from"./consts.js";class c{static async publishFromLocalToRemote(e){if(D.isDevelopMode||!D.isProductionEnv)return!1;const{baseDbDir:t,chunkSize:s=B,changedSourceFiles:o=[],removedSourceFiles:n=[]}=e,a=$(),[i,r]=await Promise.all([v.create({baseDbDir:t,databaseType:"local"}),v.create({baseDbDir:t,databaseType:"remote"})]);if(!i||!r)return F.warn("Skipping entities remote sync: local or remote connection is unavailable"),!1;const l="changedSourceFiles"in e||"removedSourceFiles"in e,p=Array.from(new Set([...o,...n]));if(l&&p.length===0)return!0;const y=l?o.length?o:"none":void 0;try{return await c.#i({runId:a,chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#c({runId:a,chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#a({chunkSize:s,localConnection:i,remoteConnection:r,sourceFilesFilter:y}),await c.#l({runId:a,remoteConnection:r,sourceFilesFilter:l?p:void 0}),!0}catch(f){const w=c.#o(f);throw F.error(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Failed runId=${a}. ${w}`),new Error(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Failed runId=${a}. ${w}`,{cause:f instanceof Error?f:void 0})}}static#i(e){const{runId:t,localConnection:s,remoteConnection:o,sourceFilesFilter:n,chunkSize:a}=e,i=c.#e(n);return c.#t({chunkSize:a,sourceFilesFilter:n,selectRows:(r,l)=>s.client.client.select().from(d).where(h(g(d.source,"file"),i?R(d.sourceFile,i):void 0)).limit(l).offset(r).all(),decorateRow:r=>({...r,lastSeenRunId:t}),runUpsert:async r=>{await o.client.client.insert(d).values(r).onConflictDoUpdate({target:[d.key,d.source,d.revision,d.version],set:K}).run()},describeSkippedRow:r=>`entity key=${String(r.key)}`})}static#c(e){const{runId:t,localConnection:s,remoteConnection:o,sourceFilesFilter:n,chunkSize:a}=e,i=c.#e(n);return c.#t({chunkSize:a,sourceFilesFilter:n,selectRows:(r,l)=>s.client.client.select().from(u).where(h(A(u.sourceFile),i?R(u.sourceFile,i):void 0)).limit(l).offset(r).all(),decorateRow:r=>({...r,lastSeenRunId:t}),runUpsert:async r=>{await o.client.client.insert(u).values(r).onConflictDoUpdate({target:[u.sourceKey,u.targetKey,u.sourceVersion,u.targetVersion,u.sourceRevision,u.targetRevision,u.sourceToTargetRelation],set:x}).run()},describeSkippedRow:r=>{const l=r;return`relation sourceKey=${String(l.sourceKey)} targetKey=${String(l.targetKey)}`}})}static#a(e){const{localConnection:t,remoteConnection:s,sourceFilesFilter:o,chunkSize:n}=e,a=c.#e(o);return c.#t({chunkSize:n,sourceFilesFilter:o,selectRows:(i,r)=>t.client.client.select().from(m).where(a?S`EXISTS (
2
2
  SELECT 1
3
3
  FROM entities e
4
4
  WHERE e.key = ${m.entityKey}
5
5
  AND e.source = 'file'
6
6
  AND e.source_file IN (${S.join(a.map(l=>S`${l}`),S`, `)})
7
- )`:void 0).limit(r).offset(i).all(),runUpsert:async i=>{await s.client.client.insert(m).values(i).onConflictDoUpdate({target:[m.entityKey],set:U}).run()}})}static#e(e){return Array.isArray(e)&&e.length>0?e:void 0}static async#t({chunkSize:e,sourceFilesFilter:t,selectRows:s,decorateRow:o,runUpsert:n,describeSkippedRow:a}){if(t==="none")return{upserted:0,skipped:0};let i=0,r=0,l=0;for(;;){const p=await s(i,e);if(!p.length)return{upserted:r,skipped:l};const y=o?p.map(f=>o(f)):p;for(const f of c.#u(y,e,M)){const w=await c.#n({rows:f,runOperation:n,shouldSkipIsolatedRow:a?(v,T)=>c.#f(T)?(F.warn(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Skipping ${a(v)} due to remote insert error: ${c.#o(T)}`),!0):!1:void 0});r+=w.upserted,l+=w.skipped}i+=e}}static async#l({runId:e,remoteConnection:t,sourceFilesFilter:s}){const o=t.client.client,n=s?.length?s:void 0,a=await c.#r(()=>o.delete(u).where(h(A(u.sourceFile),n?R(u.sourceFile,n):void 0,I(E(u.lastSeenRunId),k(u.lastSeenRunId,e)))).run()),i=await c.#r(()=>o.delete(d).where(h(g(d.source,"file"),n?R(d.sourceFile,n):void 0,I(E(d.lastSeenRunId),k(d.lastSeenRunId,e)))).run()),r=await c.#r(()=>o.delete(m).where(S`NOT EXISTS (
7
+ )`:void 0).limit(r).offset(i).all(),runUpsert:async i=>{await s.client.client.insert(m).values(i).onConflictDoUpdate({target:[m.entityKey],set:U}).run()}})}static#e(e){return Array.isArray(e)&&e.length>0?e:void 0}static async#t({chunkSize:e,sourceFilesFilter:t,selectRows:s,decorateRow:o,runUpsert:n,describeSkippedRow:a}){if(t==="none")return{upserted:0,skipped:0};let i=0,r=0,l=0;for(;;){const p=await s(i,e);if(!p.length)return{upserted:r,skipped:l};const y=o?p.map(f=>o(f)):p;for(const f of c.#u(y,e,M)){const w=await c.#n({rows:f,runOperation:n,shouldSkipIsolatedRow:a?(N,T)=>c.#f(T)?(F.warn(`[CatalogEntitiesPublisher.publishFromLocalToRemote] Skipping ${a(N)} due to remote insert error: ${c.#o(T)}`),!0):!1:void 0});r+=w.upserted,l+=w.skipped}i+=e}}static async#l({runId:e,remoteConnection:t,sourceFilesFilter:s}){const o=t.client.client,n=s?.length?s:void 0,a=await c.#r(()=>o.delete(u).where(h(A(u.sourceFile),n?R(u.sourceFile,n):void 0,I(E(u.lastSeenRunId),k(u.lastSeenRunId,e)))).run()),i=await c.#r(()=>o.delete(d).where(h(g(d.source,"file"),n?R(d.sourceFile,n):void 0,I(E(d.lastSeenRunId),k(d.lastSeenRunId,e)))).run()),r=await c.#r(()=>o.delete(m).where(S`NOT EXISTS (
8
8
  SELECT 1
9
9
  FROM entities e
10
10
  WHERE e.key = ${m.entityKey}
11
11
  AND COALESCE(e.is_deleted, 0) = 0
12
- )`).run());return{staleEntitiesDeleted:i,staleRelationsDeleted:a,orphanAttributesDeleted:r}}static async#r(e){const t=await c.#s(e);return Number(t.rowsAffected??0)}static#u(e,t,s){const o=[];let n=[],a=0;for(const i of e){const r=c.#d(i);n.length>0&&(n.length>=t||a+r>s)&&(o.push(n),n=[],a=0),n.push(i),a+=r}return n.length>0&&o.push(n),o}static#d(e){try{return JSON.stringify(e).length}catch{return 0}}static async#n({rows:e,runOperation:t,shouldSkipIsolatedRow:s}){try{return await c.#s(()=>t(e)),{upserted:e.length,skipped:0}}catch(o){if(e.length<H){if(!s)throw o;if(await s(e[0],o))return{upserted:0,skipped:1};throw o}const n=Math.floor(e.length/2),a=await c.#n({rows:e.slice(0,n),runOperation:t,shouldSkipIsolatedRow:s}),i=await c.#n({rows:e.slice(n),runOperation:t,shouldSkipIsolatedRow:s});return{upserted:a.upserted+i.upserted,skipped:a.skipped+i.skipped}}}static#f(e){if(!(e instanceof Error))return!1;const t=e.message.toLowerCase();return t.includes("code: 11")||t.includes("too many sql variables")||t.includes("string or blob too big")||t.includes("statement too long")||t.includes("request body too large")||t.includes("payload too large")||t.includes("body too large")||t.includes("resource exhausted")}static#o(e){const s=(e instanceof Error?e.message:typeof e=="string"?e:JSON.stringify(e)).split(" params:")[0],n=c.#p(s).replace(/\s+/g," ").trim();return n.length>b?`${n.slice(0,b)}...`:n}static#p(e){const t="Failed query:",s=e.indexOf(t);if(s===-1)return e;const o=e.slice(0,s).trim();return o?`${o}. ${t} <omitted for brevity>`:`${t} <omitted for brevity>`}static#s(e){return L(e,$)}}export{c as CatalogEntitiesPublisher};
12
+ )`).run());return{staleEntitiesDeleted:i,staleRelationsDeleted:a,orphanAttributesDeleted:r}}static async#r(e){const t=await c.#s(e);return Number(t.rowsAffected??0)}static#u(e,t,s){const o=[];let n=[],a=0;for(const i of e){const r=c.#d(i);n.length>0&&(n.length>=t||a+r>s)&&(o.push(n),n=[],a=0),n.push(i),a+=r}return n.length>0&&o.push(n),o}static#d(e){try{return JSON.stringify(e).length}catch{return 0}}static async#n({rows:e,runOperation:t,shouldSkipIsolatedRow:s}){try{return await c.#s(()=>t(e)),{upserted:e.length,skipped:0}}catch(o){if(e.length<H){if(!s)throw o;if(await s(e[0],o))return{upserted:0,skipped:1};throw o}const n=Math.floor(e.length/2),a=await c.#n({rows:e.slice(0,n),runOperation:t,shouldSkipIsolatedRow:s}),i=await c.#n({rows:e.slice(n),runOperation:t,shouldSkipIsolatedRow:s});return{upserted:a.upserted+i.upserted,skipped:a.skipped+i.skipped}}}static#f(e){if(!(e instanceof Error))return!1;const t=e.message.toLowerCase();return t.includes("code: 11")||t.includes("too many sql variables")||t.includes("string or blob too big")||t.includes("statement too long")||t.includes("request body too large")||t.includes("payload too large")||t.includes("body too large")||t.includes("resource exhausted")}static#o(e){const s=(e instanceof Error?e.message:typeof e=="string"?e:JSON.stringify(e)).split(" params:")[0],n=c.#p(s).replace(/\s+/g," ").trim();return n.length>b?`${n.slice(0,b)}...`:n}static#p(e){const t="Failed query:",s=e.indexOf(t);if(s===-1)return e;const o=e.slice(0,s).trim();return o?`${o}. ${t} <omitted for brevity>`:`${t} <omitted for brevity>`}static#s(e){return O(e,L)}}export{c as CatalogEntitiesPublisher};
@@ -1 +1 @@
1
- import{and as v,eq as c,isNull as R,or as z,sql as V}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as F}from"@redocly/theme/core/constants";import{telemetryTraceStep as C}from"../../../../../telemetry/helpers/trace-step.js";import{sha1 as _}from"../../../../../utils/crypto/sha1.js";import{logger as d}from"../../../../../tools/notifiers/logger.js";import{envConfig as K}from"../../../../../config/env-config.js";import{entitiesTable as i}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{convertFilterToWhereCondition as O}from"../../../../../providers/database/pagination/filter.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{RevisionRepository as H}from"../common/revision-repository.js";import{VersionRepository as $}from"../common/version-repository.js";import{EntityAttributesWriteRepository as P}from"../entityAttributes/entity-attributes-write-repository.js";import{createEntityDbRecord as W}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as D}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromFileSchema as b}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{createEntityRelationDbRecordFromDto as j}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{EntitiesReadRepository as G}from"./entities-read-repository.js";import{RelationsReadRepository as M}from"../relations/relations-read-repository.js";import{RelationsWriteRepository as q}from"../relations/relations-write-repository.js";const E=15;class fe{#e;#t;#n;#o;#r;#i;#a;#u;#s;constructor(e,t,s){this.#e=e,this.#r=t,this.#i=s,this.#t=new H(e),this.#n=new $(e),this.#o=new P(e),this.#a=new G(e),this.#u=new M(e),this.#s=new q(e,t,s)}async createEntity({entity:e,source:t,fileHash:s,sourceFile:n,isRootEntity:r,isDeleted:o,rbacTeams:u,errorOnSkip:h=!1,revision:f}){return C("catalog_entities.remote_repository.create_entity",async()=>{const{relations:l=[],...p}=e,y=_(JSON.stringify(p)),g=e.version??F,A=f??new Date().toISOString(),L=await this.#t.shouldSkipRevisionCreation(e.key,g,y,r,o);if(Array.isArray(u)&&await this.#o.upsertEntityAttributes({entityKey:e.key,rbacTeams:u,organizationId:this.#r,projectId:this.#i}),L){if(h)throw new Error("Entity validation failed: entity already exists");return d.warn(`Entity ${e.key} already exists, skipping creation`),null}const{shouldSetNewCurrentRevision:w,hasCurrentRevision:x}=await this.#t.getCurrentRevisionInfo({key:e.key,version:g,revision:A}),k=W({entity:{...e,revision:A,hash:y,isCurrent:w,isDefaultVersion:w,isDeleted:o,version:g},organizationId:this.#r,projectId:this.#i,source:t,sourceFile:n??null,fileHash:s??null}),{key:S,...T}=k;if(w&&x&&(await this.#t.markAllRevisionsAsNotCurrent(S),await this.#n.markAllVersionsAsNotDefault(S)),K.isDevelopMode&&!K.REDOCLY_INTERNAL_DEV)return await this.#l(k,l);const N=await this.#e.client.insert(i).values(k).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:T}).returning();return N.length?(l&&await this.#s.createEntityRelations(l.map(I=>({...I,sourceKey:e.key,targetKey:I.key}))),D(N[0])):null})}async updateEntity(e,t){return C("catalog_entities.remote_repository.update_entity",async()=>{try{d.info(`Updating entity ${t.key} in remote database`);const{shouldSetNewCurrentRevision:s,hasCurrentRevision:n}=await this.#t.getCurrentRevisionInfo({key:t.key,version:e.version??t.version??F,revision:t.revision});s&&n&&(await this.#t.markAllRevisionsAsNotCurrent(t.key),await this.#n.markAllVersionsAsNotDefault(t.key));const r=W({entity:{...t,...e,hash:_(JSON.stringify({...t,...e})),isCurrent:s,isDefaultVersion:s,createdAt:t.createdAt??void 0},organizationId:this.#r,projectId:this.#i,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,scorecardsStatus:h,...f}=r,l=await this.#e.client.insert(i).values(r).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...f,scorecardsStatus:V`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return l.length?D(l[0]):null}catch(s){return d.error("Error updating entity",s),null}})}async setEntitiesAsOutdated(e){try{const t=O(e);await this.#e.client.update(i).set({scorecardsStatus:"OUTDATED"}).where(t)}catch(t){d.error("Error updating entities as outdated",t)}}async#l(e,t){const{key:s,source:n,version:r,isDefaultVersion:o,...u}=e,l=await this.#e.client.select({id:i.id}).from(i).where(v(c(i.key,s),r?c(i.version,r):R(i.version))).limit(1).get()!=null?await this.#e.client.update(i).set(u).where(v(c(i.key,s),r?c(i.version,r):R(i.version))).returning():await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:u}).returning(),p=t?.map(y=>{const g=b({relation:y,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#r,projectId:this.#i});return this.#e.client.insert(a).values(g).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision,a.sourceToTargetRelation],set:g}).run()})??[];return await m(p,E,async y=>y),D(l[0])}async softDeleteEntitiesWithRelations({filter:e,revision:t,fileHash:s}){const r={op:"AND",conditions:[e,{field:"is_deleted",operator:"equal",value:!1}]};for(;;){const o=await this.#a.getEntities({paginationParams:{filter:r,limit:500}});if(o.items.length===0)break;const u=await this.#c({entities:o.items,revision:t,fileHash:s});await this.#d(u,t)}}async deleteEntity(e){return C("catalog_entities.remote_repository.delete_entity",async()=>{try{return await this.#s.deleteEntityRelationsOnEntityRemoval(e),await this.#e.client.delete(i).where(c(i.id,e.id)),await this.#t.ensureDefaultAndCurrentRevisionForKey(e.key),e.id}catch(t){return d.error("Error deleting entity",t),null}})}async deleteEntities(e){try{const t=O(e);if(!t)return!1;const s=await this.#e.client.delete(i).where(t).returning({key:i.key,source:i.source,isCurrent:i.isCurrent,isDefaultVersion:i.isDefaultVersion,version:i.version});if(s.length===0)return!0;const n=s.reduce((r,o)=>((o.isCurrent||o.isDefaultVersion)&&r.add(o.key),r),new Set);if(n.size===0)return!0;await m(Array.from(n),E,async r=>this.#t.ensureDefaultAndCurrentRevisionForKey(r));for(const r of s)await this.#e.client.delete(a).where(z(v(c(a.sourceKey,r.key),...r.version?[c(a.sourceVersion,r.version)]:[R(a.sourceVersion)]),v(c(a.targetKey,r.key),...r.version?[c(a.targetVersion,r.version)]:[R(a.targetVersion)])));return!0}catch(t){return d.error("Error deleting entities",t),!1}}async updateEntityScorecardsStatus(e,t){try{return(await this.#e.client.update(i).set({scorecardsStatus:t}).where(c(i.id,e)).returning()).length>0}catch(s){return d.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(e,t){try{return(await this.#e.client.update(i).set({scorecardsStatus:t}).where(V`${i.id} = ${e} AND ${i.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return d.error("Error updating entity scorecards status if calculating",s),!1}}async#c({entities:e,revision:t,fileHash:s}){try{return(await m(e,E,async r=>{const o={type:r.type,key:r.key,title:r.title,summary:r.summary??void 0,tags:r.tags??void 0,metadata:r.metadata??void 0,git:r.git??void 0,contact:r.contact??void 0,links:r.links??void 0,version:r.version??void 0};return this.createEntity({entity:o,sourceFile:r.sourceFile??"",fileHash:s,isDeleted:!0,errorOnSkip:!1,source:r.source,revision:t})})).filter(r=>r!==null)}catch(n){return d.error("Error soft deleting entities",n),[]}}async#d(e,t){try{if(e.length===0)return!0;const s=await m(e,E,async n=>(await this.#u.getRelationsForEntity(n.key,n.version,t)).map(o=>{if(!o)return null;const u=o.direction,h=o.sourceToTargetRelation,f=o.targetKey,l=u==="outgoing"?n.key:f,p=u==="outgoing"?f:n.key,y=u==="outgoing"?h:h.startsWith("reverse:")?h.slice(8):h;return!y||!l||!p?null:j({type:y,sourceKey:l,targetKey:p,sourceVersion:n.version,targetVersion:n.version,sourceRevision:t,targetRevision:t,isDeleted:!0},this.#r,this.#i)}).filter(o=>o!==null));return await m(s.flat(),E,async n=>this.#s.upsertEntityRelation(n)),!0}catch(s){return d.error("Error soft deleting entity relations",s),!1}}}export{fe as EntitiesWriteRepository};
1
+ import{and as v,eq as c,isNull as R,or as z,sql as V}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as F}from"@redocly/theme/core/constants";import{telemetryTraceStep as C}from"../../../../../telemetry/helpers/trace-step.js";import{sha1 as _}from"../../../../../utils/crypto/sha1.js";import{logger as y}from"../../../../../tools/notifiers/logger.js";import{envConfig as K}from"../../../../../config/env-config.js";import{entitiesTable as i}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{convertFilterToWhereCondition as O}from"../../../../../providers/database/pagination/filter.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{RevisionRepository as H}from"../common/revision-repository.js";import{VersionRepository as P}from"../common/version-repository.js";import{EntityAttributesWriteRepository as $}from"../entityAttributes/entity-attributes-write-repository.js";import{createEntityDbRecord as W}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as D}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromFileSchema as b}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{createEntityRelationDbRecordFromDto as j}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{EntitiesReadRepository as G}from"./entities-read-repository.js";import{RelationsReadRepository as M}from"../relations/relations-read-repository.js";import{RelationsWriteRepository as q}from"../relations/relations-write-repository.js";const E=15;class fe{#e;#t;#n;#o;#r;#i;#a;#u;#s;constructor(e,t,s){this.#e=e,this.#r=t,this.#i=s,this.#t=new H(e),this.#n=new P(e),this.#o=new $(e),this.#a=new G(e),this.#u=new M(e),this.#s=new q(e,t,s)}async createEntity({entity:e,source:t,fileHash:s,sourceFile:n,isRootEntity:r,isDeleted:o,rbacTeams:u,errorOnSkip:h=!1,revision:f}){return C("catalog_entities.remote_repository.create_entity",async()=>{const{relations:l=[],...p}=e,d=_(JSON.stringify(p)),g=e.version??F,A=f??new Date().toISOString(),L=await this.#t.shouldSkipRevisionCreation(e.key,g,d,r,o);if(Array.isArray(u)&&await this.#o.upsertEntityAttributes({entityKey:e.key,rbacTeams:u,organizationId:this.#r,projectId:this.#i}),L){if(h)throw new Error("Entity validation failed: entity already exists");return null}const{shouldSetNewCurrentRevision:w,hasCurrentRevision:T}=await this.#t.getCurrentRevisionInfo({key:e.key,version:g,revision:A}),k=W({entity:{...e,revision:A,hash:d,isCurrent:w,isDefaultVersion:w,isDeleted:o,version:g},organizationId:this.#r,projectId:this.#i,source:t,sourceFile:n??null,fileHash:s??null}),{key:S,...x}=k;if(w&&T&&(await this.#t.markAllRevisionsAsNotCurrent(S),await this.#n.markAllVersionsAsNotDefault(S)),K.isDevelopMode&&!K.REDOCLY_INTERNAL_DEV)return await this.#l(k,l);const N=await this.#e.client.insert(i).values(k).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:x}).returning();return N.length?(l&&await this.#s.createEntityRelations(l.map(I=>({...I,sourceKey:e.key,targetKey:I.key}))),D(N[0])):null})}async updateEntity(e,t){return C("catalog_entities.remote_repository.update_entity",async()=>{try{y.info(`Updating entity ${t.key} in remote database`);const{shouldSetNewCurrentRevision:s,hasCurrentRevision:n}=await this.#t.getCurrentRevisionInfo({key:t.key,version:e.version??t.version??F,revision:t.revision});s&&n&&(await this.#t.markAllRevisionsAsNotCurrent(t.key),await this.#n.markAllVersionsAsNotDefault(t.key));const r=W({entity:{...t,...e,hash:_(JSON.stringify({...t,...e})),isCurrent:s,isDefaultVersion:s,createdAt:t.createdAt??void 0},organizationId:this.#r,projectId:this.#i,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,scorecardsStatus:h,...f}=r,l=await this.#e.client.insert(i).values(r).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...f,scorecardsStatus:V`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return l.length?D(l[0]):null}catch(s){return y.error("Error updating entity",s),null}})}async setEntitiesAsOutdated(e){try{const t=O(e);await this.#e.client.update(i).set({scorecardsStatus:"OUTDATED"}).where(t)}catch(t){y.error("Error updating entities as outdated",t)}}async#l(e,t){const{key:s,source:n,version:r,isDefaultVersion:o,...u}=e,l=await this.#e.client.select({id:i.id}).from(i).where(v(c(i.key,s),r?c(i.version,r):R(i.version))).limit(1).get()!=null?await this.#e.client.update(i).set(u).where(v(c(i.key,s),r?c(i.version,r):R(i.version))).returning():await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:u}).returning(),p=t?.map(d=>{const g=b({relation:d,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#r,projectId:this.#i});return this.#e.client.insert(a).values(g).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision,a.sourceToTargetRelation],set:g}).run()})??[];return await m(p,E,async d=>d),D(l[0])}async softDeleteEntitiesWithRelations({filter:e,revision:t,fileHash:s}){const r={op:"AND",conditions:[e,{field:"is_deleted",operator:"equal",value:!1}]};for(;;){const o=await this.#a.getEntities({paginationParams:{filter:r,limit:500}});if(o.items.length===0)break;const u=await this.#c({entities:o.items,revision:t,fileHash:s});await this.#d(u,t)}}async deleteEntity(e){return C("catalog_entities.remote_repository.delete_entity",async()=>{try{return await this.#s.deleteEntityRelationsOnEntityRemoval(e),await this.#e.client.delete(i).where(c(i.id,e.id)),await this.#t.ensureDefaultAndCurrentRevisionForKey(e.key),e.id}catch(t){return y.error("Error deleting entity",t),null}})}async deleteEntities(e){try{const t=O(e);if(!t)return!1;const s=await this.#e.client.delete(i).where(t).returning({key:i.key,source:i.source,isCurrent:i.isCurrent,isDefaultVersion:i.isDefaultVersion,version:i.version});if(s.length===0)return!0;const n=s.reduce((r,o)=>((o.isCurrent||o.isDefaultVersion)&&r.add(o.key),r),new Set);if(n.size===0)return!0;await m(Array.from(n),E,async r=>this.#t.ensureDefaultAndCurrentRevisionForKey(r));for(const r of s)await this.#e.client.delete(a).where(z(v(c(a.sourceKey,r.key),...r.version?[c(a.sourceVersion,r.version)]:[R(a.sourceVersion)]),v(c(a.targetKey,r.key),...r.version?[c(a.targetVersion,r.version)]:[R(a.targetVersion)])));return!0}catch(t){return y.error("Error deleting entities",t),!1}}async updateEntityScorecardsStatus(e,t){try{return(await this.#e.client.update(i).set({scorecardsStatus:t}).where(c(i.id,e)).returning()).length>0}catch(s){return y.error("Error updating entity scorecards status",s),!1}}async updateEntityScorecardsStatusIfCalculating(e,t){try{return(await this.#e.client.update(i).set({scorecardsStatus:t}).where(V`${i.id} = ${e} AND ${i.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(s){return y.error("Error updating entity scorecards status if calculating",s),!1}}async#c({entities:e,revision:t,fileHash:s}){try{return(await m(e,E,async r=>{const o={type:r.type,key:r.key,title:r.title,summary:r.summary??void 0,tags:r.tags??void 0,metadata:r.metadata??void 0,git:r.git??void 0,contact:r.contact??void 0,links:r.links??void 0,version:r.version??void 0};return this.createEntity({entity:o,sourceFile:r.sourceFile??"",fileHash:s,isDeleted:!0,errorOnSkip:!1,source:r.source,revision:t})})).filter(r=>r!==null)}catch(n){return y.error("Error soft deleting entities",n),[]}}async#d(e,t){try{if(e.length===0)return!0;const s=await m(e,E,async n=>(await this.#u.getRelationsForEntity(n.key,n.version,t)).map(o=>{if(!o)return null;const u=o.direction,h=o.sourceToTargetRelation,f=o.targetKey,l=u==="outgoing"?n.key:f,p=u==="outgoing"?f:n.key,d=u==="outgoing"?h:h.startsWith("reverse:")?h.slice(8):h;return!d||!l||!p?null:j({type:d,sourceKey:l,targetKey:p,sourceVersion:n.version,targetVersion:n.version,sourceRevision:t,targetRevision:t,isDeleted:!0},this.#r,this.#i)}).filter(o=>o!==null));return await m(s.flat(),E,async n=>this.#s.upsertEntityRelation(n)),!0}catch(s){return y.error("Error soft deleting entity relations",s),!1}}}export{fe as EntitiesWriteRepository};
@@ -1 +1 @@
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};
1
+ import{FileHashStatus as A,FileType as f}from"../../persistence/file-hashes/types.js";import{envConfig as F}from"../../config/env-config.js";import{CATALOG_BASE_SLUG as h}from"../../../constants/catalog-entities.js";import{telemetryTraceStep as N}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as m}from"./utils/catalog-data-collector.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as H,ENTITIES_MAP_GLOBAL_DATA_KEY as L}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 x}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as B}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as M}from"../../persistence/file-hashes/services/file-hashes-service.js";import{CatalogEntitiesService as k}from"./database/catalog-entities-service.js";import{CatalogEntitiesPublisher as Y}from"./database/catalog-entities-publisher.js";import{ArazzoEntitiesExtractor as j}from"./extensions/extractors/api-description/arazzo-entities-extractor.js";import{FsEntitiesExtractor as q}from"./extensions/extractors/fs-entities-extractor.js";import{HashManager as z}from"./utils/hash-manager.js";import{RbacConfigHashCache as U}from"./utils/rbac-config-hash-cache.js";import{OpenApiEntitiesExtractor as W}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const J="catalog-entity-template",Z="catalog-entity";let D=!0;async function $(){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,s=t.registerServerPropsGetter(Z,b("../get-server-props.js")),g=t.createTemplate(J,b("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:h,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[s],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 N("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:s}=e;m.resetForRun();const g=D&&F.isDevelopMode,n=await G.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),T=new U(n),{rbacConfigChanged:p}=await T.syncAndDetectChange(r.access?.rbac??null),l=g||p,a=await k.getInstance({baseDbDir:t.serverOutDir,removeExisting:g,databaseType:"local",runWithPragmaWalWriteOptimization:!0}),E=await M.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),c=new z(E),S=[new q({fileHashManager:c,context:e,catalogEntitiesService:a,catalogConfig:o,shouldCalculateEntities:l}),new W({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:f.OPENAPI_DESCRIPTION,shouldCalculateEntities:l}),new x({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:f.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:l}),new B({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:f.GRAPHQL_DESCRIPTION,shouldCalculateEntities:l}),new j({actions:t,context:e,catalogEntitiesService:a,fileHashManager:c,fileType:f.ARAZZO_DESCRIPTION,shouldCalculateEntities:l})];s.info("Starting entities extractors...");const P=s.startTiming();await a.transaction(async()=>{await Promise.all(S.map(async d=>d.extract()))});const O=a.getEntitySources();t.setGlobalData({[L]:O}),await n.deleteByNamespace(H),s.infoTime(P,"Entities extractors finished");const{changedSourceFiles:I,removedSourceFiles:C}=m.getPublishDelta(),_=s.startTiming();await Y.publishFromLocalToRemote(p?{baseDbDir:t.serverOutDir}:{baseDbDir:t.serverOutDir,changedSourceFiles:I,removedSourceFiles:C})&&s.infoTime(_,"Entities published to the database"),C.length&&await E.deleteFileHashes({op:"AND",conditions:[{field:"status",operator:"equal",value:A.OUTDATED},{field:"file_path",operator:"in",value:C}]});const v=m.getFileHashConfirmations();for(const{fileType:d,filePath:w,hash:R}of v)await E.upsertFileHash({fileType:d,filePath:w,hash:R,status:A.UP_TO_DATE});const u=await m.getCatalogEntitiesData(a);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 Ct=$;export{$ as catalogEntitiesPlugin,Ct as default};
@@ -1 +1 @@
1
- import{envConfig as t}from"../../../../config/env-config.js";async function u({ctx:r,catalogEntitiesService:s,addedEntities:n,removedEntities:a}){if(t.REDOCLY_ENV!=="production"){r.get("logger").info("Skipping pages stats upsert in non-production environment");return}if(!t.BH_API_URL||!t.ORGANIZATION_ID||!t.PROJECT_ID)throw new Error("Pages stats service not configured");const o=r.req.header("apiKey");if(!o)throw new Error("API key is required to upsert pages stats");const{total:i}=await s.getEntitiesCount("remote",n,a?.length),p={remoteEntityPages:i,isReported:!1},g=new URL(`/api/orgs/${t.ORGANIZATION_ID}/projects/${t.PROJECT_ID}/project-pages-stats`,t.BH_API_URL).toString();try{const e=await fetch(g,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(p)});if(!e.ok)throw new Error(e.statusText)}catch(e){throw new Error(`Failed to upsert project pages stats: ${e?.message}`)}}export{u as upsertPagesStats};
1
+ import{envConfig as t}from"../../../../config/env-config.js";async function u({ctx:r,catalogEntitiesService:s,addedEntities:n,removedEntities:i}){if(!t.isProductionEnv){r.get("logger").info("Skipping pages stats upsert in non-production environment");return}if(!t.BH_API_URL||!t.ORGANIZATION_ID||!t.PROJECT_ID)throw new Error("Pages stats service not configured");const o=r.req.header("apiKey");if(!o)throw new Error("API key is required to upsert pages stats");const{total:a}=await s.getEntitiesCount("remote",n,i?.length),p={remoteEntityPages:a,isReported:!1},g=new URL(`/api/orgs/${t.ORGANIZATION_ID}/projects/${t.PROJECT_ID}/project-pages-stats`,t.BH_API_URL).toString();try{const e=await fetch(g,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(p)});if(!e.ok)throw new Error(e.statusText)}catch(e){throw new Error(`Failed to upsert project pages stats: ${e?.message}`)}}export{u as upsertPagesStats};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/redoc",
3
- "version": "0.133.0-next.2",
3
+ "version": "0.133.0-next.3",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -90,14 +90,14 @@
90
90
  "xpath": "0.0.34",
91
91
  "yaml-ast-parser": "0.0.43",
92
92
  "zod": "^3.25.76",
93
- "@redocly/asyncapi-docs": "1.10.0-next.2",
93
+ "@redocly/asyncapi-docs": "1.10.0-next.3",
94
94
  "@redocly/config": "0.48.1",
95
- "@redocly/graphql-docs": "1.10.0-next.2",
96
- "@redocly/openapi-docs": "3.21.0-next.2",
95
+ "@redocly/graphql-docs": "1.10.0-next.3",
96
+ "@redocly/openapi-docs": "3.21.0-next.3",
97
97
  "@redocly/portal-legacy-ui": "0.16.0-next.0",
98
- "@redocly/portal-plugin-mock-server": "0.18.0-next.2",
98
+ "@redocly/portal-plugin-mock-server": "0.18.0-next.3",
99
99
  "@redocly/realm-asyncapi-sdk": "0.11.0-next.2",
100
- "@redocly/theme": "0.65.0-next.2"
100
+ "@redocly/theme": "0.65.0-next.3"
101
101
  },
102
102
  "peerDependencies": {
103
103
  "react": "^19.2.4",