@redocly/redoc-revel 0.138.0-next.17 → 0.138.0-next.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/cli/develop.js +1 -1
- package/dist/cli/translations/collect-config-translations.js +1 -1
- package/dist/server/entitlements/entitlements-provider.js +1 -1
- package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/index.js +2 -2
- package/dist/server/types/web-server.d.ts +1 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/dev-server.js +1 -1
- package/dist/server/web-server/http.d.ts +2 -1
- package/dist/server/web-server/http.js +2 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @redocly/redoc-revel
|
|
2
2
|
|
|
3
|
+
## 0.138.0-next.18
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c692c909bb4: Improved the `preview` command to use the next free port and log a warning when the requested port is already in use.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- b98352301b8: Updated `@redocly/openapi-core` to version `2.62.1`.
|
|
12
|
+
- Updated dependencies [b98352301b8]
|
|
13
|
+
- @redocly/api-docs@0.3.0-next.15
|
|
14
|
+
- @redocly/portal-plugin-mock-server@0.23.0-next.3
|
|
15
|
+
|
|
3
16
|
## 0.138.0-next.17
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/dist/cli/develop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as t}from"../server/tools/notifiers/logger.js";import{reporter as c}from"../server/tools/notifiers/reporter.js";import{green as v}from"../server/tools/notifiers/helpers/colors.js";import{envConfig as m}from"../server/config/env-config.js";import{resolveCache as w}from"../server/esbuild/plugins/themes-resolver.js";import{getBilledPagesCount as p}from"../server/utils/index.js";import{createClientCompiler as
|
|
1
|
+
import{logger as t}from"../server/tools/notifiers/logger.js";import{reporter as c}from"../server/tools/notifiers/reporter.js";import{green as v}from"../server/tools/notifiers/helpers/colors.js";import{envConfig as m}from"../server/config/env-config.js";import{resolveCache as w}from"../server/esbuild/plugins/themes-resolver.js";import{getBilledPagesCount as p}from"../server/utils/index.js";import{createClientCompiler as R,createServerCompiler as S}from"../server/esbuild/esbuild.js";import{initPlugins as C,runPlugins as f,writeClientEntries as E}from"../server/plugins/lifecycle.js";import{startDevServer as h}from"../server/web-server/dev-server.js";import{validateAllMarkdowns as g}from"../server/plugins/markdown/compiler.js";import{reportAllErrors as b}from"../server/utils/report-all-errors.js";import{copyMigrationsFolder as y}from"../server/providers/database/copy-migrations.js";import{listenStdin as L}from"./utils/listen-stdin.js";const P=20;async function q(i,e){t.info("Starting project preview mode."),e.devLogin=i["dev-login"]!==!1,E(e),t.startTiming("initial-js"),await T(e),t.infoTime("initial-js","JavaScript compiled");const{pluginInstances:l,lifecycleContext:n}=await C({contentDir:e.contentDir,outdir:e.outdir,serverOutDir:void 0,devLogin:e.devLogin,setGlobalConfig:e.setGlobalConfig});e.lifecycleContext=n,y(e),await f(l,e,n,{failFast:!0});const d=async()=>{const r=performance.now();c.clearErrors(),await f(l,e,n),m.REDOCLY_EXP_DISABLE_MD_VALIDATION?t.info("Skipping markdown validation step"):await g(e,n),D().then(async()=>{await b(n);const a=p(e.getAllRoutes()),o=c.summary(` \u{1F440} Last change processed in ${v(Math.round(performance.now()-r)+"ms")}`,a);e.runListeners("errors-updated",void 0,o),e.runListeners("pages-updated",void 0,a),e.runListeners("routes-updated")})};m.REDOCLY_EXP_DISABLE_MD_VALIDATION?t.info("Skipping markdown validation step"):await g(e,n),await b(n);const s=p(e.getAllRoutes());c.summary(" \u{1F440} Watching for changes...",s),e.runListeners("pages-updated",void 0,s),n.fs.watch(async()=>{w.clear(),await d()}),t.verbose("Starting development server."),await h(e,n,{port:Number(i.port||4e3),maxPortRetries:m.isReunite?0:P}),L()}async function T(i){let e=!0,l=!0;const n=async r=>{r==="client"?e=!0:l=!0,i.runListeners("build-started");const a=e!=l;a&&i.startEsbuildRun(),i.buildRevision>0&&await i.waitForPluginsRun(),r!=="client"&&i.noteRequestHandlersEntryBuildStart(),a&&t.startTiming("rebuild")},d=async r=>{r==="client"?e=!1:(l=!1,i.markRequestHandlersEntryUpdated()),!(e||l)&&(i.finishEsbuildRun(),i.buildRevision++,t.infoTime("rebuild","JavaScript re-compiled"),await i.reloadMarkdocOptions(),i.markUserCodeReady(),i.runListeners("build-updated"),i.lifecycleContext&&i.buildRevision>1&&i.lifecycleContext.fs.emitCodeUpdated())},s=[new Promise((r,a)=>{const o={label:"client",buildStart(){t.verbose("Start compiling client code."),t.startTiming(this.label)},buildEnd(){t.verboseTime(this.label,"Client compiled"),r(!0)},rebuildStart:()=>n("client"),rebuildEnd:()=>d("client")};R(i,i.outdir,"development",o).then(u=>u.watch()).catch(a)}),new Promise((r,a)=>{const o={label:"server",buildStart(){t.verbose("Start compiling server code."),t.startTiming(this.label)},buildEnd(){t.verboseTime(this.label,"Server compiled"),r(!0)},rebuildStart:()=>n("server"),rebuildEnd:()=>d("server")};S(i,i.serverOutDir,"development",o).then(u=>u.watch()).catch(a)})];await Promise.all(s),await i.reloadMarkdocOptions()}function D(){return new Promise(i=>{setTimeout(i,0)})}export{q as develop};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const i="TranslationKey",
|
|
1
|
+
const i="TranslationKey",g=async({getConfig:e,cache:t,fs:s})=>{const a=await e(),n=r(a),o=s.scan(/sidebars.yaml$/),l=await Promise.all(o.map(f=>t.load(f.relativePath,"yaml").then(d=>d.data)));return{...r(l),...n}},r=e=>{const t={};if(!e)return{};if(Array.isArray(e))for(const s of e)Object.assign(t,r(s));if(typeof e=="object")for(const[s,a]of Object.entries(e))if(s.endsWith(i)&&typeof a=="string"){const n=s.slice(0,i.length*-1),o=e[n];if(!c(n)||!c(a)||!y(o))continue;t[a]=o||""}else Object.assign(t,r(a));return t},c=e=>e.trim().length>0,y=e=>e==null||typeof e=="string";export{g as collectConfigTranslations};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ENTITLEMENTS_JWKS_URL as
|
|
1
|
+
import{ENTITLEMENTS_JWKS_URL as i}from"../constants/common.js";import{PLAN_GATES_DEFAULTS as c}from"../constants/entitlements.js";import{envConfig as r}from"../config/env-config.js";import{logger as a}from"../tools/notifiers/logger.js";import{reporter as l}from"../tools/notifiers/reporter.js";import{PRODUCT_GATES as p}from"../../config/product-gates.js";import{EJECT_IGNORE_CONFIG as m}from"../../config/eject-ignore.js";import*as o from"../web-server/jwt/jwt.js";import{AlgorithmTypes as f}from"../web-server/jwt/types.js";class s{static#e;#a=null;#t={};constructor(){}static instance(){return s.#e||(s.#e=new s),s.#e}get entitlements(){return this.#a}async init(t={}){this.#t=t;try{await this.#o()}catch(e){a.warn("Failed to process entitlements information: "+e.message),a.verbose(e.message)}}canAccessFeature=t=>t?this.entitlements&&!!this.entitlements[t]:!0;async getPackageEjectIgnore(){const t=[];for(const[e,n]of Object.entries(m))this.canAccessFeature(e)&&t.push(...n);return t}#n(){return r.PLAN_GATES||""}async#s(){let t;try{t=await fetch(i).then(e=>e.json())}catch(e){return a.warn("Failed to get JWKS information: "+e.message),!1}try{const e=t.keys&&t.keys.length>0?t.keys[0]:null,n=this.#n();return e&&n?await o.verify(n,e,f.RS256,this.#t.ignoreTokenExpiration):!1}catch(e){return a.warn("Failed to verify plan gates token: "+e.message),!1}}async#r(){if(await this.#s()){const{payload:t}=o.decode(this.#n());if(t){if(!r.REDOCLY_ENV&&t.exp){const e=t.exp*1e3,n=new Date(e);a.info(`Entitlements token expires on ${n.toISOString()} (in ${Math.ceil((e-new Date().getTime())/(1440*60*1e3))} days)`)}return t}}await l.panicOnContentError("Plan gates token is not valid or empty.")}async#o(){const t=this.#t.developModePlan&&!this.#n()?c[this.#t.developModePlan]:await this.#r();this.#a={...p,...t}}}export{s as EntitlementsProvider};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const u=[({label:n,labelTranslationKey:o})=>n?{label:n,labelTranslationKey:o}:void 0,({icon:n,srcSet:o})=>{const t=typeof n=="string"?n:void 0;return t||o?{icon:t,srcSet:o}:void 0},({badges:n})=>n?{badges:n}:void 0];function c(n,o,t){if(!t)return n;const r=
|
|
1
|
+
const u=[({label:n,labelTranslationKey:o})=>n?{label:n,labelTranslationKey:o}:void 0,({icon:n,srcSet:o})=>{const t=typeof n=="string"?n:void 0;return t||o?{icon:t,srcSet:o}:void 0},({badges:n})=>n?{badges:n}:void 0];function c(n,o,t){if(!t)return n;const r=f(t);return n.map(e=>i(e,o)?{...e,...r}:e)}function f(n){const o={};for(const t of u)Object.assign(o,t(n));return o}function i(n,o){return n.link===o}export{c as applyNavItemToRoot};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readdir as S,appendFile as A}from"node:fs/promises";import l from"node:path";import{createReadStream as v,existsSync as w}from"node:fs";import{createInterface as O}from"node:readline";import{SEARCH_GROUP_FACET_FIELD as C,SEARCH_PRODUCT_FIELD as N,SEARCH_VERSION_FIELD as j}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as H,SEARCH_DATA_EXPORT_FOLDER as
|
|
2
|
-
`}async function*P(
|
|
1
|
+
import{readdir as S,appendFile as A}from"node:fs/promises";import l from"node:path";import{createReadStream as v,existsSync as w}from"node:fs";import{createInterface as O}from"node:readline";import{SEARCH_GROUP_FACET_FIELD as C,SEARCH_PRODUCT_FIELD as N,SEARCH_VERSION_FIELD as j}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as H,SEARCH_DATA_EXPORT_FOLDER as _,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as L}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as T}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as M}from"../../../../config/env-config.js";import{ensureDir as u}from"../../../../utils/index.js";import{FlexSearchIndex as b}from"./search-index.js";const F=".jsonl";function R(h){return`${JSON.stringify(h)}
|
|
2
|
+
`}async function*P(h){const t=O({input:v(h,{encoding:"utf8"}),crlfDelay:1/0});for await(const s of t)s&&(yield JSON.parse(s))}class K{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:H},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#n(t,s){const i=this.#e.get(t);if(i)return i.find(n=>n.id===s)}#i(t,s){let i=this.#n(t,s);return i||(i=new b(s,this.#s),this.#e.set(t,[...this.#e.get(t)??[],i])),i}async addDocuments(t,s){if(t.length){const{group:i,locale:n,outDir:c}=s,o=this.#i(n,i);for(const r of t)o.add(r),M.isBuildMode&&(this.#t++,this.#t>=L&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,s,i){return await T("com.redocly.search.performed",async n=>{n?.setAttribute("id","searchQueryId"),n?.setAttribute("object","searchQuery"),n?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:c,locale:o,filter:r,loadMore:a}=t,d=this.#e.get(o)??[],m=[];let g="";const D=["v:default"];if(n?.setAttribute("locale",o),r)for(const e of r)e.field===C?m.push(...e.values):e.field===N?g=`p:${e.values[0]}`:e.field===j&&e.values.length&&e.values.length===2&&D.push(`v:${e.values[0]}:${e.values[1]}`);const y={auth:s,query:c,offset:0,SEARCH_GROUP_FACET_FIELD:C,product:g,versions:D},x=[],f={facets:{},documents:{}};if(a){const e=this.#n(o,a.groupKey);e&&x.push(e.search({...y,offset:a.offset}))}else for(const e of d)m&&m.length?m.includes(e.id)&&x.push(e.search(y)):x.push(e.search(y));const E=await Promise.all(x),$=E.some(e=>e.hasCoveringHit);for(const e of E)if(!($&&!e.hasCoveringHit)){f.documents={...f.documents,...e.documents};for(const[p,I]of Object.entries(e.facets))f.facets[p]?f.facets[p]=[...f.facets[p],...I]:f.facets[p]=I}return f})}async exportDocuments(t){const s=u(l.join(t,_));for(const[i,n]of this.#e){const c=u(l.join(s,i));for(const o of n){const r=Array.from(o.documents,d=>R({document:d}));if(r.length===0)continue;const a=u(l.join(c,`${o.id}${F}`));await A(a,r.join(""),{encoding:"utf8"}),o.clearDocuments()}}this.#t=0}async exportIndexes(t){const s=u(l.join(t,_));for(const[i,n]of this.#e){const c=u(l.join(s,i));for(const o of n){const r=u(l.join(c,`${o.id}${F}`));await o.export((a,d)=>A(r,R({index:[String(a),d]}),{encoding:"utf8"}))}}this.#e.clear()}async import(t){const s=`${t}/${_}`;if(!w(s))return;const i=await S(s);for(const n of i){const c=await S(`${s}/${n}`);for(const o of c){const r=`${s}/${n}/${o}`,a=l.parse(o).name;await this.#i(n,a).import(P(r))}}}countFacets(t,s,i){const n={};for(const[c,o]of i)n[c]=o.values.map(r=>({value:r,count:0,isCounterVisible:!1}));return n}cleanupFacetValues(t){}}export{K as FlexSearch};
|
|
@@ -3,6 +3,7 @@ import type { Adapter, UserClaims } from '../plugins/dev-onboarding/api/types.js
|
|
|
3
3
|
import type { PageRouteDetails } from './plugins/common.js';
|
|
4
4
|
export type ServerOptions = {
|
|
5
5
|
port?: number;
|
|
6
|
+
maxPortRetries?: number;
|
|
6
7
|
};
|
|
7
8
|
export type RequestContext = {
|
|
8
9
|
remoteAddr: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as
|
|
1
|
+
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as x,REDOCLY_ROUTE_RBAC as E}from"@redocly/config";import{MCP_ROUTE as U,PUBLIC_MCP_ROUTE as k}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as w}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as D,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L,GRAPHQL_SPEC_SLUG as M}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as g,PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_ASSETS_FOLDER as B}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as b}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as W}from"../constants/rbac.js";import{removeTrailingSlash as T}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as G}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as z}from"../../utils/guards/is-truthy.js";import{canExpandConfig as K,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const j=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]),rt=new Set(Object.values(w).map(t=>T(t.split(":")[0])));function It(t,e){const r=j.indexOf(t.toUpperCase()),n=j.indexOf(e.toUpperCase());return r>n?t:e}const A={};function I(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=A[d]??P(a);A[d]=p;const _=`fsPath:${a}`,S=A[_]??P($(a));return A[_]=S,!!(n&&p(n))||!!(o&&S(o))};if(st(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function Ft(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function Nt(t,e){return O(t,W,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&rt.has(T(t.slug))||(t.slug===U||t.slug===k||t.slug===b)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[x]||I(o,t[E]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ut(t,e,r,n){if(!t.startsWith(C)&&!t.startsWith(g))return!0;const o=t.replace(new RegExp(`^${C}/`),"").replace(new RegExp(`^${g}/`),"").replace(new RegExp(`^${M}/`),""),c=o==="."?"":o,i={[E]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function kt(t,e,r,n,o){if(!t.startsWith(B))return!0;const s=t.match(/\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[E]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function wt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==D):f=[D],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=N(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===x||c===E)continue;if(et.has(c)){s[c]=t[c];continue}const i=N(t[c],e,r,n);if(!t.link&&(c==="items"||c==="menu"&&t.type==="tab")&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&nt(i)&&ot(i)}return o?void 0:s}return t}function Mt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Bt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===L?[[s,c]]:[[s,c]].concat(t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c]))),o=Object.fromEntries(n);return{...e,content:o}}async function bt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function nt(t){return m(t)&&Object.keys(t).length>0}function ot(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function st(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const ct=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Wt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(ct(t))return it(t);await Y.panicOnContentError(`You are using an incorrect format of ${G("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},it=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=T(n);r[o]=e.content[n]}e.content=r}return e};function $t(t,e){const r=t.fsPath,n=t.slug,o=[],s=K(e)&&(r||n)?Q(e,[r,n].filter(z)):null;if(s){const i=e?.teamNamePatterns?.map(f=>f.replace("{teamPathSegment}",s.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i)}const c=I(s?{content:{...J(e),...e.content}}:e,t);return o.push(...at(c)),ft(e,o)}function at(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function ft(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{j as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Bt as applyL10nToRbacConfig,kt as canAccessAsset,Ft as canAccessFeature,O as canAccessResource,Ut as canDownloadApiDefinition,ft as expandTeamsForRead,at as extractTeamsFromScopeItems,N as filterDataByAccessDeep,wt as getAuthDetailsFromCookies,It as getHigherRole,$t as getRbacTeamsListForResource,I as getScopeItemsForResource,F as hasScopeAccess,ct as isRbacConfigValid,Nt as isResourcePubliclyAccessible,it as normalizeRbacConfig,Wt as parseRbacConfig,Mt as parseTeamClaimToArray,bt as resolveDirectoryHashes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ServerRoutes as
|
|
1
|
+
import{ServerRoutes as n}from"../../constants/api.js";import{reporter as s}from"../tools/notifiers/reporter.js";import{logger as p}from"../tools/notifiers/logger.js";import{telemetry as f}from"../telemetry/index.js";import{installDevRoutes as l,installProdRoutes as v}from"./routes/index.js";import{createRouter as u}from"./router.js";import{readStaticAsset as d}from"./node-asset-reader.js";import{createLlmsTxtGenerator as S}from"../plugins/search/llmstxt/create-llms-txt-generator.js";import{startHttpServer as D}from"./http.js";import{listenStore as R}from"./store-ws.js";import{ejectComponentDataHandler as w}from"./routes/eject.js";import{attachWsServer as g}from"./ws.js";import{DatabasePreconnectService as O}from"../providers/database/database-preconnect-service.js";import{KvService as x}from"../persistence/kv/services/kv-service.js";import{runScorecardsWorker as E}from"../plugins/scorecards/workers/run-scorecards-worker.js";import{isScorecardsEnabled as b}from"../utils/is-scorecards-enabled.js";import{isRealmOrReef as y}from"../utils/is-realm-or-reef.js";async function M(r,i,a){f.initialize(!0);const{port:m=4e3,maxPortRetries:c}=a,t=u();if(t.get(n.EJECT_COMPONENT,w(r)),l(t,r),v(t,r,{readStaticAsset:d,resolveRouteData:e=>r.resolveRouteStaticData(e,i),llmsTxtGenerator:S(r,i)}),y()){await O.init(r.serverOutDir);const e=await x.getInstance({baseDbDir:r.serverOutDir});setInterval(()=>{e.clearExpired().catch(o=>{p.error("Failed to clear expired KV entries",o)})},300*1e3)}try{await r.userCodeReady;const e=await D(t,m,{maxPortRetries:c}),o=g(e);R(r,o),b(r.config)&&await E(r.serverOutDir,r.config.scorecards)}catch(e){await s.panic(e)}}export{M as startDevServer};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as http from 'node:http';
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
3
|
import type { Hono } from 'hono';
|
|
4
|
+
import type { ServerOptions } from '../types';
|
|
4
5
|
declare global {
|
|
5
6
|
var redoclyCookieStorage: AsyncLocalStorage<string> | undefined;
|
|
6
7
|
}
|
|
7
|
-
export declare function startHttpServer(router: Hono, port?: number | string): Promise<http.Server>;
|
|
8
|
+
export declare function startHttpServer(router: Hono, port?: number | string, { maxPortRetries }?: Pick<ServerOptions, 'maxPortRetries'>): Promise<http.Server>;
|
|
8
9
|
//# sourceMappingURL=http.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
%s`,e.message,e.stack))}const
|
|
1
|
+
import*as L from"node:http";import*as H from"node:net";import{AsyncLocalStorage as I}from"node:async_hooks";import{Readable as y,Stream as C}from"node:stream";import{pipeline as P}from"node:stream/promises";import{ReadableStream as $}from"node:stream/web";import{getPathPrefix as R}from"@redocly/theme/core/utils";import{ALLOWED_CORS_ORIGINS as k}from"../constants/common.js";import{logger as l}from"../tools/notifiers/logger.js";import{shutdowner as D}from"../tools/shutdowner.js";import{envConfig as O}from"../config/env-config.js";import{getClientIp as T}from"./utils/get-client-ip.js";import{normalizeIpAddress as x}from"./utils.js";import{CORS_PROXY_STREAM_HEADER as U}from"./routes/cors-proxy.js";const E=new I;globalThis.redoclyCookieStorage=E;const S=65535;async function Q(t,a=4e3,{maxPortRetries:d=0}={}){const s=parseInt(String(a),10);if(!Number.isInteger(s)||s<0||s>S)throw new RangeError(`Port must be an integer from 0 to ${S}. Received: ${a}.`);const i=L.createServer(async(r,o)=>{const b=r.headers.cookie||"";E.run(b,async()=>{let c;try{const e=new URL(r.url||"",`http://${r.headers.host}`),f=[],m=r.rawHeaders.length;for(let w=0;w<m;w+=2)f.push([r.rawHeaders[w],r.rawHeaders[w+1]]);const h={headers:f,method:r.method};r.method==="GET"||r.method==="HEAD"||(h.body=y.toWeb(r),h.duplex="half");const p=new Request(e.toString(),h),A=T(p)||"127.0.0.1",v=p?.headers?.get("x-forwarded-host")||x(r.socket.remoteAddress);p.context={remoteAddr:{hostname:v,port:r.socket.localPort,ipAddress:A},url:e},c=await t.fetch(p)}catch(e){c=new Response(null,{status:500}),e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError"?c=new Response(null,{status:504}):e.code==="ERR_INVALID_URL"&&(c=new Response("Invalid URL",{status:404})),l.error(`Error while handling request: %s
|
|
2
|
+
%s`,e.message,e.stack))}const u=r.headers.origin;u&&k.some(e=>u===e)&&(o.setHeader("Access-Control-Allow-Origin",u),o.setHeader("Access-Control-Allow-Credentials","true"));for(const[e,f]of c.headers||[])try{e==="set-cookie"?o.setHeader(e,c.headers.getSetCookie(e)):o.setHeader(e,f)}catch(m){l.error(`Error while setting header: ${m?.message}`)}if(o.setHeader("Vary","Cookie"),o.statusCode=c.status||500,c.body)try{if(M(c)){const e=new C.Transform({transform(f,m,h){if(o.closed||o.destroyed)return h();o.write(f,m)?process.nextTick(h):o.once("drain",h)},flush(f){if(o.closed||o.destroyed)return f();o.end(),f()}});await P(c.body instanceof $?y.fromWeb(c.body):c.body,e)}else{const e=await c.text();o.setHeader("Content-Length",Buffer.byteLength(e)),o.end(e)}}catch(e){console.error(e);const f=e instanceof Error?e:new Error("unknown error",{cause:e});o.destroy(f)}else o.end()})});D.registerShutdownCallback(()=>new Promise(r=>{l.verbose("Shutting down http server"),i.close(()=>{l.verbose("Http server shut down"),r()})}));const n=await g(i,s,d);return i.on("error",r=>{l.error("Http server error: %s",r.message)}),n!==s&&l.warn(`Port ${s} is already in use. Using port ${n} instead.`),O.isDevelopMode?l.logInFooter("server",` \u{1F310} Preview URL: http://127.0.0.1:${n}${R()}`):l.logInFooter("server",`Server started at: http://127.0.0.1:${n}${R()}`),i}async function g(t,a,d){const s=d>0,i=s?Math.min(a+d,S):a;for(let n=a;n<=i;n++)if(!(s&&!await N(n)))try{return await _(t,n),n}catch(r){if(!s||r.code!=="EADDRINUSE")throw r}throw Object.assign(new Error(`Ports ${a}-${i} are already in use.`),{code:"EADDRINUSE"})}function _(t,a){return new Promise((d,s)=>{const i=r=>{t.removeListener("listening",n),s(r)},n=()=>{t.removeListener("error",i),d()};t.once("error",i),t.once("listening",n),t.listen(a)})}function N(t){return new Promise(a=>{const d=H.createServer();d.once("error",s=>a(s.code!=="EADDRINUSE")),d.listen(t,"127.0.0.1",()=>d.close(()=>a(!0)))})}function M(t){const a=t.headers.get("content-type")||"",d=t.headers.get("x-accel-buffering")||"",s=t.headers.get("content-encoding"),i=t.headers.get("content-length"),n=t.headers.get("transfer-encoding");return t.headers.get(U)==="1"||s||n||i||/^no$/i.test(d)||!/^(text\/(?!event-stream\b))/i.test(a)}export{Q as startHttpServer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/redoc-revel",
|
|
3
|
-
"version": "0.138.0-next.
|
|
3
|
+
"version": "0.138.0-next.18",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"@opentelemetry/sdk-trace-web": "2.8.0",
|
|
34
34
|
"@opentelemetry/semantic-conventions": "1.40.0",
|
|
35
35
|
"@redocly/ajv": "8.18.0",
|
|
36
|
-
"@redocly/api-docs": "0.3.0-next.
|
|
36
|
+
"@redocly/api-docs": "0.3.0-next.15",
|
|
37
37
|
"@redocly/config": "0.65.0",
|
|
38
|
-
"@redocly/openapi-core": "2.
|
|
38
|
+
"@redocly/openapi-core": "2.62.1",
|
|
39
39
|
"@redocly/portal-legacy-ui": "0.19.0",
|
|
40
|
-
"@redocly/portal-plugin-mock-server": "0.23.0-next.
|
|
40
|
+
"@redocly/portal-plugin-mock-server": "0.23.0-next.3",
|
|
41
41
|
"@redocly/realm-asyncapi-sdk": "0.16.0-next.5",
|
|
42
42
|
"@redocly/theme": "0.70.0-next.11",
|
|
43
43
|
"@shikijs/transformers": "3.21.0",
|