@redocly/redoc-reef 0.140.0-next.5 → 0.140.0-next.6
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 +30 -0
- package/dist/compiled/@redocly/pii/index.js +1 -0
- package/dist/compiled/@redocly/pii/package.json +1 -0
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/get-graphql-type-list.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/list-graphql-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/types.d.ts +4 -4
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/types.d.ts +2 -2
- package/dist/server/tools/notifiers/formatter.js +3 -3
- package/package.json +6 -6
- package/dist/server/tools/notifiers/helpers/privacy/mask-email.d.ts +0 -25
- package/dist/server/tools/notifiers/helpers/privacy/mask-email.js +0 -1
- package/dist/server/tools/notifiers/helpers/privacy/mask-subject.d.ts +0 -13
- package/dist/server/tools/notifiers/helpers/privacy/mask-subject.js +0 -1
- package/dist/server/tools/notifiers/helpers/privacy/remove-pii-from-url.d.ts +0 -25
- package/dist/server/tools/notifiers/helpers/privacy/remove-pii-from-url.js +0 -1
- package/dist/server/tools/notifiers/helpers/privacy/remove-pii.d.ts +0 -36
- package/dist/server/tools/notifiers/helpers/privacy/remove-pii.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @redocly/redoc-reef
|
|
2
2
|
|
|
3
|
+
## 0.140.0-next.6
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5b82f282c92: Deprecated the `mcp.docs` config object and moved its options to `mcp`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- bed4a5f394a: Fixed an issue where C# request samples in OpenAPI docs sent number, boolean, and `null` values from the request body example as strings.
|
|
12
|
+
C# request samples also compile when the example contains strings with quotes, backslashes, or line breaks, or empty, nested, or mixed-type arrays.
|
|
13
|
+
- 4e12a3d89f3: Improved server-side rendering performance for OpenAPI reference pages with heavily reused schemas.
|
|
14
|
+
- 185f2658cab: Fixed an issue in OpenAPI docs where request and response samples were empty when a discriminator option's property referenced part of another schema.
|
|
15
|
+
- b4ba4341a95: Updated `@redocly/openapi-core` to version `2.71.1`.
|
|
16
|
+
- ff91adf1e0d: Fixed security vulnerabilities `GHSA-cg2g-xh64-v4q7`, `GHSA-mrv2-3pqr-j5jr` and `GHSA-c6gr-qvv4-5v3f` by upgrading `dompurify` to version `3.4.17`.
|
|
17
|
+
- 725184fbef9: Fixed an issue where the Docs MCP setup snippets gave every site without `mcp.docs.name` the same server name, which caused a name conflict in the MCP client when users connected more than one site.
|
|
18
|
+
If `mcp.docs.name` is not set, the server name is based on the site's domain.
|
|
19
|
+
- 2f973409954: Fixed the `connect-mcp` tag so it no longer displays a connect button on sites that don't serve an MCP server.
|
|
20
|
+
- 22cd58473a8: Fixed an issue in the **Try it** console where the edited request body was replaced with the documented example when the content type changed.
|
|
21
|
+
For example, when users switched from JSON to XML and back.
|
|
22
|
+
- Updated dependencies [bed4a5f394a]
|
|
23
|
+
- Updated dependencies [4e12a3d89f3]
|
|
24
|
+
- Updated dependencies [185f2658cab]
|
|
25
|
+
- Updated dependencies [b4ba4341a95]
|
|
26
|
+
- Updated dependencies [ff91adf1e0d]
|
|
27
|
+
- Updated dependencies [725184fbef9]
|
|
28
|
+
- Updated dependencies [2f973409954]
|
|
29
|
+
- @redocly/api-docs@0.5.0-next.4
|
|
30
|
+
- @redocly/theme@0.72.0-next.3
|
|
31
|
+
- @redocly/portal-plugin-mock-server@0.25.0-next.1
|
|
32
|
+
|
|
3
33
|
## 0.140.0-next.5
|
|
4
34
|
|
|
5
35
|
### Minor Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var v=(i,l)=>()=>{try{return l||i((l={exports:{}}).exports,l),l.exports}catch(c){throw l=0,c}},g=v(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0}),i.maskSubject=i.maskEmail=void 0;var l=t=>{if(!t||typeof t!="string"||!t.includes("@"))return t;let[e="",r]=t.split("@");return`${e.length>2?e.slice(0,2)+"*".repeat(e.length-2):"*".repeat(e.length)}@${r}`};i.maskEmail=l;var c=/[a-zA-Z0-9._%+-]/,b=/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,s=t=>{var e;let r="",a=0,n=0;for(;n<t.length;){let d=t.indexOf("@",n);if(d===-1)break;let o=d;for(;o>a&&c.test(t.charAt(o-1));)o--;let p=o<d?(e=b.exec(t.slice(d+1)))===null||e===void 0?void 0:e[0]:void 0;if(!p){n=d+1;continue}let m=d+1+p.length;r+=t.slice(a,o)+(0,i.maskEmail)(t.slice(o,m)),a=m,n=m}return r+t.slice(a)};i.maskSubject=s}),h=v(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0}),i.removePii=s,i.removePiiFromUrl=t;var l={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,replacement:"[date_removed]"}};function c(e){return typeof e=="string"}function b(e={}){let r={email:{enabled:!0,replacement:"[email_removed]"},phone:{enabled:!0,replacement:"[phone_removed]"},ssn:{enabled:!0,replacement:"[SSN_removed]"},creditCard:{enabled:!0,replacement:"[credit_card_removed]"},address:{enabled:!0,replacement:"[address_removed]"},passport:{enabled:!0,replacement:"[passport_number_removed]"},driversLicense:{enabled:!0,replacement:"[driver_license_removed]"},zipCode:{enabled:!0,replacement:"[zip_code_removed]"},bankAccount:{enabled:!0,replacement:"[bank_account_removed]"},dateOfBirth:{enabled:!0,replacement:"[date_removed]"}};for(let[a,n]of Object.entries(e))r[a]?r[a]=Object.assign(Object.assign({},r[a]),n):r[a]=n;return r}function s(e,r={}){if(!c(e))return e;let a=b(r),n=e;for(let[d,o]of Object.entries(a)){if(!o.enabled)continue;let p=l[d],m=p?.pattern||o.pattern,f=o.replacement||p?.replacement||"[PII removed]";m&&(n=n.replace(m,f))}return n}function t(e){if(!c(e))return e;try{let r=new URL(e,"http://example.com");for(let[a,n]of r.searchParams.entries()){let d=String(s(n));r.searchParams.set(a,d)}return e.startsWith("http://")||e.startsWith("https://")?r.toString():r.pathname+r.search+r.hash}catch{return String(s(e))}}});Object.defineProperty(exports,"__esModule",{value:!0}),exports.removePiiFromUrl=exports.removePii=exports.maskSubject=exports.maskEmail=void 0;var u=g();Object.defineProperty(exports,"maskEmail",{enumerable:!0,get:function(){return u.maskEmail}}),Object.defineProperty(exports,"maskSubject",{enumerable:!0,get:function(){return u.maskSubject}});var _=h();Object.defineProperty(exports,"removePii",{enumerable:!0,get:function(){return _.removePii}}),Object.defineProperty(exports,"removePiiFromUrl",{enumerable:!0,get:function(){return _.removePiiFromUrl}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"@redocly/pii","main":"index.js"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import w from"path";import{lintConfig as $,loadConfig as
|
|
1
|
+
import w from"path";import{lintConfig as $,loadConfig as E,createConfigTypes as L}from"@redocly/openapi-core";import{rootRedoclyConfigSchema as q}from"@redocly/config";import{deepMerge as x}from"../../../../../utils/object/deep-merge.js";import{isPlainObject as g}from"../../../../../utils/guards/is-plain-object.js";import{logger as d}from"../../../../tools/notifiers/logger.js";import{BRANCH_ENV_PREFIX as j}from"../../../../../constants/common.js";import{sanitizeBranchName as O}from"../../../../utils/envs/sanitize-branch-name.js";import{envConfig as R}from"../../../../config/env-config.js";import{ajv as S,safeParsePartial as B}from"../../safe-parse.js";import{formatConfigProblem as I}from"../../format-error.js";import{ExternalResolver as M}from"../../../../fs/utils/external-ref-resolver.js";import{resolveMutuallyExclusiveProps as N}from"../../resolve-mutual-exclusion.js";function y(e,t,s,r){t in e&&e[t]&&typeof e[t]=="string"&&(/^https?:\/\/.*/.test(e[t])||r(new Error(`Invalid ${s} URL: "${e[t]}". ${s} must start with "http://" or "https://".`)))}function k(e,t){if("access"in e&&e.access&&typeof e.access=="object"){const s=e.access;y(s,"logoutReturnUrl","access.logoutReturnUrl",t),y(s,"residency","access.residency",t);const r=["requiresLogin","logoutReturnUrl","residency","sso","rbac"];for(const n of r)n in s&&s[n]!==void 0&&n in e&&e[n]!==void 0&&t(new Error(`Property '${n}' is defined both at root level and in 'access' object. Please use 'access.${n}' to define this configuration.`))}}function _(e){return S.compile(q.properties.graphql.properties.servers.items.properties.url)(e)}function C(e,t,s){if(g(e)&&Array.isArray(e.servers))for(const r of e.servers){const n=g(r)?r.url:void 0;if(typeof n=="string"&&!_(n)){const c=e.servers.indexOf(r),a=`${t}.servers[${c}].url`;s(new Error(`Invalid ${a}: "${n}". It must be an absolute http:// or https:// URL.`))}}}function D(e,t){if(C(e.graphql,"graphql",t),!!g(e.apis))for(const[s,r]of Object.entries(e.apis))g(r)&&C(r.graphql,`apis.${s}.graphql`,t)}async function ie(e,t,s,r){const c=t.getFileInfo(e)?.realRelativePath||e;async function a(){const p=new M(t),f=w.join(t.cwd,c),l=await E({configPath:f,externalRefResolver:p}),m=await r(l.resolvedConfig);if(m===void 0)return l.resolvedConfig;const h=l.document?.source,P=[...h?await $({config:l,externalConfigTypes:L(m,l)}):[],...h?N(l.resolvedConfig,h):[]];if(P.length>0)for(const U of P)s(new Error(I(U,t.cwd)));return l.resolvedConfig}const i=t.exists(e)?await a():{},T=F(i),b=await r(i);y(i,"residency","Residency",s),y(i,"logoutReturnUrl","Logout return URL",s),k(i,s),D(i,s);let u=b?B(b,i):i;u=z(u);const{env:v}=u;if(v){const p=R.REDOCLY_ENV,f=v[p]||{},l=R.PUBLIC_REDOCLY_BRANCH_NAME||"",m=l?O(l):"",h=m&&v[`${j}${m}`]||{};u=x(u,h,f)}const o=V(u,T);if(o.imports&&o.imports.length>0){d.warn("The 'imports' property is deprecated. Please use 'plugins' property instead.");const p=new Set([...o.plugins||[],...o.imports.map(f=>w.posix.join(f,"plugin.js"))]);o.plugins=Array.from(p),delete o.imports}if(o.catalog&&(d.warn("The 'catalog' property is deprecated. Please use 'catalogClassic' property instead."),o.catalogClassic={...o.catalog},delete o.catalog),o.scorecard&&(d.warn("The 'scorecard' property is deprecated. Please use 'scorecardClassic' property instead."),o.scorecardClassic=o.scorecard,delete o.scorecard),o.search?.ai){d.warn("The 'search.ai' property is deprecated. Please use 'aiAssistant' property instead.");const p={...o.search?.ai,...o.aiAssistant,suggestions:o.aiAssistant?.suggestions?.length?o.aiAssistant.suggestions:o.search?.ai.suggestions||[]};o.aiAssistant=p,delete o.search.ai}return G(o)}function G(e){const t={...e},r={..."access"in e&&e.access&&typeof e.access=="object"?e.access:{}},n=["requiresLogin","logoutReturnUrl","residency","sso","idps","rbac"],c=[];for(const a of n){const i=t[a];i!==void 0&&(c.push(a),a==="requiresLogin"&&r.requiresLogin===void 0&&(r.requiresLogin=i),a==="logoutReturnUrl"&&r.logoutReturnUrl===void 0&&(r.logoutReturnUrl=i),a==="residency"&&r.residency===void 0&&(r.residency=i),a==="sso"&&r.sso===void 0&&(r.sso=i),a==="idps"&&r.idps===void 0&&(r.idps=i),a==="rbac"&&r.rbac===void 0&&(r.rbac=i),delete t[a])}return c.length>0&&d.warn(`The following properties at root level are deprecated: ${c.join(", ")}. Please move them to the 'access' object.`),Object.keys(r).length>0&&(t.access=r),t}function z(e){const t=Object.entries(e.env??{});[e,...t.map(([,n])=>n)].some(n=>n?.mcp?.docs)&&d.warn("The 'mcp.docs' property is deprecated. Please use the 'mcp' properties instead.");const s=e.mcp?{...e,mcp:A(e.mcp)}:e;if(!e.env)return s;const r=t.map(([n,c])=>[n,c?.mcp?{...c,mcp:A(c.mcp)}:c]);return{...s,env:Object.fromEntries(r)}}function A(e){const t=e.docs??{},s={};(e.hide??t.hide)!==void 0&&(s.hide=e.hide===!0||t.hide===!0);const r=e.name??t.name;r!==void 0&&(s.name=r);const n=e.ignore??t.ignore;n!==void 0&&(s.ignore=n);const c=e.publicEndpoint??t.publicEndpoint;return c!==void 0&&(s.publicEndpoint=c),{...e,...s,docs:{...t,...s}}}function F(e){if(!e.theme)return[];d.warn("The 'theme' property in redocly.yaml is deprecated. Please move all of the properties from 'theme' to the root of the config.");const t=[];for(const s of Object.keys(e.theme))e[s]==null?t.push(s):d.warn(`Detected both '${s}' and 'theme.${s}' properties in redocly.yaml. The 'theme.${s}' property will be ignored and needs to be removed or merged into the '${s}'.`);return t}function V(e,t){if(!e.theme||t.length===0)return e;const s={...e};for(const r of t)s[r]=e.theme[r];return delete s.theme,s}export{G as ensureAccessBackwardsCompatibility,ie as readAndValidateConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FIELD_SCOPE_KINDS as n,GRAPHQL_TYPE_KINDS as u}from"./constants.js";import{respondWithGraphqlSchema as g,paginate as d}from"./tool-helpers.js";import{groupSchemaTypes as h,fieldMembers as y,filterMembersReferencingType as S,matchesFilter as b}from"./utils.js";function T(r,p,t){if(p==="fields"){if(t&&!n.some(e=>e===t))throw new Error(`scope "fields" lists the fields of object, interface, and input types; kind must be ${n.map(e=>`"${e}"`).join(", ")}, or omitted.`);return y(r,t)}const o=h(r);return(t?[t]:u).flatMap(e=>o[e].map(s=>({kind:e,...s})))}const E=(r,p)=>g(r.name,p,({name:t,schema:o})=>{const{kind:e,scope:s="members",filter:f,referencesType:l,page:m
|
|
1
|
+
import{FIELD_SCOPE_KINDS as n,GRAPHQL_TYPE_KINDS as u}from"./constants.js";import{respondWithGraphqlSchema as g,paginate as d}from"./tool-helpers.js";import{groupSchemaTypes as h,fieldMembers as y,filterMembersReferencingType as S,matchesFilter as b}from"./utils.js";function T(r,p,t){if(p==="fields"){if(t&&!n.some(e=>e===t))throw new Error(`scope "fields" lists the fields of object, interface, and input types; kind must be ${n.map(e=>`"${e}"`).join(", ")}, or omitted.`);return y(r,t)}const o=h(r);return(t?[t]:u).flatMap(e=>o[e].map(s=>({kind:e,...s})))}const E=(r,p)=>g(r.name,p,({name:t,schema:o})=>{const{kind:e,scope:s="members",filter:f,referencesType:l,page:m,limit:a}=r;let i=T(o,s,e);return l&&(i=S(o,i,l)),f&&(i=i.filter(c=>b(c,f))),JSON.stringify({name:t,...d(i,m??1,a??300)},null,2)});var D={"get-graphql-type-list":E};export{D as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{paginate as p,textResult as m}from"./tool-helpers.js";const c=async(r,l)=>{const{filter:i,page:o
|
|
1
|
+
import{paginate as p,textResult as m}from"./tool-helpers.js";const c=async(r,l)=>{const{filter:i,page:o,limit:n}=r;let t=l.graphqlDescriptions;if(i){const e=i.toLowerCase();t=t.filter(s=>s.name.toLowerCase().includes(e))}const a=p(t,o??1,n??300);return m(JSON.stringify({...a,items:a.items.map(({name:e,description:s})=>({name:e,description:s}))}))};var g={"list-graphql-apis":c};export{g as default};
|
|
@@ -14,8 +14,8 @@ export type SchemaMemberWithKind = SchemaMember & {
|
|
|
14
14
|
export type GroupedSchemaTypes = Record<GraphqlTypeKind, SchemaMember[]>;
|
|
15
15
|
export type ListGraphqlApisArgs = {
|
|
16
16
|
filter?: string;
|
|
17
|
-
page?: number;
|
|
18
|
-
limit?: number;
|
|
17
|
+
page?: number | null;
|
|
18
|
+
limit?: number | null;
|
|
19
19
|
};
|
|
20
20
|
export type GetGraphqlTypeListArgs = {
|
|
21
21
|
name: string;
|
|
@@ -23,8 +23,8 @@ export type GetGraphqlTypeListArgs = {
|
|
|
23
23
|
scope?: GraphqlListScope;
|
|
24
24
|
filter?: string;
|
|
25
25
|
referencesType?: string;
|
|
26
|
-
page?: number;
|
|
27
|
-
limit?: number;
|
|
26
|
+
page?: number | null;
|
|
27
|
+
limit?: number | null;
|
|
28
28
|
};
|
|
29
29
|
export type GetGraphqlTypeArgs = {
|
|
30
30
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCallableApis as b}from"../../../gateway-mcp/callable-apis.js";import{filterApiDescriptionsByName as d}from"../../utils/api-name-matching.js";import{apiTitleKey as y,countApiTitles as A,orderSharedTitles as T}from"../../utils/api-titles.js";const x=async(
|
|
1
|
+
import{getCallableApis as b}from"../../../gateway-mcp/callable-apis.js";import{filterApiDescriptionsByName as d}from"../../utils/api-name-matching.js";import{apiTitleKey as y,countApiTitles as A,orderSharedTitles as T}from"../../utils/api-titles.js";const x=async(l,s)=>{const{filter:a}=l,n=l.page??1,e=l.limit??300,o=new Set(b(s).map(i=>i.relativePath)),m=o.size>0,c=T(Object.values(s.apiDescriptionsMap)),f=A(c);let t=c;a&&(t=d(t,a));const p=(n-1)*e,u=p+e,g=Math.ceil(t.length/e),h=t.length;return t=t.slice(p,u),{content:[{type:"text",text:JSON.stringify({items:t.map(({relativePath:i,fetchEligible:D,...r})=>({filePath:i,...r,...(f.get(y(r.name))??0)>1?{ambiguousTitle:!0}:{},...m?{callable:o.has(i)}:{}})),limit:e,total:h,page:n,totalPages:g})}]}};var I={"list-apis":x};export{I as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as E from"node:path";import{envConfig as R}from"../../config/env-config.js";import{maskEmail as T
|
|
2
|
-
`},y=({context:e,message:
|
|
3
|
-
`},D=e=>(e%500<100?x:e%400<100?b:A)(`status="${e}"`),j=()=>{const e=new Date().getTimezoneOffset()*6e4;return new Date(Date.now()-e).toISOString().slice(0,-1)},V=e=>
|
|
1
|
+
import*as E from"node:path";import{envConfig as R}from"../../config/env-config.js";import{maskEmail as T,maskSubject as C,removePii as w,removePiiFromUrl as $}from"../../../compiled/@redocly/pii/index.js";import{red as x,green as A,bold as F,blue as l,gray as r,yellow as b,cyan as v}from"./helpers/colors.js";function P(e,s){return s?e:w(e)}var n;(function(e){e.INFO="INFO",e.WARN="WARN",e.ERROR="ERROR",e.SUCCESS="SUCCESS",e.VERBOSE="VERBOSE",e.HTTP="HTTP"})(n||(n={}));const I={[n.VERBOSE]:0,[n.HTTP]:1,[n.INFO]:2,[n.SUCCESS]:2,[n.WARN]:3,[n.ERROR]:4};function J(e,s){return I[e]>=I[s]}function W(e){if(!e)return;const s=e.toUpperCase();if(s in n)return s}const H={[n.INFO]:l,[n.SUCCESS]:A,[n.WARN]:b,[n.ERROR]:x,[n.HTTP]:v,[n.VERBOSE]:r},N={"%ap":e=>l(E.resolve(e)),"%rp":e=>l(E.relative(process.cwd(),e)),"%s":e=>e?.toString(),"%c":e=>l(e)},M={format(e){return R.REDOCLY_LOG_FORMAT==="JSON"?y(e):U(e)},interpolate(e,...s){const u=Object.keys(N).map(a=>`(${a})`).join("|"),o=new RegExp(u,"g");let i,c=e;for(;(i=o.exec(e))!==null;){i.index===o.lastIndex&&o.lastIndex++;const a=s.shift();if(a===void 0)break;const t=i[0];c=c.replace(t,N[t](a))}return c}};var z=M;const U=e=>{const{level:s,message:u,duration:o,context:i,preSanitized:c}=e,a=R.isRuntimeMode,t=[H[s](F(`[${s.toLowerCase()}]`))];if(a&&t.push(r(`time="${j()}"`)),i){const{email:m,ipAddress:f,subject:d,method:S,pathname:p,statusCode:h,teams:g,apiFunction:O}=i;O&&t.push(l(`fn="${O}"`)),h&&t.push(D(h)),e.level===n.HTTP&&(S&&t.push(r(`method="${S}"`)),p&&t.push(r(`path="${$(p)}"`))),f&&t.push(r(`ip="${f}"`)),m&&t.push(r(`email="${T(m)}"`)),d&&t.push(r(`sub="${C(d)}"`)),g?.length&&t.push(r(`teams="${g.join(", ")}"`))}if(u){const m=a?`msg="${String(P(u,c)).replaceAll?.('"','\\"')}"`:String(u);t.push(m)}return e.level===n.HTTP&&i?.userAgent&&t.push(r(`agent="${i.userAgent}"`)),o&&t.push(V(o)),t.join(" ")+`
|
|
2
|
+
`},y=({context:e,message:s,preSanitized:u,...o})=>{const{method:i,pathname:c,statusCode:a,userAgent:t,subject:m,email:f,teams:d,apiFunction:S}=e||{},p={...o,email:f&&T(f),subject:m&&C(m),teams:d,apiFunction:S,...o.level===n.HTTP?{method:i,pathname:String($(c)),statusCode:a,userAgent:t}:{message:String(P(String(s??""),u))}};return R.isRuntimeMode&&(p.time=j()),JSON.stringify(p,["time","level","scope","message","duration","method","pathname","statusCode","userAgent","subject","ipAddress","email","apiFunction"])+`
|
|
3
|
+
`},D=e=>(e%500<100?x:e%400<100?b:A)(`status="${e}"`),j=()=>{const e=new Date().getTimezoneOffset()*6e4;return new Date(Date.now()-e).toISOString().slice(0,-1)},V=e=>r(`dur="${Math.round(e)}ms"`);export{n as LogLevel,z as default,W as parseLogLevel,J as shouldLog};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/redoc-reef",
|
|
3
|
-
"version": "0.140.0-next.
|
|
3
|
+
"version": "0.140.0-next.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,14 +33,14 @@
|
|
|
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.5.0-next.
|
|
37
|
-
"@redocly/config": "0.
|
|
36
|
+
"@redocly/api-docs": "0.5.0-next.4",
|
|
37
|
+
"@redocly/config": "0.68.0",
|
|
38
38
|
"@redocly/markdoc": "0.7.0-beta.2",
|
|
39
|
-
"@redocly/openapi-core": "2.
|
|
39
|
+
"@redocly/openapi-core": "2.71.1",
|
|
40
40
|
"@redocly/portal-legacy-ui": "0.19.0",
|
|
41
|
-
"@redocly/portal-plugin-mock-server": "0.25.0-next.
|
|
41
|
+
"@redocly/portal-plugin-mock-server": "0.25.0-next.1",
|
|
42
42
|
"@redocly/realm-asyncapi-sdk": "0.17.0",
|
|
43
|
-
"@redocly/theme": "0.72.0-next.
|
|
43
|
+
"@redocly/theme": "0.72.0-next.3",
|
|
44
44
|
"@shikijs/transformers": "3.21.0",
|
|
45
45
|
"@tanstack/react-query": "5.62.3",
|
|
46
46
|
"@tanstack/react-table": "8.21.3",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Masks the username part of an email address for privacy or anonymization.
|
|
3
|
-
*
|
|
4
|
-
* The function preserves the domain while replacing most characters in the username
|
|
5
|
-
* with asterisks (`*`). It keeps the first two characters visible when the username
|
|
6
|
-
* is longer than two characters. If the input is invalid or not a string containing
|
|
7
|
-
* an `@` symbol, it returns the original value unchanged.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* maskEmail("john.doe@example.com");
|
|
12
|
-
* // → "jo******@example.com"
|
|
13
|
-
*
|
|
14
|
-
* maskEmail("ab@example.com");
|
|
15
|
-
* // → "ab@example.com"
|
|
16
|
-
*
|
|
17
|
-
* maskEmail("a@example.com");
|
|
18
|
-
* // → "*@example.com"
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* @param email - The email address to mask.
|
|
22
|
-
* @returns A masked version of the email, or the original value if invalid.
|
|
23
|
-
*/
|
|
24
|
-
export declare const maskEmail: (email: string) => string;
|
|
25
|
-
//# sourceMappingURL=mask-email.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const r=e=>{if(!e||typeof e!="string"||!e.includes("@"))return e;const[n,t]=e.split("@");return`${n.length>2?n.slice(0,2)+"*".repeat(n.length-2):"*".repeat(n.length)}@${t}`};export{r as maskEmail};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Masks all email addresses found within a given subject string.
|
|
3
|
-
*
|
|
4
|
-
* This utility searches the input text for any email-like patterns and replaces
|
|
5
|
-
* each one using the {@link maskEmail} function, preserving the rest of the string.
|
|
6
|
-
* It is typically used to sanitize or anonymize email addresses before logging,
|
|
7
|
-
* displaying, or transmitting text content.
|
|
8
|
-
*
|
|
9
|
-
* @param subject - The text that may contain one or more email addresses.
|
|
10
|
-
* @returns A new string with all detected email addresses masked.
|
|
11
|
-
*/
|
|
12
|
-
export declare const maskSubject: (subject: string) => string;
|
|
13
|
-
//# sourceMappingURL=mask-subject.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{maskEmail as c}from"./mask-email.js";const r=/[a-zA-Z0-9._%+-]/,m=/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,d=e=>{let o="",i=0,a=0;for(;a<e.length;){const n=e.indexOf("@",a);if(n===-1)break;let t=n;for(;t>i&&r.test(e.charAt(t-1));)t--;const s=t<n?m.exec(e.slice(n+1))?.[0]:void 0;if(!s){a=n+1;continue}const l=n+1+s.length;o+=e.slice(i,t)+c(e.slice(t,l)),i=l,a=l}return o+e.slice(i)};export{d as maskSubject};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sanitizes personally identifiable information (PII) found within a URL or query string.
|
|
3
|
-
*
|
|
4
|
-
* This function scans all query parameter values and removes or masks any PII using
|
|
5
|
-
* the {@link removePii} function. It gracefully handles both absolute and relative URLs.
|
|
6
|
-
*
|
|
7
|
-
* - If the input is not a string, it is returned unchanged.
|
|
8
|
-
* - If parsing as a URL fails, the function falls back to applying {@link removePii}
|
|
9
|
-
* directly on the raw string.
|
|
10
|
-
* - The output preserves the original format (absolute or relative).
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* removePiiFromUrl('https://example.com?email=john.doe@example.com&phone=555-123-4567');
|
|
15
|
-
* // → 'https://example.com/?email=[email_removed]&phone=[phone_removed]'
|
|
16
|
-
*
|
|
17
|
-
* removePiiFromUrl('/profile?ssn=123-45-6789');
|
|
18
|
-
* // → '/profile?ssn=[SSN_removed]'
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* @param url - The input URL string or relative path to sanitize.
|
|
22
|
-
* @returns A sanitized URL string with PII masked, or the input value unchanged if not a string.
|
|
23
|
-
*/
|
|
24
|
-
export declare function removePiiFromUrl(url: unknown): unknown;
|
|
25
|
-
//# sourceMappingURL=remove-pii-from-url.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{isString as n}from"../../../../../utils/string/is-string.js";import{removePii as e}from"./remove-pii.js";function m(t){if(!n(t))return t;try{const r=new URL(t,"http://example.com");for(const[i,s]of r.searchParams.entries()){const a=String(e(s));r.searchParams.set(i,a)}return t.startsWith("http://")||t.startsWith("https://")?r.toString():r.pathname+r.search+r.hash}catch{return String(e(t))}}export{m as removePiiFromUrl};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Implementation of PII sanitization from @coffeeandfun/remove-pii (MIT licensed) without unnecessary methods
|
|
3
|
-
*/
|
|
4
|
-
type PIIConfigOption = {
|
|
5
|
-
enabled: false;
|
|
6
|
-
replacement?: string;
|
|
7
|
-
pattern?: RegExp;
|
|
8
|
-
} | {
|
|
9
|
-
enabled: true;
|
|
10
|
-
replacement: string;
|
|
11
|
-
pattern?: RegExp;
|
|
12
|
-
};
|
|
13
|
-
type PIIConfig = {
|
|
14
|
-
[key: string]: PIIConfigOption;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Removes or masks personally identifiable information (PII) from a given text string.
|
|
18
|
-
*
|
|
19
|
-
* This function identifies and replaces sensitive data such as email addresses,
|
|
20
|
-
* phone numbers, credit card numbers, and other personal identifiers with
|
|
21
|
-
* configurable placeholder strings. It’s a lightweight implementation inspired by
|
|
22
|
-
* `@coffeeandfun/remove-pii` (MIT licensed), keeping only the essential sanitization logic.
|
|
23
|
-
*
|
|
24
|
-
* By default, all common PII patterns (email, phone, SSN, credit card, address,
|
|
25
|
-
* passport number, driver’s license, ZIP code, bank account, and date of birth)
|
|
26
|
-
* are detected and replaced. Custom configuration can override or disable any pattern.
|
|
27
|
-
*
|
|
28
|
-
* Non-string inputs are returned unchanged.
|
|
29
|
-
*
|
|
30
|
-
* @param text - The input text that may contain personally identifiable information.
|
|
31
|
-
* @param options - Optional configuration to enable, disable, or customize PII replacements.
|
|
32
|
-
* @returns A sanitized string with PII masked or removed; if the input is not a string, returns it unchanged.
|
|
33
|
-
*/
|
|
34
|
-
export declare function removePii(text: unknown, options?: PIIConfig): unknown;
|
|
35
|
-
export {};
|
|
36
|
-
//# sourceMappingURL=remove-pii.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{isString as m}from"../../../../../utils/string/is-string.js";const s={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,replacement:"[date_removed]"}};function l(n={}){const e={email:{enabled:!0,replacement:"[email_removed]"},phone:{enabled:!0,replacement:"[phone_removed]"},ssn:{enabled:!0,replacement:"[SSN_removed]"},creditCard:{enabled:!0,replacement:"[credit_card_removed]"},address:{enabled:!0,replacement:"[address_removed]"},passport:{enabled:!0,replacement:"[passport_number_removed]"},driversLicense:{enabled:!0,replacement:"[driver_license_removed]"},zipCode:{enabled:!0,replacement:"[zip_code_removed]"},bankAccount:{enabled:!0,replacement:"[bank_account_removed]"},dateOfBirth:{enabled:!0,replacement:"[date_removed]"}};for(const[r,t]of Object.entries(n))e[r]?e[r]={...e[r],...t}:e[r]=t;return e}function b(n,e={}){if(!m(n))return n;const r=l(e);let t=n;for(const[c,a]of Object.entries(r)){if(!a.enabled)continue;const d=s[c],o=d?.pattern||a.pattern,p=a.replacement||d?.replacement||"[PII removed]";o&&(t=t.replace(o,p))}return t}export{b as removePii};
|