@redocly/revel-reef 0.130.0-next.4 → 0.130.0-next.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/bin.js +1 -1
  3. package/dist/cli/prepare/copy-env-files.js +1 -1
  4. package/dist/constants/common.d.ts +1 -0
  5. package/dist/constants/common.js +1 -1
  6. package/dist/server/api-routes/execute-api-route.js +1 -1
  7. package/dist/server/constants/plugins/catalog-entities.d.ts +1 -0
  8. package/dist/server/constants/plugins/catalog-entities.js +1 -1
  9. package/dist/server/esbuild/esbuild.js +3 -3
  10. package/dist/server/node-bundle-entry.js +1 -1
  11. package/dist/server/persistence/kv/repositories/kv-remote-repository.d.ts +1 -0
  12. package/dist/server/persistence/kv/repositories/kv-remote-repository.js +2 -1
  13. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +4 -4
  14. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +2 -2
  15. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
  16. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
  17. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  18. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  19. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +54 -0
  20. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +1 -0
  21. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +9 -8
  22. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
  23. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +9 -8
  24. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
  25. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +9 -8
  26. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
  27. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +9 -8
  28. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
  29. package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +7 -13
  30. package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
  31. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +9 -6
  32. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
  33. package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +9 -2
  34. package/dist/server/plugins/mcp/docs-mcp/tools/search.js +1 -1
  35. package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +2 -1
  36. package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
  37. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +9 -2
  38. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
  39. package/dist/server/plugins/mcp/handlers/handle-mcp-request.d.ts +5 -0
  40. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -0
  41. package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -1
  42. package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +1 -1
  43. package/dist/server/plugins/mcp/types.d.ts +40 -0
  44. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +3 -0
  45. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -0
  46. package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.d.ts +12 -0
  47. package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.js +1 -0
  48. package/dist/server/plugins/scorecards/database/scorecards-config-service.d.ts +11 -0
  49. package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -0
  50. package/dist/server/plugins/scorecards/workers/run-scorecards-worker.d.ts +2 -1
  51. package/dist/server/plugins/scorecards/workers/run-scorecards-worker.js +1 -1
  52. package/dist/server/plugins/scorecards/workers/scorecards.d.ts +2 -0
  53. package/dist/server/plugins/scorecards/workers/scorecards.js +1 -1
  54. package/dist/server/providers/database/base-repository.d.ts +1 -0
  55. package/dist/server/providers/database/base-repository.js +1 -1
  56. package/dist/server/providers/database/database-connection-factory.js +1 -1
  57. package/dist/server/providers/database/databases/main-sqlite/migrations/0006_change-scorecards-config-timestamps-field-types.sql +19 -0
  58. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0006_snapshot.json +261 -0
  59. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/_journal.json +7 -0
  60. package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.d.ts +24 -18
  61. package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.js +1 -1
  62. package/dist/server/ssr/server-side-props/get-server-props-from-user-handler.js +1 -1
  63. package/dist/server/store.d.ts +3 -1
  64. package/dist/server/store.js +1 -1
  65. package/dist/server/types/plugins/common.d.ts +3 -1
  66. package/dist/server/utils/envs/load-env-variables.d.ts +1 -1
  67. package/dist/server/utils/envs/load-env-variables.js +1 -1
  68. package/dist/server/utils/envs/sanitize-branch-name.d.ts +6 -0
  69. package/dist/server/utils/envs/sanitize-branch-name.js +1 -0
  70. package/dist/server/utils/lifecycle-hooks.js +1 -1
  71. package/dist/server/utils/time/with-timestamp.d.ts +42 -10
  72. package/dist/server/utils/time/with-timestamp.js +1 -1
  73. package/dist/server/web-server/dev-server.js +1 -1
  74. package/dist/server/web-server/handle-api-route-request.js +1 -1
  75. package/dist/server/workers/mcp-tool-worker-pool.d.ts +4 -0
  76. package/dist/server/workers/mcp-tool-worker-pool.js +1 -0
  77. package/dist/server/workers/mcp-tool-worker.d.ts +2 -0
  78. package/dist/server/workers/mcp-tool-worker.js +1 -0
  79. package/dist/server/workers/types.d.ts +6 -0
  80. package/dist/utils/env/is-local-development.js +1 -1
  81. package/package.json +7 -7
  82. package/dist/server/plugins/mcp/workers/run-api-routes-worker.d.ts +0 -5
  83. package/dist/server/plugins/mcp/workers/run-api-routes-worker.js +0 -1
  84. package/dist/server/workers/mcp-worker-pool.d.ts +0 -4
  85. package/dist/server/workers/mcp-worker-pool.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @redocly/revel-reef
2
2
 
3
+ ## 0.130.0-next.5
4
+
5
+ ### Minor Changes
6
+
7
+ - f117f86b3b: Added `login-button` Markdoc tag to render a login button on project pages.
8
+
9
+ ### Patch Changes
10
+
11
+ - 2db5a19a31: Fixed an issue where project builds could fail due to unset environment variables, despite the variables existing in the cloud environment.
12
+ - 1ff6da217d: Added support for branch-specific configuration in `redocly.yaml`.
13
+ - 80e735d6d3: Updated `@redocly/openapi-core` to version `2.14.7`.
14
+ - Updated dependencies [80e735d6d3]
15
+ - Updated dependencies [f117f86b3b]
16
+ - @redocly/openapi-docs@3.18.0-next.4
17
+ - @redocly/theme@0.62.0-next.3
18
+ - @redocly/asyncapi-docs@1.7.0-next.4
19
+ - @redocly/portal-plugin-mock-server@0.15.0-next.4
20
+ - @redocly/graphql-docs@1.7.0-next.0
21
+
3
22
  ## 0.130.0-next.4
4
23
 
5
24
  ### Patch Changes
