@threads/json-patch-ot
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -0,1 +1,8 @@ | ||
# [1.1.0](https://github.com/ThreadsStyling/json-patch-ot/compare/v1.0.1...v1.1.0) (2019-07-08) | ||
### Features | ||
* prepping for public release ([#11](https://github.com/ThreadsStyling/json-patch-ot/issues/11)) ([7827cdb](https://github.com/ThreadsStyling/json-patch-ot/commit/7827cdb)) | ||
## [1.0.1](https://github.com/ThreadsStyling/json-patch-ot/compare/v1.0.0...v1.0.1) (2019-06-28) | ||
@@ -2,0 +9,0 @@ |
@@ -41,4 +41,14 @@ export interface Options { | ||
} | ||
export declare type PathProp = 'path' | 'from'; | ||
export declare type Operation = OperationAdd | OperationRemove | OperationReplace | OperationCopy | OperationMove | OperationTest; | ||
export declare type PathOperation = OperationAdd | OperationRemove | OperationReplace | OperationTest; | ||
export declare type FromOperation = OperationMove | OperationCopy; | ||
export declare type Operation = FromOperation | PathOperation; | ||
export declare type PathProp = keyof Pick<PathOperation & FromOperation, 'from' | 'path'>; | ||
/** | ||
* Takes array of proposed patches and transforms them against an array of already accepted patches. | ||
* @param acceptedOps Array of already accepted patches | ||
* @param proposedOps Array of proposed patches | ||
* @param options Options object | ||
* | ||
* @returns Array of transformed changes | ||
*/ | ||
export default function JSONPatchOT(acceptedOps: Operation[], proposedOps: Operation[], options?: Options): Operation[]; |
@@ -13,8 +13,9 @@ "use strict"; | ||
})(OpType = exports.OpType || (exports.OpType = {})); | ||
const shiftIndices = (acceptedOp, proposedOps, isAdd = false, pathProp = 'path') => { | ||
const lastSlash = acceptedOp[pathProp].lastIndexOf('/'); | ||
function shiftIndices(acceptedOp, proposedOps, isAdd = false, pathProp = 'path') { | ||
const path = acceptedOp[pathProp]; | ||
const lastSlash = path.lastIndexOf('/'); | ||
if (lastSlash === -1) | ||
return; | ||
const index = acceptedOp[pathProp].substr(lastSlash + 1); | ||
const arrayPath = acceptedOp[pathProp].substr(0, lastSlash + 1); | ||
const index = path.substr(lastSlash + 1); | ||
const arrayPath = path.substr(0, lastSlash + 1); | ||
if (!utils_1.isValidIndex(index)) | ||
@@ -25,2 +26,4 @@ return; | ||
if (pathOfSameArray) { | ||
// Does not use `pathProp` on the proposedOp since we need to deal with | ||
// both path types on the proposedOp anyway. See below it deals with `from`. | ||
proposedOp.path = utils_1.replacePathIndices(proposedOp.path, arrayPath, index, isAdd); | ||
@@ -34,16 +37,23 @@ } | ||
} | ||
}; | ||
} | ||
const allowWhitelist = (acceptedOp, proposedOp) => { | ||
return (proposedOp.op === 'add' || proposedOp.op === 'test') && acceptedOp.path === proposedOp.path; | ||
}; | ||
const removeOperations = (acceptedOp, proposedOps, options, skipWhitelist = false, pathProp = 'path') => { | ||
const isFromOperation = (operation) => { | ||
return operation.op === OpType.move || operation.op === OpType.copy; | ||
}; | ||
function removeOperations(acceptedOp, proposedOps, options, skipWhitelist = false, pathProp = 'path') { | ||
const { acceptedWinsOnEqualPath } = options; | ||
let currentIndex = 0; | ||
let proposedOp; | ||
// remove operation objects within replaced JSON node | ||
while (proposedOps[currentIndex]) { | ||
proposedOp = proposedOps[currentIndex]; | ||
const matchesFromToPath = proposedOp.from && | ||
(proposedOp.from === acceptedOp[pathProp] || proposedOp.from.indexOf(acceptedOp[pathProp] + '/') === 0); | ||
const matchesPathToPath = (acceptedWinsOnEqualPath && acceptedOp[pathProp] === proposedOp.path) || | ||
proposedOp.path.indexOf(acceptedOp[pathProp] + '/') === 0; | ||
let matchesFromToPath = false; | ||
const acceptedPath = acceptedOp[pathProp]; | ||
if (isFromOperation(proposedOp)) { | ||
matchesFromToPath = proposedOp.from === acceptedPath || proposedOp.from.indexOf(acceptedPath + '/') === 0; | ||
} | ||
const matchesPathToPath = (acceptedWinsOnEqualPath && acceptedPath === proposedOp.path) || | ||
proposedOp.path.indexOf(`${acceptedPath}/`) === 0; | ||
const shouldSkip = skipWhitelist ? allowWhitelist(acceptedOp, proposedOp) : false; | ||
@@ -56,3 +66,3 @@ if (!shouldSkip && (matchesFromToPath || matchesPathToPath)) { | ||
} | ||
}; | ||
} | ||
const removeTransformer = (acceptedOp, proposedOps) => { | ||
@@ -69,7 +79,11 @@ removeOperations(acceptedOp, proposedOps, { acceptedWinsOnEqualPath: true }, true); | ||
}; | ||
const copyTransformer = (acceptedOp, proposedOps, options) => { | ||
shiftIndices(acceptedOp, proposedOps, true); | ||
removeOperations(acceptedOp, proposedOps, options); | ||
}; | ||
const moveTransformer = (acceptedOp, proposedOps, options) => { | ||
removeOperations(acceptedOp, proposedOps, { acceptedWinsOnEqualPath: true }, true, 'from'); | ||
shiftIndices(acceptedOp, proposedOps, false, 'from'); | ||
shiftIndices(acceptedOp, proposedOps, true, 'path'); | ||
removeOperations(acceptedOp, proposedOps, options, false, 'path'); | ||
removeOperations(acceptedOp, proposedOps, { acceptedWinsOnEqualPath: true }, true, 'from'); // like a remove | ||
shiftIndices(acceptedOp, proposedOps, false, 'from'); // like a remove | ||
shiftIndices(acceptedOp, proposedOps, true, 'path'); // like an add | ||
removeOperations(acceptedOp, proposedOps, options, false, 'path'); // like an add | ||
}; | ||
@@ -80,4 +94,5 @@ const transformAgainst = { | ||
[OpType.add]: addTransformer, | ||
[OpType.copy]: addTransformer, | ||
[OpType.copy]: copyTransformer, | ||
[OpType.move]: moveTransformer, | ||
[OpType.test]: undefined, | ||
}; | ||
@@ -90,2 +105,10 @@ const reduceJSONPatches = (options) => (proposedOps, acceptedOp) => { | ||
}; | ||
/** | ||
* Takes array of proposed patches and transforms them against an array of already accepted patches. | ||
* @param acceptedOps Array of already accepted patches | ||
* @param proposedOps Array of proposed patches | ||
* @param options Options object | ||
* | ||
* @returns Array of transformed changes | ||
*/ | ||
function JSONPatchOT(acceptedOps, proposedOps, options = {}) { | ||
@@ -92,0 +115,0 @@ const clonedProposed = JSON.parse(JSON.stringify(proposedOps)); |
@@ -15,6 +15,7 @@ "use strict"; | ||
const rest = result.substr(slashIndex); | ||
// For incUp we need to match equal to aswell since that element will be bumped foreward. | ||
const isOldBigger = incUp ? oldIndex >= index : oldIndex > index; | ||
const shouldChangeIndex = isValidIndex(oldIndex) && isOldBigger; | ||
if (shouldChangeIndex) { | ||
return arrayPath + (parseInt(oldIndex, 10) + (incUp ? 1 : -1)) + rest; | ||
return `${arrayPath}${parseInt(oldIndex, 10) + (incUp ? 1 : -1)}${rest}`; | ||
} | ||
@@ -21,0 +22,0 @@ else { |
{ | ||
"name": "@threads/json-patch-ot", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Library to reconcile JSON patch changes using Operational Transformation", | ||
@@ -25,3 +25,3 @@ "main": "lib/index.js", | ||
"lint": "yarn tslint", | ||
"tslint": "tslint './src/**/*.{ts,tsx}' -t verbose", | ||
"tslint": "tslint './src/**/*.{ts,tsx}' -t verbose -p .", | ||
"commitmsg": "commitlint -E GIT_PARAMS" | ||
@@ -52,3 +52,3 @@ }, | ||
"@semantic-release/npm": "^4.0.0", | ||
"@threads/tslint": "^3.1.0", | ||
"@threads/tsconfig": "^1.0.0", | ||
"@types/jest": "^23.1.5", | ||
@@ -66,3 +66,3 @@ "@types/node": "^10.5.2", | ||
"tslint": "^5.10.0", | ||
"typescript": "^2.9.2" | ||
"typescript": "^3.5.2" | ||
}, | ||
@@ -69,0 +69,0 @@ "dependencies": {}, |
@@ -9,2 +9,4 @@ # json-patch-ot | ||
**Note:** This project only exposes commonjs es2018 modules. | ||
## Example | ||
@@ -14,2 +16,4 @@ | ||
```js | ||
import jsonPatchOT, { Operation } from "@threads/json-patch-ot"; | ||
// [0, 1, 2, 3, 4, 5, 6]; <- Starting array | ||
@@ -48,2 +52,4 @@ const acceptedOps: Operation[] = [ | ||
```js | ||
import jsonPatchOT, { Operation } from "@threads/json-patch-ot"; | ||
const options = {acceptedWinsOnEqualPath: true}; | ||
@@ -66,1 +72,13 @@ const acceptedOps: Operation[] = [ | ||
<!-- prettier-ignore-end --> | ||
## Acknowledgements | ||
Thanks to Palindrom's [JSON-Patch-OT](https://github.com/Palindrom/JSON-Patch-OT/) lib which this was originally built upon. | ||
## License | ||
MIT | ||
## Work in progress | ||
**Please note:** This is a work in progress. You are free to use it how you like, but be aware that you do so at your own risk. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
107748
19
947
81
1
1