allof-merge
Version:
Simplify JsonSchema/Openapi by combining allOf safely
8 lines (7 loc) • 15.3 kB
JavaScript
/*!
* allof-merge v0.6.7
* Copyright (C) 2012-2025 Damir Yusipov
* Date: Sun, 17 Aug 2025 19:54:52 GMT
*/
function e(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(n=Object.getOwnPropertySymbols(e);s<n.length;s++)t.indexOf(n[s])<0&&Object.prototype.propertyIsEnumerable.call(e,n[s])&&(r[n[s]]=e[n[s]])}return r}function t(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(n=Object.getOwnPropertySymbols(e);s<n.length;s++)t.indexOf(n[s])<0&&Object.prototype.propertyIsEnumerable.call(e,n[s])&&(r[n[s]]=e[n[s]])}return r}const r=(e={},t,r,n)=>{const s=`/${t}`,o="function"==typeof e["/**"]?e["/**"]({key:t,path:r,value:n}):e["/**"],i="function"==typeof e["/*"]?e["/*"]({key:t,path:r,value:n}):e["/*"];let a={};if(s in e)a=e[s];else if(!o&&!i)return;return a="function"==typeof a?a({key:t,path:r,value:n}):a,i&&(a=Object.assign(Object.assign({},i),a)),o?Object.assign(Object.assign({"/**":e["/**"]},o),a):a},n=e=>{const t={},r=e.reduce(((e,t)=>(Object.keys(t).forEach((t=>e.add(t))),e)),new Set);for(const s of r.keys()){const r=e.filter((e=>s in e));if(1!==r.length){if("/"!==s.charAt(0))throw new Error(`Cannot merge rules. Duplicate key: ${s}. Rules should not have same Rule key`);t[s]=(e,t)=>{const o=r.map((r=>"function"==typeof r[s]?r[s](e,t):r[s]));return n(o)}}else t[s]=r[0][s]}return t},s=e=>"object"==typeof e&&null!==e,o=e=>Array.isArray(e),i=(e,i,a={})=>{var l,f;i=o(i)?i:[i];const c=o(a.rules)?n(a.rules):a.rules,u=[{data:e,state:a.state,path:[],keys:[],keyIndex:-1,rules:c}];for(;u.length>0;){const e=u[u.length-1];if(e.keyIndex>=e.keys.length){for(;null===(l=e.hooks)||void 0===l?void 0:l.length;)e.hooks.pop()();u.pop();continue}const n=e.keys[e.keyIndex++],[a,p,d]=u.length>1?[e.data[n],[...e.path,n],r(e.rules,n,[...e.path,n],e.data[n])]:[e.data,e.path,c];let y={value:a,path:p,key:n,state:e.state,rules:d};const h=[];for(const e of i){if(!e||"function"!=typeof e)continue;const r=null!==(f=e(y))&&void 0!==f?f:{},{terminate:n,done:s,exitHook:o}=r,i=t(r,["terminate","done","exitHook"]);if(n)return;if(o&&h.push(o),y=Object.assign(Object.assign({},y),i),s){y=null;break}}if(y&&s(y.value)){const e=o(y.value)?[...y.value.keys()]:Object.keys(y.value);u.push({hooks:h,state:y.state,data:y.value,path:p,keys:e,keyIndex:0,rules:y.rules})}else for(;h.length;)h.pop()()}},a=()=>{const e=new WeakMap;let t;return[({value:e})=>{t=e},({value:r,path:n,key:o,state:i})=>{if(o=n.length?o:"#",s(t)&&s(r)){if(e.has(t))return i.node[o]=e.get(t),{done:!0};const n=Array.isArray(r)?[]:{};i.node[o]=n,e.set(t,n)}else i.node[o]=r;return{value:r,state:Object.assign(Object.assign({},i),{node:i.node[o]})}}]};class l extends Map{add(e,t){const r=this.get(e);return r?r.push(t):this.set(e,[t]),this}}const f=(e,t)=>{const r={};for(const n of t)n in e&&(r[n]=e[n],delete e[n]);return r},c=(e,t)=>{if(Array.isArray(e)&&Array.isArray(t))return[...e,...t];if(s(e)&&s(t)){const r=Object.assign({},e);for(const e of Object.keys(t))r[e]=c(r[e],t[e]);return r}return t},u=e=>e&&e.$ref&&"string"==typeof e.$ref,p=e=>e&&e.anyOf&&Array.isArray(e.anyOf),d=e=>e&&e.oneOf&&Array.isArray(e.oneOf),y=(e,t="")=>{const[r=t,n]=e.split("#"),s=n&&"/"!==n?n:"";return{filePath:r,pointer:s,normalized:h(r,s),jsonPath:m(s)}},h=(e,t)=>e?`${e}${t?"#"+t:""}`:t?`#${t}`:"#",g=(e,t,r=[t])=>{if(!s(e))return;let n=e;const o=m(t);for(const t of o)if(Array.isArray(n)&&n.length>+t)n=n[+t];else if(s(n)&&t in n)n=n[t];else{if(!u(n))return;{const t=y(n.$ref);n=t.filePath||r.includes(t.pointer)?void 0:g(e,t.pointer,[...r,t.pointer])}}return n},O={slash:/\//g,tilde:/~/g,escapedSlash:/~1/g,escapedTilde:/~0/g},m=e=>e.split("/").map((e=>decodeURIComponent(e.replace(O.escapedSlash,"/").replace(O.escapedTilde,"~")))).slice(1),$=e=>e.length?"/"+e.map((e=>encodeURIComponent(String(e).replace(O.tilde,"~0").replace(O.slash,"~1")))).join("/"):"",b=(e,t)=>JSON.stringify(e)==JSON.stringify(t),v=e=>{let t=1;for(;e*t%1!=0;)t*=10;return t};function j(e){const t=e.reduce(((e,t)=>Math.max(e,v(t))),0);return e.reduce(((e,r)=>Math.round(e*t*r*t/k(e*t,r*t))/t))}function k(e,t){return 0===t?e:k(t,e%t)}const A=e=>{if(0===e.length)return[[]];const t=e[0],r=e.slice(1),n=A(r),s=[];for(const e of t)for(const t of n)s.push([e,...t]);return s},x=e=>{const t=[];for(const r of e){if(!("properties"in r))continue;const n=new Set(Object.keys(r.properties)),s=new l;for(const t of n.values())for(const o of e)if(!(o==r||o.properties&&t in o.properties))if("patternProperties"in o&&o.patternProperties)for(const e of Object.keys(o.patternProperties))new RegExp(e).test(t)||n.delete(t);else"additionalProperties"in o&&(!1===o.additionalProperties?n.delete(t):"object"==typeof o.additionalProperties&&s.add(t,o.additionalProperties));if(!n.size)continue;const o={};for(const e of n.values())s.has(e)?o[e]={allOf:[r.properties[e],...s.get(e)]}:o[e]=r.properties[e];t.push(o)}return t},P=e=>{const t=[];for(const r of e){if(!("patternProperties"in r))continue;const n=new Set(Object.keys(r.patternProperties));for(const t of e)if(t!=r&&"additionalProperties"in t&&!t.additionalProperties)for(const e of n.values())t.patternProperties&&e in t.patternProperties||n.delete(e);if(!n.size)continue;const s={};for(const e of n.values())s[e]=r.patternProperties[e];t.push(s)}return t},I=e=>{const t={},r=R(e);for(const[e,n]of Object.entries(r))n.includes(!1)?t[e]=!1:t[e]=n.length>1?{allOf:n}:n[0];return t},w=(e,t)=>!!e.reduce(((e,t)=>e&&!0===t),!0)||E(e,t),S=()=>"Could not merge values, they are probably incompatible",M=e=>`Merge rule not found for key: ${e}`,R=e=>{const t={};for(const r of e)for(const e of Object.keys(r))Array.isArray(t[e])?t[e].push(r[e]):t[e]=[r[e]];return t},E=(e,t)=>{if(e.includes(!1))return!1;const r={},n=R(e);"properties"in n&&(n.properties=x(e)),"patternProperties"in n&&(n.patternProperties=P(e));for(let[s,o]of Object.entries(n)){if(!o.length)continue;const n=t.mergeRules;let i=`/${s}`in n?n[`/${s}`]:n["/?"];i=i&&!("$"in i)&&"/"in i?i["/"]:i,i="function"==typeof i?i():i;const a=i&&"$"in i?i.$:void 0;if(!a)throw new Error(M(s));const l=o.length>1?a(o,Object.assign(Object.assign({},t),{allOfItems:e})):o[0];void 0===l?t.mergeError(o):r[s]=l}return Object.keys(r).length?r:void 0},H=([e])=>e,C=e=>e[e.length-1],q=e=>e.reduce(((e,t)=>e||t),!1),N=e=>Math.min(...e),J=e=>Math.max(...e),z=e=>e.length>1?e.reduce(((e,t)=>`${e}(?=${t})`),""):e[0],B=([e,...t])=>t.reduce(((e,t)=>e.filter((e=>t.includes(e)))),e),L=([e,...t])=>t.find((t=>!b(t,e)))?void 0:e,U=([e,...t])=>t.reduce(((e,t)=>c(e,t)),e),D=e=>A(e).map((e=>({allOf:e}))),T=e=>({anyOf:e}),W=e=>j(e),F=(e,t)=>{const r=e.map((e=>e.map((e=>JSON.stringify(e))))),n=B(r).map((e=>JSON.parse(e))).sort();return n.length||t.mergeError(e),n},G=(e,t)=>{const r=e.map((e=>Array.isArray(e)?e:[e])),n=B(r);return 1===n.length?n[0]:n.length?n:void 0},K=e=>{const t=new Set;for(const r of e)for(const e of r)t.add(e);return Array.from(t).sort()},Q=(e,t)=>{const r={},n=R(e);for(const[e,t]of Object.entries(n)){if(t.reduce(((e,t)=>e&&Array.isArray(t)),!0))r[e]=K(t);else{const n=t.map((e=>Array.isArray(e)?{required:e}:e));r[e]=n.length>1?{allOf:n}:n[0]}}return r},V=(e,t)=>{if(!e.reduce(((e,t)=>Array.isArray(t)||e),!1))return E(e,t);const r=[];let n=1/0,s=0;const o=new l;for(const e of t.allOfItems)"additionalItems"in e&&e.additionalItems&&"items"in e&&Array.isArray(e.items)&&o.add(e.items.length,e.additionalItems),"items"in e&&(r.push(e.items),Array.isArray(e.items)&&(s=Math.max(s,e.items.length),"additionalItems"in e&&!1===e.additionalItems&&(n=Math.min(n,e.items.length))));const i=Math.min(s,n),a=[...Array(i)].map((()=>({allOf:[]})));for(const e of r)if(Array.isArray(e))for(let t=0;t<i;t++){const r=[];for(let e=0;e<=t;e++)o.has(e)&&r.push(...o.get(e));t<e.length?a[t].allOf.push(r.length?Object.assign(Object.assign({},e[t]),{allOf:r}):e[t]):a[t].allOf.push(!r.length||{allOf:r})}else a.forEach((({allOf:t})=>t.push(e)));return a},X=(e,t)=>{const r=[],n=[];for(const e of t.allOfItems)"items"in e&&!Array.isArray(e.items)&&n.push(e.items),"additionalItems"in e&&"items"in e&&Array.isArray(e.items)&&r.push(e.additionalItems);return n.length&&r.forEach((e=>e.allOf=n)),E(r,t)},Y=["draft-04","draft-06"],Z=(e="draft-06",t={})=>Object.assign(Object.assign(Object.assign(Object.assign({"/maximum":{$:N},"/exclusiveMaximum":{$:q},"/minimum":{$:J},"/exclusiveMinimum":{$:q},"/maxLength":{$:N},"/minLength":{$:J},"/maxItems":{$:N},"/minItems":{$:J},"/uniqueItems":{$:q},"/maxProperties":{$:N},"/minProperties":{$:J},"/required":{$:K},"/multipleOf":{$:W},"/enum":{$:F},"/type":{$:G},"/allOf":{"/*":()=>Z(e,t),$:D},"/not":{$:T},"/oneOf":{"/*":()=>Z(e,t),$:D,sibling:["definitions","$defs","$id","$schema"]},"/anyOf":{"/*":()=>Z(e,t),$:D,sibling:["definitions","$defs","$id","$schema"]},"/properties":{"/*":()=>Z(e,t),$:I},"/items":()=>Object.assign(Object.assign({},Z(e,t)),{$:V,"/*":({key:r})=>"number"==typeof r?Z(e,t):{}}),"/additionalProperties":()=>Object.assign(Object.assign({},Z(e,t)),{$:w}),"/additionalItems":()=>Object.assign(Object.assign({},Z(e,t)),{$:X}),"/patternProperties":{"/*":()=>Z(e,t),$:I},"/pattern":{$:z},"/readOnly":{$:q},"/writeOnly":{$:q},"/example":{$:U},"/examples":{$:U},"/deprecated":{$:q}},"draft-04"!==e?{"/propertyNames":()=>Z(e,t),"/contains":()=>Z(e,t),"/dependencies":{"/*":()=>Z(e,t),$:Q},"/const":{$:L},"/exclusiveMaximum":{$:N},"/exclusiveMinimum":{$:J},"/$defs":{"/*":()=>Z(e,t),$:U}}:{}),{"/definitions":{"/*":()=>Z(e,t),$:U},"/xml":{$:U},"/externalDocs":{$:C},"/description":{$:C},"/title":{$:C},"/format":{$:C},"/default":{$:C},"/?":{$:C}}),t),{$:E}),_=["3.0.x","3.1.x"],ee=e=>Z(e,{"/discriminator":{$:U},"/oneOf":{"/*":()=>ee(e),$:D,sibling:["discriminator"]},"/anyOf":{"/*":()=>ee(e),$:D,sibling:["discriminator"]}}),te=e=>"3.0.x"===e?Object.assign(Object.assign({},ee("draft-04")),{"/items":({key:e})=>Object.assign(Object.assign({},ee("draft-04")),{$:V})}):ee("draft-06"),re=e=>({"/*":{"/schema":te(e)}}),ne=e=>({"/content":{"/*":{"/schema":te(e),"/encoding":{"/headers":re(e)}}}}),se=e=>({"/*":{"/headers":re(e),"/content":{"/*":{"/schema":te(e),"/encoding":{"/headers":re(e)}}}}}),oe=(e="3.0.x")=>({"/paths":{"/*":{"/*":{"/parameters":re(e),"/requestBody":ne(e),"/responses":se(e)},"/parameters":re(e)}},"/components":{"/schemas":{"/*":te(e)},"/responses":se(e),"/parameters":re(e),"/requestBodies":{"/*":ne(e)},"/headers":re(e)}}),ie=Z("draft-06",{"/args":()=>ie,"/nullable":{$:q},"/specifiedByURL":{$:C},"/values":{$:U,"/*":{$:U,"/description":{$:C},"/deprecated":{$:C,"/reason":{$:C}}}},"/interfaces":{$:U,"/*":{$:U}},"/directives":{$:U,"/*":()=>Object.assign(Object.assign({},ie),{"/meta":{$:U}})}}),ae={"/queries":{"/*":()=>ie},"/mutations":{"/*":()=>ie},"/subscriptions":{"/*":()=>ie},"/components":{"/*":{"/*":ie},"/directives":{"/*":{"/args":()=>ie}}}},le=(t,r,n)=>{const s=n.sibling||[],o=t,i=r,a=o[i],l=e(o,["symbol"==typeof i?i:i+""]),c=f(l,s);return Object.keys(l).length?Object.assign({[r]:a.map((e=>({allOf:[l,e]})))},c):t},fe=(t,r,n,s)=>{const o=[],i=$(r),a=[],l={pointer:i,data:"",refs:[]};for(const r of t)if(u(r)&&!a.includes(r.$ref)){""===l.data&&(l.data=JSON.stringify(t));const{$ref:f}=r,c=e(r,["$ref"]),{filePath:u,normalized:p,pointer:d}=y(f);if(i===d)continue;const h=s.find((e=>e.refs.includes(r.$ref)&&e.data===l.data&&d!==e.pointer));if(h)return{allOfItems:[{$ref:`#${h.pointer}`}],brokenRefs:a};l.refs.push(p);const O=u?void 0:g(n,d);void 0===O?(a.push(p),o.push(r)):o.push(O),Object.keys(c).length&&o.push(c)}else o.push(r);l.refs.length&&s.push(l);const f=ce(o);return f.find((e=>u(e)&&!a.includes(e.$ref)))?fe(f,r,n,s):{allOfItems:f,brokenRefs:a}},ce=t=>{const r=[];for(const n of t)if(s(n))if(n.allOf&&Array.isArray(n.allOf)){const{allOf:t}=n,s=e(n,["allOf"]),o=Object.keys(s).length?[...t,s]:t;r.push(...ce(o))}else r.push(n);return r},ue=e=>{if("object"!=typeof e||!e)return Z();if("openapi"in e&&"string"==typeof e.openapi&&/3.+/.test(e.openapi)){const t=e.openapi.startsWith("3.1")?"3.1.x":"3.0.x";return oe(t)}return"graphapi"in e&&"string"==typeof e.graphapi?ae:Z()},pe=(e,t)=>{var r;const n=null!==(r=null==t?void 0:t.rules)&&void 0!==r?r:ue(e);return((e,t=[],r={})=>{var n;t=Array.isArray(t)?t:[t];const s={"#":void 0},o=Object.assign({state:Object.assign(Object.assign({},null!==(n=r.state)&&void 0!==n?n:{}),{root:s,node:s})},r.rules?{rules:r.rules}:{}),[l,f]=a();return i(e,[l,...t,f],o),s["#"]})(e,de(t),{rules:n})},de=t=>{const r=new Map;let n=null==t?void 0:t.source;const o=[];return({value:i,key:a,path:l,rules:f,state:c})=>{var u;l.length||(null==t?void 0:t.source)||(n=i);const y=e=>{var n;const s=ye(l);s?r.set(...s):null===(n=null==t?void 0:t.onMergeError)||void 0===n||n.call(t,S(),l,e)},h=()=>{const{node:e}=c,t=$(l);if(r.has(t)){const n=r.get(t),s=e[a];Array.isArray(s)&&(s.length<2&&y((null==i?void 0:i.allOf)||[]),s.splice(n,1))}};if(!s(i)||Array.isArray(i))return{exitHook:h};if(!(e=>!!e&&e["/allOf"]&&"$"in e["/allOf"])(f))return{exitHook:h};const{allOf:g}=i,O=e(i,["allOf"]),m=[];if(Array.isArray(g)&&m.push(...g),m.length)Object.keys(O).length&&m.push(O);else{const{$ref:r}=O,n=e(O,["$ref"]);if((null==t?void 0:t.mergeRefSibling)&&r&&Object.keys(n).length>0)m.push({$ref:r},n);else if(null==t?void 0:t.mergeCombinarySibling){if(p(O)&&f["/anyOf"])return{value:le(O,"anyOf",f["/anyOf"]),exitHook:h};if(d(O)&&f["/oneOf"])return{value:le(O,"oneOf",f["/oneOf"]),exitHook:h}}}if(!m.length)return{value:O,exitHook:h};const{allOfItems:b,brokenRefs:v}=fe(m,l,n,o);if(v.length){for(const e of v)null===(u=null==t?void 0:t.onRefResolveError)||void 0===u||u.call(t,"Cannot resolve $ref",l,e);return{value:{allOf:b},exitHook:h}}if(b.length<2)return{value:b.length?b[0]:{},exitHook:h};const j=E(b,{allOfItems:b,mergeRules:f,mergeError:y});return(null==t?void 0:t.mergeCombinarySibling)&&p(j)?{value:le(j,"anyOf",f["/anyOf"]),exitHook:h}:(null==t?void 0:t.mergeCombinarySibling)&&d(j)?{value:le(j,"oneOf",f["/oneOf"]),exitHook:h}:{value:j,exitHook:h}}},ye=e=>{for(let t=e.length-2;t>=0;t--)if("anyOf"===e[t]||"oneOf"===e[t]){const r=e.slice(0,t+1);return[$(r),e[t+1]]}};export{l as MapArray,X as additionalItemsMergeResolver,w as additionalPropertiesMergeResolver,de as allOfResolverHook,q as alternative,$ as buildPointer,k as calculateGCD,j as calculateLCM,h as createRef,Q as dependenciesMergeResolver,L as equal,A as findCombinations,v as findMultiplierForInteger,H as first,R as getAllOfItemsMap,P as getPatternPropertiesForMerge,x as getPropertiesForMerge,ae as graphapiMergeRules,B as intersectItems,p as isAnyOfNode,b as isEqual,d as isOneOfNode,u as isRefNode,V as itemsMergeResolver,E as jsonSchemaMergeResolver,Z as jsonSchemaMergeRules,Y as jsonSchemaVersion,C as last,J as maxValue,pe as merge,D as mergeArray,F as mergeEnum,W as mergeMultipleOf,T as mergeNot,U as mergeObjects,z as mergePattern,K as mergeStringItems,G as mergeTypes,c as mergeValues,N as minValue,te as openApiJsonSchemaMergeRules,oe as openApiMergeRules,_ as openApiVersion,m as parsePointer,y as parseRef,O as pathMask,f as popValues,I as propertiesMergeResolver,g as resolvePointer,ue as selectMergeRules};
//# sourceMappingURL=index.mjs.map