package/dist/bin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import"./cli/utils/node-version-check.js";import o from"mri";import*as r from"node:path";import{tmpdir as A}from"node:os";import*as x from"node:fs";import"./server/node-fetch-polyfill.js";import{cliCommandNames as g}from"./constants/common.js";import{initPlugins as T}from"./server/plugins/lifecycle.js";import{loadEnvVariables as y}from"./server/utils/envs/load-env-variables.js";import{PORTAL_VERSION as k}from"./server/version.js";import{logger as p}from"./server/tools/notifiers/logger.js";import{reporter as t}from"./server/tools/notifiers/reporter.js";import{sha as R}from"./server/utils/crypto/sha.js";import{develop as S}from"./cli/develop.js";import{eject as V}from"./cli/eject/index.js";import{beforeCommand as w}from"./server/utils/lifecycle-hooks.js";import{Store as C}from"./server/store.js";import{prepare as I}from"./cli/prepare/index.js";import{fromCurrentDir as L}from"./server/utils/paths.js";import{translationsCliOpts as M}from"./cli/translations/options.js";import{generateTranslations as N}from"./cli/translations/index.js";import{EntitlementsProvider as _}from"./server/entitlements/entitlements-provider.js";import{isValidPlan as F}from"./server/entitlements/is-valid-plan.js";import{stopAllCompilers as U}from"./server/esbuild/esbuild.js";import{copyLibsqlPrebuiltBinary as $}from"./cli/prepare/libsql/copy-prebuilt-binary.js";import{telemetry as d}from"./cli/telemetry/index.js";import{stats as q}from"./cli/stats/index.js";import{statsCliOpts as B}from"./cli/stats/options.js";const n=process.argv[2];let i;const f={alias:{d:"project-dir",p:"port"},default:{"project-dir":process.env.REDOCLY_CONTENT_DIR||process.cwd(),outdir:"public"}},G={alias:f.alias,default:{...f.default,plan:"enterprise"}},Y={alias:{d:"prepareDir"},default:{prepareDir:"public"}},z={boolean:["force"],alias:{f:"force",d:"project-dir"},default:{"project-dir":process.cwd()}};process.on("uncaughtException",async function(e){e?.code==="ERR_INVALID_STATE"?console.log("Ignore premature close error"):(p.error("Uncaught exception occurred. Stopping compilers."),await U(),p.error("Exiting due to uncaught exception"),await t.panic(e))});try{n||await t.panicOnContentError("Command not specified.");const e=_.instance();switch(["prepare","serve","stats"].includes(n)&&await e.init(),["eject","translate"].includes(n)&&await e.init({developModePlan:"enterprise"}),n){case"develop":case"preview":const a=o(process.argv.slice(3),G),E=r.resolve(a["project-dir"]),j=r.join(A(),"redocly-public-"+R(E)),l=a.plan.toLowerCase();F(l)||await t.panicOnContentError(`Invalid --plan argument value '${l}'.`),await e.init({developModePlan:l}),i=new C({contentDir:r.resolve(a["project-dir"]),outdir:j,serverOutDir:L(import.meta.url,"./server/esbuild/cache/server")}),await w(g.DEVELOP,a,i),await S(a,i);break;case"prepare":const s=o(process.argv.slice(3),f),u=r.resolve(r.join(s.outdir,"server"));i=new C({contentDir:r.resolve(s["project-dir"]),outdir:r.resolve(s.outdir,"client"),serverOutDir:u}),await w(g.PREPARE,s,i),$(u),await I(s,i);break;case"serve":y();const b=o(process.argv.slice(3),Y),O=r.resolve(b.prepareDir);d.sendServeCliCommandExecutedMessage();const v=r.join(O,"server","index.mjs");x.existsSync(v)||await t.panic("Server not found. Please run `realm prepare` first"),import(v).catch(async c=>{await t.panic("Failed to load server",c)});break;case"eject":e.canAccessFeature("themeEjecting")||await t.panicOnContentError('The "eject" command is not available for this project');const m=o(process.argv.slice(3),z),{lifecycleContext:{getConfig:h,fs:D}}=await T({outdir:"",contentDir:r.resolve(m["project-dir"]),setGlobalConfig:()=>null});D.dispose(),d.sendCliCommandEjectExecutedMessage({arguments:m}),await V({...m,config:await h()}),p.clearAllTimeouts();break;case"translate":if(e.canAccessFeature("l10n")){const c=o(process.argv.slice(3),M);d.sendCliCommandTranslateExecutedMessage({arguments:c}),await N(c)}else await t.panicOnContentError('The "translate" command is not available for this project');break;case"stats":const P=o(process.argv.slice(3),B);await q(P);break;case"--version":console.log(k);break;default:await t.panicOnContentError(`Unknown command "${n}"`)}}catch(e){p.error("Exiting due to uncaught exception"),await t.panic(e)}
2
+ import"./cli/utils/node-version-check.js";import o from"mri";import*as r from"node:path";import{tmpdir as A}from"node:os";import*as x from"node:fs";import"./server/node-fetch-polyfill.js";import{cliCommandNames as g}from"./constants/common.js";import{initPlugins as T}from"./server/plugins/lifecycle.js";import{loadEnvVariables as y}from"./server/utils/envs/load-env-variables.js";import{PORTAL_VERSION as k}from"./server/version.js";import{logger as p}from"./server/tools/notifiers/logger.js";import{reporter as t}from"./server/tools/notifiers/reporter.js";import{sha as R}from"./server/utils/crypto/sha.js";import{develop as S}from"./cli/develop.js";import{eject as V}from"./cli/eject/index.js";import{beforeCommand as w}from"./server/utils/lifecycle-hooks.js";import{Store as C}from"./server/store.js";import{prepare as I}from"./cli/prepare/index.js";import{fromCurrentDir as L}from"./server/utils/paths.js";import{translationsCliOpts as M}from"./cli/translations/options.js";import{generateTranslations as N}from"./cli/translations/index.js";import{EntitlementsProvider as _}from"./server/entitlements/entitlements-provider.js";import{isValidPlan as F}from"./server/entitlements/is-valid-plan.js";import{stopAllCompilers as U}from"./server/esbuild/esbuild.js";import{copyLibsqlPrebuiltBinary as $}from"./cli/prepare/libsql/copy-prebuilt-binary.js";import{telemetry as d}from"./cli/telemetry/index.js";import{stats as q}from"./cli/stats/index.js";import{statsCliOpts as B}from"./cli/stats/options.js";const n=process.argv[2];let i;const f={alias:{d:"project-dir",p:"port"},default:{"project-dir":process.env.REDOCLY_CONTENT_DIR||process.cwd(),outdir:"public"}},G={alias:f.alias,default:{...f.default,plan:"enterprise"}},Y={alias:{d:"prepareDir"},default:{prepareDir:"public"}},z={boolean:["force"],alias:{f:"force",d:"project-dir"},default:{"project-dir":process.cwd()}};process.on("uncaughtException",async function(e){e?.code==="ERR_INVALID_STATE"?console.log("Ignore premature close error"):(p.error("Uncaught exception occurred. Stopping compilers."),await U(),p.error("Exiting due to uncaught exception"),await t.panic(e))});try{n||await t.panicOnContentError("Command not specified.");const e=_.instance();switch(["prepare","serve","stats"].includes(n)&&await e.init(),["eject","translate"].includes(n)&&await e.init({developModePlan:"enterprise"}),n){case"develop":case"preview":const a=o(process.argv.slice(3),G),E=r.resolve(a["project-dir"]),j=r.join(A(),"redocly-public-"+R(E)),l=a.plan.toLowerCase();F(l)||await t.panicOnContentError(`Invalid --plan argument value '${l}'.`),await e.init({developModePlan:l}),i=new C({contentDir:r.resolve(a["project-dir"]),outdir:j,serverOutDir:L(import.meta.url,"./server/esbuild/cache/server")}),await w(g.DEVELOP,a,i),await S(a,i);break;case"prepare":const s=o(process.argv.slice(3),f),u=r.resolve(r.join(s.outdir,"server"));i=new C({contentDir:r.resolve(s["project-dir"]),outdir:r.resolve(s.outdir,"client"),serverOutDir:u}),await w(g.PREPARE,s,i),$(u),await I(s,i);break;case"serve":await y();const b=o(process.argv.slice(3),Y),O=r.resolve(b.prepareDir);d.sendServeCliCommandExecutedMessage();const v=r.join(O,"server","index.mjs");x.existsSync(v)||await t.panic("Server not found. Please run `realm prepare` first"),import(v).catch(async c=>{await t.panic("Failed to load server",c)});break;case"eject":e.canAccessFeature("themeEjecting")||await t.panicOnContentError('The "eject" command is not available for this project');const m=o(process.argv.slice(3),z),{lifecycleContext:{getConfig:h,fs:D}}=await T({outdir:"",contentDir:r.resolve(m["project-dir"]),setGlobalConfig:()=>null});D.dispose(),d.sendCliCommandEjectExecutedMessage({arguments:m}),await V({...m,config:await h()}),p.clearAllTimeouts();break;case"translate":if(e.canAccessFeature("l10n")){const c=o(process.argv.slice(3),M);d.sendCliCommandTranslateExecutedMessage({arguments:c}),await N(c)}else await t.panicOnContentError('The "translate" command is not available for this project');break;case"stats":const P=o(process.argv.slice(3),B);await q(P);break;case"--version":console.log(k);break;default:await t.panicOnContentError(`Unknown command "${n}"`)}}catch(e){p.error("Exiting due to uncaught exception"),await t.panic(e)}
@@ -1 +1 @@
1
- import r from"node:path";import{copyFileSync as p,existsSync as s,mkdirSync as v}from"node:fs";import{readEnvVariable as l}from"../../server/utils/envs/read-env-variable.js";import{logger as u}from"../../server/tools/notifiers/logger.js";const b=e=>{const n=a();s(e.serverOutDir)||v(e.serverOutDir,{recursive:!0});const i=[];for(const o of n){const t=r.join(e.contentDir,o);if(!s(t))continue;const c=r.join(e.serverOutDir,o);p(t,c),i.push(o)}i.length>0&&u.info(`Env files included in bundle: ${i.map(()=>"%rp").join(", ")}`,...i)},a=()=>{const e=l("REDOCLY_ENV"),n=[".env"];switch(e){case"production":n.push(".env.production");break;case"preview":n.push(".env.preview");break;case"development":default:n.push(".env.development");break}return n};export{b as copyEnvFiles};
1
+ import t from"node:path";import{copyFileSync as a,existsSync as s,mkdirSync as v}from"node:fs";import{readEnvVariable as c}from"../../server/utils/envs/read-env-variable.js";import{logger as l}from"../../server/tools/notifiers/logger.js";import{sanitizeBranchName as u}from"../../server/utils/envs/sanitize-branch-name.js";const F=n=>{const i=m();s(n.serverOutDir)||v(n.serverOutDir,{recursive:!0});const e=[];for(const o of i){const r=t.join(n.contentDir,o);if(!s(r))continue;const p=t.join(n.serverOutDir,o);a(r,p),e.push(o)}e.length>0&&l.info(`Env files included in bundle: ${e.map(()=>"%rp").join(", ")}`,...e)},m=()=>{const n=c("REDOCLY_ENV"),i=c("PUBLIC_REDOCLY_BRANCH_NAME"),e=[".env"];switch(i&&e.push(`.env.branch.${u(i)}`),n){case"production":e.push(".env.production");break;case"preview":e.push(".env.preview");break;case"development":default:e.push(".env.development");break}return e};export{F as copyEnvFiles};
@@ -94,6 +94,7 @@ export declare const FsErrors: {
94
94
  export declare const DEFAULT_LOCALE_PLACEHOLDER = "default_locale";
95
95
  export declare const SIDEBAR_PREFIX = "sidebar-";
96
96
  export declare const PUBLIC_ENV_PREFIX = "PUBLIC_";
97
+ export declare const BRANCH_ENV_PREFIX = "branch.";
97
98
  export declare const MARKDOC_ERROR_TYPES: readonly ["BROKEN_LINK", "MARKDOC", "RESOLVE"];
98
99
  export declare const UI_ACCESSIBLE_CONFIG_PROPS: (keyof UiAccessibleConfig & keyof RedoclyConfig)[];
99
100
  export declare const SEARCH_CATEGORY_FIELD = "redocly_category";
@@ -1 +1 @@
1
- const E="openapi_docs",n="asyncapi_docs",A="graphql_docs",T="/_spec-gql",O="markdoc",p="tags",i="*",R={"*":"read"},L=["openid","email"],I=1440*60,C="anonymous",l="authenticated",S="**",d="Reunite",N="translations.yaml",P="redocly.yaml",u="@redocly/theme",D="@theme",h="/app-data.json",x="/eject-component",e=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",g=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(o=>o.trim()).filter(Boolean).concat(e):[e];var a;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(a||(a={}));var r;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(r||(r={}));const t="entityKey",c="entityRelationId",U={INFO:"/_info",EJECT_COMPONENT:"/eject-component/:componentName",SHARED_PAGE_DATA:"/page-data/shared/*",PAGE_DATA:"/page-data/*",APP_DATA:"/app-data.json",AUTHORIZATION:"/authorize",OIDC_CALLBACK:"/_auth/oidc",SAML_CALLBACK:"/_auth/saml2",REDOCLY_CALLBACK:"/_auth/redocly",REPLAY_OAUTH2_CALLBACK:"/_auth/replay-oauth2",REDOCLY_LOGIN_CALLBACK:"/_auth/redocly/redocly-login",REDOCLY_TOKEN_LOGIN:"/_auth/redocly-token-login",SEARCH:"/_search",SEARCH_FACETS:"/_search-facets",LOGOUT:"/logout",POST_LOGOUT:"/post-logout",LOGIN:"/login",IDP_LOGIN:"/_auth/idp-login",INVITE:"/invite/:code",RESOLVE_ROUTE_BY_PATH:"/resolve-route-by-path",RESOLVE_ROUTES_BY_PATHS:"/resolve-routes-by-paths",RESOLVE_ROUTE_BY_SLUG:"/resolve-route-by-slug",GET_ROUTES_BY_LINE:"/get-routes-by-line",FEEDBACK:"/feedback",TELEMETRY:"/_events",OTEL_TRACES:"/_otel/v1/traces",HEALTH:"/_health",ASK_AI:"/_ask-ai",CATALOG_ENTITIES:`/catalog-entities/:${t}?`,CATALOG_ENTITIES_RELATIONS:`/catalog-entities-relations/:${c}?`,BFF_CATALOG_ENTITIES:`/bff/catalog-entities/:${t}?`,BFF_CATALOG_RELATED_ENTITIES:`/bff/catalog-related-entities/:${t}`,BFF_CATALOG_REVISIONS:`/bff/catalog-revisions/:${t}`,MCP_OAUTH_AUTHORIZATION_SERVER:"/.well-known/oauth-authorization-server",MCP_OAUTH_PROTECTED_RESOURCE:"/.well-known/oauth-protected-resource/mcp",MCP_DYNAMIC_CLIENT_REGISTRATION:"/_mcp/register",MCP_AUTHORIZATION:"/_mcp/oauth2/auth",MCP_TOKEN_PORTAL:"/_mcp/oauth2/token-portal",MCP_CALLBACK:"/_mcp/oauth/callback",SCORECARDS:"/scorecards"};var _;(function(o){o.AI_SEARCH="aiSearch"})(_||(_={}));const m="/login",M="/invite",G={AUTH0_PASS:"/auth/auth0-pass"},b={NotExist:"ENOENT"},H="default_locale",v="sidebar-",F="PUBLIC_",y=["BROKEN_LINK","MARKDOC","RESOLVE"],B=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],s="redocly_category",k="redocly_product",f="redocly_version",K="redocly_teams",V=s,Y={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",mcp:"mcp",banner:"banner"};export{g as ALLOWED_CORS_ORIGINS,n as ASYNC_API_DOCS_TEMPLATE_ID,t as CATALOG_ENTITY_KEY,c as CATALOG_ENTITY_RELATION_ID,P as CONFIG_FILE_NAME,O as CUSTOM_MARKDOC_OPTIONS_PATH,p as CUSTOM_MARKDOC_TAGS_PATH,C as DEFAULT_ANONYMOUS_VISITOR_TEAM,l as DEFAULT_AUTHENTICATED_TEAM,I as DEFAULT_COOKIE_EXPIRATION,H as DEFAULT_LOCALE_PLACEHOLDER,S as DEFAULT_RBAC_SCOPE,d as DEFAULT_SSO_IDP_TITLE,u as DEFAULT_THEME_NAME,m as DEV_LOGIN_SLUG,x as EJECT_COMPONENT_URL,G as ExternalRoutes,Y as FEATURE,r as FEEDBACK_TYPES,b as FsErrors,h as GLOBAL_DATA_URL,T as GRAPHQL_SPEC_SLUG,A as GRAPHQL_TEMPLATE_ID,M as INVITE_SLUG,y as MARKDOC_ERROR_TYPES,E as OPENAPI_DOCS_TEMPLATE_ID,F as PUBLIC_ENV_PREFIX,R as PUBLIC_RBAC_SCOPE_ITEM,i as RBAC_ALL_OTHER_TEAMS,L as REQUIRED_OIDC_SCOPES,_ as RbacFeatures,s as SEARCH_CATEGORY_FIELD,V as SEARCH_GROUP_FACET_FIELD,k as SEARCH_PRODUCT_FIELD,K as SEARCH_RBAC_FIELD,f as SEARCH_VERSION_FIELD,e as SERVER_EDITOR_APP_URL,v as SIDEBAR_PREFIX,U as ServerRoutes,N as TRANSLATIONS_FILE_NAME,B as UI_ACCESSIBLE_CONFIG_PROPS,D as USER_THEME_ALIAS,a as cliCommandNames};
1
+ const E="openapi_docs",n="asyncapi_docs",A="graphql_docs",T="/_spec-gql",O="markdoc",p="tags",R="*",i={"*":"read"},L=["openid","email"],I=1440*60,C="anonymous",l="authenticated",S="**",d="Reunite",N="translations.yaml",P="redocly.yaml",u="@redocly/theme",D="@theme",h="/app-data.json",x="/eject-component",e=process.env.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",g=process.env.REDOCLY_CORS_ORIGINS?process.env.REDOCLY_CORS_ORIGINS.split(",").map(o=>o.trim()).filter(Boolean).concat(e):[e];var r;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(r||(r={}));var a;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(a||(a={}));const t="entityKey",c="entityRelationId",U={INFO:"/_info",EJECT_COMPONENT:"/eject-component/:componentName",SHARED_PAGE_DATA:"/page-data/shared/*",PAGE_DATA:"/page-data/*",APP_DATA:"/app-data.json",AUTHORIZATION:"/authorize",OIDC_CALLBACK:"/_auth/oidc",SAML_CALLBACK:"/_auth/saml2",REDOCLY_CALLBACK:"/_auth/redocly",REPLAY_OAUTH2_CALLBACK:"/_auth/replay-oauth2",REDOCLY_LOGIN_CALLBACK:"/_auth/redocly/redocly-login",REDOCLY_TOKEN_LOGIN:"/_auth/redocly-token-login",SEARCH:"/_search",SEARCH_FACETS:"/_search-facets",LOGOUT:"/logout",POST_LOGOUT:"/post-logout",LOGIN:"/login",IDP_LOGIN:"/_auth/idp-login",INVITE:"/invite/:code",RESOLVE_ROUTE_BY_PATH:"/resolve-route-by-path",RESOLVE_ROUTES_BY_PATHS:"/resolve-routes-by-paths",RESOLVE_ROUTE_BY_SLUG:"/resolve-route-by-slug",GET_ROUTES_BY_LINE:"/get-routes-by-line",FEEDBACK:"/feedback",TELEMETRY:"/_events",OTEL_TRACES:"/_otel/v1/traces",HEALTH:"/_health",ASK_AI:"/_ask-ai",CATALOG_ENTITIES:`/catalog-entities/:${t}?`,CATALOG_ENTITIES_RELATIONS:`/catalog-entities-relations/:${c}?`,BFF_CATALOG_ENTITIES:`/bff/catalog-entities/:${t}?`,BFF_CATALOG_RELATED_ENTITIES:`/bff/catalog-related-entities/:${t}`,BFF_CATALOG_REVISIONS:`/bff/catalog-revisions/:${t}`,MCP_OAUTH_AUTHORIZATION_SERVER:"/.well-known/oauth-authorization-server",MCP_OAUTH_PROTECTED_RESOURCE:"/.well-known/oauth-protected-resource/mcp",MCP_DYNAMIC_CLIENT_REGISTRATION:"/_mcp/register",MCP_AUTHORIZATION:"/_mcp/oauth2/auth",MCP_TOKEN_PORTAL:"/_mcp/oauth2/token-portal",MCP_CALLBACK:"/_mcp/oauth/callback",SCORECARDS:"/scorecards"};var _;(function(o){o.AI_SEARCH="aiSearch"})(_||(_={}));const m="/login",M="/invite",G={AUTH0_PASS:"/auth/auth0-pass"},b={NotExist:"ENOENT"},H="default_locale",F="sidebar-",v="PUBLIC_",y="branch.",B=["BROKEN_LINK","MARKDOC","RESOLVE"],k=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],s="redocly_category",f="redocly_product",V="redocly_version",K="redocly_teams",Y=s,w={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",mcp:"mcp",banner:"banner"};export{g as ALLOWED_CORS_ORIGINS,n as ASYNC_API_DOCS_TEMPLATE_ID,y as BRANCH_ENV_PREFIX,t as CATALOG_ENTITY_KEY,c as CATALOG_ENTITY_RELATION_ID,P as CONFIG_FILE_NAME,O as CUSTOM_MARKDOC_OPTIONS_PATH,p as CUSTOM_MARKDOC_TAGS_PATH,C as DEFAULT_ANONYMOUS_VISITOR_TEAM,l as DEFAULT_AUTHENTICATED_TEAM,I as DEFAULT_COOKIE_EXPIRATION,H as DEFAULT_LOCALE_PLACEHOLDER,S as DEFAULT_RBAC_SCOPE,d as DEFAULT_SSO_IDP_TITLE,u as DEFAULT_THEME_NAME,m as DEV_LOGIN_SLUG,x as EJECT_COMPONENT_URL,G as ExternalRoutes,w as FEATURE,a as FEEDBACK_TYPES,b as FsErrors,h as GLOBAL_DATA_URL,T as GRAPHQL_SPEC_SLUG,A as GRAPHQL_TEMPLATE_ID,M as INVITE_SLUG,B as MARKDOC_ERROR_TYPES,E as OPENAPI_DOCS_TEMPLATE_ID,v as PUBLIC_ENV_PREFIX,i as PUBLIC_RBAC_SCOPE_ITEM,R as RBAC_ALL_OTHER_TEAMS,L as REQUIRED_OIDC_SCOPES,_ as RbacFeatures,s as SEARCH_CATEGORY_FIELD,Y as SEARCH_GROUP_FACET_FIELD,f as SEARCH_PRODUCT_FIELD,K as SEARCH_RBAC_FIELD,V as SEARCH_VERSION_FIELD,e as SERVER_EDITOR_APP_URL,F as SIDEBAR_PREFIX,U as ServerRoutes,N as TRANSLATIONS_FILE_NAME,k as UI_ACCESSIBLE_CONFIG_PROPS,D as USER_THEME_ALIAS,r as cliCommandNames};
@@ -1 +1 @@
1
- import{Hono as f}from"hono";import{TrieRouter as m}from"hono/router/trie-router";import{Logger as g}from"../tools/notifiers/logger.js";import{importApiRoutesHandler as q}from"./import-api-routes-handlers.js";import{getBodyWithSizeCheck as w}from"./helpers/get-body-with-size-check.js";import{setupLogger as h}from"./helpers/setup-logger.js";import{telemetry as s}from"../telemetry/index.js";import{KvService as D}from"../persistence/kv/services/kv-service.js";import{enhanceContext as R}from"./helpers/enhance-context.js";const i=new g({forceNonInteractive:!0});async function S(e){s.initialize(),h(i,e.requestHandlerId);const o=new f({router:new m}),{requestHandlers:a}=await q(e.serverOutDir),u=a[e.requestHandlerId],c=(await u()).default,l=async()=>await D.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:e.sqldRemoteDatabaseUrl,sqldRemoteDatabaseAuthToken:e.sqldRemoteDatabaseAuthToken});o.all(e.slug,async t=>{const r=await c(t.req.raw,R({honoCtx:t,ctx:e.ctxData,telemetry:s,getKv:l}),e.staticData);return r instanceof Response?r:typeof r=="string"?t.text(r):t.json(r)}),o.onError((t,r)=>{if(i.error(`[${e.requestHandlerId}] ${t.message} ${t.stack}`),t instanceof SyntaxError)return r.text(t.message,500);throw t});const n=await o.request(e.req.url,e.req),d=await w(n,e.maxResponseSizeMB);return{status:n.status,headers:Object.fromEntries(n.headers.entries()),body:d}}export{S as executeApiRoute};
1
+ import{Hono as f}from"hono";import{TrieRouter as m}from"hono/router/trie-router";import{Logger as g}from"../tools/notifiers/logger.js";import{importApiRoutesHandler as q}from"./import-api-routes-handlers.js";import{getBodyWithSizeCheck as h}from"./helpers/get-body-with-size-check.js";import{setupLogger as w}from"./helpers/setup-logger.js";import{telemetry as s}from"../telemetry/index.js";import{KvService as D}from"../persistence/kv/services/kv-service.js";import{enhanceContext as R}from"./helpers/enhance-context.js";const i=new g({forceNonInteractive:!0});async function S(e){s.initialize(),w(i,e.requestHandlerId);const o=new f({router:new m}),{requestHandlers:a}=await q(e.serverOutDir),u=a[e.requestHandlerId],c=(await u()).default,l=async()=>D.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:e.sqldRemoteDatabaseUrl,sqldRemoteDatabaseAuthToken:e.sqldRemoteDatabaseAuthToken});o.all(e.slug,async t=>{const r=await c(t.req.raw,R({honoCtx:t,ctx:e.ctxData,telemetry:s,getKv:l}),e.staticData);return r instanceof Response?r:typeof r=="string"?t.text(r):t.json(r)}),o.onError((t,r)=>{if(i.error(`[${e.requestHandlerId}] ${t.message} ${t.stack}`),t instanceof SyntaxError)return r.text(t.message,500);throw t});const n=await o.request(e.req.url,e.req),d=await h(n,e.maxResponseSizeMB);return{status:n.status,headers:Object.fromEntries(n.headers.entries()),body:d}}export{S as executeApiRoute};
@@ -17,4 +17,5 @@ export declare const CATALOG_FILTERS_CACHE_TTL_IN_SECONDS: number;
17
17
  export declare const CATALOG_ENTITIES_DEFAULT_CONFIG: EntitiesCatalogConfig;
18
18
  export declare const CATALOG_ENTITIES_FILES_REGEX: RegExp;
19
19
  export declare const ALLOWED_CATALOG_QUERY_PARAMS: readonly ["after", "before", "sort", "filter", "search", "limit", "skip"];
20
+ export declare const SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR = "NO_SQLD_DEPLOYMENT_YET";
20
21
  //# sourceMappingURL=catalog-entities.d.ts.map
@@ -1 +1 @@
1
- const e=["node_modules","dist","build",".git","@l10n"],l="/catalogs",a={ALL:"all",SERVICES:"services",DOMAINS:"domains",TEAMS:"teams",USERS:"users",API_DESCRIPTIONS:"api-descriptions",DATA_SCHEMAS:"data-schemas",API_OPERATIONS:"api-operations"},s="catalog:entitySources",i="catalog-filters",o=300,t=[{title:"Domains",property:"domains"},{title:"Owner",property:"owners"},{title:"Tags",property:"tags"}],c={show:!1,catalogs:{all:{slug:a.ALL,hide:!1,includes:[],excludes:[],filters:[{title:"Type",property:"type"},...t],titleTranslationKey:"catalog.catalogs.all.title",descriptionTranslationKey:"catalog.catalogs.all.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.all.switcherLabel"},services:{slug:a.SERVICES,hide:!1,includes:[{type:"service"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.service.title",descriptionTranslationKey:"catalog.catalogs.service.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.service.switcherLabel"},domains:{slug:a.DOMAINS,hide:!1,includes:[{type:"domain"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.domain.title",descriptionTranslationKey:"catalog.catalogs.domain.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.domain.switcherLabel"},teams:{slug:a.TEAMS,hide:!1,includes:[{type:"team"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.team.title",descriptionTranslationKey:"catalog.catalogs.team.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.team.switcherLabel"},users:{slug:a.USERS,hide:!1,includes:[{type:"user"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.user.title",descriptionTranslationKey:"catalog.catalogs.user.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.user.switcherLabel"},apiDescriptions:{slug:a.API_DESCRIPTIONS,hide:!1,includes:[{type:"api-description"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiDescription.title",descriptionTranslationKey:"catalog.catalogs.apiDescription.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiDescription.switcherLabel"},dataSchemas:{slug:a.DATA_SCHEMAS,hide:!1,includes:[{type:"data-schema"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.dataSchema.title",descriptionTranslationKey:"catalog.catalogs.dataSchema.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.dataSchema.switcherLabel"},apiOperations:{slug:a.API_OPERATIONS,hide:!1,includes:[{type:"api-operation"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiOperation.title",descriptionTranslationKey:"catalog.catalogs.apiOperation.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiOperation.switcherLabel"}}},r=/\.(entity|entities)\.(yaml|yml)$/,n=["after","before","sort","filter","search","limit","skip"];export{n as ALLOWED_CATALOG_QUERY_PARAMS,l as CATALOG_BASE_SLUG,c as CATALOG_ENTITIES_DEFAULT_CONFIG,r as CATALOG_ENTITIES_FILES_REGEX,i as CATALOG_FILTERS_CACHE_NAMESPACE,o as CATALOG_FILTERS_CACHE_TTL_IN_SECONDS,a as CATALOG_SLUGS,s as ENTITIES_MAP_GLOBAL_DATA_KEY,e as ENTITY_SCHEMA_EXCLUDED_FOLDERS};
1
+ const e=["node_modules","dist","build",".git","@l10n"],l="/catalogs",a={ALL:"all",SERVICES:"services",DOMAINS:"domains",TEAMS:"teams",USERS:"users",API_DESCRIPTIONS:"api-descriptions",DATA_SCHEMAS:"data-schemas",API_OPERATIONS:"api-operations"},s="catalog:entitySources",i="catalog-filters",o=300,t=[{title:"Domains",property:"domains"},{title:"Owner",property:"owners"},{title:"Tags",property:"tags"}],c={show:!1,catalogs:{all:{slug:a.ALL,hide:!1,includes:[],excludes:[],filters:[{title:"Type",property:"type"},...t],titleTranslationKey:"catalog.catalogs.all.title",descriptionTranslationKey:"catalog.catalogs.all.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.all.switcherLabel"},services:{slug:a.SERVICES,hide:!1,includes:[{type:"service"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.service.title",descriptionTranslationKey:"catalog.catalogs.service.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.service.switcherLabel"},domains:{slug:a.DOMAINS,hide:!1,includes:[{type:"domain"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.domain.title",descriptionTranslationKey:"catalog.catalogs.domain.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.domain.switcherLabel"},teams:{slug:a.TEAMS,hide:!1,includes:[{type:"team"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.team.title",descriptionTranslationKey:"catalog.catalogs.team.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.team.switcherLabel"},users:{slug:a.USERS,hide:!1,includes:[{type:"user"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.user.title",descriptionTranslationKey:"catalog.catalogs.user.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.user.switcherLabel"},apiDescriptions:{slug:a.API_DESCRIPTIONS,hide:!1,includes:[{type:"api-description"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiDescription.title",descriptionTranslationKey:"catalog.catalogs.apiDescription.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiDescription.switcherLabel"},dataSchemas:{slug:a.DATA_SCHEMAS,hide:!1,includes:[{type:"data-schema"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.dataSchema.title",descriptionTranslationKey:"catalog.catalogs.dataSchema.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.dataSchema.switcherLabel"},apiOperations:{slug:a.API_OPERATIONS,hide:!1,includes:[{type:"api-operation"}],excludes:[],filters:t,titleTranslationKey:"catalog.catalogs.apiOperation.title",descriptionTranslationKey:"catalog.catalogs.apiOperation.description",catalogSwitcherLabelTranslationKey:"catalog.catalogs.apiOperation.switcherLabel"}}},r=/\.(entity|entities)\.(yaml|yml)$/,n=["after","before","sort","filter","search","limit","skip"],g="NO_SQLD_DEPLOYMENT_YET";export{n as ALLOWED_CATALOG_QUERY_PARAMS,l as CATALOG_BASE_SLUG,c as CATALOG_ENTITIES_DEFAULT_CONFIG,r as CATALOG_ENTITIES_FILES_REGEX,i as CATALOG_FILTERS_CACHE_NAMESPACE,o as CATALOG_FILTERS_CACHE_TTL_IN_SECONDS,a as CATALOG_SLUGS,s as ENTITIES_MAP_GLOBAL_DATA_KEY,e as ENTITY_SCHEMA_EXCLUDED_FOLDERS,g as SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR};
@@ -1,3 +1,3 @@
1
- import{context as a}from"esbuild";import{mkdirSync as j,writeFileSync as b,existsSync as M}from"node:fs";import*as m from"node:path";import{RUNTIME_RESOURCES_DIR as Y,TELEMETRY_ENABLED as V}from"../constants/common.js";import{fromCurrentDir as t}from"../utils/paths.js";import{NodeBrowserPlugin as S}from"./plugins/node-browser.js";import{PortalImport as l}from"./plugins/portal-import.js";import{ThemesResolver as u}from"./plugins/themes-resolver.js";import{AssetsResolver as E}from"./plugins/assets-resolver.js";import{EsbuildErrorCollector as _}from"./plugins/esbuild-compile-resolver.js";import{OpenapiDocsModuleReplacer as f}from"./plugins/openapi-docs-module-replacer/index.js";import{ServerPropsResolver as R}from"./plugins/server-props-resolver.js";import{StyledComponentsSSR as v}from"./plugins/styled-components-ssr.js";import{DependencyResolver as d}from"./plugins/dependency-resolver.js";import{YamlLoader as L}from"./plugins/yaml-loader.js";import{ApiRequestHandlersResolver as A}from"./plugins/api-request-handlers-resolver.js";import{MiddlewareResolver as N}from"./plugins/middleware-resolver.js";import{OnRebuild as D}from"./plugins/on-rebuild.js";import{getPublicEnvVariables as $}from"../utils/envs/get-public-env-variables.js";import{PORTAL_VERSION as w}from"../version.js";import{AsyncApiPatch as O}from"./plugins/async-api-patch.js";import{telemetryTraceStep as T}from"../../cli/telemetry/helpers/trace-step.js";const C={bundle:!0,format:"esm",chunkNames:"chunks/[name]-[hash]"};function y(e){const o=m.join(e,"tsconfig.json");return M(o)?o:void 0}const p=new Set;async function ie(){await Promise.all([...p].map(e=>e.dispose())),p.clear()}async function ce(e,o,r="production",n){return await T("build.create_client_compiler",async()=>{const c=$(),i={};Object.entries(c).map(([I,h])=>i[`process.env.${I}`]=JSON.stringify(h));const s=[...n?[D(n)]:[],S({path:"path-browserify",fs:"{}",tty:"tty-browserify",os:"os-browserify",http:"stream-http",https:"stream-http",readline:"{}",crypto:"{}",stream:"{}",zlib:"{}","https-proxy-agent":"{}"}),u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),d(),l(),L(),O(),v(),f()],g=[t(import.meta.url,"../../client/browser-entry.js"),t(import.meta.url,"../../client/user-tags-entry.js")],P=await a({...C,entryPoints:g,outdir:m.join(o,Y),sourcemap:r!=="production"&&process.env.ENABLE_SOURCE_MAPS==="true",plugins:s,tsconfig:y(e.contentDir),mainFields:["browser","module","main"],metafile:r!=="production",minify:r==="production",splitting:!0,external:["constants","zlib","stream","https","vm","module","worker_threads","child_process","@swc/core"],inject:[process.env.INSPECT_MODE==="true"?t(import.meta.url,"../../client/inspect-mode-hooks.js"):"",t(import.meta.url,"./web-shim.js")].filter(Boolean),define:{...i,"process.env.NODE_ENV":`"${r}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"process.env.SERVER_EDITOR_APP_URL":`"${process.env.SERVER_EDITOR_APP_URL}"`,"process.env.ENABLE_COMMENTS":`"${process.env.ENABLE_COMMENTS}"`,"process.env.REDOCLY_TELEMETRY":V?'""':'"off"',"process.env.REDOCLY_PORTAL_VERSION":`"${w}"`,"process.env":`{"NODE_ENV": "${r}"}`,"process.platform":'"browser"',"process.browser":"true","module.hot":"false",global:"{}",...process.env.REDOCLY_PREFIX_PATHS&&{"process.env.REDOCLY_PREFIX_PATHS":`"${process.env.REDOCLY_PREFIX_PATHS}"`},...process.env.INSPECT_MODE==="true"&&{"process.env.INSPECT_MODE":`${process.env.INSPECT_MODE}`},...process.env.MAIN_API_URL&&{"process.env.MAIN_API_URL":`"${process.env.MAIN_API_URL}"`}},logLevel:"silent"});return p.add(P),P})}async function pe(e,o,r="development",n){j(o,{recursive:!0}),b(m.join(o,"package.json"),JSON.stringify({name:"@redocly/portal/server-cache",type:"module"}));const c=[...n?[D(n)]:[],u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),A(e),N(e),d(),l(),L(),O(),v(),f()],i=[t(import.meta.url,"../../client/server-entry.js"),t(import.meta.url,"../../client/user-tags-entry.js"),t(import.meta.url,"../../client/server-props-entry.js"),t(import.meta.url,"../../client/api-request-handlers-entry.js"),t(import.meta.url,"../../client/middleware-entry.js")],s=await a({...C,entryPoints:i,outdir:o,plugins:c,sourcemap:r!=="production"&&process.env.ENABLE_SOURCE_MAPS==="true",minify:r==="production",tsconfig:y(e.contentDir),mainFields:["module","main"],splitting:!0,external:["react","react-router-dom","@dr.pogodin/react-helmet","@swc/core","pnpapi","canvas"],banner:{js:`import { createRequire as topLevelCreateRequire } from 'module';
2
- const require = topLevelCreateRequire(import.meta.url);`},platform:"node",define:{"process.env.NODE_ENV":`"${r}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"module.hot":"false"},logLevel:"silent"});return p.add(s),s}async function ae(e,o,r="production",n){return await T("build.create_server_compiler",async()=>{const c=[...n?[D(n)]:[],S({"node-fetch":"{}",webpack:"{}",swagger2openapi:"{}"}),u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),A(e),N(e),d(),l(),L(),O(),v(),f()],i=[{in:t(import.meta.url,"../node-bundle-entry.js"),out:"index"},{in:t(import.meta.url,"../../client/user-tags-entry.js"),out:"user-tags-entry"},{in:t(import.meta.url,"../workers/api-routes-worker.js"),out:"api-routes-worker"},{in:t(import.meta.url,"../workers/scorecards-worker.js"),out:"scorecards-worker"}],s=await a({...C,entryPoints:i,outExtension:{".js":".mjs"},outdir:o,platform:"node",plugins:c,tsconfig:y(e.contentDir),mainFields:["module","main"],metafile:r!=="production",minify:r==="production",splitting:!1,define:{"process.env.NODE_ENV":`"${r}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"process.env.REDOCLY_STATIC_BUNDLE":"true","process.env.REDOCLY_PORTAL_VERSION":`"${w}"`,"module.hot":"false",...process.env.REDOCLY_PREFIX_PATHS&&{"process.env.REDOCLY_PREFIX_PATHS":`"${process.env.REDOCLY_PREFIX_PATHS}"`}},banner:{js:`import { createRequire as topLevelCreateRequire } from 'module';
3
- const require = topLevelCreateRequire(import.meta.url);`},logLevel:"silent"});return p.add(s),s})}export{ce as createClientCompiler,ae as createNodeBundleCompiler,pe as createServerCompiler,ie as stopAllCompilers};
1
+ import{context as m}from"esbuild";import{mkdirSync as j,writeFileSync as b,existsSync as M}from"node:fs";import*as a from"node:path";import{RUNTIME_RESOURCES_DIR as Y,TELEMETRY_ENABLED as k}from"../constants/common.js";import{fromCurrentDir as r}from"../utils/paths.js";import{NodeBrowserPlugin as S}from"./plugins/node-browser.js";import{PortalImport as l}from"./plugins/portal-import.js";import{ThemesResolver as u}from"./plugins/themes-resolver.js";import{AssetsResolver as E}from"./plugins/assets-resolver.js";import{EsbuildErrorCollector as _}from"./plugins/esbuild-compile-resolver.js";import{OpenapiDocsModuleReplacer as f}from"./plugins/openapi-docs-module-replacer/index.js";import{ServerPropsResolver as R}from"./plugins/server-props-resolver.js";import{StyledComponentsSSR as v}from"./plugins/styled-components-ssr.js";import{DependencyResolver as d}from"./plugins/dependency-resolver.js";import{YamlLoader as L}from"./plugins/yaml-loader.js";import{ApiRequestHandlersResolver as A}from"./plugins/api-request-handlers-resolver.js";import{MiddlewareResolver as N}from"./plugins/middleware-resolver.js";import{OnRebuild as D}from"./plugins/on-rebuild.js";import{getPublicEnvVariables as V}from"../utils/envs/get-public-env-variables.js";import{PORTAL_VERSION as w}from"../version.js";import{AsyncApiPatch as O}from"./plugins/async-api-patch.js";import{telemetryTraceStep as T}from"../../cli/telemetry/helpers/trace-step.js";const C={bundle:!0,format:"esm",chunkNames:"chunks/[name]-[hash]"};function y(e){const o=a.join(e,"tsconfig.json");return M(o)?o:void 0}const p=new Set;async function ie(){await Promise.all([...p].map(e=>e.dispose())),p.clear()}async function ce(e,o,t="production",n){return await T("build.create_client_compiler",async()=>{const c=V(),i={};Object.entries(c).map(([I,h])=>i[`process.env.${I}`]=JSON.stringify(h));const s=[...n?[D(n)]:[],S({path:"path-browserify",fs:"{}",tty:"tty-browserify",os:"os-browserify",http:"stream-http",https:"stream-http",readline:"{}",crypto:"{}",stream:"{}",zlib:"{}","https-proxy-agent":"{}"}),u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),d(),l(),L(),O(),v(),f()],g=[r(import.meta.url,"../../client/browser-entry.js"),r(import.meta.url,"../../client/user-tags-entry.js")],P=await m({...C,entryPoints:g,outdir:a.join(o,Y),sourcemap:t!=="production"&&process.env.ENABLE_SOURCE_MAPS==="true",plugins:s,tsconfig:y(e.contentDir),mainFields:["browser","module","main"],metafile:t!=="production",minify:t==="production",splitting:!0,external:["constants","zlib","stream","https","vm","module","worker_threads","child_process","@swc/core"],inject:[process.env.INSPECT_MODE==="true"?r(import.meta.url,"../../client/inspect-mode-hooks.js"):"",r(import.meta.url,"./web-shim.js")].filter(Boolean),define:{...i,"process.env.NODE_ENV":`"${t}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"process.env.SERVER_EDITOR_APP_URL":`"${process.env.SERVER_EDITOR_APP_URL}"`,"process.env.ENABLE_COMMENTS":`"${process.env.ENABLE_COMMENTS}"`,"process.env.REDOCLY_TELEMETRY":k?'""':'"off"',"process.env.REDOCLY_PORTAL_VERSION":`"${w}"`,"process.env":`{"NODE_ENV": "${t}"}`,"process.platform":'"browser"',"process.browser":"true","module.hot":"false",global:"{}",...process.env.REDOCLY_PREFIX_PATHS&&{"process.env.REDOCLY_PREFIX_PATHS":`"${process.env.REDOCLY_PREFIX_PATHS}"`},...process.env.INSPECT_MODE==="true"&&{"process.env.INSPECT_MODE":`${process.env.INSPECT_MODE}`},...process.env.MAIN_API_URL&&{"process.env.MAIN_API_URL":`"${process.env.MAIN_API_URL}"`}},logLevel:"silent"});return p.add(P),P})}async function pe(e,o,t="development",n){j(o,{recursive:!0}),b(a.join(o,"package.json"),JSON.stringify({name:"@redocly/portal/server-cache",type:"module"}));const c=[...n?[D(n)]:[],u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),A(e),N(e),d(),l(),L(),O(),v(),f()],i=[r(import.meta.url,"../../client/server-entry.js"),r(import.meta.url,"../../client/user-tags-entry.js"),r(import.meta.url,"../../client/server-props-entry.js"),r(import.meta.url,"../../client/api-request-handlers-entry.js"),r(import.meta.url,"../../client/middleware-entry.js")],s=await m({...C,entryPoints:i,outdir:o,plugins:c,sourcemap:t!=="production"&&process.env.ENABLE_SOURCE_MAPS==="true",minify:t==="production",tsconfig:y(e.contentDir),mainFields:["module","main"],splitting:!0,external:["react","react-router-dom","@dr.pogodin/react-helmet","@swc/core","pnpapi","canvas"],banner:{js:`import { createRequire as topLevelCreateRequire } from 'module';
2
+ const require = topLevelCreateRequire(import.meta.url);`},platform:"node",define:{"process.env.NODE_ENV":`"${t}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"module.hot":"false"},logLevel:"silent"});return p.add(s),s}async function me(e,o,t="production",n){return await T("build.create_server_compiler",async()=>{const c=[...n?[D(n)]:[],S({"node-fetch":"{}",webpack:"{}",swagger2openapi:"{}"}),u(e,e.contentDir),E(e,e.contentDir),_(e,e.contentDir),R(e),A(e),N(e),d(),l(),L(),O(),v(),f()],i=[{in:r(import.meta.url,"../node-bundle-entry.js"),out:"index"},{in:r(import.meta.url,"../../client/user-tags-entry.js"),out:"user-tags-entry"},{in:r(import.meta.url,"../workers/api-routes-worker.js"),out:"api-routes-worker"},{in:r(import.meta.url,"../workers/scorecards-worker.js"),out:"scorecards-worker"},{in:r(import.meta.url,"../workers/mcp-tool-worker.js"),out:"mcp-tool-worker"}],s=await m({...C,entryPoints:i,outExtension:{".js":".mjs"},outdir:o,platform:"node",plugins:c,tsconfig:y(e.contentDir),mainFields:["module","main"],metafile:t!=="production",minify:t==="production",splitting:!1,define:{"process.env.NODE_ENV":`"${t}"`,"process.env.REDOCLY_LOCAL_DEV":`"${process.env.REDOCLY_LOCAL_DEV}"`,"process.env.REDOCLY_STATIC_BUNDLE":"true","process.env.REDOCLY_PORTAL_VERSION":`"${w}"`,"module.hot":"false",...process.env.REDOCLY_PREFIX_PATHS&&{"process.env.REDOCLY_PREFIX_PATHS":`"${process.env.REDOCLY_PREFIX_PATHS}"`}},banner:{js:`import { createRequire as topLevelCreateRequire } from 'module';
3
+ const require = topLevelCreateRequire(import.meta.url);`},logLevel:"silent"});return p.add(s),s})}export{ce as createClientCompiler,me as createNodeBundleCompiler,pe as createServerCompiler,ie as stopAllCompilers};
@@ -1 +1 @@
1
- import{resolve as a,dirname as p}from"node:path";import{fileURLToPath as f}from"node:url";import{readFile as l}from"fs/promises";import{createReadStream as u}from"fs";import{telemetry as d}from"./telemetry/index.js";import{createRouter as v}from"./web-server/router.js";import{installProdRoutes as S}from"./web-server/routes/index.js";import{Store as g}from"./store.js";import{loadEnvVariables as D}from"./utils/envs/load-env-variables.js";import{startHttpServer as E}from"./web-server/http.js";import{readStaticData as P}from"./utils/static-data.js";import{startIdleTimeout as b}from"./web-server/middleware/idleTimeoutMiddleware.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{DatabasePreconnectService as x}from"./providers/database/database-preconnect-service.js";import{isBuildMode as I}from"./utils/envs/is-build-mode.js";import{KvService as y}from"./persistence/kv/services/kv-service.js";import{runScorecardsWorker as N}from"./plugins/scorecards/workers/run-scorecards-worker.js";import{isCatalogEntitiesEnabled as O}from"./utils/is-catalog-entities-enabled.js";import{isScorecardsEnabled as T}from"./utils/is-scorecards-enabled.js";import{renderPage as _}from"./ssr/index.js";if(!I()){let c=function(){const r=process.argv.findIndex(o=>o==="--port"||o==="-p");if(r===-1)return null;const e=process.argv[r+1];if(e.startsWith("-"))return null;const i=parseInt(e,10);return isNaN(i)?null:i};const t=p(f(import.meta.url));D(t);const n=JSON.parse(await l(a(t,"./store.json"),"utf-8")),s=g.fromJson(n,{outdir:a(t,"../client"),serverOutDir:t,serverMode:!0,contentDir:""});if(await R.instance().init({ignoreTokenExpiration:!0}),O()){await x.init(t);const r=await y.getInstance({baseDbDir:t});setInterval(()=>r.clearExpired(),300*1e3)}m(s).catch(r=>{console.error(r)});async function m(r){d.initialize();const e=await v();S(e,r,{readStaticAsset:async o=>u(o),resolveRouteData:async o=>P(o.slug,r.outdir)}),w.printErrors();const i=c();return await E(e,i??process.env.PORT??4e3),b(),T(r.config)&&N(r.serverOutDir),e}}export{_ as renderPage};
1
+ import{resolve as a,dirname as p}from"node:path";import{fileURLToPath as f}from"node:url";import{readFile as l}from"fs/promises";import{createReadStream as d}from"fs";import{telemetry as u}from"./telemetry/index.js";import{createRouter as v}from"./web-server/router.js";import{installProdRoutes as S}from"./web-server/routes/index.js";import{Store as g}from"./store.js";import{loadEnvVariables as D}from"./utils/envs/load-env-variables.js";import{startHttpServer as E}from"./web-server/http.js";import{readStaticData as w}from"./utils/static-data.js";import{startIdleTimeout as P}from"./web-server/middleware/idleTimeoutMiddleware.js";import{reporter as b}from"./tools/notifiers/reporter.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{DatabasePreconnectService as x}from"./providers/database/database-preconnect-service.js";import{isBuildMode as I}from"./utils/envs/is-build-mode.js";import{KvService as y}from"./persistence/kv/services/kv-service.js";import{runScorecardsWorker as N}from"./plugins/scorecards/workers/run-scorecards-worker.js";import{isCatalogEntitiesEnabled as O}from"./utils/is-catalog-entities-enabled.js";import{isScorecardsEnabled as T}from"./utils/is-scorecards-enabled.js";import{renderPage as _}from"./ssr/index.js";if(!I()){let c=function(){const r=process.argv.findIndex(o=>o==="--port"||o==="-p");if(r===-1)return null;const e=process.argv[r+1];if(e.startsWith("-"))return null;const i=parseInt(e,10);return isNaN(i)?null:i};const t=p(f(import.meta.url));await D(t);const n=JSON.parse(await l(a(t,"./store.json"),"utf-8")),s=g.fromJson(n,{outdir:a(t,"../client"),serverOutDir:t,serverMode:!0,contentDir:""});if(await R.instance().init({ignoreTokenExpiration:!0}),O()){await x.init(t);const r=await y.getInstance({baseDbDir:t});setInterval(()=>r.clearExpired(),300*1e3)}m(s).catch(r=>{console.error(r)});async function m(r){u.initialize();const e=await v();S(e,r,{readStaticAsset:async o=>d(o),resolveRouteData:async o=>w(o.slug,r.outdir)}),b.printErrors();const i=c();return await E(e,i??process.env.PORT??4e3),P(),T(r.config)&&N(r.serverOutDir,r.config.scorecards),e}}export{_ as renderPage};
@@ -6,6 +6,7 @@ export declare class KvRemoteRepository extends BaseRepository {
6
6
  #private;
7
7
  constructor(dbConnection: DatabaseConnection);
8
8
  static getInstance(options: RepositoryInstanceOptions): Promise<KvRemoteRepository | null>;
9
+ sync(): Promise<void>;
9
10
  get<T extends KvValue = KvValue>(key: KvKey): Promise<T | null>;
10
11
  getMany<T extends KvValue = KvValue>(keys: KvKey[]): Promise<(KvListEntry<T> | null)[]>;
11
12
  list<T extends KvValue = KvValue>(selector: KvListSelector, options?: KvListOptions): Promise<KvListResponse<T>>;
@@ -1 +1,2 @@
1
- import{eq as E,and as g,gte as m,gt as M,lt as f,asc as B,desc as D,or as K,isNull as C,sql as c,inArray as q,count as $}from"drizzle-orm";import{logger as l}from"../../../tools/notifiers/logger.js";import{kvTable as t}from"../../../providers/database/databases/sqld-sqlite/schemas/kv-table.js";import{BaseRepository as I}from"../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as N}from"../../../providers/database/database-connection-factory.js";import{createKvValue as S}from"../mappers/create-kv-value.js";import{createKvDbRecord as Q,encodeKvKey as d}from"../mappers/create-kv-db-record.js";import{decodeCursor as U}from"../helpers/decode-cursor.js";import{encodeCursor as V}from"../helpers/encode-cursor.js";import{createKvListEntry as b}from"../mappers/create-kv-list-entry.js";const Y="";class u extends I{static#e;constructor(e){super(e)}static async getInstance(e){if(!u.#e)try{const r=await N.create("sqld-remote",e);if(!r)return u.#e=null,null;u.#e=new u(r)}catch(r){return l.error("Error creating kv remote repository",r),u.#e=null,null}return u.#e}async get(e){try{const r=d(e),n=await this.databaseClient.client.select().from(t).where(g(E(t.encodedKey,r),K(C(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`)))).get();return n?S(n):null}catch(r){return l.error("Error getting kv entry by key",r),null}}async getMany(e){try{if(e.length===0)return[];const r=e.map(i=>d(i)),n=K(C(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`)),s=await this.databaseClient.client.select().from(t).where(g(q(t.encodedKey,r),n)).all(),o=new Map(s.map(i=>[i.encodedKey,i]));return e.map((i,x)=>{const p=r[x],w=o.get(p);return w?b(w):null})}catch(r){return l.error("Error getting multiple kv entries",r),[]}}async list(e,r){try{const n=r?.limit??100,s=r?.reverse??!1,o=[],v=K(C(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`));if(o.push(v),"prefix"in e){const a=d(e.prefix),y="start"in e?d(e.start):a,k="end"in e?d(e.end):a+Y;o.push(m(t.encodedKey,y)),o.push(f(t.encodedKey,k))}else if("start"in e&&"end"in e){const a=d(e.start),y=d(e.end);o.push(m(t.encodedKey,a)),o.push(f(t.encodedKey,y))}if(r?.cursor){const a=U(r.cursor),y=s?f(t.encodedKey,a):M(t.encodedKey,a);o.push(y)}const i=this.databaseClient.client.select().from(t),x=o.length>0?i.where(g(...o)):i,p=this.databaseClient.client.select({count:$()}).from(t),A=(await(o.length>0?p.where(g(...o)):p).get())?.count??0,h=await x.orderBy(s?D(t.encodedKey):B(t.encodedKey)).limit(n).all();return{items:h.map(a=>b(a)),total:A,cursor:A>h.length?V(h[h.length-1]?.encodedKey):null}}catch(n){return l.error("Error listing kv entries",n),{items:[],total:0,cursor:null}}}async set(e,r,n){try{const s=Q({key:e,value:r,ttlInSeconds:n?.ttlInSeconds});return await this.databaseClient.client.insert(t).values(s).onConflictDoUpdate({target:[t.encodedKey],set:{value:s.value,expiresAt:s.expiresAt,updatedAt:s.updatedAt}}),b(s)}catch(s){return l.error("Error saving kv entry",s),null}}async delete(e){try{const r=d(e);await this.databaseClient.client.delete(t).where(E(t.encodedKey,r))}catch(r){l.error("Error deleting kv entry by key",r)}}async clearExpired(){try{await this.databaseClient.client.delete(t).where(f(c`datetime(${t.expiresAt})`,c`datetime('now')`))}catch(e){l.error("Error clearing expired kv entries",e)}}async transaction(e){return this.databaseClient.transactionsManager.transaction(async()=>e({get:async n=>this.get(n),getMany:async n=>this.getMany(n),set:async(n,s,o)=>this.set(n,s,o),delete:async n=>this.delete(n)}))}}export{Y as KV_KEY_END_BOUNDARY,u as KvRemoteRepository};
1
+ import{eq as E,and as g,gte as m,gt as M,lt as f,asc as D,desc as B,or as K,isNull as b,sql as c,inArray as q,count as N}from"drizzle-orm";import{logger as d}from"../../../tools/notifiers/logger.js";import{kvTable as t}from"../../../providers/database/databases/sqld-sqlite/schemas/kv-table.js";import{BaseRepository as $}from"../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as I}from"../../../providers/database/database-connection-factory.js";import{createKvValue as S}from"../mappers/create-kv-value.js";import{createKvDbRecord as V,encodeKvKey as l}from"../mappers/create-kv-db-record.js";import{decodeCursor as L}from"../helpers/decode-cursor.js";import{encodeCursor as Q}from"../helpers/encode-cursor.js";import{createKvListEntry as C}from"../mappers/create-kv-list-entry.js";const U="";class u extends ${static#e;#t=!1;constructor(e){super(e)}static async getInstance(e){if(!u.#e)try{const r=await I.create("sqld-remote",e);if(!r)return u.#e=null,null;u.#e=new u(r)}catch(r){return d.error("Error creating kv remote repository",r),u.#e=null,null}return u.#e}async sync(){if(!this.#t&&this.isNonRemoteDatabaseMode()){d.warn(`KV database is currently operating in local mode: not connected to the remote database.
2
+ All changes and data will only persist locally and will not be synced remotely.`),this.#t=!0;return}await this.databaseClient.sync()}async get(e){try{const r=l(e),n=await this.databaseClient.client.select().from(t).where(g(E(t.encodedKey,r),K(b(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`)))).get();return n?S(n):null}catch(r){return d.error("Error getting kv entry by key",r),null}}async getMany(e){try{if(e.length===0)return[];const r=e.map(i=>l(i)),n=K(b(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`)),a=await this.databaseClient.client.select().from(t).where(g(q(t.encodedKey,r),n)).all(),s=new Map(a.map(i=>[i.encodedKey,i]));return e.map((i,w)=>{const h=r[w],x=s.get(h);return x?C(x):null})}catch(r){return d.error("Error getting multiple kv entries",r),[]}}async list(e,r){try{const n=r?.limit??100,a=r?.reverse??!1,s=[],v=K(b(t.expiresAt),m(c`datetime(${t.expiresAt})`,c`datetime('now')`));if(s.push(v),"prefix"in e){const o=l(e.prefix),y="start"in e?l(e.start):o,k="end"in e?l(e.end):o+U;s.push(m(t.encodedKey,y)),s.push(f(t.encodedKey,k))}else if("start"in e&&"end"in e){const o=l(e.start),y=l(e.end);s.push(m(t.encodedKey,o)),s.push(f(t.encodedKey,y))}if(r?.cursor){const o=L(r.cursor),y=a?f(t.encodedKey,o):M(t.encodedKey,o);s.push(y)}const i=this.databaseClient.client.select().from(t),w=s.length>0?i.where(g(...s)):i,h=this.databaseClient.client.select({count:N()}).from(t),A=(await(s.length>0?h.where(g(...s)):h).get())?.count??0,p=await w.orderBy(a?B(t.encodedKey):D(t.encodedKey)).limit(n).all();return{items:p.map(o=>C(o)),total:A,cursor:A>p.length?Q(p[p.length-1]?.encodedKey):null}}catch(n){return d.error("Error listing kv entries",n),{items:[],total:0,cursor:null}}}async set(e,r,n){try{const a=V({key:e,value:r,ttlInSeconds:n?.ttlInSeconds});return await this.databaseClient.client.insert(t).values(a).onConflictDoUpdate({target:[t.encodedKey],set:{value:a.value,expiresAt:a.expiresAt,updatedAt:a.updatedAt}}),C(a)}catch(a){return d.error("Error saving kv entry",a),null}}async delete(e){try{const r=l(e);await this.databaseClient.client.delete(t).where(E(t.encodedKey,r))}catch(r){d.error("Error deleting kv entry by key",r)}}async clearExpired(){try{await this.databaseClient.client.delete(t).where(f(c`datetime(${t.expiresAt})`,c`datetime('now')`))}catch(e){d.error("Error clearing expired kv entries",e)}}async transaction(e){return this.databaseClient.transactionsManager.transaction(async()=>e({get:async n=>this.get(n),getMany:async n=>this.getMany(n),set:async(n,a,s)=>this.set(n,a,s),delete:async n=>this.delete(n)}))}}export{U as KV_KEY_END_BOUNDARY,u as KvRemoteRepository};
@@ -82,12 +82,12 @@ export declare class CatalogEntitiesService {
82
82
  }>>;
83
83
  createEntityRelation(relation: EntityRelationDtoSchema): Promise<{
84
84
  id: string;
85
+ createdAt: string;
86
+ updatedAt: string;
85
87
  organizationId: string;
86
88
  projectId: string;
87
89
  sourceFile: string | null;
88
90
  isDeleted: boolean | null;
89
- createdAt: string;
90
- updatedAt: string;
91
91
  sourceKey: string;
92
92
  targetKey: string;
93
93
  sourceVersion: string;
@@ -101,12 +101,12 @@ export declare class CatalogEntitiesService {
101
101
  createEntitiesRelations(entities: EntityRelationDtoSchema[]): Promise<BulkSyncResult<DatabaseEntityRelation>>;
102
102
  updateEntityRelation(id: string, relation: EntityRelationDtoSchema): Promise<{
103
103
  id: string;
104
+ createdAt: string;
105
+ updatedAt: string;
104
106
  organizationId: string;
105
107
  projectId: string;
106
108
  sourceFile: string | null;
107
109
  isDeleted: boolean | null;
108
- createdAt: string;
109
- updatedAt: string;
110
110
  sourceKey: string;
111
111
  targetKey: string;
112
112
  sourceVersion: string;
@@ -59,12 +59,12 @@ export declare class CatalogEntitiesLocalRepository extends BaseRepository {
59
59
  createEntities(createEntitiesParams: CreateEntityParams[]): Promise<void>;
60
60
  createEntityRelation(entityRelation: EntityRelationDtoSchema): Promise<{
61
61
  id: string;
62
+ createdAt: string;
63
+ updatedAt: string;
62
64
  organizationId: string;
63
65
  projectId: string;
64
66
  sourceFile: string | null;
65
67
  isDeleted: boolean | null;
66
- createdAt: string;
67
- updatedAt: string;
68
68
  sourceKey: string;
69
69
  targetKey: string;
70
70
  sourceVersion: string;
@@ -1 +1 @@
1
- import{and as d,desc as I,eq as u,isNull as v,or as K,sql as k}from"drizzle-orm";import{logger as h}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as w}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as U}from"../../../../../utils/crypto/sha1.js";import{isWebView as x}from"../../../../../../utils/env/is-web-view.js";import{VERSION_NOT_SPECIFIED as S}from"@redocly/theme/core/constants";import{entitiesAttributesTable as E}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js";import{createEntityDbRecord as z}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as A}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as e}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as o}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as T}from"../../../../../providers/database/pagination/filter.js";import{compareVersionsDescending as L}from"../../../utils/version-compare.js";import{createEntityAttributesDbRecord as N}from"../../mappers/create-entity-attributes-db-record.js";const D=15;class ie{#e;#t;#r;constructor(t,r,i){this.#e=t,this.#t=r,this.#r=i}async createEntity({entity:t,fileHash:r,sourceFile:i,revision:a=new Date().toISOString(),isRootEntity:n=!1,isDeleted:s=!1,rbacTeams:c=[]}){try{const{relations:l=[],...m}=t,V=U(JSON.stringify(m)),f=t.version??S;if(await this.#i(t.key,f,V,n,s))return{result:"skipped",entityKey:t.key};const{shouldBeCurrent:p,shouldBeDefaultVersion:y}=await this.#o(t.key,f),g=z({entity:{...t,revision:a,hash:V,isCurrent:p,isDefaultVersion:y,isDeleted:s,version:f},sourceFile:i,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:r}),{key:F,source:j,...b}=g;if(await this.#a({key:F,isCurrent:p,isDefaultVersion:y}),x())return await this.#c(g,l,c),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f};const O=this.#e.client.insert(e).values(g).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:b}),B=this.#e.client.insert(E).values(N({rbacTeams:c,entityKey:t.key,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[E.entityKey],set:{rbacTeams:JSON.stringify(c)}}),P=l?.length&&l.length>0?this.#e.client.insert(o).values(l.map(C=>A({relation:C,sourceFile:i,fileHash:r,sourceKey:t.key,sourceVersion:f,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation]}).run():Promise.resolve();return await w([O,P,B],D,async C=>C),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:f}}catch(l){return h.error("Error adding entity",l),{result:"error",entityKey:t.key}}}async deleteEntity(t){try{return await this.#e.client.delete(e).where(u(e.key,t)),t}catch(r){return h.error("Error deleting entity",r),null}}async deleteEntities(t){try{const r=T(t);if(!r)return!1;const i=await this.#e.client.delete(e).where(r).returning({key:e.key,source:e.source,isCurrent:e.isCurrent,isDefaultVersion:e.isDefaultVersion,version:e.version});if(i.length===0)return!0;const a=i.reduce((n,s)=>((s.isCurrent||s.isDefaultVersion)&&n.add(s.key),n),new Set);if(a.size===0)return!0;await w(Array.from(a),D,async n=>this.#u(n));for(const n of i)await this.#e.client.delete(o).where(K(d(u(o.sourceKey,n.key),...n.version?[u(o.sourceVersion,n.version)]:[v(o.sourceVersion)]),d(u(o.targetKey,n.key),...n.version?[u(o.targetVersion,n.version)]:[v(o.targetVersion)])));return!0}catch(r){return h.error("Error deleting entities",r),!1}}async deleteEntityRelation(t){try{return await this.#e.client.delete(o).where(u(o.id,t)),t}catch{return null}}async softDeleteEntities(t,r,i){try{const a=t.map(s=>{const c={type:s.type,key:s.key,title:s.title,summary:s.summary??void 0,tags:s.tags??void 0,metadata:s.metadata??void 0,git:s.git??void 0,contact:s.contact??void 0,links:s.links??void 0,version:s.version??void 0};return this.createEntity({entity:c,revision:r,sourceFile:s.sourceFile??"",fileHash:i,isDeleted:!0})});return await w(a,D,async s=>s)}catch(a){return h.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(t){try{const r=T(t);return r?(await this.#e.client.delete(o).where(r),!0):!1}catch(r){return h.error("Error deleting entity relations",r),!1}}async upsertEntityRelation(t){if(!t)return null;try{const{sourceKey:r,targetKey:i,sourceVersion:a,targetVersion:n,sourceRevision:s,targetRevision:c,...l}=t,m=await this.#e.client.insert(o).values(t).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation],set:l}).returning();return m?.length?m[0]:null}catch(r){return h.error("Error creating entity relation",r),null}}async#i(t,r,i,a,n){if(a||n)return!1;const s=await this.#e.client.select({hash:e.hash,isDeleted:e.isDeleted}).from(e).where(d(u(e.key,t),u(e.source,"file"),r?u(e.version,r):v(e.version))).orderBy(I(e.revision)).limit(1).run();if(s.rows.length===0)return!1;const c=s.rows[0];return c.is_deleted?!1:c.hash===i}async#s(t){return(await this.#e.client.select({version:e.version,isDefaultVersion:e.isDefaultVersion,revision:e.revision,createdAt:e.createdAt}).from(e).where(d(u(e.key,t),u(e.source,"file"))).orderBy(I(e.createdAt)).run()).rows.map(i=>({version:i.version,isDefaultVersion:!!i.isDefaultVersion,revision:i.revision,createdAt:new Date(i.createdAt)}))}#n(t){const r=t.find(n=>n.isDefaultVersion);if(r)return r;const{versionedEntities:i,unversionedEntities:a}=t.reduce((n,s)=>(s.version!==null&&s.version!==S?n.versionedEntities.push(s):n.unversionedEntities.push(s),n),{versionedEntities:[],unversionedEntities:[]});if(i.length>0){i.sort((c,l)=>L(c.version,l.version));const n=i[0].version,s=i.filter(c=>c.version===n);return s.sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime()),s[0]}return a.length>0?(a.sort((n,s)=>s.createdAt.getTime()-n.createdAt.getTime()),a[0]):null}async#o(t,r){const i=await this.#e.client.select({currentDefaultVersion:k`max(case when ${e.isDefaultVersion} = 1 then ${e.version} else null end)`,versionMatchCount:k`count(case when ${e.version} = ${r} then 1 else null end)`}).from(e).where(d(u(e.key,t),u(e.source,"file"))).get(),a=i?.currentDefaultVersion,n=(i?.versionMatchCount??0)>0;return r&&r===a?{shouldBeCurrent:!0,shouldBeDefaultVersion:!1}:{shouldBeCurrent:!n,shouldBeDefaultVersion:!n}}async#a({key:t,isCurrent:r,isDefaultVersion:i}){if(!r&&!i)return;const a={},n=[];r&&(a.isCurrent=!1,n.push(u(e.isCurrent,!0))),i&&(a.isDefaultVersion=!1,n.push(u(e.isDefaultVersion,!0))),await this.#e.client.update(e).set(a).where(d(u(e.key,t),u(e.source,"file"),K(...n))).run()}#u=async t=>{const r=await this.#s(t),i=this.#n(r);if(!i){h.warn("No latest version found for key",t);return}await this.#e.client.update(e).set({isDefaultVersion:!0,isCurrent:!0}).where(d(u(e.key,t),u(e.revision,i.revision),i.version?u(e.version,i.version):v(e.version))).run()};async#c(t,r,i){const{key:a,source:n,version:s,isDefaultVersion:c,...l}=t,f=(await this.#e.client.select({id:e.id}).from(e).where(d(u(e.key,a),u(e.source,n??"file"),s?u(e.version,s):v(e.version))).limit(1).run()).rows.length>0?this.#e.client.update(e).set(l).where(d(u(e.key,a),u(e.source,n??"file"),s?u(e.version,s):v(e.version))).run():this.#e.client.insert(e).values(t).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:l}).run(),R=r?.map(y=>{const g=A({relation:y,sourceFile:t.sourceFile??"",fileHash:t.fileHash??"",sourceKey:t.key,sourceVersion:t.version??null,sourceRevision:t.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(o).values(g).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation],set:g}).run()})??[],p=this.#e.client.insert(E).values(N({rbacTeams:i,entityKey:t.key,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[E.entityKey],set:{rbacTeams:JSON.stringify(i)}});await w([f,...R,p],D,async y=>y)}async updateEntityScorecardsStatus(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(u(e.id,t)).returning()).length>0}catch(i){return h.error("Error updating entity scorecards status",i),!1}}async updateEntityScorecardsStatusIfCalculating(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(k`${e.id} = ${t} AND ${e.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(i){return h.error("Error updating entity scorecards status if calculating",i),!1}}}export{ie as CatalogEntitiesLocalWriteRepository};
1
+ import{and as d,desc as I,eq as u,isNull as v,or as K,sql as k}from"drizzle-orm";import{logger as f}from"../../../../../tools/notifiers/logger.js";import{promiseMapLimit as w}from"../../../../../utils/async/promise-map-limit.js";import{sha1 as U}from"../../../../../utils/crypto/sha1.js";import{isWebView as x}from"../../../../../../utils/env/is-web-view.js";import{VERSION_NOT_SPECIFIED as S}from"@redocly/theme/core/constants";import{entitiesAttributesTable as E}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js";import{createEntityDbRecord as z}from"../../mappers/create-entity-db-record.js";import{createEntityRelationDbRecordFromFileSchema as A}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{entitiesTable as e}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{entitiesRelationsTable as o}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{convertFilterToWhereCondition as T}from"../../../../../providers/database/pagination/filter.js";import{compareVersionsDescending as L}from"../../../utils/version-compare.js";import{createEntityAttributesDbRecord as F}from"../../mappers/create-entity-attributes-db-record.js";const D=15;class ie{#e;#t;#r;constructor(t,r,i){this.#e=t,this.#t=r,this.#r=i}async createEntity({entity:t,fileHash:r,sourceFile:i,revision:a=new Date().toISOString(),isRootEntity:n=!1,isDeleted:s=!1,rbacTeams:c=[]}){try{const{relations:l=[],...m}=t,V=U(JSON.stringify(m)),h=t.version??S;if(await this.#i(t.key,h,V,n,s))return{result:"skipped",entityKey:t.key};const{shouldBeCurrent:p,shouldBeDefaultVersion:y}=await this.#o(t.key,h),g=z({entity:{...t,revision:a,hash:V,isCurrent:p,isDefaultVersion:y,isDeleted:s,version:h},sourceFile:i,organizationId:this.#t,projectId:this.#r,source:"file",fileHash:r}),{key:N,source:j,...b}=g;if(await this.#a({key:N,isCurrent:p,isDefaultVersion:y}),x())return await this.#c(g,l,c),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:h};const O=this.#e.client.insert(e).values(g).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:b}),B=this.#e.client.insert(E).values(F({rbacTeams:c,entityKey:t.key,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[E.entityKey],set:{rbacTeams:JSON.stringify(c)}}),P=l?.length&&l.length>0?this.#e.client.insert(o).values(l.map(C=>A({relation:C,sourceFile:i,fileHash:r,sourceKey:t.key,sourceVersion:h,sourceRevision:a??null,organizationId:this.#t,projectId:this.#r}))).onConflictDoNothing({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation]}).run():Promise.resolve();return await w([O,P,B],D,async C=>C),{result:"created",entityKey:t.key,entityRevision:a,entityVersion:h}}catch(l){return f.error("Error adding entity",l),{result:"error",entityKey:t.key}}}async deleteEntity(t){try{return await this.#e.client.delete(e).where(u(e.key,t)),t}catch(r){return f.error("Error deleting entity",r),null}}async deleteEntities(t){try{const r=T(t);if(!r)return!1;const i=await this.#e.client.delete(e).where(r).returning({key:e.key,source:e.source,isCurrent:e.isCurrent,isDefaultVersion:e.isDefaultVersion,version:e.version});if(i.length===0)return!0;const a=i.reduce((n,s)=>((s.isCurrent||s.isDefaultVersion)&&n.add(s.key),n),new Set);if(a.size===0)return!0;await w(Array.from(a),D,async n=>this.#u(n));for(const n of i)await this.#e.client.delete(o).where(K(d(u(o.sourceKey,n.key),...n.version?[u(o.sourceVersion,n.version)]:[v(o.sourceVersion)]),d(u(o.targetKey,n.key),...n.version?[u(o.targetVersion,n.version)]:[v(o.targetVersion)])));return!0}catch(r){return f.error("Error deleting entities",r),!1}}async deleteEntityRelation(t){try{return await this.#e.client.delete(o).where(u(o.id,t)),t}catch{return null}}async softDeleteEntities(t,r,i){try{const a=t.map(s=>{const c={type:s.type,key:s.key,title:s.title,summary:s.summary??void 0,tags:s.tags??void 0,metadata:s.metadata??void 0,git:s.git??void 0,contact:s.contact??void 0,links:s.links??void 0,version:s.version??void 0};return this.createEntity({entity:c,revision:r,sourceFile:s.sourceFile??"",fileHash:i,isDeleted:!0})});return await w(a,D,async s=>s)}catch(a){return f.error("Error soft deleting entities",a),[]}}async deleteEntityRelations(t){try{const r=T(t);return r?(await this.#e.client.delete(o).where(r),!0):!1}catch(r){return f.error("Error deleting entity relations",r),!1}}async upsertEntityRelation(t){if(!t)return null;try{const{sourceKey:r,targetKey:i,sourceVersion:a,targetVersion:n,sourceRevision:s,targetRevision:c,...l}=t,m=await this.#e.client.insert(o).values(t).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation],set:l}).returning();return m?.length?m[0]:null}catch(r){return f.error("Error creating entity relation",r),null}}async#i(t,r,i,a,n){if(a||n)return!1;const s=await this.#e.client.select({hash:e.hash,isDeleted:e.isDeleted}).from(e).where(d(u(e.key,t),u(e.source,"file"),r?u(e.version,r):v(e.version))).orderBy(I(e.revision)).limit(1).run();if(s.rows.length===0)return!1;const c=s.rows[0];return c.is_deleted?!1:c.hash===i}async#s(t){return(await this.#e.client.select({version:e.version,isDefaultVersion:e.isDefaultVersion,revision:e.revision,createdAt:e.createdAt}).from(e).where(d(u(e.key,t),u(e.source,"file"))).orderBy(I(e.createdAt)).run()).rows.map(i=>({version:i.version,isDefaultVersion:!!i.isDefaultVersion,revision:i.revision,createdAt:new Date(i.createdAt)}))}#n(t){const r=t.find(n=>n.isDefaultVersion);if(r)return r;const{versionedEntities:i,unversionedEntities:a}=t.reduce((n,s)=>(s.version!==null&&s.version!==S?n.versionedEntities.push(s):n.unversionedEntities.push(s),n),{versionedEntities:[],unversionedEntities:[]});if(i.length>0){i.sort((c,l)=>L(c.version,l.version));const n=i[0].version,s=i.filter(c=>c.version===n);return s.sort((c,l)=>l.createdAt.getTime()-c.createdAt.getTime()),s[0]}return a.length>0?(a.sort((n,s)=>s.createdAt.getTime()-n.createdAt.getTime()),a[0]):null}async#o(t,r){const i=await this.#e.client.select({currentDefaultVersion:k`max(case when ${e.isDefaultVersion} = 1 then ${e.version} else null end)`,versionMatchCount:k`count(case when ${e.version} = ${r} then 1 else null end)`}).from(e).where(d(u(e.key,t),u(e.source,"file"))).get(),a=i?.currentDefaultVersion,n=(i?.versionMatchCount??0)>0;return r&&r===a?{shouldBeCurrent:!0,shouldBeDefaultVersion:!1}:{shouldBeCurrent:!n,shouldBeDefaultVersion:!n}}async#a({key:t,isCurrent:r,isDefaultVersion:i}){if(!r&&!i)return;const a={},n=[];r&&(a.isCurrent=!1,n.push(u(e.isCurrent,!0))),i&&(a.isDefaultVersion=!1,n.push(u(e.isDefaultVersion,!0))),await this.#e.client.update(e).set(a).where(d(u(e.key,t),u(e.source,"file"),K(...n))).run()}#u=async t=>{const r=await this.#s(t),i=this.#n(r);i&&await this.#e.client.update(e).set({isDefaultVersion:!0,isCurrent:!0}).where(d(u(e.key,t),u(e.revision,i.revision),i.version?u(e.version,i.version):v(e.version))).run()};async#c(t,r,i){const{key:a,source:n,version:s,isDefaultVersion:c,...l}=t,h=(await this.#e.client.select({id:e.id}).from(e).where(d(u(e.key,a),u(e.source,n??"file"),s?u(e.version,s):v(e.version))).limit(1).run()).rows.length>0?this.#e.client.update(e).set(l).where(d(u(e.key,a),u(e.source,n??"file"),s?u(e.version,s):v(e.version))).run():this.#e.client.insert(e).values(t).onConflictDoUpdate({target:[e.key,e.source,e.revision,e.version],set:l}).run(),R=r?.map(y=>{const g=A({relation:y,sourceFile:t.sourceFile??"",fileHash:t.fileHash??"",sourceKey:t.key,sourceVersion:t.version??null,sourceRevision:t.revision??null,organizationId:this.#t,projectId:this.#r});return this.#e.client.insert(o).values(g).onConflictDoUpdate({target:[o.sourceKey,o.targetKey,o.sourceVersion,o.targetVersion,o.sourceRevision,o.targetRevision,o.sourceToTargetRelation],set:g}).run()})??[],p=this.#e.client.insert(E).values(F({rbacTeams:i,entityKey:t.key,organizationId:this.#t,projectId:this.#r})).onConflictDoUpdate({target:[E.entityKey],set:{rbacTeams:JSON.stringify(i)}});await w([h,...R,p],D,async y=>y)}async updateEntityScorecardsStatus(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(u(e.id,t)).returning()).length>0}catch(i){return f.error("Error updating entity scorecards status",i),!1}}async updateEntityScorecardsStatusIfCalculating(t,r){try{return(await this.#e.client.update(e).set({scorecardsStatus:r}).where(k`${e.id} = ${t} AND ${e.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}catch(i){return f.error("Error updating entity scorecards status if calculating",i),!1}}}export{ie as CatalogEntitiesLocalWriteRepository};
@@ -1 +1 @@
1
- import{eq as h,sql as f}from"drizzle-orm";import{convertFilterToWhereCondition as w}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{logger as i}from"../../../../../tools/notifiers/logger.js";import{entitiesTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{telemetryTraceStep as a}from"../../../../../telemetry/helpers/trace-step.js";import{BaseRepository as _}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as b}from"../../../../../providers/database/database-connection-factory.js";import{entitiesRelationsTable as n}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{createEntityDbRecord as p}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as g}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as C}from"../../mappers/create-entity-relation-db-record-from-dto.js";const I=15;class s extends _{static#e;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(e){super(e)}async sync(){return a("catalog_entities.remote_repository.sync",async()=>{await this.#t(),await this.databaseClient.sync()})}static async getInstance(e){return await a("catalog_entities.remote_repository.get_instance",async t=>{if(!s.#e)try{const o=await b.create("sqld-remote",e);if(!o)return i.error("Failed to create db connection for catalog entities remote repository"),t?.error(new Error("Failed to create db connection for catalog entities remote repository")),s.#e=null,null;s.#e=new s(o)}catch(o){return i.error("Error creating db connection for catalog entities remote repository",o),t?.error(o),s.#e=null,null}return s.#e})}async createEntity(e){return a("catalog_entities.remote_repository.create_entity",async()=>{await this.#t();try{i.info(`Adding entity ${e.key} to remote database`);const t=p({entity:e,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:d,...u}=t,l=await this.databaseClient.client.insert(r).values(t).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:u}).returning();return l.length?(e.relations&&await this.createEntityRelations(e.relations.map(c=>({...c,sourceKey:e.key,targetKey:c.key}))),g(l[0])):null}catch(t){throw i.error("Error adding entity",t),t}})}async updateEntity(e){return a("catalog_entities.remote_repository.update_entity",async()=>{await this.#t();try{i.info(`Updating entity ${e.key} in remote database`);const t=p({entity:e,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:d,scorecardsStatus:u,...l}=t,c=await this.databaseClient.client.insert(r).values(t).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:{...l,scorecardsStatus:f`CASE WHEN ${r.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return c.length?g(c[0]):null}catch(t){return i.error("Error updating entity",t),null}})}async deleteEntity(e){return a("catalog_entities.remote_repository.delete_entity",async()=>{await this.#t();try{return await this.databaseClient.client.delete(r).where(h(r.key,e)),e}catch(t){return i.error("Error deleting entity",t),null}})}async createEntityRelations(e){return a("catalog_entities.remote_repository.create_entity_relations",async()=>(await this.#t(),await E(e,I,async t=>this.createEntityRelation(t))))}async createEntityRelation(e){return a("catalog_entities.remote_repository.create_entity_relation",async()=>{if(await this.#t(),!e)return null;try{const t=C(e,this.organizationId,this.projectId),{sourceKey:o,targetKey:d,sourceVersion:u,targetVersion:l,sourceRevision:c,targetRevision:D,...m}=t,y=await this.databaseClient.client.insert(n).values(t).onConflictDoUpdate({target:[n.sourceKey,n.targetKey,n.sourceVersion,n.targetVersion,n.sourceRevision,n.targetRevision,n.sourceToTargetRelation],set:m}).returning();return y.length?y[0]:null}catch(t){throw i.error("Error creating entity relation",t),t}})}async deleteEntityRelation(e){return a("catalog_entities.remote_repository.delete_entity_relation",async()=>{await this.#t();try{return await this.databaseClient.client.delete(n).where(h(n.id,e)),e}catch(t){return i.error("Error deleting entity relation",t),null}})}async deleteEntitiesRelations(e){return a("catalog_entities.remote_repository.delete_entities_relations",async()=>{await this.#t();try{const t=w(e);return t?(await this.databaseClient.client.delete(n).where(t),!0):!1}catch(t){return i.error("Error deleting entities relations",t),!1}})}#t(){return a("catalog_entities.remote_repository.db_health",async e=>{if(this.databaseClient.dbClient.$client.closed){const t=new Error("The remote database connection is closed!");throw e?.error(t),t}})}}export{s as CatalogEntitiesRemoteRepository};
1
+ import{eq as h,sql as f}from"drizzle-orm";import{convertFilterToWhereCondition as w}from"../../../../../providers/database/pagination/filter.js";import{promiseMapLimit as b}from"../../../../../utils/async/promise-map-limit.js";import{logger as n}from"../../../../../tools/notifiers/logger.js";import{entitiesTable as r}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-table.js";import{telemetryTraceStep as i}from"../../../../../telemetry/helpers/trace-step.js";import{BaseRepository as E}from"../../../../../providers/database/base-repository.js";import{DatabaseConnectionFactory as _}from"../../../../../providers/database/database-connection-factory.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js";import{createEntityDbRecord as g}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as m}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromDto as C}from"../../mappers/create-entity-relation-db-record-from-dto.js";const D=15;class s extends E{static#t;#r=!1;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t)}async sync(){if(!this.#r&&this.isNonRemoteDatabaseMode()){n.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.#r=!0;return}return i("catalog_entities.remote_repository.sync",async()=>{await this.#e(),await this.databaseClient.sync()})}static async getInstance(t){return await i("catalog_entities.remote_repository.get_instance",async e=>{if(!s.#t)try{const o=await _.create("sqld-remote",t);if(!o)return n.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")),s.#t=null,null;s.#t=new s(o)}catch(o){return n.error("Error creating db connection for catalog entities remote repository",o),e?.error(o),s.#t=null,null}return s.#t})}async createEntity(t){return i("catalog_entities.remote_repository.create_entity",async()=>{await this.#e();try{n.info(`Adding entity ${t.key} to remote database`);const e=g({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,...d}=e,l=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:d}).returning();return l.length?(t.relations&&await this.createEntityRelations(t.relations.map(c=>({...c,sourceKey:t.key,targetKey:c.key}))),m(l[0])):null}catch(e){throw n.error("Error adding entity",e),e}})}async updateEntity(t){return i("catalog_entities.remote_repository.update_entity",async()=>{await this.#e();try{n.info(`Updating entity ${t.key} in remote database`);const e=g({entity:t,organizationId:this.organizationId,projectId:this.projectId,source:"remote",sourceFile:null,fileHash:null}),{key:o,source:u,scorecardsStatus:d,...l}=e,c=await this.databaseClient.client.insert(r).values(e).onConflictDoUpdate({target:[r.key,r.source,r.revision,r.version],set:{...l,scorecardsStatus:f`CASE WHEN ${r.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return c.length?m(c[0]):null}catch(e){return n.error("Error updating entity",e),null}})}async deleteEntity(t){return i("catalog_entities.remote_repository.delete_entity",async()=>{await this.#e();try{return await this.databaseClient.client.delete(r).where(h(r.key,t)),t}catch(e){return n.error("Error deleting entity",e),null}})}async createEntityRelations(t){return i("catalog_entities.remote_repository.create_entity_relations",async()=>(await this.#e(),await b(t,D,async e=>this.createEntityRelation(e))))}async createEntityRelation(t){return i("catalog_entities.remote_repository.create_entity_relation",async()=>{if(await this.#e(),!t)return null;try{const e=C(t,this.organizationId,this.projectId),{sourceKey:o,targetKey:u,sourceVersion:d,targetVersion:l,sourceRevision:c,targetRevision:I,...p}=e,y=await this.databaseClient.client.insert(a).values(e).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision,a.sourceToTargetRelation],set:p}).returning();return y.length?y[0]:null}catch(e){throw n.error("Error creating entity relation",e),e}})}async deleteEntityRelation(t){return i("catalog_entities.remote_repository.delete_entity_relation",async()=>{await this.#e();try{return await this.databaseClient.client.delete(a).where(h(a.id,t)),t}catch(e){return n.error("Error deleting entity relation",e),null}})}async deleteEntitiesRelations(t){return i("catalog_entities.remote_repository.delete_entities_relations",async()=>{await this.#e();try{const e=w(t);return e?(await this.databaseClient.client.delete(a).where(e),!0):!1}catch(e){return n.error("Error deleting entities relations",e),!1}})}#e(){return i("catalog_entities.remote_repository.db_health",async t=>{if(this.databaseClient.dbClient.$client.closed){const e=new Error("The remote database connection is closed!");throw t?.error(e),e}})}}export{s as CatalogEntitiesRemoteRepository};
@@ -1 +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[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};
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[g]=Object.entries(r.catalogs??{}).find(([E,s])=>!s?.hide)||[];g&&t.addRedirect(m,{type:302,to:`${m}/${g}`}),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",g=d&&p,E=!O(A,r.rbac);A=r.rbac;const s=g&&E,a=await L.getInstance({baseDbDir:t.serverOutDir,removeExisting:!0,runOnlyLocalDatabase:!0,runWithPragmaWalWriteOptimization:!0}),T=await R.getInstance({baseDbDir:t.serverOutDir}),l=new F(T),y=[new x({fileHashManager:l,context:e,catalogEntitiesService:a,catalogConfig:o,shouldCalculateEntities:s}),new H({actions:t,context:e,catalogEntitiesService:a,fileHashManager:l,fileType:u.OPENAPI_DESCRIPTION,shouldCalculateEntities:s}),new w({actions:t,context:e,catalogEntitiesService:a,fileHashManager:l,fileType:u.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:s}),new N({actions:t,context:e,catalogEntitiesService:a,fileHashManager:l,fileType:u.GRAPHQL_DESCRIPTION,shouldCalculateEntities:s}),new G({actions:t,context:e,catalogEntitiesService:a,fileHashManager:l,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 c=await I.getCatalogEntitiesData(a);i?.setAttribute("totalEntities",c.totalEntitiesCount),i?.setAttribute("entitiesCountByType",JSON.stringify(c.countOfEntitiesByType)),i?.setAttribute("totalFilesSkippedByHash",c.totalFilesSkippedByHash),i?.setAttribute("totalProcessedFiles",c.totalProcessedFiles),i?.setAttribute("extractors",c.extractors),d=!1})}}}var rt=Y;export{Y as catalogEntitiesPlugin,rt as default};
@@ -1 +1 @@
1
- import w from"path";import{lintConfig as R,loadConfig as C,createConfigTypes as T}from"@redocly/openapi-core";import{deepMerge as U}from"../../../../../utils/object/deep-merge.js";import{readEnvVariable as A}from"../../../../utils/envs/read-env-variable.js";import{logger as l}from"../../../../tools/notifiers/logger.js";import{safeParsePartial as L}from"../../safe-parse.js";import{formatConfigProblem as $}from"../../format-error.js";import{ExternalResolver as q}from"../../../../fs/utils/external-ref-resolver.js";import{resolveMutuallyExclusiveProps as x}from"../../resolve-mutual-exclusion.js";function f(o,e,t,r){e in o&&o[e]&&typeof o[e]=="string"&&(/^https?:\/\/.*/.test(o[e])||r(new Error(`Invalid ${t} URL: "${o[e]}". ${t} must start with "http://" or "https://".`)))}function j(o,e){if("access"in o&&o.access&&typeof o.access=="object"){const t=o.access;f(t,"logoutReturnUrl","access.logoutReturnUrl",e),f(t,"residency","access.residency",e);const r=["requiresLogin","logoutReturnUrl","residency","sso","rbac"];for(const n of r)n in t&&t[n]!==void 0&&n in o&&o[n]!==void 0&&e(new Error(`Property '${n}' is defined both at root level and in 'access' object. Please use 'access.${n}' to define this configuration.`))}}async function z(o,e,t,r){const m=e.getFileInfo(o)?.realRelativePath||o;async function d(){const c=new q(e),u=w.join(e.cwd,m),i=await C({configPath:u,externalRefResolver:c}),y=await r(i.resolvedConfig);if(y===void 0)return i.resolvedConfig;const v=[...i.document?.source?await R({config:i,externalConfigTypes:T(y,i)}):[],...i.document?.source?x(i.resolvedConfig,i.document?.source):[]];if(v.length>0)for(const b of v)t(new Error($(b,e.cwd)));return i.resolvedConfig}const a=await e.exists(o)?await d():{},P=E(a),g=await r(a);f(a,"residency","Residency",t),f(a,"logoutReturnUrl","Logout return URL",t),j(a,t);let p=g?L(g,a):a;const{env:h}=p;if(h){const c=A("REDOCLY_ENV")||"development",u=h[c]||{};p=U(p,u)}const s=M(p,P);if(s.imports&&s.imports.length>0){l.warn("The 'imports' property is deprecated. Please use 'plugins' property instead.");const c=new Set([...s.plugins||[],...s.imports.map(u=>w.posix.join(u,"plugin.js"))]);s.plugins=Array.from(c),delete s.imports}if(s.catalog&&(l.warn("The 'catalog' property is deprecated. Please use 'catalogClassic' property instead."),s.catalogClassic={...s.catalog},delete s.catalog),s.scorecard&&(l.warn("The 'scorecard' property is deprecated. Please use 'scorecardClassic' property instead."),s.scorecardClassic=s.scorecard,delete s.scorecard),s.search?.ai){l.warn("The 'search.ai' property is deprecated. Please use 'aiAssistant' property instead.");const c={...s.search?.ai,...s.aiAssistant,suggestions:s.aiAssistant?.suggestions?.length?s.aiAssistant.suggestions:s.search?.ai.suggestions||[]};s.aiAssistant=c,delete s.search.ai}return k(s)}function k(o){const e="access"in o?o.access:void 0;if(!e||typeof e!="object")return o;const t={...o},r=[{name:"requiresLogin",type:"boolean"},{name:"logoutReturnUrl",type:"string"},{name:"residency",type:"string"},{name:"sso",type:"string | string[]"},{name:"rbac",type:"object"}],n=[];for(const m of r){const d=m.name;d in t&&t[d]!==void 0&&!(d in e)&&n.push(d)}return n.length>0&&l.warn(`The following properties at root level are deprecated: ${n.join(", ")}. Please move them to the 'access' object.`),"requiresLogin"in e&&e.requiresLogin!==void 0&&(t.requiresLogin=e.requiresLogin),"logoutReturnUrl"in e&&e.logoutReturnUrl!==void 0&&(t.logoutReturnUrl=e.logoutReturnUrl),"residency"in e&&e.residency!==void 0&&(t.residency=e.residency),"sso"in e&&e.sso!==void 0&&(t.sso=e.sso),"rbac"in e&&e.rbac!==void 0&&(t.rbac=e.rbac),delete t.access,t}function E(o){if(!o.theme)return[];l.warn("The 'theme' property in redocly.yaml is deprecated. Please move all of the properties from 'theme' to the root of the config.");const e=[];for(const t of Object.keys(o.theme))o[t]==null?e.push(t):l.warn(`Detected both '${t}' and 'theme.${t}' properties in redocly.yaml. The 'theme.${t}' property will be ignored and needs to be removed or merged into the '${t}'.`);return e}function M(o,e){if(!o.theme||e.length===0)return o;const t={...o};for(const r of e)t[r]=o.theme[r];return delete t.theme,t}export{z as readAndValidateConfig};
1
+ import w from"path";import{lintConfig as T,loadConfig as A,createConfigTypes as U}from"@redocly/openapi-core";import{deepMerge as L}from"../../../../../utils/object/deep-merge.js";import{readEnvVariable as R}from"../../../../utils/envs/read-env-variable.js";import{logger as l}from"../../../../tools/notifiers/logger.js";import{BRANCH_ENV_PREFIX as $}from"../../../../../constants/common.js";import{sanitizeBranchName as E}from"../../../../utils/envs/sanitize-branch-name.js";import{safeParsePartial as q}from"../../safe-parse.js";import{formatConfigProblem as x}from"../../format-error.js";import{ExternalResolver as B}from"../../../../fs/utils/external-ref-resolver.js";import{resolveMutuallyExclusiveProps as j}from"../../resolve-mutual-exclusion.js";function m(o,e,t,i){e in o&&o[e]&&typeof o[e]=="string"&&(/^https?:\/\/.*/.test(o[e])||i(new Error(`Invalid ${t} URL: "${o[e]}". ${t} must start with "http://" or "https://".`)))}function N(o,e){if("access"in o&&o.access&&typeof o.access=="object"){const t=o.access;m(t,"logoutReturnUrl","access.logoutReturnUrl",e),m(t,"residency","access.residency",e);const i=["requiresLogin","logoutReturnUrl","residency","sso","rbac"];for(const n of i)n in t&&t[n]!==void 0&&n in o&&o[n]!==void 0&&e(new Error(`Property '${n}' is defined both at root level and in 'access' object. Please use 'access.${n}' to define this configuration.`))}}async function G(o,e,t,i){const g=e.getFileInfo(o)?.realRelativePath||o;async function d(){const c=new B(e),u=w.join(e.cwd,g),r=await A({configPath:u,externalRefResolver:c}),p=await i(r.resolvedConfig);if(p===void 0)return r.resolvedConfig;const P=[...r.document?.source?await T({config:r,externalConfigTypes:U(p,r)}):[],...r.document?.source?j(r.resolvedConfig,r.document?.source):[]];if(P.length>0)for(const C of P)t(new Error(x(C,e.cwd)));return r.resolvedConfig}const a=await e.exists(o)?await d():{},b=I(a),y=await i(a);m(a,"residency","Residency",t),m(a,"logoutReturnUrl","Logout return URL",t),N(a,t);let f=y?q(y,a):a;const{env:h}=f;if(h){const c=R("REDOCLY_ENV")||"development",u=h[c]||{},r=R("PUBLIC_REDOCLY_BRANCH_NAME")||"",p=r?E(r):"",v=p&&h[`${$}${p}`]||{};f=L(f,v,u)}const s=M(f,b);if(s.imports&&s.imports.length>0){l.warn("The 'imports' property is deprecated. Please use 'plugins' property instead.");const c=new Set([...s.plugins||[],...s.imports.map(u=>w.posix.join(u,"plugin.js"))]);s.plugins=Array.from(c),delete s.imports}if(s.catalog&&(l.warn("The 'catalog' property is deprecated. Please use 'catalogClassic' property instead."),s.catalogClassic={...s.catalog},delete s.catalog),s.scorecard&&(l.warn("The 'scorecard' property is deprecated. Please use 'scorecardClassic' property instead."),s.scorecardClassic=s.scorecard,delete s.scorecard),s.search?.ai){l.warn("The 'search.ai' property is deprecated. Please use 'aiAssistant' property instead.");const c={...s.search?.ai,...s.aiAssistant,suggestions:s.aiAssistant?.suggestions?.length?s.aiAssistant.suggestions:s.search?.ai.suggestions||[]};s.aiAssistant=c,delete s.search.ai}return _(s)}function _(o){const e="access"in o?o.access:void 0;if(!e||typeof e!="object")return o;const t={...o},i=[{name:"requiresLogin",type:"boolean"},{name:"logoutReturnUrl",type:"string"},{name:"residency",type:"string"},{name:"sso",type:"string | string[]"},{name:"rbac",type:"object"}],n=[];for(const g of i){const d=g.name;d in t&&t[d]!==void 0&&!(d in e)&&n.push(d)}return n.length>0&&l.warn(`The following properties at root level are deprecated: ${n.join(", ")}. Please move them to the 'access' object.`),"requiresLogin"in e&&e.requiresLogin!==void 0&&(t.requiresLogin=e.requiresLogin),"logoutReturnUrl"in e&&e.logoutReturnUrl!==void 0&&(t.logoutReturnUrl=e.logoutReturnUrl),"residency"in e&&e.residency!==void 0&&(t.residency=e.residency),"sso"in e&&e.sso!==void 0&&(t.sso=e.sso),"rbac"in e&&e.rbac!==void 0&&(t.rbac=e.rbac),delete t.access,t}function I(o){if(!o.theme)return[];l.warn("The 'theme' property in redocly.yaml is deprecated. Please move all of the properties from 'theme' to the root of the config.");const e=[];for(const t of Object.keys(o.theme))o[t]==null?e.push(t):l.warn(`Detected both '${t}' and 'theme.${t}' properties in redocly.yaml. The 'theme.${t}' property will be ignored and needs to be removed or merged into the '${t}'.`);return e}function M(o,e){if(!o.theme||e.length===0)return o;const t={...o};for(const i of e)t[i]=o.theme[i];return delete t.theme,t}export{G as readAndValidateConfig};
@@ -0,0 +1,54 @@
1
+ import type { JSONSchemaType } from '@redocly/ajv';
2
+ import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
3
+ import type { OpenAPIDefinition } from '@redocly/openapi-docs';
4
+ import type { AccessInfo, ApiDescriptionInfo, McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
5
+ export type DocsMcpToolRegistrationOptions = {
6
+ server: McpServer;
7
+ baseUrl: string;
8
+ outdir: string;
9
+ apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
10
+ headers?: Record<string, string | string[] | undefined>;
11
+ accessInfo: AccessInfo;
12
+ };
13
+ /** Keys that can be passed to the tool context (excludes 'server' which is not serializable) */
14
+ export type ContextKey = Exclude<keyof DocsMcpToolRegistrationOptions, 'server'>;
15
+ export type ApiDefinitionResult = {
16
+ success: true;
17
+ definition: OpenAPIDefinition;
18
+ } | {
19
+ success: false;
20
+ response: McpToolWorkerResponse;
21
+ };
22
+ export declare abstract class DocsMcpTool<TName extends keyof ToolArgsMap> {
23
+ abstract readonly name: TName;
24
+ abstract readonly description: string;
25
+ readonly schema: JSONSchemaType<ToolArgsMap[TName]>;
26
+ /**
27
+ * Array of context keys that this tool requires.
28
+ * The base class will extract these from DocsMcpToolRegistrationOptions
29
+ * and pass them to executeAction.
30
+ */
31
+ abstract readonly requiredContext: readonly ContextKey[];
32
+ constructor(schema: JSONSchemaType<ToolArgsMap[TName]>);
33
+ /**
34
+ * Builds the context object by picking only the required keys from options.
35
+ */
36
+ protected getContext(options: DocsMcpToolRegistrationOptions): McpToolWorkerParams['context'];
37
+ register(options: DocsMcpToolRegistrationOptions): void;
38
+ /**
39
+ * Wraps the tool execution with telemetry and error handling.
40
+ * Subclasses should call this method and implement executeAction for the actual logic.
41
+ */
42
+ execute(args: ToolArgsMap[TName], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
43
+ /**
44
+ * Implement the actual tool logic here. Called by execute() which handles telemetry.
45
+ */
46
+ protected abstract executeAction(args: ToolArgsMap[TName], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
47
+ /**
48
+ * Helper method for tools that need to load an API definition.
49
+ * Handles finding the API by name and loading the definition from the file system.
50
+ * Requires 'outdir' and 'accessInfo' in requiredContext.
51
+ */
52
+ protected getApiDefinition(name: string, context: McpToolWorkerParams['context']): Promise<ApiDefinitionResult>;
53
+ }
54
+ //# sourceMappingURL=docs-mcp-tool.d.ts.map
@@ -0,0 +1 @@
1
+ import{telemetry as i}from"../../../../telemetry/index.js";import{mcpToolWorkers as n,MCP_TOOL_WORKER_KEY as a}from"../../../../workers/mcp-tool-worker-pool.js";import{findApiDescriptionByName as p}from"../utils.js";import{getApiDescriptionFromFs as u}from"./utils.js";function f(o,t,s){return{toolName:o,args:t,context:s}}class g{schema;constructor(t){this.schema=t}getContext(t){const s={};for(const e of this.requiredContext)s[e]=t[e];return{...s,apiDescriptionsMap:t.apiDescriptionsMap}}register(t){const s=async(e,r)=>{const c=f(this.name,e,this.getContext(t));return await n.exec(a,[c],{timeout:6e4})};t.server.tool(this.name,this.description,this.schema,s)}async execute(t,s){try{const e=await this.executeAction(t,s);return i.sendMcpToolCalledMessage({server_type:"docs",tool:this.name}),e}catch(e){throw i.sendMcpErrorMessage({server_type:"docs",tool:this.name,message:e instanceof Error?e.message:String(e),stack:e instanceof Error&&e.stack||""}),e}}async getApiDefinition(t,s){if(!s.outdir||!s.accessInfo)throw new Error("Missing required context: outdir and accessInfo");const e=p(s.apiDescriptionsMap,t);if(!e)return{success:!1,response:{content:[{type:"text",text:`No API found matching "${t}".`}]}};const r=await u({relativePath:e.relativePath||"",outdir:s.outdir,accessInfo:s.accessInfo});return r?{success:!0,definition:r}:{success:!1,response:{content:[{type:"text",text:`Spec not found from the file system with "${t}".`}]}}}}export{g as DocsMcpTool};
@@ -1,9 +1,10 @@
1
- import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
2
- import type { AccessInfo, ApiDescriptionInfo } from '../../types.js';
3
- export declare function registerGetEndpointTools({ server, apiDescriptionsMap, outdir, accessInfo, }: {
4
- server: McpServer;
5
- apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
6
- outdir: string;
7
- accessInfo: AccessInfo;
8
- }): void;
1
+ import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
+ import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
+ export declare class GetEndpointInfoTool extends DocsMcpTool<'get-endpoint-info'> {
4
+ readonly name = "get-endpoint-info";
5
+ readonly description = "Get comprehensive information about specific endpoint including parameters, security, and examples";
6
+ readonly requiredContext: readonly ContextKey[];
7
+ constructor();
8
+ protected executeAction(args: ToolArgsMap['get-endpoint-info'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
+ }
9
10
  //# sourceMappingURL=get-endpoint-info.d.ts.map
@@ -1 +1 @@
1
- import{findApiDescriptionByName as P,resolveParameters as v,resolveRequestBody as x,resolveResponses as O}from"../utils.js";import{checkEndpointAndDeleteXMcp as S}from"../../utils/xmcp-utils.js";import{telemetry as c}from"../../../../telemetry/index.js";import{getApiDescriptionFromFs as A}from"./utils.js";const p="get-endpoint-info",d=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],L={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...d,...d.map(n=>n.toLowerCase())],minLength:1}}};function N({server:n,apiDescriptionsMap:m,outdir:l,accessInfo:u}){n.tool(p,"Get comprehensive information about specific endpoint including parameters, security, and examples",L,async({name:s,path:r,method:a})=>{try{const t=P(m,s);if(!t)return{content:[{type:"text",text:`No API found matching "${s}".`}]};const e=await A({relativePath:t?.relativePath||"",outdir:l,accessInfo:u});if(!e)return{content:[{type:"text",text:`Spec not found from the file system with "${s}".`}]};const f=r.startsWith("/")?r:`/${r}`,{title:y=""}=e.info||{},i=e.paths?.[f],h=a.toLowerCase();if(!i)return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const o=i[h];if(!o||!S(o,"docs"))return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const E=i?.parameters||[],T=o.parameters||[],g={...o,parameters:v({pathParams:E,opParams:T,definition:e}),requestBody:x(o.requestBody,e),responses:O(o.responses,e)};return c.sendMcpToolCalledMessage({server_type:"docs",tool:p}),{content:[{type:"text",text:JSON.stringify({api:y,version:e.info?.version||"",servers:e.servers||[],endpoint:{path:r,method:a.toUpperCase(),...g},globalSecurity:e.security||[],securitySchemes:e.components?.securitySchemes||[]},null,2)}]}}catch(t){throw c.sendMcpErrorMessage({server_type:"docs",tool:p,message:t?.message||"",stack:t?.stack||""}),t}})}export{N as registerGetEndpointTools};
1
+ import{resolveParameters as T,resolveRequestBody as y,resolveResponses as P}from"../utils.js";import{isMcpEndpoint as g}from"./utils.js";import{DocsMcpTool as x}from"./docs-mcp-tool.js";import{checkEndpointAndDeleteXMcp as v}from"../../utils/xmcp-utils.js";const p=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],S={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...p,...p.map(r=>r.toLowerCase())],minLength:1}}};class D extends x{name="get-endpoint-info";description="Get comprehensive information about specific endpoint including parameters, security, and examples";requiredContext=["outdir","accessInfo"];constructor(){super(S)}async executeAction(a,c){const{name:d,path:o,method:i}=a,n=await this.getApiDefinition(d,c);if(!n.success)return n.response;const{definition:e}=n,m=o.startsWith("/")?o:`/${o}`,{title:u=""}=e.info||{},s=e.paths?.[m],h=i.toLowerCase();if(!s)return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const t=s[h];if(!g(t)||!v(t,"docs"))return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const f=s?.parameters||[],l=t.parameters||[],E={...t,parameters:T({pathParams:f,opParams:l,definition:e}),requestBody:y(t.requestBody,e),responses:P(t.responses,e)};return{content:[{type:"text",text:JSON.stringify({api:u,version:e.info?.version||"",servers:e.servers||[],endpoint:{path:o,method:i.toUpperCase(),...E},globalSecurity:e.security||[],securitySchemes:e.components?.securitySchemes||[]},null,2)}]}}}export{D as GetEndpointInfoTool};
@@ -1,9 +1,10 @@
1
- import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
2
- import type { AccessInfo, ApiDescriptionInfo } from '../../types.js';
3
- export declare function registerGetEndpointsTools({ server, apiDescriptionsMap, outdir, accessInfo, }: {
4
- server: McpServer;
5
- apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
6
- outdir: string;
7
- accessInfo: AccessInfo;
8
- }): void;
1
+ import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
+ import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
+ export declare class GetEndpointsTool extends DocsMcpTool<'get-endpoints'> {
4
+ readonly name = "get-endpoints";
5
+ readonly description = "Get all endpoints for a specific API";
6
+ readonly requiredContext: readonly ContextKey[];
7
+ constructor();
8
+ protected executeAction(args: ToolArgsMap['get-endpoints'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
+ }
9
10
  //# sourceMappingURL=get-endpoints.d.ts.map
@@ -1 +1 @@
1
- import{findApiDescriptionByName as f}from"../utils.js";import{getApiDescriptionFromFs as d,getEndpointsFromPaths as l}from"./utils.js";import{telemetry as i}from"../../../../telemetry/index.js";const n="get-endpoints",m={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1}}};function u({server:s,apiDescriptionsMap:p,outdir:c,accessInfo:a}){s.tool(n,"Get all endpoints for a specific API",m,async({name:o})=>{try{const t=f(p,o);if(!t)return{content:[{type:"text",text:`No API found matching "${o}".`}]};const e=await d({relativePath:t?.relativePath||"",outdir:c,accessInfo:a});if(!e)return{content:[{type:"text",text:`Spec not found from the file system with "${o}".`}]};const r=l(e);return r.length===0?{content:[{type:"text",text:"No endpoints found"}]}:(i.sendMcpToolCalledMessage({server_type:"docs",tool:n}),{content:[{type:"text",text:JSON.stringify({api:e.info?.title||"",version:e.info?.version||"",servers:e.servers||[],endpoints:r},null,2)}]})}catch(t){throw i.sendMcpErrorMessage({server_type:"docs",tool:n,message:t?.message||"",stack:t?.stack||""}),t}})}export{u as registerGetEndpointsTools};
1
+ import{DocsMcpTool as r}from"./docs-mcp-tool.js";import{getEndpointsFromPaths as p}from"./utils.js";const c={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1}}};class u extends r{name="get-endpoints";description="Get all endpoints for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(c)}async executeAction(o,i){const{name:s}=o,e=await this.getApiDefinition(s,i);if(!e.success)return e.response;const{definition:t}=e,n=p(t);return n.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",servers:t.servers||[],endpoints:n},null,2)}]}}}export{u as GetEndpointsTool};
@@ -1,9 +1,10 @@
1
- import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
2
- import type { AccessInfo, ApiDescriptionInfo } from '../../types.js';
3
- export declare function registerGetFullApiDescriptionTools({ server, apiDescriptionsMap, outdir, accessInfo, }: {
4
- server: McpServer;
5
- apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
6
- outdir: string;
7
- accessInfo: AccessInfo;
8
- }): void;
1
+ import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
+ import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
+ export declare class GetFullApiDescriptionTool extends DocsMcpTool<'get-full-api-description'> {
4
+ readonly name = "get-full-api-description";
5
+ readonly description = "Get the complete OpenAPI description";
6
+ readonly requiredContext: readonly ContextKey[];
7
+ constructor();
8
+ protected executeAction(args: ToolArgsMap['get-full-api-description'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
+ }
9
10
  //# sourceMappingURL=get-full-api-description.d.ts.map