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