@iodev/patch-and-resolve 1.0.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.
@@ -0,0 +1,30 @@
1
+ (function(O,w){typeof exports=="object"&&typeof module<"u"?w(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],w):(O=typeof globalThis<"u"?globalThis:O||self,w(O.PatchAndResolve={},O.React))})(this,(function(O,w){"use strict";var re={exports:{}},G={};/**
2
+ * @license React
3
+ * react-jsx-runtime.production.min.js
4
+ *
5
+ * Copyright (c) Facebook, Inc. and its affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */var xe;function He(){if(xe)return G;xe=1;var s=w,o=Symbol.for("react.element"),u=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,a=s.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,g={key:!0,ref:!0,__self:!0,__source:!0};function v(y,d,C){var m,l={},p=null,j=null;C!==void 0&&(p=""+C),d.key!==void 0&&(p=""+d.key),d.ref!==void 0&&(j=d.ref);for(m in d)i.call(d,m)&&!g.hasOwnProperty(m)&&(l[m]=d[m]);if(y&&y.defaultProps)for(m in d=y.defaultProps,d)l[m]===void 0&&(l[m]=d[m]);return{$$typeof:o,type:y,key:p,ref:j,props:l,_owner:a.current}}return G.Fragment=u,G.jsx=v,G.jsxs=v,G}var X={};/**
10
+ * @license React
11
+ * react-jsx-runtime.development.js
12
+ *
13
+ * Copyright (c) Facebook, Inc. and its affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ */var ye;function Ke(){return ye||(ye=1,process.env.NODE_ENV!=="production"&&(function(){var s=w,o=Symbol.for("react.element"),u=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),g=Symbol.for("react.profiler"),v=Symbol.for("react.provider"),y=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),C=Symbol.for("react.suspense"),m=Symbol.for("react.suspense_list"),l=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),j=Symbol.for("react.offscreen"),P=Symbol.iterator,N="@@iterator";function V(e){if(e===null||typeof e!="object")return null;var r=P&&e[P]||e[N];return typeof r=="function"?r:null}var A=s.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;function k(e){{for(var r=arguments.length,t=new Array(r>1?r-1:0),c=1;c<r;c++)t[c-1]=arguments[c];L("error",e,t)}}function L(e,r,t){{var c=A.ReactDebugCurrentFrame,b=c.getStackAddendum();b!==""&&(r+="%s",t=t.concat([b]));var R=t.map(function(x){return String(x)});R.unshift("Warning: "+r),Function.prototype.apply.call(console[e],console,R)}}var D=!1,J=!1,f=!1,S=!1,_=!1,te;te=Symbol.for("react.module.reference");function ie(e){return!!(typeof e=="string"||typeof e=="function"||e===i||e===g||_||e===a||e===C||e===m||S||e===j||D||J||f||typeof e=="object"&&e!==null&&(e.$$typeof===p||e.$$typeof===l||e.$$typeof===v||e.$$typeof===y||e.$$typeof===d||e.$$typeof===te||e.getModuleId!==void 0))}function le(e,r,t){var c=e.displayName;if(c)return c;var b=r.displayName||r.name||"";return b!==""?t+"("+b+")":t}function Q(e){return e.displayName||"Context"}function W(e){if(e==null)return null;if(typeof e.tag=="number"&&k("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case i:return"Fragment";case u:return"Portal";case g:return"Profiler";case a:return"StrictMode";case C:return"Suspense";case m:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case y:var r=e;return Q(r)+".Consumer";case v:var t=e;return Q(t._context)+".Provider";case d:return le(e,e.render,"ForwardRef");case l:var c=e.displayName||null;return c!==null?c:W(e.type)||"Memo";case p:{var b=e,R=b._payload,x=b._init;try{return W(x(R))}catch{return null}}}return null}var U=Object.assign,q=0,Ce,Se,Pe,Ee,we,_e,Te;function ke(){}ke.__reactDisabledLog=!0;function qe(){{if(q===0){Ce=console.log,Se=console.info,Pe=console.warn,Ee=console.error,we=console.group,_e=console.groupCollapsed,Te=console.groupEnd;var e={configurable:!0,enumerable:!0,value:ke,writable:!0};Object.defineProperties(console,{info:e,log:e,warn:e,error:e,group:e,groupCollapsed:e,groupEnd:e})}q++}}function er(){{if(q--,q===0){var e={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:U({},e,{value:Ce}),info:U({},e,{value:Se}),warn:U({},e,{value:Pe}),error:U({},e,{value:Ee}),group:U({},e,{value:we}),groupCollapsed:U({},e,{value:_e}),groupEnd:U({},e,{value:Te})})}q<0&&k("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}}var ce=A.ReactCurrentDispatcher,ue;function ne(e,r,t){{if(ue===void 0)try{throw Error()}catch(b){var c=b.stack.trim().match(/\n( *(at )?)/);ue=c&&c[1]||""}return`
18
+ `+ue+e}}var fe=!1,oe;{var rr=typeof WeakMap=="function"?WeakMap:Map;oe=new rr}function Oe(e,r){if(!e||fe)return"";{var t=oe.get(e);if(t!==void 0)return t}var c;fe=!0;var b=Error.prepareStackTrace;Error.prepareStackTrace=void 0;var R;R=ce.current,ce.current=null,qe();try{if(r){var x=function(){throw Error()};if(Object.defineProperty(x.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(x,[])}catch(I){c=I}Reflect.construct(e,[],x)}else{try{x.call()}catch(I){c=I}e.call(x.prototype)}}else{try{throw Error()}catch(I){c=I}e()}}catch(I){if(I&&c&&typeof I.stack=="string"){for(var h=I.stack.split(`
19
+ `),F=c.stack.split(`
20
+ `),E=h.length-1,T=F.length-1;E>=1&&T>=0&&h[E]!==F[T];)T--;for(;E>=1&&T>=0;E--,T--)if(h[E]!==F[T]){if(E!==1||T!==1)do if(E--,T--,T<0||h[E]!==F[T]){var M=`
21
+ `+h[E].replace(" at new "," at ");return e.displayName&&M.includes("<anonymous>")&&(M=M.replace("<anonymous>",e.displayName)),typeof e=="function"&&oe.set(e,M),M}while(E>=1&&T>=0);break}}}finally{fe=!1,ce.current=R,er(),Error.prepareStackTrace=b}var K=e?e.displayName||e.name:"",B=K?ne(K):"";return typeof e=="function"&&oe.set(e,B),B}function tr(e,r,t){return Oe(e,!1)}function nr(e){var r=e.prototype;return!!(r&&r.isReactComponent)}function se(e,r,t){if(e==null)return"";if(typeof e=="function")return Oe(e,nr(e));if(typeof e=="string")return ne(e);switch(e){case C:return ne("Suspense");case m:return ne("SuspenseList")}if(typeof e=="object")switch(e.$$typeof){case d:return tr(e.render);case l:return se(e.type,r,t);case p:{var c=e,b=c._payload,R=c._init;try{return se(R(b),r,t)}catch{}}}return""}var ee=Object.prototype.hasOwnProperty,Ae={},Fe=A.ReactDebugCurrentFrame;function ae(e){if(e){var r=e._owner,t=se(e.type,e._source,r?r.type:null);Fe.setExtraStackFrame(t)}else Fe.setExtraStackFrame(null)}function or(e,r,t,c,b){{var R=Function.call.bind(ee);for(var x in e)if(R(e,x)){var h=void 0;try{if(typeof e[x]!="function"){var F=Error((c||"React class")+": "+t+" type `"+x+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof e[x]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw F.name="Invariant Violation",F}h=e[x](r,x,c,t,null,"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED")}catch(E){h=E}h&&!(h instanceof Error)&&(ae(b),k("%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).",c||"React class",t,x,typeof h),ae(null)),h instanceof Error&&!(h.message in Ae)&&(Ae[h.message]=!0,ae(b),k("Failed %s type: %s",t,h.message),ae(null))}}}var sr=Array.isArray;function de(e){return sr(e)}function ar(e){{var r=typeof Symbol=="function"&&Symbol.toStringTag,t=r&&e[Symbol.toStringTag]||e.constructor.name||"Object";return t}}function ir(e){try{return De(e),!1}catch{return!0}}function De(e){return""+e}function Ie(e){if(ir(e))return k("The provided key is an unsupported type %s. This value must be coerced to a string before before using it here.",ar(e)),De(e)}var Ne=A.ReactCurrentOwner,lr={key:!0,ref:!0,__self:!0,__source:!0},Ve,Me;function cr(e){if(ee.call(e,"ref")){var r=Object.getOwnPropertyDescriptor(e,"ref").get;if(r&&r.isReactWarning)return!1}return e.ref!==void 0}function ur(e){if(ee.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function fr(e,r){typeof e.ref=="string"&&Ne.current}function dr(e,r){{var t=function(){Ve||(Ve=!0,k("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",r))};t.isReactWarning=!0,Object.defineProperty(e,"key",{get:t,configurable:!0})}}function pr(e,r){{var t=function(){Me||(Me=!0,k("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)",r))};t.isReactWarning=!0,Object.defineProperty(e,"ref",{get:t,configurable:!0})}}var hr=function(e,r,t,c,b,R,x){var h={$$typeof:o,type:e,key:r,ref:t,props:x,_owner:R};return h._store={},Object.defineProperty(h._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(h,"_self",{configurable:!1,enumerable:!1,writable:!1,value:c}),Object.defineProperty(h,"_source",{configurable:!1,enumerable:!1,writable:!1,value:b}),Object.freeze&&(Object.freeze(h.props),Object.freeze(h)),h};function vr(e,r,t,c,b){{var R,x={},h=null,F=null;t!==void 0&&(Ie(t),h=""+t),ur(r)&&(Ie(r.key),h=""+r.key),cr(r)&&(F=r.ref,fr(r,b));for(R in r)ee.call(r,R)&&!lr.hasOwnProperty(R)&&(x[R]=r[R]);if(e&&e.defaultProps){var E=e.defaultProps;for(R in E)x[R]===void 0&&(x[R]=E[R])}if(h||F){var T=typeof e=="function"?e.displayName||e.name||"Unknown":e;h&&dr(x,T),F&&pr(x,T)}return hr(e,h,F,b,c,Ne.current,x)}}var pe=A.ReactCurrentOwner,We=A.ReactDebugCurrentFrame;function H(e){if(e){var r=e._owner,t=se(e.type,e._source,r?r.type:null);We.setExtraStackFrame(t)}else We.setExtraStackFrame(null)}var he;he=!1;function ve(e){return typeof e=="object"&&e!==null&&e.$$typeof===o}function Je(){{if(pe.current){var e=W(pe.current.type);if(e)return`
22
+
23
+ Check the render method of \``+e+"`."}return""}}function gr(e){return""}var Ye={};function xr(e){{var r=Je();if(!r){var t=typeof e=="string"?e:e.displayName||e.name;t&&(r=`
24
+
25
+ Check the top-level render call using <`+t+">.")}return r}}function ze(e,r){{if(!e._store||e._store.validated||e.key!=null)return;e._store.validated=!0;var t=xr(r);if(Ye[t])return;Ye[t]=!0;var c="";e&&e._owner&&e._owner!==pe.current&&(c=" It was passed a child from "+W(e._owner.type)+"."),H(e),k('Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.',t,c),H(null)}}function Le(e,r){{if(typeof e!="object")return;if(de(e))for(var t=0;t<e.length;t++){var c=e[t];ve(c)&&ze(c,r)}else if(ve(e))e._store&&(e._store.validated=!0);else if(e){var b=V(e);if(typeof b=="function"&&b!==e.entries)for(var R=b.call(e),x;!(x=R.next()).done;)ve(x.value)&&ze(x.value,r)}}}function yr(e){{var r=e.type;if(r==null||typeof r=="string")return;var t;if(typeof r=="function")t=r.propTypes;else if(typeof r=="object"&&(r.$$typeof===d||r.$$typeof===l))t=r.propTypes;else return;if(t){var c=W(r);or(t,e.props,"prop",c,e)}else if(r.PropTypes!==void 0&&!he){he=!0;var b=W(r);k("Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?",b||"Unknown")}typeof r.getDefaultProps=="function"&&!r.getDefaultProps.isReactClassApproved&&k("getDefaultProps is only used on classic React.createClass definitions. Use a static property named `defaultProps` instead.")}}function mr(e){{for(var r=Object.keys(e.props),t=0;t<r.length;t++){var c=r[t];if(c!=="children"&&c!=="key"){H(e),k("Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.",c),H(null);break}}e.ref!==null&&(H(e),k("Invalid attribute `ref` supplied to `React.Fragment`."),H(null))}}var Ue={};function Be(e,r,t,c,b,R){{var x=ie(e);if(!x){var h="";(e===void 0||typeof e=="object"&&e!==null&&Object.keys(e).length===0)&&(h+=" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");var F=gr();F?h+=F:h+=Je();var E;e===null?E="null":de(e)?E="array":e!==void 0&&e.$$typeof===o?(E="<"+(W(e.type)||"Unknown")+" />",h=" Did you accidentally export a JSX literal instead of a component?"):E=typeof e,k("React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",E,h)}var T=vr(e,r,t,b,R);if(T==null)return T;if(x){var M=r.children;if(M!==void 0)if(c)if(de(M)){for(var K=0;K<M.length;K++)Le(M[K],e);Object.freeze&&Object.freeze(M)}else k("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else Le(M,e)}if(ee.call(r,"key")){var B=W(e),I=Object.keys(r).filter(function(Pr){return Pr!=="key"}),ge=I.length>0?"{key: someKey, "+I.join(": ..., ")+": ...}":"{key: someKey}";if(!Ue[B+ge]){var Sr=I.length>0?"{"+I.join(": ..., ")+": ...}":"{}";k(`A props object containing a "key" prop is being spread into JSX:
26
+ let props = %s;
27
+ <%s {...props} />
28
+ React keys must be passed directly to JSX without using spread:
29
+ let props = %s;
30
+ <%s key={someKey} {...props} />`,ge,B,Sr,B),Ue[B+ge]=!0}}return e===i?mr(T):yr(T),T}}function br(e,r,t){return Be(e,r,t,!0)}function Rr(e,r,t){return Be(e,r,t,!1)}var jr=Rr,Cr=br;X.Fragment=i,X.jsx=jr,X.jsxs=Cr})()),X}var me;function Ge(){return me||(me=1,process.env.NODE_ENV==="production"?re.exports=He():re.exports=Ke()),re.exports}var n=Ge();const be=({conflicts:s,onResolveAll:o,onClose:u,renderConflictValue:i})=>{const[a,g]=w.useState(0),[v,y]=w.useState(new Map),d=s[a],C=s.length,m=a===0,l=a===C-1,p=v.get(a),j=D=>{y(new Map(v.set(a,D)))},P=D=>n.jsx("pre",{style:{backgroundColor:"#f5f5f5",padding:"15px",borderRadius:"4px",overflow:"auto",maxHeight:"300px",fontSize:"13px",margin:0},children:JSON.stringify(D,null,2)}),N=(D,J)=>{const f=p===(J==="local"?"use-local":"use-remote");return i?i(D,{conflict:d,side:J,isSelected:f}):P(D)},V=()=>{m||g(a-1)},A=()=>{!l&&p&&g(a+1)},k=()=>{if(v.size===C){const D=[];v.forEach((J,f)=>{D.push({conflictIndex:f,strategy:J})}),o(D)}},L=v.size===C;return n.jsx("div",{style:{position:"fixed",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(0, 0, 0, 0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e3},children:n.jsxs("div",{style:{backgroundColor:"white",padding:"30px",borderRadius:"8px",maxWidth:"900px",width:"90%",maxHeight:"80vh",overflow:"auto"},children:[n.jsx("h2",{children:"Patch Conflict Resolution"}),n.jsxs("p",{style:{color:"#666"},children:["Conflict ",a+1," of ",C]}),n.jsxs("div",{style:{backgroundColor:"#fff3cd",padding:"15px",borderRadius:"4px",marginTop:"20px",border:"1px solid #ffc107"},children:[n.jsxs("div",{style:{marginBottom:"10px"},children:[n.jsx("strong",{children:"Field:"})," ",n.jsx("code",{children:d.path})]}),d.remotePatchIndex!==void 0&&n.jsxs("div",{style:{marginBottom:"10px",fontSize:"14px",color:"#666"},children:["Conflict from remote patch #",d.remotePatchIndex+1]})]}),n.jsxs("div",{style:{display:"flex",gap:"20px",marginTop:"20px"},children:[n.jsxs("div",{style:{flex:1},children:[n.jsx("h3",{children:"Local Value"}),n.jsx("div",{style:{border:p==="use-local"?"2px solid #4CAF50":"1px solid #ddd",borderRadius:"4px"},children:N(d.localValue,"local")}),n.jsx("button",{onClick:()=>j("use-local"),style:{marginTop:"10px",padding:"10px 20px",backgroundColor:p==="use-local"?"#4CAF50":"#ddd",color:p==="use-local"?"white":"#333",border:"none",borderRadius:"4px",cursor:"pointer",width:"100%",fontWeight:p==="use-local"?"bold":"normal"},children:p==="use-local"?"✓ Selected":"Use Local"})]}),n.jsxs("div",{style:{flex:1},children:[n.jsx("h3",{children:"Remote Value"}),n.jsx("div",{style:{border:p==="use-remote"?"2px solid #2196F3":"1px solid #ddd",borderRadius:"4px"},children:N(d.remoteValue,"remote")}),n.jsx("button",{onClick:()=>j("use-remote"),style:{marginTop:"10px",padding:"10px 20px",backgroundColor:p==="use-remote"?"#2196F3":"#ddd",color:p==="use-remote"?"white":"#333",border:"none",borderRadius:"4px",cursor:"pointer",width:"100%",fontWeight:p==="use-remote"?"bold":"normal"},children:p==="use-remote"?"✓ Selected":"Use Remote"})]})]}),n.jsxs("div",{style:{display:"flex",gap:"10px",marginTop:"30px",justifyContent:"space-between"},children:[n.jsxs("div",{style:{display:"flex",gap:"10px"},children:[n.jsx("button",{onClick:V,disabled:m,style:{padding:"10px 20px",backgroundColor:m?"#e0e0e0":"#757575",color:"white",border:"none",borderRadius:"4px",cursor:m?"not-allowed":"pointer"},children:"← Previous"}),n.jsx("button",{onClick:A,disabled:l||!p,style:{padding:"10px 20px",backgroundColor:l||!p?"#e0e0e0":"#757575",color:"white",border:"none",borderRadius:"4px",cursor:l||!p?"not-allowed":"pointer"},children:"Next →"})]}),n.jsxs("div",{style:{display:"flex",gap:"10px"},children:[n.jsx("button",{onClick:u,style:{padding:"10px 20px",backgroundColor:"#999",color:"white",border:"none",borderRadius:"4px",cursor:"pointer"},children:"Cancel"}),n.jsxs("button",{onClick:k,disabled:!L,style:{padding:"10px 20px",backgroundColor:L?"#4CAF50":"#e0e0e0",color:"white",border:"none",borderRadius:"4px",cursor:L?"pointer":"not-allowed",fontWeight:"bold"},children:["Finish (",v.size,"/",C,")"]})]})]}),!p&&n.jsx("p",{style:{marginTop:"15px",color:"#ff9800",fontSize:"14px",textAlign:"center"},children:"Please select either Local or Remote to continue"})]})})};function Y(s,o){const u=o.split(".");let i=s;for(const a of u){if(i==null)return;i=i[a]}return i}function Z(s,o,u){const i=o.split(".");let a=s;for(let g=0;g<i.length-1;g++){const v=i[g];(a[v]===null||typeof a[v]!="object")&&(a[v]={}),a=a[v]}a[i[i.length-1]]=u}function Xe(s,o){const u=o.split(".");let i=s;for(const a of u){if(i===null||typeof i!="object"||!(a in i))return!1;i=i[a]}return!0}function z(s,o=""){const u=[];if(s===null||typeof s!="object"||Array.isArray(s))return o?[o]:[];const i=Object.keys(s);if(i.length===0)return o?[o]:[];for(const a of i){if(a==="version")continue;const g=o?`${o}.${a}`:a,v=s[a];if(v===null||typeof v!="object"||Array.isArray(v))u.push(g);else{const y=z(v,g);u.push(...y)}}return u}function $(s,o){if(s===o)return!0;if(s===null||o===null||typeof s!="object"||typeof o!="object"||Array.isArray(s)!==Array.isArray(o))return!1;if(Array.isArray(s))return s.length!==o.length?!1:s.every((a,g)=>$(a,o[g]));const u=Object.keys(s),i=Object.keys(o);return u.length!==i.length?!1:u.every(a=>i.includes(a)&&$(s[a],o[a]))}class Re{mergePatches(o,u){const i=[],a=z(o),g=JSON.parse(JSON.stringify(o)),v=new Set(a);for(let y=0;y<u.length;y++){const d=u[y],C=z(d);for(const l of C){if(v.has(l)){const j=Y(o,l),P=Y(d,l);$(j,P)||i.find(V=>V.path===l)||i.push({path:l,localValue:j,remoteValue:P,remotePatchIndex:y})}const p=Y(d,l);Z(g,l,p)}const m=this.getHigherVersion(g.version,d.version);m!==void 0&&(g.version=m)}return i.length===0?{success:!0,merged:g}:{success:!1,conflicts:i,basePatch:o}}applyResolutions(o,u,i){const a=JSON.parse(JSON.stringify(o)),g=new Map;i.forEach(l=>{g.set(l.conflictIndex,l)});const v=[],y=z(o),d=new Set(y);for(let l=0;l<u.length;l++){const p=u[l],j=z(p);for(const P of j)if(d.has(P)){const N=Y(o,P),V=Y(p,P);$(N,V)||v.push({path:P,localValue:N,remoteValue:V,remotePatchIndex:l})}}const C=new Set;v.forEach((l,p)=>{C.add(l.path);const j=g.get(p);j&&(j.strategy==="use-local"?Z(a,l.path,l.localValue):Z(a,l.path,l.remoteValue))}),u.forEach(l=>{z(l).forEach(j=>{if(!C.has(j)){const P=Y(l,j);Z(a,j,P)}})});const m=[o.version,...u.map(l=>l.version)].filter(l=>l!==void 0);return m.length>0&&(a.version=Math.max(...m)),{resolutions:i,resolved:a}}getHigherVersion(o,u){if(!(o===void 0&&u===void 0))return o===void 0?u:u===void 0?o:Math.max(o,u)}}function je(s){const[o,u]=w.useState(null),[i,a]=w.useState(!1),[g,v]=w.useState(null),[y,d]=w.useState([]),C=new Re,m=w.useCallback((j,P)=>{var N,V;a(!0),v(j),d(P);try{const A=C.mergePatches(j,P);return u(A),A.success&&A.merged?(N=s==null?void 0:s.onMergeSuccess)==null||N.call(s,A.merged):(V=s==null?void 0:s.onConflict)==null||V.call(s,A),A}finally{a(!1)}},[s]),l=w.useCallback(j=>{if(!g||y.length===0)return null;const P=C.applyResolutions(g,y,j);return u(null),v(null),d([]),P.resolved},[g,y]),p=w.useCallback(()=>{u(null),v(null),d([])},[]);return{merging:i,mergeResult:o,hasConflict:o&&!o.success,mergePatches:m,applyResolutions:l,clearConflict:p}}const Ze=({onMergeComplete:s})=>{var D,J;const[o,u]=w.useState(JSON.stringify({version:15,message:"Hello from desktop",x:100,y:50,user:{name:"Alice",location:{city:"Boston",state:"MA",zip:"02101"}}},null,2)),[i,a]=w.useState([{version:16,message:"Hello from mobile",x:110,y:60,user:{name:"Alice",location:{city:"New York",state:"NY",zip:"10001"}}},{version:17,z:300}]),[g,v]=w.useState([JSON.stringify({version:16,message:"Hello from mobile",x:110,y:60,user:{name:"Alice",location:{city:"New York",state:"NY",zip:"10001"}}},null,2),JSON.stringify({version:17,z:300},null,2)]),[y,d]=w.useState(null),[C,m]=w.useState(!1),{mergePatches:l,applyResolutions:p}=je({onMergeSuccess:f=>{d({success:!0,merged:f}),s==null||s(f)},onConflict:f=>{d(f),m(!0)}}),j=()=>{d(null);try{const f=JSON.parse(o),S=g.map(_=>JSON.parse(_));l(f,S)}catch(f){d({success:!1,conflicts:[{path:"JSON Parse Error",localValue:"Invalid JSON",remoteValue:String(f)}]})}},P=f=>{const S=p(f);S&&(d({success:!0,merged:S}),m(!1),s==null||s(S))},N=f=>{u(f)},V=(f,S)=>{const _=[...g];_[f]=S,v(_)},A=()=>{const S={version:Math.max(...i.map(_=>_.version||0))+1};a([...i,S]),v([...g,JSON.stringify(S,null,2)])},k=f=>{a(i.filter((S,_)=>_!==f)),v(g.filter((S,_)=>_!==f))},L=(f,S)=>{const{isSelected:_}=S;if(typeof f=="string")return n.jsx("div",{style:{backgroundColor:_?"#e8f5e9":"#f5f5f5",padding:"20px",borderRadius:"4px",display:"flex",alignItems:"center",justifyContent:"center",minHeight:"80px"},children:n.jsx("div",{style:{fontSize:"18px",fontWeight:"bold",color:_?"#2e7d32":"#1976d2"},children:f})});const te=f&&typeof f=="object"&&"message"in f,ie=f&&typeof f=="object"&&("x"in f||"y"in f);if(te||ie){const le=f.message||"Preview",Q=f.x||0,W=f.y||0;return n.jsxs("div",{style:{backgroundColor:_?"#e8f5e9":"#f5f5f5",padding:"20px",borderRadius:"4px",minHeight:"150px",position:"relative"},children:[n.jsxs("div",{style:{fontSize:"12px",color:"#666",marginBottom:"10px",fontFamily:"monospace"},children:["Position: x=",Q,", y=",W]}),n.jsx("div",{style:{position:"absolute",left:`${20+Q}px`,top:`${40+W/10}px`,padding:"8px 12px",backgroundColor:_?"#4CAF50":"#2196F3",color:"white",borderRadius:"4px",fontSize:"14px",boxShadow:"0 2px 4px rgba(0,0,0,0.2)",maxWidth:"200px",wordWrap:"break-word"},children:le}),n.jsx("pre",{style:{marginTop:"80px",fontSize:"11px",color:"#666",backgroundColor:"rgba(255,255,255,0.5)",padding:"8px",borderRadius:"4px",overflow:"auto"},children:JSON.stringify(f,null,2)})]})}return n.jsx("pre",{style:{backgroundColor:_?"#e8f5e9":"#f5f5f5",padding:"15px",borderRadius:"4px",overflow:"auto",maxHeight:"300px",fontSize:"13px",margin:0},children:JSON.stringify(f,null,2)})};return n.jsxs("div",{style:{padding:"20px",fontFamily:"system-ui, sans-serif"},children:[n.jsx("h1",{children:"Patch Merge Demo"}),n.jsx("p",{children:"Merge multiple remote patches into a local patch. Example: Desktop has version 15, server has versions 16-20. Patches are merged sequentially. If any conflicts occur, step through them one at a time."}),n.jsxs("div",{style:{display:"flex",gap:"20px",marginBottom:"20px"},children:[n.jsxs("div",{style:{flex:1},children:[n.jsx("h2",{children:"Local Patch (Your Changes)"}),n.jsx("textarea",{value:o,onChange:f=>N(f.target.value),rows:10,style:{width:"100%",fontFamily:"monospace",padding:"10px"}})]}),n.jsxs("div",{style:{flex:1},children:[n.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[n.jsx("h2",{children:"Remote Patches (From Server)"}),n.jsx("button",{onClick:A,style:{padding:"5px 10px",fontSize:"14px",cursor:"pointer",backgroundColor:"#2196F3",color:"white",border:"none",borderRadius:"4px"},children:"+ Add Patch"})]}),i.map((f,S)=>n.jsxs("div",{style:{marginBottom:"10px",position:"relative"},children:[n.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"5px"},children:[n.jsxs("small",{style:{color:"#666"},children:["Remote Patch #",S+1," ",f.version?`(v${f.version})`:""]}),n.jsx("button",{onClick:()=>k(S),style:{padding:"2px 6px",fontSize:"12px",cursor:"pointer",backgroundColor:"#f44336",color:"white",border:"none",borderRadius:"4px"},children:"× Remove"})]}),n.jsx("textarea",{value:g[S],onChange:_=>V(S,_.target.value),rows:4,style:{width:"100%",fontFamily:"monospace",padding:"10px",fontSize:"12px"}})]},S))]})]}),n.jsx("button",{onClick:j,style:{padding:"10px 20px",fontSize:"16px",cursor:"pointer",backgroundColor:"#4CAF50",color:"white",border:"none",borderRadius:"4px"},children:"Merge Patches"}),y&&n.jsx("div",{style:{marginTop:"20px"},children:y.success?n.jsxs("div",{style:{backgroundColor:"#d4edda",border:"1px solid #c3e6cb",padding:"15px",borderRadius:"4px"},children:[n.jsx("h3",{style:{marginTop:0,color:"#155724"},children:"✓ Merged Successfully!"}),n.jsx("pre",{style:{backgroundColor:"#fff",padding:"10px",borderRadius:"4px"},children:JSON.stringify(y.merged,null,2)})]}):n.jsxs("div",{style:{backgroundColor:"#fff3cd",border:"1px solid #ffc107",padding:"15px",borderRadius:"4px"},children:[n.jsxs("h3",{style:{marginTop:0,color:"#856404"},children:["⚠ ",(D=y.conflicts)==null?void 0:D.length," Conflict",((J=y.conflicts)==null?void 0:J.length)!==1?"s":""," Detected"]}),n.jsx("p",{children:"The patches modify the same fields. A modal will help you resolve them one at a time."})]})}),C&&y&&!y.success&&y.conflicts&&n.jsx(be,{conflicts:y.conflicts,onResolveAll:P,onClose:()=>m(!1),renderConflictValue:L})]})};function $e(s){const o={};for(const u of s){if(u.op!=="add"&&u.op!=="replace")continue;const i=u.path.match(/^\/([^/]+)$/);if(!i){console.warn(`jsonPatchToDiff: Ignoring nested or invalid path: ${u.path}`);continue}const a=i[1];o[a]=u.value}return o}function Qe(s){return Object.entries(s).filter(([o])=>o!=="version").map(([o,u])=>({op:"replace",path:`/${o}`,value:u}))}O.ConflictModal=be,O.ConflictResolver=Re,O.PatchManager=Ze,O.deepEqual=$,O.diffToJsonPatch=Qe,O.getAllPaths=z,O.getNestedValue=Y,O.hasNestedPath=Xe,O.jsonPatchToDiff=$e,O.setNestedValue=Z,O.usePatchMerger=je,Object.defineProperty(O,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,41 @@
1
+ import { Patch, MergeResult, ConflictResolution, ResolveResult } from '../types';
2
+ /**
3
+ * Service for merging patches and resolving conflicts
4
+ */
5
+ export declare class ConflictResolver {
6
+ /**
7
+ * Merge multiple remote patches into a local patch with deep (nested) conflict detection.
8
+ *
9
+ * **Conflict Rules:**
10
+ * - Conflicts occur ONLY when the exact same path is modified by both local and remote patches
11
+ * - Different paths merge automatically, even if they share a parent object
12
+ * - Example: local changes `user.name`, remote changes `user.address.city` → No conflict (different paths)
13
+ * - Example: local changes `user.name`, remote changes `user.name` → Conflict (same path)
14
+ *
15
+ * **Path Format:**
16
+ * - Uses dot notation: "user.name", "pages.0.container.text.fontSize"
17
+ * - Arrays are treated as single values (conflicts if entire array differs)
18
+ * - Flat objects work perfectly fine (treated as depth-1 nested objects)
19
+ *
20
+ * **Note:** Later remote patches can overwrite earlier remote patches without conflict.
21
+ * Conflicts only occur between the local patch and remote patches.
22
+ *
23
+ * @param localPatch - The base patch with potential nested structure
24
+ * @param remotePatches - Array of remote patches to merge
25
+ * @returns MergeResult with either merged patch or conflicts requiring resolution
26
+ */
27
+ mergePatches(localPatch: Patch, remotePatches: Patch[]): MergeResult;
28
+ /**
29
+ * Apply conflict resolutions to produce the final merged patch.
30
+ *
31
+ * @param localPatch - The base patch with potential nested structure
32
+ * @param remotePatches - Array of remote patches
33
+ * @param resolutions - Array of conflict resolutions
34
+ * @returns Final resolved patch with deep merging
35
+ */
36
+ applyResolutions(localPatch: Patch, remotePatches: Patch[], resolutions: ConflictResolution[]): ResolveResult;
37
+ /**
38
+ * Get the higher version number from two optional versions
39
+ */
40
+ private getHigherVersion;
41
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Represents a patch - changes to be applied to a document
3
+ */
4
+ export type Patch = Record<string, any>;
5
+ /**
6
+ * Represents a single conflict between local and remote values
7
+ */
8
+ export interface Conflict {
9
+ /**
10
+ * Field path that has conflicting values
11
+ */
12
+ path: string;
13
+ /**
14
+ * Value from the local patch
15
+ */
16
+ localValue: any;
17
+ /**
18
+ * Value from the remote patch
19
+ */
20
+ remoteValue: any;
21
+ /**
22
+ * Index of the remote patch that caused this conflict (if merging multiple patches)
23
+ */
24
+ remotePatchIndex?: number;
25
+ }
26
+ /**
27
+ * Result of attempting to merge patches
28
+ */
29
+ export interface MergeResult {
30
+ /**
31
+ * Whether the patches were successfully merged automatically
32
+ */
33
+ success: boolean;
34
+ /**
35
+ * The merged patch if successful
36
+ */
37
+ merged?: Patch;
38
+ /**
39
+ * Conflicts that require manual resolution
40
+ */
41
+ conflicts?: Conflict[];
42
+ /**
43
+ * Base patch that was being merged into
44
+ */
45
+ basePatch?: Patch;
46
+ }
47
+ /**
48
+ * Strategy for resolving a single conflict
49
+ */
50
+ export type ResolveStrategy = 'use-local' | 'use-remote';
51
+ /**
52
+ * Resolution for a single conflict
53
+ */
54
+ export interface ConflictResolution {
55
+ /**
56
+ * Index of the conflict being resolved
57
+ */
58
+ conflictIndex: number;
59
+ /**
60
+ * Strategy chosen to resolve this conflict
61
+ */
62
+ strategy: ResolveStrategy;
63
+ }
64
+ /**
65
+ * Result of manual conflict resolution
66
+ */
67
+ export interface ResolveResult {
68
+ /**
69
+ * All resolutions applied
70
+ */
71
+ resolutions: ConflictResolution[];
72
+ /**
73
+ * The final resolved patch
74
+ */
75
+ resolved: Patch;
76
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Utilities for working with nested object paths
3
+ */
4
+ /**
5
+ * Get a value from a nested object using a dot-notation path
6
+ * @param obj - The object to get the value from
7
+ * @param path - Dot-notation path (e.g., "user.address.city")
8
+ * @returns The value at the path, or undefined if not found
9
+ */
10
+ export declare function getNestedValue(obj: any, path: string): any;
11
+ /**
12
+ * Set a value in a nested object using a dot-notation path
13
+ * Creates intermediate objects as needed
14
+ * @param obj - The object to modify (will be mutated)
15
+ * @param path - Dot-notation path (e.g., "user.address.city")
16
+ * @param value - The value to set
17
+ */
18
+ export declare function setNestedValue(obj: any, path: string, value: any): void;
19
+ /**
20
+ * Check if a path exists in an object
21
+ * @param obj - The object to check
22
+ * @param path - Dot-notation path
23
+ * @returns true if the path exists
24
+ */
25
+ export declare function hasNestedPath(obj: any, path: string): boolean;
26
+ /**
27
+ * Get all leaf paths from a nested object
28
+ * @param obj - The object to extract paths from
29
+ * @param prefix - Current path prefix (used recursively)
30
+ * @returns Array of dot-notation paths to all leaf values
31
+ *
32
+ * @example
33
+ * const obj = { user: { name: "John", address: { city: "NYC" } } };
34
+ * getAllPaths(obj) // ["user.name", "user.address.city"]
35
+ */
36
+ export declare function getAllPaths(obj: any, prefix?: string): string[];
37
+ /**
38
+ * Deep equality check for values
39
+ */
40
+ export declare function deepEqual(a: any, b: any): boolean;
@@ -0,0 +1,44 @@
1
+ import { Patch } from '../types';
2
+ /**
3
+ * JSON Patch operation types (RFC 6902)
4
+ */
5
+ export interface JsonPatchOperation {
6
+ op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';
7
+ path: string;
8
+ value?: any;
9
+ from?: string;
10
+ }
11
+ /**
12
+ * Converts a JSON Patch (RFC 6902) array of operations to a simple diff object.
13
+ * Only processes 'add' and 'replace' operations for top-level paths.
14
+ * Ignores 'remove', 'move', 'copy', and 'test' operations as they don't map to simple diffs.
15
+ * Nested paths (e.g., "/user/name") are not supported - only top-level fields (e.g., "/name").
16
+ *
17
+ * @param operations - Array of JSON Patch operations
18
+ * @returns A patch object representing the changes
19
+ *
20
+ * @example
21
+ * const operations = [
22
+ * { op: "replace", path: "/message", value: "Hello" },
23
+ * { op: "add", path: "/x", value: 100 }
24
+ * ];
25
+ * const diff = jsonPatchToDiff(operations);
26
+ * // Returns: { message: "Hello", x: 100 }
27
+ */
28
+ export declare function jsonPatchToDiff(operations: JsonPatchOperation[]): Patch;
29
+ /**
30
+ * Converts a simple diff object to a JSON Patch (RFC 6902) array of operations.
31
+ * All changes are converted to 'replace' operations.
32
+ *
33
+ * @param diff - A patch object representing changes
34
+ * @returns Array of JSON Patch operations
35
+ *
36
+ * @example
37
+ * const diff = { message: "Hello", x: 100 };
38
+ * const operations = diffToJsonPatch(diff);
39
+ * // Returns: [
40
+ * // { op: "replace", path: "/message", value: "Hello" },
41
+ * // { op: "replace", path: "/x", value: 100 }
42
+ * // ]
43
+ */
44
+ export declare function diffToJsonPatch(diff: Patch): JsonPatchOperation[];
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@iodev/patch-and-resolve",
3
+ "version": "1.0.6",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "./dist/patch-and-resolve.umd.js",
7
+ "module": "./dist/patch-and-resolve.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/patch-and-resolve.es.js",
13
+ "require": "./dist/patch-and-resolve.umd.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "dev": "vite",
21
+ "build": "tsc && vite build",
22
+ "build:lib": "tsc && vite build --mode library",
23
+ "preview": "vite preview",
24
+ "type-check": "tsc --noEmit",
25
+ "lint": "eslint . --ext .ts,.tsx --report-unused-disable-directives --max-warnings 40",
26
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
27
+ "test": "vitest run",
28
+ "test:unit": "vitest run",
29
+ "test:watch": "vitest",
30
+ "test:ui": "vitest --ui",
31
+ "test:e2e": "playwright test --project=chromium",
32
+ "test:e2e:ui": "playwright test --project=chromium --ui",
33
+ "test:e2e:headed": "playwright test --project=chromium --headed",
34
+ "test:all": "npm run test:unit && npm run test:e2e",
35
+ "prepare": "husky",
36
+ "semantic-release": "semantic-release"
37
+ },
38
+ "dependencies": {
39
+ "react": "^18.0.0",
40
+ "react-dom": "^18.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@commitlint/cli": "^19.6.0",
44
+ "@commitlint/config-conventional": "^19.6.0",
45
+ "@eslint/js": "^9.39.2",
46
+ "@playwright/test": "^1.49.1",
47
+ "@semantic-release/changelog": "^6.0.3",
48
+ "@semantic-release/git": "^10.0.1",
49
+ "@types/react": "^18.3.18",
50
+ "@types/react-dom": "^18.3.5",
51
+ "@typescript-eslint/eslint-plugin": "^8.21.0",
52
+ "@typescript-eslint/parser": "^8.21.0",
53
+ "@vitejs/plugin-react": "^4.3.4",
54
+ "@vitest/ui": "^2.1.8",
55
+ "eslint": "^9.18.0",
56
+ "eslint-plugin-react": "^7.37.3",
57
+ "eslint-plugin-react-hooks": "^5.1.0",
58
+ "eslint-plugin-react-refresh": "^0.4.16",
59
+ "globals": "^15.15.0",
60
+ "husky": "^9.1.7",
61
+ "jsdom": "^25.0.1",
62
+ "semantic-release": "^24.2.0",
63
+ "typescript": "^5.7.2",
64
+ "vite": "^6.0.3",
65
+ "vite-plugin-dts": "^4.3.0",
66
+ "vitest": "^2.1.8"
67
+ },
68
+ "peerDependencies": {
69
+ "react": "^18.0.0",
70
+ "react-dom": "^18.0.0"
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "https://github.com/isaac76/patchAndResolve.git"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
78
+ }
79
+ }