From 97342846813e316ad08385baa3e8ad236d5daafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Wed, 31 Jul 2019 14:49:54 +0200 Subject: [PATCH 01/31] Export non-bundled module --- module/core.js | 376 ++++++++++++++++++++++++++++++++++++++++++++++ module/duplex.js | 180 ++++++++++++++++++++++ module/helpers.js | 171 +++++++++++++++++++++ package.json | 5 +- src/core.ts | 2 +- 5 files changed, 732 insertions(+), 2 deletions(-) create mode 100644 module/core.js create mode 100644 module/duplex.js create mode 100644 module/helpers.js diff --git a/module/core.js b/module/core.js new file mode 100644 index 00000000..d079e802 --- /dev/null +++ b/module/core.js @@ -0,0 +1,376 @@ +import * as areEquals from 'fast-deep-equal'; +import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers'; +export var JsonPatchError = PatchError; +export var deepClone = _deepClone; +/* We use a Javascript hash to store each + function. Each hash entry (property) uses + the operation identifiers specified in rfc6902. + In this way, we can map each patch operation + to its dedicated function in efficient way. + */ +/* The operations applicable to an object */ +var objOps = { + add: function (obj, key, document) { + obj[key] = this.value; + return { newDocument: document }; + }, + remove: function (obj, key, document) { + var removed = obj[key]; + delete obj[key]; + return { newDocument: document, removed: removed }; + }, + replace: function (obj, key, document) { + var removed = obj[key]; + obj[key] = this.value; + return { newDocument: document, removed: removed }; + }, + move: function (obj, key, document) { + /* in case move target overwrites an existing value, + return the removed value, this can be taxing performance-wise, + and is potentially unneeded */ + var removed = getValueByPointer(document, this.path); + if (removed) { + removed = _deepClone(removed); + } + var originalValue = applyOperation(document, { op: "remove", path: this.from }).removed; + applyOperation(document, { op: "add", path: this.path, value: originalValue }); + return { newDocument: document, removed: removed }; + }, + copy: function (obj, key, document) { + var valueToCopy = getValueByPointer(document, this.from); + // enforce copy by value so further operations don't affect source (see issue #177) + applyOperation(document, { op: "add", path: this.path, value: _deepClone(valueToCopy) }); + return { newDocument: document }; + }, + test: function (obj, key, document) { + return { newDocument: document, test: areEquals(obj[key], this.value) }; + }, + _get: function (obj, key, document) { + this.value = obj[key]; + return { newDocument: document }; + } +}; +/* The operations applicable to an array. Many are the same as for the object */ +var arrOps = { + add: function (arr, i, document) { + if (isInteger(i)) { + arr.splice(i, 0, this.value); + } + else { // array props + arr[i] = this.value; + } + // this may be needed when using '-' in an array + return { newDocument: document, index: i }; + }, + remove: function (arr, i, document) { + var removedList = arr.splice(i, 1); + return { newDocument: document, removed: removedList[0] }; + }, + replace: function (arr, i, document) { + var removed = arr[i]; + arr[i] = this.value; + return { newDocument: document, removed: removed }; + }, + move: objOps.move, + copy: objOps.copy, + test: objOps.test, + _get: objOps._get +}; +/** + * Retrieves a value from a JSON document by a JSON pointer. + * Returns the value. + * + * @param document The document to get the value from + * @param pointer an escaped JSON pointer + * @return The retrieved value + */ +export function getValueByPointer(document, pointer) { + if (pointer == '') { + return document; + } + var getOriginalDestination = { op: "_get", path: pointer }; + applyOperation(document, getOriginalDestination); + return getOriginalDestination.value; +} +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the {newDocument, result} of the operation. + * It modifies the `document` and `operation` objects - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyOperation(document, jsonpatch._deepClone(operation))`. + * + * @param document The document to patch + * @param operation The operation to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return `{newDocument, result}` after the operation + */ +export function applyOperation(document, operation, validateOperation, mutateDocument, banPrototypeModifications, index) { + if (validateOperation === void 0) { validateOperation = false; } + if (mutateDocument === void 0) { mutateDocument = true; } + if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } + if (index === void 0) { index = 0; } + if (validateOperation) { + if (typeof validateOperation == 'function') { + validateOperation(operation, 0, document, operation.path); + } + else { + validator(operation, 0); + } + } + /* ROOT OPERATIONS */ + if (operation.path === "") { + var returnValue = { newDocument: document }; + if (operation.op === 'add') { + returnValue.newDocument = operation.value; + return returnValue; + } + else if (operation.op === 'replace') { + returnValue.newDocument = operation.value; + returnValue.removed = document; //document we removed + return returnValue; + } + else if (operation.op === 'move' || operation.op === 'copy') { // it's a move or copy to root + returnValue.newDocument = getValueByPointer(document, operation.from); // get the value by json-pointer in `from` field + if (operation.op === 'move') { // report removed item + returnValue.removed = document; + } + return returnValue; + } + else if (operation.op === 'test') { + returnValue.test = areEquals(document, operation.value); + if (returnValue.test === false) { + throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + returnValue.newDocument = document; + return returnValue; + } + else if (operation.op === 'remove') { // a remove on root + returnValue.removed = document; + returnValue.newDocument = null; + return returnValue; + } + else if (operation.op === '_get') { + operation.value = document; + return returnValue; + } + else { /* bad operation */ + if (validateOperation) { + throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); + } + else { + return returnValue; + } + } + } /* END ROOT OPERATIONS */ + else { + if (!mutateDocument) { + document = _deepClone(document); + } + var path = operation.path || ""; + var keys = path.split('/'); + var obj = document; + var t = 1; //skip empty element - http://jsperf.com/to-shift-or-not-to-shift + var len = keys.length; + var existingPathFragment = undefined; + var key = void 0; + var validateFunction = void 0; + if (typeof validateOperation == 'function') { + validateFunction = validateOperation; + } + else { + validateFunction = validator; + } + while (true) { + key = keys[t]; + if (banPrototypeModifications && key == '__proto__') { + throw new TypeError('JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README'); + } + if (validateOperation) { + if (existingPathFragment === undefined) { + if (obj[key] === undefined) { + existingPathFragment = keys.slice(0, t).join('/'); + } + else if (t == len - 1) { + existingPathFragment = operation.path; + } + if (existingPathFragment !== undefined) { + validateFunction(operation, 0, document, existingPathFragment); + } + } + } + t++; + if (Array.isArray(obj)) { + if (key === '-') { + key = obj.length; + } + else { + if (validateOperation && !isInteger(key)) { + throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", index, operation, document); + } // only parse key when it's an integer for `arr.prop` to work + else if (isInteger(key)) { + key = ~~key; + } + } + if (t >= len) { + if (validateOperation && operation.op === "add" && key > obj.length) { + throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document); + } + var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch + if (returnValue.test === false) { + throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return returnValue; + } + } + else { + if (key && key.indexOf('~') != -1) { + key = unescapePathComponent(key); + } + if (t >= len) { + var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch + if (returnValue.test === false) { + throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return returnValue; + } + } + obj = obj[key]; + } + } +} +/** + * Apply a full JSON Patch array on a JSON document. + * Returns the {newDocument, result} of the patch. + * It modifies the `document` object and `patch` - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyPatch(document, jsonpatch._deepClone(patch))`. + * + * @param document The document to patch + * @param patch The patch to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return An array of `{newDocument, result}` after the patch + */ +export function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) { + if (mutateDocument === void 0) { mutateDocument = true; } + if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } + if (validateOperation) { + if (!Array.isArray(patch)) { + throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); + } + } + if (!mutateDocument) { + document = _deepClone(document); + } + var results = new Array(patch.length); + for (var i = 0, length_1 = patch.length; i < length_1; i++) { + // we don't need to pass mutateDocument argument because if it was true, we already deep cloned the object, we'll just pass `true` + results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i); + document = results[i].newDocument; // in case root was replaced + } + results.newDocument = document; + return results; +} +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the updated document. + * Suitable as a reducer. + * + * @param document The document to patch + * @param operation The operation to apply + * @return The updated document + */ +export function applyReducer(document, operation, index) { + var operationResult = applyOperation(document, operation); + if (operationResult.test === false) { // failed test + throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return operationResult.newDocument; +} +/** + * Validates a single operation. Called from `jsonpatch.validate`. Throws `JsonPatchError` in case of an error. + * @param {object} operation - operation object (patch) + * @param {number} index - index of operation in the sequence + * @param {object} [document] - object where the operation is supposed to be applied + * @param {string} [existingPathFragment] - comes along with `document` + */ +export function validator(operation, index, document, existingPathFragment) { + if (typeof operation !== 'object' || operation === null || Array.isArray(operation)) { + throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document); + } + else if (!objOps[operation.op]) { + throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); + } + else if (typeof operation.path !== 'string') { + throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document); + } + else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) { + // paths that aren't empty string should start with "/" + throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document); + } + else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') { + throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document); + } + else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) { + throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document); + } + else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && hasUndefined(operation.value)) { + throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document); + } + else if (document) { + if (operation.op == "add") { + var pathLen = operation.path.split("/").length; + var existingPathLen = existingPathFragment.split("/").length; + if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) { + throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document); + } + } + else if (operation.op === 'replace' || operation.op === 'remove' || operation.op === '_get') { + if (operation.path !== existingPathFragment) { + throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document); + } + } + else if (operation.op === 'move' || operation.op === 'copy') { + var existingValue = { op: "_get", path: operation.from, value: undefined }; + var error = validate([existingValue], document); + if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') { + throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document); + } + } + } +} +/** + * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. + * If error is encountered, returns a JsonPatchError object + * @param sequence + * @param document + * @returns {JsonPatchError|undefined} + */ +export function validate(sequence, document, externalValidator) { + try { + if (!Array.isArray(sequence)) { + throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); + } + if (document) { + //clone document and sequence so that we can safely try applying operations + applyPatch(_deepClone(document), _deepClone(sequence), externalValidator || true); + } + else { + externalValidator = externalValidator || validator; + for (var i = 0; i < sequence.length; i++) { + externalValidator(sequence[i], i, document, undefined); + } + } + } + catch (e) { + if (e instanceof JsonPatchError) { + return e; + } + else { + throw e; + } + } +} diff --git a/module/duplex.js b/module/duplex.js new file mode 100644 index 00000000..101b0d47 --- /dev/null +++ b/module/duplex.js @@ -0,0 +1,180 @@ +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers'; +import { applyPatch } from './core'; +/* export all core functions and types */ +export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator } from './core'; +/* export some helpers */ +export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers'; +var beforeDict = new WeakMap(); +var Mirror = /** @class */ (function () { + function Mirror(obj) { + this.observers = new Map(); + this.obj = obj; + } + return Mirror; +}()); +var ObserverInfo = /** @class */ (function () { + function ObserverInfo(callback, observer) { + this.callback = callback; + this.observer = observer; + } + return ObserverInfo; +}()); +function getMirror(obj) { + return beforeDict.get(obj); +} +function getObserverFromMirror(mirror, callback) { + return mirror.observers.get(callback); +} +function removeObserverFromMirror(mirror, observer) { + mirror.observers.delete(observer.callback); +} +/** + * Detach an observer from an object + */ +export function unobserve(root, observer) { + observer.unobserve(); +} +/** + * Observes changes made to an object, which can then be retrieved using generate + */ +export function observe(obj, callback) { + var patches = []; + var observer; + var mirror = getMirror(obj); + if (!mirror) { + mirror = new Mirror(obj); + beforeDict.set(obj, mirror); + } + else { + var observerInfo = getObserverFromMirror(mirror, callback); + observer = observerInfo && observerInfo.observer; + } + if (observer) { + return observer; + } + observer = {}; + mirror.value = _deepClone(obj); + if (callback) { + observer.callback = callback; + observer.next = null; + var dirtyCheck = function () { + generate(observer); + }; + var fastCheck = function () { + clearTimeout(observer.next); + observer.next = setTimeout(dirtyCheck); + }; + if (typeof window !== 'undefined') { //not Node + window.addEventListener('mouseup', fastCheck); + window.addEventListener('keyup', fastCheck); + window.addEventListener('mousedown', fastCheck); + window.addEventListener('keydown', fastCheck); + window.addEventListener('change', fastCheck); + } + } + observer.patches = patches; + observer.object = obj; + observer.unobserve = function () { + generate(observer); + clearTimeout(observer.next); + removeObserverFromMirror(mirror, observer); + if (typeof window !== 'undefined') { + window.removeEventListener('mouseup', fastCheck); + window.removeEventListener('keyup', fastCheck); + window.removeEventListener('mousedown', fastCheck); + window.removeEventListener('keydown', fastCheck); + window.removeEventListener('change', fastCheck); + } + }; + mirror.observers.set(callback, new ObserverInfo(callback, observer)); + return observer; +} +/** + * Generate an array of patches from an observer + */ +export function generate(observer, invertible) { + if (invertible === void 0) { invertible = false; } + var mirror = beforeDict.get(observer.object); + _generate(mirror.value, observer.object, observer.patches, "", invertible); + if (observer.patches.length) { + applyPatch(mirror.value, observer.patches); + } + var temp = observer.patches; + if (temp.length > 0) { + observer.patches = []; + if (observer.callback) { + observer.callback(temp); + } + } + return temp; +} +// Dirty check if obj is different from mirror, generate patches and update mirror +function _generate(mirror, obj, patches, path, invertible) { + if (obj === mirror) { + return; + } + if (typeof obj.toJSON === "function") { + obj = obj.toJSON(); + } + var newKeys = _objectKeys(obj); + var oldKeys = _objectKeys(mirror); + var changed = false; + var deleted = false; + //if ever "move" operation is implemented here, make sure this test runs OK: "should not generate the same patch twice (move)" + for (var t = oldKeys.length - 1; t >= 0; t--) { + var key = oldKeys[t]; + var oldVal = mirror[key]; + if (hasOwnProperty(obj, key) && !(obj[key] === undefined && oldVal !== undefined && Array.isArray(obj) === false)) { + var newVal = obj[key]; + if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) { + _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key), invertible); + } + else { + if (oldVal !== newVal) { + changed = true; + if (invertible) { + patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) }); + } + patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: _deepClone(newVal) }); + } + } + } + else if (Array.isArray(mirror) === Array.isArray(obj)) { + if (invertible) { + patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) }); + } + patches.push({ op: "remove", path: path + "/" + escapePathComponent(key) }); + deleted = true; // property has been deleted + } + else { + if (invertible) { + patches.push({ op: "test", path: path, value: mirror }); + } + patches.push({ op: "replace", path: path, value: obj }); + changed = true; + } + } + if (!deleted && newKeys.length == oldKeys.length) { + return; + } + for (var t = 0; t < newKeys.length; t++) { + var key = newKeys[t]; + if (!hasOwnProperty(mirror, key) && obj[key] !== undefined) { + patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: _deepClone(obj[key]) }); + } + } +} +/** + * Create an array of patches from the differences in two objects + */ +export function compare(tree1, tree2, invertible) { + if (invertible === void 0) { invertible = false; } + var patches = []; + _generate(tree1, tree2, patches, '', invertible); + return patches; +} diff --git a/module/helpers.js b/module/helpers.js new file mode 100644 index 00000000..10844fe8 --- /dev/null +++ b/module/helpers.js @@ -0,0 +1,171 @@ +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var _hasOwnProperty = Object.prototype.hasOwnProperty; +export function hasOwnProperty(obj, key) { + return _hasOwnProperty.call(obj, key); +} +export function _objectKeys(obj) { + if (Array.isArray(obj)) { + var keys = new Array(obj.length); + for (var k = 0; k < keys.length; k++) { + keys[k] = "" + k; + } + return keys; + } + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var i in obj) { + if (hasOwnProperty(obj, i)) { + keys.push(i); + } + } + return keys; +} +; +/** +* Deeply clone the object. +* https://jsperf.com/deep-copy-vs-json-stringify-json-parse/25 (recursiveDeepCopy) +* @param {any} obj value to clone +* @return {any} cloned obj +*/ +export function _deepClone(obj) { + switch (typeof obj) { + case "object": + return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5 + case "undefined": + return null; //this is how JSON.stringify behaves for array items + default: + return obj; //no need to clone primitives + } +} +//3x faster than cached /^\d+$/.test(str) +export function isInteger(str) { + var i = 0; + var len = str.length; + var charCode; + while (i < len) { + charCode = str.charCodeAt(i); + if (charCode >= 48 && charCode <= 57) { + i++; + continue; + } + return false; + } + return true; +} +/** +* Escapes a json pointer path +* @param path The raw pointer +* @return the Escaped path +*/ +export function escapePathComponent(path) { + if (path.indexOf('/') === -1 && path.indexOf('~') === -1) + return path; + return path.replace(/~/g, '~0').replace(/\//g, '~1'); +} +/** + * Unescapes a json pointer path + * @param path The escaped pointer + * @return The unescaped path + */ +export function unescapePathComponent(path) { + return path.replace(/~1/g, '/').replace(/~0/g, '~'); +} +export function _getPathRecursive(root, obj) { + var found; + for (var key in root) { + if (hasOwnProperty(root, key)) { + if (root[key] === obj) { + return escapePathComponent(key) + '/'; + } + else if (typeof root[key] === 'object') { + found = _getPathRecursive(root[key], obj); + if (found != '') { + return escapePathComponent(key) + '/' + found; + } + } + } + } + return ''; +} +export function getPath(root, obj) { + if (root === obj) { + return '/'; + } + var path = _getPathRecursive(root, obj); + if (path === '') { + throw new Error("Object not found in root"); + } + return '/' + path; +} +/** +* Recursively checks whether an object has any undefined values inside. +*/ +export function hasUndefined(obj) { + if (obj === undefined) { + return true; + } + if (obj) { + if (Array.isArray(obj)) { + for (var i = 0, len = obj.length; i < len; i++) { + if (hasUndefined(obj[i])) { + return true; + } + } + } + else if (typeof obj === "object") { + var objKeys = _objectKeys(obj); + var objKeysLength = objKeys.length; + for (var i = 0; i < objKeysLength; i++) { + if (hasUndefined(obj[objKeys[i]])) { + return true; + } + } + } + } + return false; +} +function patchErrorMessageFormatter(message, args) { + var messageParts = [message]; + for (var key in args) { + var value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print + if (typeof value !== 'undefined') { + messageParts.push(key + ": " + value); + } + } + return messageParts.join('\n'); +} +var PatchError = /** @class */ (function (_super) { + __extends(PatchError, _super); + function PatchError(message, name, index, operation, tree) { + var _newTarget = this.constructor; + var _this = _super.call(this, patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree })) || this; + _this.name = name; + _this.index = index; + _this.operation = operation; + _this.tree = tree; + Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 + _this.message = patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree }); + return _this; + } + return PatchError; +}(Error)); +export { PatchError }; diff --git a/package.json b/package.json index 23335243..ca63a8fb 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "license": "MIT", "main": "lib/duplex.js", + "module": "module/duplex.js", "typings": "lib/duplex.d.ts", "engines": { "node": ">= 0.4.0" @@ -47,7 +48,9 @@ "webpack-cli": "^3.3.5" }, "scripts": { - "tsc": "tsc", + "tsc": "npm run tsc-common && npm run tsc-module", + "tsc-common": "tsc", + "tsc-module": "tsc --module ES6 --moduleResolution node --outDir \"module/\"", "version": "tsc && webpack && git add -A", "build": "tsc && webpack", "serve": "http-server -p 5000 --silent", diff --git a/src/core.ts b/src/core.ts index 5515f5dd..9dda3d3d 100644 --- a/src/core.ts +++ b/src/core.ts @@ -5,7 +5,7 @@ */ declare var require: any; -const areEquals = require('fast-deep-equal'); +import * as areEquals from 'fast-deep-equal'; import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers'; export const JsonPatchError = PatchError; From c28821f290f5472c62b4f73a12e95519815a1d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Wed, 31 Jul 2019 16:43:28 +0200 Subject: [PATCH 02/31] Use extensions in imports, so they could be handled by ES6 modules --- module/core.js | 2 +- module/duplex.js | 8 ++++---- src/core.ts | 2 +- src/duplex.ts | 8 ++++---- src/helpers.ts | 2 -- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/module/core.js b/module/core.js index d079e802..f0535e18 100644 --- a/module/core.js +++ b/module/core.js @@ -1,5 +1,5 @@ import * as areEquals from 'fast-deep-equal'; -import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers'; +import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers.js'; export var JsonPatchError = PatchError; export var deepClone = _deepClone; /* We use a Javascript hash to store each diff --git a/module/duplex.js b/module/duplex.js index 101b0d47..23694440 100644 --- a/module/duplex.js +++ b/module/duplex.js @@ -3,12 +3,12 @@ * (c) 2017 Joachim Wester * MIT license */ -import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers'; -import { applyPatch } from './core'; +import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers.js'; +import { applyPatch } from './core.js'; /* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator } from './core'; +export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator } from './core.js'; /* export some helpers */ -export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers'; +export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.js'; var beforeDict = new WeakMap(); var Mirror = /** @class */ (function () { function Mirror(obj) { diff --git a/src/core.ts b/src/core.ts index 9dda3d3d..918e8178 100644 --- a/src/core.ts +++ b/src/core.ts @@ -6,7 +6,7 @@ declare var require: any; import * as areEquals from 'fast-deep-equal'; -import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers'; +import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers.js'; export const JsonPatchError = PatchError; export const deepClone = _deepClone; diff --git a/src/duplex.ts b/src/duplex.ts index d151ba0a..c3624755 100644 --- a/src/duplex.ts +++ b/src/duplex.ts @@ -3,14 +3,14 @@ * (c) 2017 Joachim Wester * MIT license */ -import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers'; -import { applyPatch, Operation } from './core'; +import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers.js'; +import { applyPatch, Operation } from './core.js'; /* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, Operation, AddOperation, RemoveOperation, ReplaceOperation, MoveOperation, CopyOperation, TestOperation, GetOperation, validate, validator, OperationResult } from './core'; +export { applyOperation, applyPatch, applyReducer, getValueByPointer, Operation, AddOperation, RemoveOperation, ReplaceOperation, MoveOperation, CopyOperation, TestOperation, GetOperation, validate, validator, OperationResult } from './core.js'; /* export some helpers */ -export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers'; +export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.js'; export interface Observer { object: T; diff --git a/src/helpers.ts b/src/helpers.ts index b7fe6b07..fad6242a 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -4,8 +4,6 @@ * MIT license */ -import { Operation } from "./core"; - const _hasOwnProperty = Object.prototype.hasOwnProperty; export function hasOwnProperty(obj, key) { return _hasOwnProperty.call(obj, key); From b4b9de77d09e732f154c1784377bd9394ce99996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Wed, 31 Jul 2019 16:57:15 +0200 Subject: [PATCH 03/31] Add compiled lib files to the repo, to make the flow with `npm link` and `npm install` from github work seamlessly --- .gitignore | 4 - lib/core.js | 383 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/duplex.js | 195 +++++++++++++++++++++++++ lib/helpers.js | 181 +++++++++++++++++++++++ 4 files changed, 759 insertions(+), 4 deletions(-) create mode 100644 lib/core.js create mode 100644 lib/duplex.js create mode 100644 lib/helpers.js diff --git a/.gitignore b/.gitignore index 87aa911f..259a81af 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,5 @@ npm-debug.log # Typescript *.d.ts -# compiled files -src/*.js -lib/* - # SauceLabs logs *.log \ No newline at end of file diff --git a/lib/core.js b/lib/core.js new file mode 100644 index 00000000..f6814b4a --- /dev/null +++ b/lib/core.js @@ -0,0 +1,383 @@ +Object.defineProperty(exports, "__esModule", { value: true }); +var areEquals = require("fast-deep-equal"); +var helpers_js_1 = require("./helpers.js"); +exports.JsonPatchError = helpers_js_1.PatchError; +exports.deepClone = helpers_js_1._deepClone; +/* We use a Javascript hash to store each + function. Each hash entry (property) uses + the operation identifiers specified in rfc6902. + In this way, we can map each patch operation + to its dedicated function in efficient way. + */ +/* The operations applicable to an object */ +var objOps = { + add: function (obj, key, document) { + obj[key] = this.value; + return { newDocument: document }; + }, + remove: function (obj, key, document) { + var removed = obj[key]; + delete obj[key]; + return { newDocument: document, removed: removed }; + }, + replace: function (obj, key, document) { + var removed = obj[key]; + obj[key] = this.value; + return { newDocument: document, removed: removed }; + }, + move: function (obj, key, document) { + /* in case move target overwrites an existing value, + return the removed value, this can be taxing performance-wise, + and is potentially unneeded */ + var removed = getValueByPointer(document, this.path); + if (removed) { + removed = helpers_js_1._deepClone(removed); + } + var originalValue = applyOperation(document, { op: "remove", path: this.from }).removed; + applyOperation(document, { op: "add", path: this.path, value: originalValue }); + return { newDocument: document, removed: removed }; + }, + copy: function (obj, key, document) { + var valueToCopy = getValueByPointer(document, this.from); + // enforce copy by value so further operations don't affect source (see issue #177) + applyOperation(document, { op: "add", path: this.path, value: helpers_js_1._deepClone(valueToCopy) }); + return { newDocument: document }; + }, + test: function (obj, key, document) { + return { newDocument: document, test: areEquals(obj[key], this.value) }; + }, + _get: function (obj, key, document) { + this.value = obj[key]; + return { newDocument: document }; + } +}; +/* The operations applicable to an array. Many are the same as for the object */ +var arrOps = { + add: function (arr, i, document) { + if (helpers_js_1.isInteger(i)) { + arr.splice(i, 0, this.value); + } + else { // array props + arr[i] = this.value; + } + // this may be needed when using '-' in an array + return { newDocument: document, index: i }; + }, + remove: function (arr, i, document) { + var removedList = arr.splice(i, 1); + return { newDocument: document, removed: removedList[0] }; + }, + replace: function (arr, i, document) { + var removed = arr[i]; + arr[i] = this.value; + return { newDocument: document, removed: removed }; + }, + move: objOps.move, + copy: objOps.copy, + test: objOps.test, + _get: objOps._get +}; +/** + * Retrieves a value from a JSON document by a JSON pointer. + * Returns the value. + * + * @param document The document to get the value from + * @param pointer an escaped JSON pointer + * @return The retrieved value + */ +function getValueByPointer(document, pointer) { + if (pointer == '') { + return document; + } + var getOriginalDestination = { op: "_get", path: pointer }; + applyOperation(document, getOriginalDestination); + return getOriginalDestination.value; +} +exports.getValueByPointer = getValueByPointer; +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the {newDocument, result} of the operation. + * It modifies the `document` and `operation` objects - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyOperation(document, jsonpatch._deepClone(operation))`. + * + * @param document The document to patch + * @param operation The operation to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return `{newDocument, result}` after the operation + */ +function applyOperation(document, operation, validateOperation, mutateDocument, banPrototypeModifications, index) { + if (validateOperation === void 0) { validateOperation = false; } + if (mutateDocument === void 0) { mutateDocument = true; } + if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } + if (index === void 0) { index = 0; } + if (validateOperation) { + if (typeof validateOperation == 'function') { + validateOperation(operation, 0, document, operation.path); + } + else { + validator(operation, 0); + } + } + /* ROOT OPERATIONS */ + if (operation.path === "") { + var returnValue = { newDocument: document }; + if (operation.op === 'add') { + returnValue.newDocument = operation.value; + return returnValue; + } + else if (operation.op === 'replace') { + returnValue.newDocument = operation.value; + returnValue.removed = document; //document we removed + return returnValue; + } + else if (operation.op === 'move' || operation.op === 'copy') { // it's a move or copy to root + returnValue.newDocument = getValueByPointer(document, operation.from); // get the value by json-pointer in `from` field + if (operation.op === 'move') { // report removed item + returnValue.removed = document; + } + return returnValue; + } + else if (operation.op === 'test') { + returnValue.test = areEquals(document, operation.value); + if (returnValue.test === false) { + throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + returnValue.newDocument = document; + return returnValue; + } + else if (operation.op === 'remove') { // a remove on root + returnValue.removed = document; + returnValue.newDocument = null; + return returnValue; + } + else if (operation.op === '_get') { + operation.value = document; + return returnValue; + } + else { /* bad operation */ + if (validateOperation) { + throw new exports.JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); + } + else { + return returnValue; + } + } + } /* END ROOT OPERATIONS */ + else { + if (!mutateDocument) { + document = helpers_js_1._deepClone(document); + } + var path = operation.path || ""; + var keys = path.split('/'); + var obj = document; + var t = 1; //skip empty element - http://jsperf.com/to-shift-or-not-to-shift + var len = keys.length; + var existingPathFragment = undefined; + var key = void 0; + var validateFunction = void 0; + if (typeof validateOperation == 'function') { + validateFunction = validateOperation; + } + else { + validateFunction = validator; + } + while (true) { + key = keys[t]; + if (banPrototypeModifications && key == '__proto__') { + throw new TypeError('JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README'); + } + if (validateOperation) { + if (existingPathFragment === undefined) { + if (obj[key] === undefined) { + existingPathFragment = keys.slice(0, t).join('/'); + } + else if (t == len - 1) { + existingPathFragment = operation.path; + } + if (existingPathFragment !== undefined) { + validateFunction(operation, 0, document, existingPathFragment); + } + } + } + t++; + if (Array.isArray(obj)) { + if (key === '-') { + key = obj.length; + } + else { + if (validateOperation && !helpers_js_1.isInteger(key)) { + throw new exports.JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", index, operation, document); + } // only parse key when it's an integer for `arr.prop` to work + else if (helpers_js_1.isInteger(key)) { + key = ~~key; + } + } + if (t >= len) { + if (validateOperation && operation.op === "add" && key > obj.length) { + throw new exports.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document); + } + var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch + if (returnValue.test === false) { + throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return returnValue; + } + } + else { + if (key && key.indexOf('~') != -1) { + key = helpers_js_1.unescapePathComponent(key); + } + if (t >= len) { + var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch + if (returnValue.test === false) { + throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return returnValue; + } + } + obj = obj[key]; + } + } +} +exports.applyOperation = applyOperation; +/** + * Apply a full JSON Patch array on a JSON document. + * Returns the {newDocument, result} of the patch. + * It modifies the `document` object and `patch` - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyPatch(document, jsonpatch._deepClone(patch))`. + * + * @param document The document to patch + * @param patch The patch to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return An array of `{newDocument, result}` after the patch + */ +function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) { + if (mutateDocument === void 0) { mutateDocument = true; } + if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } + if (validateOperation) { + if (!Array.isArray(patch)) { + throw new exports.JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); + } + } + if (!mutateDocument) { + document = helpers_js_1._deepClone(document); + } + var results = new Array(patch.length); + for (var i = 0, length_1 = patch.length; i < length_1; i++) { + // we don't need to pass mutateDocument argument because if it was true, we already deep cloned the object, we'll just pass `true` + results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i); + document = results[i].newDocument; // in case root was replaced + } + results.newDocument = document; + return results; +} +exports.applyPatch = applyPatch; +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the updated document. + * Suitable as a reducer. + * + * @param document The document to patch + * @param operation The operation to apply + * @return The updated document + */ +function applyReducer(document, operation, index) { + var operationResult = applyOperation(document, operation); + if (operationResult.test === false) { // failed test + throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); + } + return operationResult.newDocument; +} +exports.applyReducer = applyReducer; +/** + * Validates a single operation. Called from `jsonpatch.validate`. Throws `JsonPatchError` in case of an error. + * @param {object} operation - operation object (patch) + * @param {number} index - index of operation in the sequence + * @param {object} [document] - object where the operation is supposed to be applied + * @param {string} [existingPathFragment] - comes along with `document` + */ +function validator(operation, index, document, existingPathFragment) { + if (typeof operation !== 'object' || operation === null || Array.isArray(operation)) { + throw new exports.JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document); + } + else if (!objOps[operation.op]) { + throw new exports.JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); + } + else if (typeof operation.path !== 'string') { + throw new exports.JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document); + } + else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) { + // paths that aren't empty string should start with "/" + throw new exports.JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document); + } + else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') { + throw new exports.JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document); + } + else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) { + throw new exports.JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document); + } + else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && helpers_js_1.hasUndefined(operation.value)) { + throw new exports.JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document); + } + else if (document) { + if (operation.op == "add") { + var pathLen = operation.path.split("/").length; + var existingPathLen = existingPathFragment.split("/").length; + if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) { + throw new exports.JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document); + } + } + else if (operation.op === 'replace' || operation.op === 'remove' || operation.op === '_get') { + if (operation.path !== existingPathFragment) { + throw new exports.JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document); + } + } + else if (operation.op === 'move' || operation.op === 'copy') { + var existingValue = { op: "_get", path: operation.from, value: undefined }; + var error = validate([existingValue], document); + if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') { + throw new exports.JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document); + } + } + } +} +exports.validator = validator; +/** + * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. + * If error is encountered, returns a JsonPatchError object + * @param sequence + * @param document + * @returns {JsonPatchError|undefined} + */ +function validate(sequence, document, externalValidator) { + try { + if (!Array.isArray(sequence)) { + throw new exports.JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); + } + if (document) { + //clone document and sequence so that we can safely try applying operations + applyPatch(helpers_js_1._deepClone(document), helpers_js_1._deepClone(sequence), externalValidator || true); + } + else { + externalValidator = externalValidator || validator; + for (var i = 0; i < sequence.length; i++) { + externalValidator(sequence[i], i, document, undefined); + } + } + } + catch (e) { + if (e instanceof exports.JsonPatchError) { + return e; + } + else { + throw e; + } + } +} +exports.validate = validate; diff --git a/lib/duplex.js b/lib/duplex.js new file mode 100644 index 00000000..f23e703b --- /dev/null +++ b/lib/duplex.js @@ -0,0 +1,195 @@ +Object.defineProperty(exports, "__esModule", { value: true }); +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +var helpers_js_1 = require("./helpers.js"); +var core_js_1 = require("./core.js"); +/* export all core functions and types */ +var core_js_2 = require("./core.js"); +exports.applyOperation = core_js_2.applyOperation; +exports.applyPatch = core_js_2.applyPatch; +exports.applyReducer = core_js_2.applyReducer; +exports.getValueByPointer = core_js_2.getValueByPointer; +exports.validate = core_js_2.validate; +exports.validator = core_js_2.validator; +/* export some helpers */ +var helpers_js_2 = require("./helpers.js"); +exports.JsonPatchError = helpers_js_2.PatchError; +exports.deepClone = helpers_js_2._deepClone; +exports.escapePathComponent = helpers_js_2.escapePathComponent; +exports.unescapePathComponent = helpers_js_2.unescapePathComponent; +var beforeDict = new WeakMap(); +var Mirror = /** @class */ (function () { + function Mirror(obj) { + this.observers = new Map(); + this.obj = obj; + } + return Mirror; +}()); +var ObserverInfo = /** @class */ (function () { + function ObserverInfo(callback, observer) { + this.callback = callback; + this.observer = observer; + } + return ObserverInfo; +}()); +function getMirror(obj) { + return beforeDict.get(obj); +} +function getObserverFromMirror(mirror, callback) { + return mirror.observers.get(callback); +} +function removeObserverFromMirror(mirror, observer) { + mirror.observers.delete(observer.callback); +} +/** + * Detach an observer from an object + */ +function unobserve(root, observer) { + observer.unobserve(); +} +exports.unobserve = unobserve; +/** + * Observes changes made to an object, which can then be retrieved using generate + */ +function observe(obj, callback) { + var patches = []; + var observer; + var mirror = getMirror(obj); + if (!mirror) { + mirror = new Mirror(obj); + beforeDict.set(obj, mirror); + } + else { + var observerInfo = getObserverFromMirror(mirror, callback); + observer = observerInfo && observerInfo.observer; + } + if (observer) { + return observer; + } + observer = {}; + mirror.value = helpers_js_1._deepClone(obj); + if (callback) { + observer.callback = callback; + observer.next = null; + var dirtyCheck = function () { + generate(observer); + }; + var fastCheck = function () { + clearTimeout(observer.next); + observer.next = setTimeout(dirtyCheck); + }; + if (typeof window !== 'undefined') { //not Node + window.addEventListener('mouseup', fastCheck); + window.addEventListener('keyup', fastCheck); + window.addEventListener('mousedown', fastCheck); + window.addEventListener('keydown', fastCheck); + window.addEventListener('change', fastCheck); + } + } + observer.patches = patches; + observer.object = obj; + observer.unobserve = function () { + generate(observer); + clearTimeout(observer.next); + removeObserverFromMirror(mirror, observer); + if (typeof window !== 'undefined') { + window.removeEventListener('mouseup', fastCheck); + window.removeEventListener('keyup', fastCheck); + window.removeEventListener('mousedown', fastCheck); + window.removeEventListener('keydown', fastCheck); + window.removeEventListener('change', fastCheck); + } + }; + mirror.observers.set(callback, new ObserverInfo(callback, observer)); + return observer; +} +exports.observe = observe; +/** + * Generate an array of patches from an observer + */ +function generate(observer, invertible) { + if (invertible === void 0) { invertible = false; } + var mirror = beforeDict.get(observer.object); + _generate(mirror.value, observer.object, observer.patches, "", invertible); + if (observer.patches.length) { + core_js_1.applyPatch(mirror.value, observer.patches); + } + var temp = observer.patches; + if (temp.length > 0) { + observer.patches = []; + if (observer.callback) { + observer.callback(temp); + } + } + return temp; +} +exports.generate = generate; +// Dirty check if obj is different from mirror, generate patches and update mirror +function _generate(mirror, obj, patches, path, invertible) { + if (obj === mirror) { + return; + } + if (typeof obj.toJSON === "function") { + obj = obj.toJSON(); + } + var newKeys = helpers_js_1._objectKeys(obj); + var oldKeys = helpers_js_1._objectKeys(mirror); + var changed = false; + var deleted = false; + //if ever "move" operation is implemented here, make sure this test runs OK: "should not generate the same patch twice (move)" + for (var t = oldKeys.length - 1; t >= 0; t--) { + var key = oldKeys[t]; + var oldVal = mirror[key]; + if (helpers_js_1.hasOwnProperty(obj, key) && !(obj[key] === undefined && oldVal !== undefined && Array.isArray(obj) === false)) { + var newVal = obj[key]; + if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) { + _generate(oldVal, newVal, patches, path + "/" + helpers_js_1.escapePathComponent(key), invertible); + } + else { + if (oldVal !== newVal) { + changed = true; + if (invertible) { + patches.push({ op: "test", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(oldVal) }); + } + patches.push({ op: "replace", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(newVal) }); + } + } + } + else if (Array.isArray(mirror) === Array.isArray(obj)) { + if (invertible) { + patches.push({ op: "test", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(oldVal) }); + } + patches.push({ op: "remove", path: path + "/" + helpers_js_1.escapePathComponent(key) }); + deleted = true; // property has been deleted + } + else { + if (invertible) { + patches.push({ op: "test", path: path, value: mirror }); + } + patches.push({ op: "replace", path: path, value: obj }); + changed = true; + } + } + if (!deleted && newKeys.length == oldKeys.length) { + return; + } + for (var t = 0; t < newKeys.length; t++) { + var key = newKeys[t]; + if (!helpers_js_1.hasOwnProperty(mirror, key) && obj[key] !== undefined) { + patches.push({ op: "add", path: path + "/" + helpers_js_1.escapePathComponent(key), value: helpers_js_1._deepClone(obj[key]) }); + } + } +} +/** + * Create an array of patches from the differences in two objects + */ +function compare(tree1, tree2, invertible) { + if (invertible === void 0) { invertible = false; } + var patches = []; + _generate(tree1, tree2, patches, '', invertible); + return patches; +} +exports.compare = compare; diff --git a/lib/helpers.js b/lib/helpers.js new file mode 100644 index 00000000..0ac28b4d --- /dev/null +++ b/lib/helpers.js @@ -0,0 +1,181 @@ +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var _hasOwnProperty = Object.prototype.hasOwnProperty; +function hasOwnProperty(obj, key) { + return _hasOwnProperty.call(obj, key); +} +exports.hasOwnProperty = hasOwnProperty; +function _objectKeys(obj) { + if (Array.isArray(obj)) { + var keys = new Array(obj.length); + for (var k = 0; k < keys.length; k++) { + keys[k] = "" + k; + } + return keys; + } + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var i in obj) { + if (hasOwnProperty(obj, i)) { + keys.push(i); + } + } + return keys; +} +exports._objectKeys = _objectKeys; +; +/** +* Deeply clone the object. +* https://jsperf.com/deep-copy-vs-json-stringify-json-parse/25 (recursiveDeepCopy) +* @param {any} obj value to clone +* @return {any} cloned obj +*/ +function _deepClone(obj) { + switch (typeof obj) { + case "object": + return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5 + case "undefined": + return null; //this is how JSON.stringify behaves for array items + default: + return obj; //no need to clone primitives + } +} +exports._deepClone = _deepClone; +//3x faster than cached /^\d+$/.test(str) +function isInteger(str) { + var i = 0; + var len = str.length; + var charCode; + while (i < len) { + charCode = str.charCodeAt(i); + if (charCode >= 48 && charCode <= 57) { + i++; + continue; + } + return false; + } + return true; +} +exports.isInteger = isInteger; +/** +* Escapes a json pointer path +* @param path The raw pointer +* @return the Escaped path +*/ +function escapePathComponent(path) { + if (path.indexOf('/') === -1 && path.indexOf('~') === -1) + return path; + return path.replace(/~/g, '~0').replace(/\//g, '~1'); +} +exports.escapePathComponent = escapePathComponent; +/** + * Unescapes a json pointer path + * @param path The escaped pointer + * @return The unescaped path + */ +function unescapePathComponent(path) { + return path.replace(/~1/g, '/').replace(/~0/g, '~'); +} +exports.unescapePathComponent = unescapePathComponent; +function _getPathRecursive(root, obj) { + var found; + for (var key in root) { + if (hasOwnProperty(root, key)) { + if (root[key] === obj) { + return escapePathComponent(key) + '/'; + } + else if (typeof root[key] === 'object') { + found = _getPathRecursive(root[key], obj); + if (found != '') { + return escapePathComponent(key) + '/' + found; + } + } + } + } + return ''; +} +exports._getPathRecursive = _getPathRecursive; +function getPath(root, obj) { + if (root === obj) { + return '/'; + } + var path = _getPathRecursive(root, obj); + if (path === '') { + throw new Error("Object not found in root"); + } + return '/' + path; +} +exports.getPath = getPath; +/** +* Recursively checks whether an object has any undefined values inside. +*/ +function hasUndefined(obj) { + if (obj === undefined) { + return true; + } + if (obj) { + if (Array.isArray(obj)) { + for (var i = 0, len = obj.length; i < len; i++) { + if (hasUndefined(obj[i])) { + return true; + } + } + } + else if (typeof obj === "object") { + var objKeys = _objectKeys(obj); + var objKeysLength = objKeys.length; + for (var i = 0; i < objKeysLength; i++) { + if (hasUndefined(obj[objKeys[i]])) { + return true; + } + } + } + } + return false; +} +exports.hasUndefined = hasUndefined; +function patchErrorMessageFormatter(message, args) { + var messageParts = [message]; + for (var key in args) { + var value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print + if (typeof value !== 'undefined') { + messageParts.push(key + ": " + value); + } + } + return messageParts.join('\n'); +} +var PatchError = /** @class */ (function (_super) { + __extends(PatchError, _super); + function PatchError(message, name, index, operation, tree) { + var _newTarget = this.constructor; + var _this = _super.call(this, patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree })) || this; + _this.name = name; + _this.index = index; + _this.operation = operation; + _this.tree = tree; + Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 + _this.message = patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree }); + return _this; + } + return PatchError; +}(Error)); +exports.PatchError = PatchError; From fa4911a79c320e26c91702314262dd7592faabb8 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 1 Aug 2019 12:03:28 +0200 Subject: [PATCH 04/31] include "deep-fast-equal" directly in core because "deep-fast-equal" exposes a CommonJS default export, which cannot be resolved when loading ``` -You can also require all API functions individually, all jsonpatch functions can be used as pure functions: - -```js -const { applyOperation } = require('fast-json-patch'); -``` - -## Usage - -#### Applying patches: - -```js -var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; -var patch = [ - { op: "replace", path: "/firstName", value: "Joachim" }, - { op: "add", path: "/lastName", value: "Wester" }, - { op: "add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } -]; -document = jsonpatch.applyPatch(document, patch).newDocument; -// document == { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [{number:"555-123"}] } }; -``` - -##### For apply individual operations you can use `applyOperation` - -`jsonpatch.applyOperation` accepts a single operation object instead of a sequence, and returns the object after applying the operation. It works with all the standard JSON patch operations (`add, replace, move, test, remove and copy`). - -```js -var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; -var operation = { op: "replace", path: "/firstName", value: "Joachim" }; -document = jsonpatch.applyOperation(document, operation).newDocument; -// document == { firstName: "Joachim", contactDetails: { phoneNumbers: [] }} -``` - -#### Using `applyReducer` with `reduce` - -If you have an array of operations, you can simple reduce them using `applyReducer` as your reducer: - -```js -var document = { firstName: "Albert", contactDetails: { phoneNumbers: [ ] } }; -var patch = [ - { op:"replace", path: "/firstName", value: "Joachim" }, - { op:"add", path: "/lastName", value: "Wester" }, - { op:"add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } -]; -var updatedDocument = patch.reduce(applyReducer, document); -// updatedDocument == { firstName:"Joachim", lastName:"Wester", contactDetails:{ phoneNumbers[ {number:"555-123"} ] } }; -``` +### In Node.js -Generating patches: +Call require to get the instance: ```js -var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; -var observer = jsonpatch.observe(document); -document.firstName = "Albert"; -document.contactDetails.phoneNumbers[0].number = "123"; -document.contactDetails.phoneNumbers.push({ number:"456" }); -var patch = jsonpatch.generate(observer); -// patch == [ -// { op: "replace", path: "/firstName", value: "Albert"}, -// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" }, -// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}} -// ]; +var jsonpatch = require('fast-json-patch/lib'); +// or, get just a single function: +const { applyOperation } = require('fast-json-patch/lib'); +const applyOperation = require('fast-json-patch/lib').applyOperation; ``` -Generating patches with test operations for values in the first object: +Or use the CommonJS export in ES6 style (Works with Webpack, Babel): ```js -var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; -var observer = jsonpatch.observe(document); -document.firstName = "Albert"; -document.contactDetails.phoneNumbers[0].number = "123"; -document.contactDetails.phoneNumbers.push({ number:"456" }); -var patch = jsonpatch.generate(observer, true); -// patch == [ -// { op: "test", path: "/firstName", value: "Joachim"}, -// { op: "replace", path: "/firstName", value: "Albert"}, -// { op: "test", path: "/contactDetails/phoneNumbers/0/number", value: "555-123" }, -// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" }, -// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}} -// ]; +import { applyOperation } from 'fast-json-patch/lib' ``` -Comparing two object trees: +Or use the ECMAScript module (Works with Webpack, Babel, and in Node 12+ with `--experimental-modules` flag): ```js -var documentA = {user: {firstName: "Albert", lastName: "Einstein"}}; -var documentB = {user: {firstName: "Albert", lastName: "Collins"}}; -var diff = jsonpatch.compare(documentA, documentB); -//diff == [{op: "replace", path: "/user/lastName", value: "Collins"}] +import { applyOperation } from 'fast-json-patch' ``` -Comparing two object trees with test operations for values in the first object: - -```js -var documentA = {user: {firstName: "Albert", lastName: "Einstein"}}; -var documentB = {user: {firstName: "Albert", lastName: "Collins"}}; -var diff = jsonpatch.compare(documentA, documentB, true); -//diff == [ -// {op: "test", path: "/user/lastName", value: "Einstein"}, -// {op: "replace", path: "/user/lastName", value: "Collins"} -// ]; -``` +## Directories -Validating a sequence of patches: +Directories used in this package: -```js -var obj = {user: {firstName: "Albert"}}; -var patches = [{op: "replace", path: "/user/firstName", value: "Albert"}, {op: "replace", path: "/user/lastName", value: "Einstein"}]; -var errors = jsonpatch.validate(patches, obj); -if (errors.length == 0) { - //there are no errors! -} -else { - for (var i=0; i < errors.length; i++) { - if (!errors[i]) { - console.log("Valid patch at index", i, patches[i]); - } - else { - console.error("Invalid patch at index", i, errors[i], patches[i]); - } - } -} -``` +- `dist/` - contains ES5 files for a Web browser +- `lib/` - contains CommonJS module and typings +- `module/` - contains ECMAScript module and typings +- `src/` - contains TypeScript source files ## API @@ -243,6 +107,19 @@ Returns an array of [`OperationResult`](#operationresult-type) objects - one ite - See [Validation notes](#validation-notes). +Example: + +```js +var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; +var patch = [ + { op: "replace", path: "/firstName", value: "Joachim" }, + { op: "add", path: "/lastName", value: "Wester" }, + { op: "add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } +]; +document = jsonpatch.applyPatch(document, patch).newDocument; +// document == { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [{number:"555-123"}] } }; +``` + #### `function applyOperation(document: T, operation: Operation, validateOperation: boolean | Validator = false, mutateDocument: boolean = true, banPrototypeModifications: boolean = true, index: number = 0): OperationResult` Applies single operation object `operation` on `document`. @@ -264,6 +141,15 @@ Returns an [`OperationResult`](#operationresult-type) object `{newDocument: any, - See [Validation notes](#validation-notes). +Example: + +```js +var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; +var operation = { op: "replace", path: "/firstName", value: "Joachim" }; +document = jsonpatch.applyOperation(document, operation).newDocument; +// document == { firstName: "Joachim", contactDetails: { phoneNumbers: [] }} +``` + #### `jsonpatch.applyReducer(document: T, operation: Operation, index: number): T` **Ideal for `patch.reduce(jsonpatch.applyReducer, document)`**. @@ -274,6 +160,19 @@ Returns the a modified document. Note: It throws `TEST_OPERATION_FAILED` error if `test` operation fails. +Example: + +```js +var document = { firstName: "Albert", contactDetails: { phoneNumbers: [ ] } }; +var patch = [ + { op:"replace", path: "/firstName", value: "Joachim" }, + { op:"add", path: "/lastName", value: "Wester" }, + { op:"add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } +]; +var updatedDocument = patch.reduce(applyReducer, document); +// updatedDocument == { firstName:"Joachim", lastName:"Wester", contactDetails:{ phoneNumbers[ {number:"555-123"} ] } }; +``` + #### `jsonpatch.deepClone(value: any): any` Returns deeply cloned value. @@ -306,6 +205,40 @@ method, it will be triggered synchronously as well. If `invertible` is true, the If there are no pending changes in `obj`, returns an empty array (length 0). +Example: + +```js +var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; +var observer = jsonpatch.observe(document); +document.firstName = "Albert"; +document.contactDetails.phoneNumbers[0].number = "123"; +document.contactDetails.phoneNumbers.push({ number:"456" }); +var patch = jsonpatch.generate(observer); +// patch == [ +// { op: "replace", path: "/firstName", value: "Albert"}, +// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" }, +// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}} +// ]; +``` + +Example of generating patches with test operations for values in the first object: + +```js +var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; +var observer = jsonpatch.observe(document); +document.firstName = "Albert"; +document.contactDetails.phoneNumbers[0].number = "123"; +document.contactDetails.phoneNumbers.push({ number:"456" }); +var patch = jsonpatch.generate(observer, true); +// patch == [ +// { op: "test", path: "/firstName", value: "Joachim"}, +// { op: "replace", path: "/firstName", value: "Albert"}, +// { op: "test", path: "/contactDetails/phoneNumbers/0/number", value: "555-123" }, +// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" }, +// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}} +// ]; +``` + #### `jsonpatch.unobserve(document: any, observer: Observer): void` Destroys the observer set up on `document`. @@ -318,6 +251,27 @@ Compares object trees `document1` and `document2` and returns the difference rel If there are no differences, returns an empty array (length 0). +Example: + +```js +var documentA = {user: {firstName: "Albert", lastName: "Einstein"}}; +var documentB = {user: {firstName: "Albert", lastName: "Collins"}}; +var diff = jsonpatch.compare(documentA, documentB); +//diff == [{op: "replace", path: "/user/lastName", value: "Collins"}] +``` + +Example of comparing two object trees with test operations for values in the first object: + +```js +var documentA = {user: {firstName: "Albert", lastName: "Einstein"}}; +var documentB = {user: {firstName: "Albert", lastName: "Collins"}}; +var diff = jsonpatch.compare(documentA, documentB, true); +//diff == [ +// {op: "test", path: "/user/lastName", value: "Einstein"}, +// {op: "replace", path: "/user/lastName", value: "Collins"} +// ]; +``` + #### `jsonpatch.validate(patch: Operation[], document?: any, validator?: Function): JsonPatchError` See [Validation notes](#validation-notes) @@ -350,6 +304,27 @@ OPERATION_PATH_ILLEGAL_ARRAY_INDEX | Expected an unsigned base-10 integer value, OPERATION_VALUE_OUT_OF_BOUNDS | The specified index MUST NOT be greater than the number of elements in the array TEST_OPERATION_FAILED | When operation is `test` and the test fails, applies to `applyReducer`. +Example: + +```js +var obj = {user: {firstName: "Albert"}}; +var patches = [{op: "replace", path: "/user/firstName", value: "Albert"}, {op: "replace", path: "/user/lastName", value: "Einstein"}]; +var errors = jsonpatch.validate(patches, obj); +if (errors.length == 0) { + //there are no errors! +} +else { + for (var i=0; i < errors.length; i++) { + if (!errors[i]) { + console.log("Valid patch at index", i, patches[i]); + } + else { + console.error("Invalid patch at index", i, errors[i], patches[i]); + } + } +} +``` + ## `OperationResult` Type Functions `applyPatch` and `applyOperation` both return `OperationResult` object. This object is: @@ -404,6 +379,29 @@ See the [ECMAScript spec](http://www.ecma-international.org/ecma-262/6.0/index.h To see the list of recent changes, see [Releases](https://github.com/Starcounter-Jack/JSON-Patch/releases). +## Footprint +4 KB minified and gzipped (12 KB minified) + +## Performance + +##### [`add` benchmark](https://run.perf.zone/view/JSON-Patch-Add-Operation-1535541298893) + +![image](https://user-images.githubusercontent.com/17054134/44784357-aa422480-ab8d-11e8-8a7e-037e692dd842.png) + +##### [`replace` benchmark](https://run.perf.zone/view/JSON-Patch-Replace-Operation-1535540952263) + +![image](https://user-images.githubusercontent.com/17054134/44784275-5fc0a800-ab8d-11e8-8a90-e87b8d5409d0.png) + +Tested on 29.08.2018. Compared libraries: + +- [Starcounter-Jack/JSON-Patch](https://www.npmjs.com/package/fast-json-patch) 2.0.6 +- [bruth/jsonpatch-js](https://www.npmjs.com/package/json-patch) 0.7.0 +- [dharmafly/jsonpatch.js](https://www.npmjs.com/package/jsonpatch) 3.0.1 +- [jiff](https://www.npmjs.com/package/jiff) 0.7.3 +- [RFC6902](https://www.npmjs.com/package/rfc6902) 2.4.0 + +We aim the tests to be fair. Our library puts performance as the #1 priority, while other libraries can have different priorities. If you'd like to update the benchmarks or add a library, please fork the [perf.zone](https://perf.zone) benchmarks linked above and open an issue to include new results. + ## License MIT diff --git a/package.json b/package.json index 66718b41..8cecedfe 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,9 @@ "url": "http://www.starcounter.com/" }, "license": "MIT", - "main": "lib/duplex.js", - "module": "module/duplex.js", - "typings": "lib/duplex.d.ts", - "engines": { - "node": ">= 0.4.0" - }, + "main": "module/duplex.js", + "typings": "module/duplex.d.ts", + "type": "module", "devDependencies": { "benchmark": "^2.1.4", "bluebird": "^3.5.5", diff --git a/test/index.html b/test/index.html index d95a7078..aec09084 100644 --- a/test/index.html +++ b/test/index.html @@ -28,6 +28,8 @@ + + diff --git a/test/spec/moduleSpec.js b/test/spec/moduleSpec.js new file mode 100644 index 00000000..ea3af748 --- /dev/null +++ b/test/spec/moduleSpec.js @@ -0,0 +1,17 @@ +import { applyPatch } from "../../module/core.js"; + +describe('ECMAScript module', function () { + it('should apply patch on an object', function () { + const obj = {}; + + applyPatch(obj, [ + { + op: 'add', + path: '/bar', + value: [1, 2, 3, 4] + } + ]); + + expect(obj.bar).toEqual([1, 2, 3, 4]); + }); +}); \ No newline at end of file From 7533a66e9d041d1af7605262f4f371a2b88f694e Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 1 Aug 2019 12:05:23 +0200 Subject: [PATCH 07/31] bump devDeps --- package-lock.json | 102 +++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9ced629..3d21374c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -700,9 +700,9 @@ "dev": true }, "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz", + "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==", "dev": true, "requires": { "bluebird": "^3.5.5", @@ -710,6 +710,7 @@ "figgy-pudding": "^3.5.1", "glob": "^7.1.4", "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", @@ -1406,9 +1407,9 @@ "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "eventemitter3": { @@ -1608,7 +1609,8 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -1782,7 +1784,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -1803,12 +1806,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1823,17 +1828,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -1950,7 +1958,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -1962,6 +1971,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1976,6 +1986,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1983,12 +1994,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2007,6 +2020,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -2087,7 +2101,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2099,6 +2114,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2184,7 +2200,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -2220,6 +2237,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2239,6 +2257,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -2282,12 +2301,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -2613,6 +2634,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3808,9 +3835,9 @@ "dev": true }, "psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", "dev": true }, "public-encrypt": { @@ -4497,9 +4524,9 @@ } }, "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4699,20 +4726,19 @@ } }, "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", + "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", "dev": true, "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", "schema-utils": "^1.0.0", "serialize-javascript": "^1.7.0", "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" } }, @@ -5117,9 +5143,9 @@ "dev": true }, "webpack": { - "version": "4.37.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.37.0.tgz", - "integrity": "sha512-iJPPvL7XpbcbwOthbzpa2BSPlmGp8lGDokAj/LdWtK80rsPoPOdANSbDBf2GAVLKZD3GhCuQ/gGkgN9HWs0Keg==", + "version": "4.38.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.38.0.tgz", + "integrity": "sha512-lbuFsVOq8PZY+1Ytz/mYOvYOo+d4IJ31hHk/7iyoeWtwN33V+5HYotSH+UIb9tq914ey0Hot7z6HugD+je3sWw==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -5197,9 +5223,9 @@ } }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.1.tgz", + "integrity": "sha512-XSz38193PTo/1csJabKaV4b53uRVotlMgqJXm3s3eje0Bu6gQTxYDqpD38CmQfDBA+gN+QqaGjasuC8I/7eW3Q==", "dev": true, "requires": { "source-list-map": "^2.0.0", From 38d173428d6b04487a98a4bb4cea0d585195ff2c Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 1 Aug 2019 17:40:37 +0200 Subject: [PATCH 08/31] update Jasmine to use ES module - replaced "jsdom" with "event-target-shim" - replaced "underscore" with "jsonpatch._areEquals" - replaced "jsonfile" with importing a ES module - use custom "jasmine-run.js" script, copied from https://github.com/Palindrom/JSON-Patch-Queue/blob/612caf0646bc4a5b3d5630d9ec37f8f2f83d2464/jasmine-run.js --- dist/fast-json-patch.js | 12 +- dist/fast-json-patch.min.js | 4 +- jasmine-run.js | 23 + lib/core.js | 11 +- lib/duplex.js | 1 + module/core.js | 10 +- module/duplex.js | 2 +- package-lock.json | 517 +++--------------- package.json | 12 +- src/core.ts | 10 +- src/duplex.ts | 6 +- test/index.html | 11 +- test/jasmine.json | 3 - test/spec/coreSpec.js | 62 +-- test/spec/duplexSpec.js | 50 +- .../{spec_tests.json => spec_tests.json.js} | 2 +- .../{tests.json => tests.json.js} | 8 +- test/spec/jsonPatchTestsSpec.js | 32 +- test/spec/moduleSpec.js | 17 - test/spec/validateSpec.js | 5 +- 20 files changed, 197 insertions(+), 601 deletions(-) create mode 100644 jasmine-run.js rename test/spec/json-patch-tests/{spec_tests.json => spec_tests.json.js} (99%) rename test/spec/json-patch-tests/{tests.json => tests.json.js} (99%) mode change 100755 => 100644 delete mode 100644 test/spec/moduleSpec.js diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index a43822c0..d6ec0eb0 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -322,7 +322,7 @@ var objOps = { return { newDocument: document }; }, test: function (obj, key, document) { - return { newDocument: document, test: areEquals(obj[key], this.value) }; + return { newDocument: document, test: _areEquals(obj[key], this.value) }; }, _get: function (obj, key, document) { this.value = obj[key]; @@ -419,7 +419,7 @@ function applyOperation(document, operation, validateOperation, mutateDocument, return returnValue; } else if (operation.op === 'test') { - returnValue.test = areEquals(document, operation.value); + returnValue.test = _areEquals(document, operation.value); if (returnValue.test === false) { throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -677,7 +677,7 @@ exports.validate = validate; // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -function areEquals(a, b) { +function _areEquals(a, b) { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { @@ -687,7 +687,7 @@ function areEquals(a, b) { if (length != b.length) return false; for (i = length; i-- !== 0;) - if (!areEquals(a[i], b[i])) + if (!_areEquals(a[i], b[i])) return false; return true; } @@ -702,13 +702,14 @@ function areEquals(a, b) { return false; for (i = length; i-- !== 0;) { key = keys[i]; - if (!areEquals(a[key], b[key])) + if (!_areEquals(a[key], b[key])) return false; } return true; } return a !== a && b !== b; } +exports._areEquals = _areEquals; ; @@ -732,6 +733,7 @@ exports.applyReducer = core_js_2.applyReducer; exports.getValueByPointer = core_js_2.getValueByPointer; exports.validate = core_js_2.validate; exports.validator = core_js_2.validator; +exports._areEquals = core_js_2._areEquals; /* export some helpers */ var helpers_js_2 = __webpack_require__(0); exports.JsonPatchError = helpers_js_2.PatchError; diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index 9a6901eb..aab6dc5a 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -5,10 +5,10 @@ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0});var o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a0&&(e.patches=[],e.callback&&e.callback(n)),n}function f(e,t,r,o,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=n._objectKeys(t),p=n._objectKeys(e),u=!1,s=p.length-1;s>=0;s--){var c=e[h=p[s]];if(!n.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==c&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"remove",path:o+"/"+n.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:o,value:e}),r.push({op:"replace",path:o,value:t}),!0);else{var l=t[h];"object"==typeof c&&null!=c&&"object"==typeof l&&null!=l?f(c,l,r,o+"/"+n.escapePathComponent(h),a):c!==l&&(!0,a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"replace",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(l)}))}}if(u||i.length!=p.length)for(s=0;s0&&(e.patches=[],e.callback&&e.callback(n)),n}function f(e,t,r,o,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=n._objectKeys(t),p=n._objectKeys(e),u=!1,s=p.length-1;s>=0;s--){var c=e[h=p[s]];if(!n.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==c&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"remove",path:o+"/"+n.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:o,value:e}),r.push({op:"replace",path:o,value:t}),!0);else{var l=t[h];"object"==typeof c&&null!=c&&"object"==typeof l&&null!=l?f(c,l,r,o+"/"+n.escapePathComponent(h),a):c!==l&&(!0,a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"replace",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(l)}))}}if(u||i.length!=p.length)for(s=0;s f.replace(/^([^\/])/, './$1')) + .map(f => import(f) + .catch(e => { + console.error('** Error loading ' + f + ': '); + console.error(e); + process.exit(1); + })) + ) + .then(() => jasmine.execute()); +}); \ No newline at end of file diff --git a/lib/core.js b/lib/core.js index a411691a..c4f67e37 100644 --- a/lib/core.js +++ b/lib/core.js @@ -43,7 +43,7 @@ var objOps = { return { newDocument: document }; }, test: function (obj, key, document) { - return { newDocument: document, test: areEquals(obj[key], this.value) }; + return { newDocument: document, test: _areEquals(obj[key], this.value) }; }, _get: function (obj, key, document) { this.value = obj[key]; @@ -140,7 +140,7 @@ function applyOperation(document, operation, validateOperation, mutateDocument, return returnValue; } else if (operation.op === 'test') { - returnValue.test = areEquals(document, operation.value); + returnValue.test = _areEquals(document, operation.value); if (returnValue.test === false) { throw new exports.JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -398,7 +398,7 @@ exports.validate = validate; // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -function areEquals(a, b) { +function _areEquals(a, b) { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { @@ -408,7 +408,7 @@ function areEquals(a, b) { if (length != b.length) return false; for (i = length; i-- !== 0;) - if (!areEquals(a[i], b[i])) + if (!_areEquals(a[i], b[i])) return false; return true; } @@ -423,11 +423,12 @@ function areEquals(a, b) { return false; for (i = length; i-- !== 0;) { key = keys[i]; - if (!areEquals(a[key], b[key])) + if (!_areEquals(a[key], b[key])) return false; } return true; } return a !== a && b !== b; } +exports._areEquals = _areEquals; ; diff --git a/lib/duplex.js b/lib/duplex.js index f23e703b..5331fcaa 100644 --- a/lib/duplex.js +++ b/lib/duplex.js @@ -14,6 +14,7 @@ exports.applyReducer = core_js_2.applyReducer; exports.getValueByPointer = core_js_2.getValueByPointer; exports.validate = core_js_2.validate; exports.validator = core_js_2.validator; +exports._areEquals = core_js_2._areEquals; /* export some helpers */ var helpers_js_2 = require("./helpers.js"); exports.JsonPatchError = helpers_js_2.PatchError; diff --git a/module/core.js b/module/core.js index 4607a0cd..f82f40b0 100644 --- a/module/core.js +++ b/module/core.js @@ -42,7 +42,7 @@ var objOps = { return { newDocument: document }; }, test: function (obj, key, document) { - return { newDocument: document, test: areEquals(obj[key], this.value) }; + return { newDocument: document, test: _areEquals(obj[key], this.value) }; }, _get: function (obj, key, document) { this.value = obj[key]; @@ -138,7 +138,7 @@ export function applyOperation(document, operation, validateOperation, mutateDoc return returnValue; } else if (operation.op === 'test') { - returnValue.test = areEquals(document, operation.value); + returnValue.test = _areEquals(document, operation.value); if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -391,7 +391,7 @@ export function validate(sequence, document, externalValidator) { // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -function areEquals(a, b) { +export function _areEquals(a, b) { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { @@ -401,7 +401,7 @@ function areEquals(a, b) { if (length != b.length) return false; for (i = length; i-- !== 0;) - if (!areEquals(a[i], b[i])) + if (!_areEquals(a[i], b[i])) return false; return true; } @@ -416,7 +416,7 @@ function areEquals(a, b) { return false; for (i = length; i-- !== 0;) { key = keys[i]; - if (!areEquals(a[key], b[key])) + if (!_areEquals(a[key], b[key])) return false; } return true; diff --git a/module/duplex.js b/module/duplex.js index 23694440..df65b7ec 100644 --- a/module/duplex.js +++ b/module/duplex.js @@ -6,7 +6,7 @@ import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers.js'; import { applyPatch } from './core.js'; /* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator } from './core.js'; +export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator, _areEquals } from './core.js'; /* export some helpers */ export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.js'; var beforeDict = new WeakMap(); diff --git a/package-lock.json b/package-lock.json index 3d21374c..b55a46fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -192,34 +192,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true - }, "acorn": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", "dev": true }, - "acorn-globals": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", - "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", - "dev": true, - "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - } - }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true - }, "adm-zip": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", @@ -319,12 +297,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -402,12 +374,6 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -593,12 +559,6 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, - "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true - }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -1079,21 +1039,6 @@ "randomfill": "^1.0.3" } }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", @@ -1109,17 +1054,6 @@ "assert-plus": "^1.0.0" } }, - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1147,12 +1081,6 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -1233,15 +1161,6 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, - "requires": { - "webidl-conversions": "^4.0.2" - } - }, "dot-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", @@ -1362,19 +1281,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -1385,12 +1291,6 @@ "estraverse": "^4.1.1" } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -1406,10 +1306,10 @@ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true }, "eventemitter3": { @@ -1618,12 +1518,6 @@ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", @@ -2528,15 +2422,6 @@ "parse-passwd": "^1.0.0" } }, - "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.1" - } - }, "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", @@ -2591,15 +2476,6 @@ "debug": "^3.1.0" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -2674,12 +2550,6 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -2898,40 +2768,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsdom": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.1.1.tgz", - "integrity": "sha512-cQZRBB33arrDAeCrAEWn1U3SvrvC8XysBua9Oqg1yWrsY/gYcusloJC3RZJXuY5eehSCmws8f2YeliCqGSkrtQ==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^6.1.1", - "acorn-globals": "^4.3.2", - "array-equal": "^1.0.0", - "cssom": "^0.3.6", - "cssstyle": "^1.2.2", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.1", - "html-encoding-sniffer": "^1.0.2", - "nwsapi": "^2.1.4", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.7", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^3.0.1", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^7.0.0", - "xml-name-validator": "^3.0.0" - } - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2965,16 +2801,6 @@ "minimist": "^1.2.0" } }, - "jsonfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", - "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^0.1.2" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3014,16 +2840,6 @@ "invert-kv": "^2.0.0" } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, "lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -3066,12 +2882,6 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -3430,12 +3240,6 @@ "path-key": "^2.0.0" } }, - "nwsapi": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", - "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", - "dev": true - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -3530,28 +3334,6 @@ } } }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -3663,12 +3445,6 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true - }, "pascal-case": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", @@ -3764,12 +3540,6 @@ "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", "dev": true }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, "portfinder": { "version": "1.0.21", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz", @@ -3804,12 +3574,6 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -4020,59 +3784,11 @@ "uuid": "^3.3.2" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - } - } - }, - "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "request-promise-native": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", - "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", - "dev": true, - "requires": { - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } } } }, @@ -4235,15 +3951,6 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "saxes": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", - "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", - "dev": true, - "requires": { - "xmlchars": "^2.1.1" - } - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -4418,12 +4125,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, @@ -4505,9 +4206,9 @@ "dev": true }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { @@ -4531,6 +4232,14 @@ "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "source-map-url": { @@ -4595,12 +4304,6 @@ } } }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -4702,12 +4405,6 @@ "upper-case": "^1.1.1" } }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", @@ -4723,6 +4420,14 @@ "commander": "^2.20.0", "source-map": "~0.6.1", "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "terser-webpack-plugin": { @@ -4740,6 +4445,14 @@ "terser": "^4.1.2", "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "through2": { @@ -4829,23 +4542,21 @@ } }, "tough-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", - "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "ip-regex": "^2.1.0", - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, "tslib": { @@ -4875,15 +4586,6 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4896,12 +4598,6 @@ "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", "dev": true }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true - }, "union": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", @@ -4941,12 +4637,6 @@ "imurmurhash": "^0.1.4" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -5105,26 +4795,6 @@ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, - "w3c-hr-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", - "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", - "dev": true, - "requires": { - "browser-process-hrtime": "^0.1.2" - } - }, - "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", - "dev": true, - "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", - "xml-name-validator": "^3.0.0" - } - }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -5136,41 +4806,35 @@ "neo-async": "^2.5.0" } }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, "webpack": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.38.0.tgz", - "integrity": "sha512-lbuFsVOq8PZY+1Ytz/mYOvYOo+d4IJ31hHk/7iyoeWtwN33V+5HYotSH+UIb9tq914ey0Hot7z6HugD+je3sWw==", + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.39.0.tgz", + "integrity": "sha512-nrxFNSEKm4T1C/EsgOgN50skt//Pl4X7kgJC1MrlE47M292LSCVmMOC47iTGL0CGxbdwhKGgeThrJcw0bstEfA==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", + "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.1", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" } }, "webpack-cli": { @@ -5230,32 +4894,14 @@ "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" - } - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "which": { @@ -5305,21 +4951,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "ws": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.1.tgz", - "integrity": "sha512-o41D/WmDeca0BqYhsr3nJzQyg9NF5X8l/UdnFNux9cS3lwB+swm8qGWX5rn+aD6xfBU3rGmtHij7g7x6LxFU3A==", - "dev": true, - "requires": { - "async-limiter": "^1.0.0" - } - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -5336,12 +4967,6 @@ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, - "xmlchars": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.1.1.tgz", - "integrity": "sha512-7hew1RPJ1iIuje/Y01bGD/mXokXxegAgVS+e+E0wSi2ILHQkYAH1+JXARwTjZSM4Z4Z+c73aKspEcqj+zPPL/w==", - "dev": true - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 8cecedfe..9898d3e9 100644 --- a/package.json +++ b/package.json @@ -30,17 +30,15 @@ "bluebird": "^3.5.5", "bluebird-retry": "^0.11.0", "chalk": "^2.4.2", + "event-target-shim": "^5.0.1", "fast-deep-equal": "^2.0.1", "http-server": "^0.11.1", "jasmine": "^3.4.0", - "jsdom": "^15.1.1", - "jsonfile": "^5.0.0", "request": "^2.88.0", "sauce-connect-launcher": "^1.2.7", "saucelabs": "^2.1.9", "selenium-webdriver": "^4.0.0-alpha.4", "typescript": "~3.5.2", - "underscore": "^1.9.1", "webpack": "^4.35.0", "webpack-cli": "^3.3.5" }, @@ -54,10 +52,12 @@ "tsc-watch": "tsc -w", "test": "npm run tsc && npm run test-core && npm run test-duplex", "test-sauce": "npm run build && node test/Sauce/Runner.js", - "test-duplex": "jasmine DUPLEX=yes JASMINE_CONFIG_PATH=test/jasmine.json", - "test-core": "jasmine DUPLEX=no JASMINE_CONFIG_PATH=test/jasmine.json test/spec/jsonPatchTestsSpec.js test/spec/coreSpec.js test/spec/validateSpec.js", + "test-duplex": "node --experimental-modules jasmine-run.js test/**/*[sS]pec.js", + "test-core": "node --experimental-modules jasmine-run.js test/spec/jsonPatchTestsSpec.js test/spec/coreSpec.js test/spec/validateSpec.js", + "test-mini": "node --experimental-modules jasmine-run.js test/spec/validateSpec.js", + "test-mini-brk": "node --inspect-brk --experimental-modules jasmine-run.js test/spec/jsonPatchTestsSpec.js", "bench": "npm run bench-core && npm run bench-duplex", "bench-core": "node test/spec/coreBenchmark.js", - "bench-duplex": "node test/spec/coreBenchmark.js DUPLEX=yes && node test/spec/duplexBenchmark.js" + "bench-duplex": "node test/spec/coreBenchmark.js && node test/spec/duplexBenchmark.js" } } diff --git a/src/core.ts b/src/core.ts index e905b00b..bd629efd 100644 --- a/src/core.ts +++ b/src/core.ts @@ -122,7 +122,7 @@ const objOps = { return { newDocument: document } }, test: function (obj, key, document) { - return { newDocument: document, test: areEquals(obj[key], this.value) } + return { newDocument: document, test: _areEquals(obj[key], this.value) } }, _get: function (obj, key, document) { this.value = obj[key]; @@ -213,7 +213,7 @@ export function applyOperation(document: T, operation: Operation, validateOpe } return returnValue; } else if (operation.op === 'test') { - returnValue.test = areEquals(document, operation.value); + returnValue.test = _areEquals(document, operation.value); if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -479,7 +479,7 @@ export function validate(sequence: Operation[], document?: T, externalValidat // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -function areEquals(a: any, b: any): boolean { +export function _areEquals(a: any, b: any): boolean { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { @@ -493,7 +493,7 @@ function areEquals(a: any, b: any): boolean { length = a.length; if (length != b.length) return false; for (i = length; i-- !== 0;) - if (!areEquals(a[i], b[i])) return false; + if (!_areEquals(a[i], b[i])) return false; return true; } @@ -510,7 +510,7 @@ function areEquals(a: any, b: any): boolean { for (i = length; i-- !== 0;) { key = keys[i]; - if (!areEquals(a[key], b[key])) return false; + if (!_areEquals(a[key], b[key])) return false; } return true; diff --git a/src/duplex.ts b/src/duplex.ts index c3624755..8c4aff99 100644 --- a/src/duplex.ts +++ b/src/duplex.ts @@ -7,7 +7,7 @@ import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './ import { applyPatch, Operation } from './core.js'; /* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, Operation, AddOperation, RemoveOperation, ReplaceOperation, MoveOperation, CopyOperation, TestOperation, GetOperation, validate, validator, OperationResult } from './core.js'; +export { applyOperation, applyPatch, applyReducer, getValueByPointer, Operation, AddOperation, RemoveOperation, ReplaceOperation, MoveOperation, CopyOperation, TestOperation, GetOperation, validate, validator, OperationResult, _areEquals } from './core.js'; /* export some helpers */ export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.js'; @@ -175,8 +175,8 @@ function _generate(mirror, obj, patches, path, invertible) { else { if (oldVal !== newVal) { changed = true; - if (invertible) { - patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) }); + if (invertible) { + patches.push({ op: "test", path: path + "/" + escapePathComponent(key), value: _deepClone(oldVal) }); } patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: _deepClone(newVal) }); } diff --git a/test/index.html b/test/index.html index aec09084..26b3607f 100644 --- a/test/index.html +++ b/test/index.html @@ -15,21 +15,20 @@ - + --> - - - - + + + + - diff --git a/test/jasmine.json b/test/jasmine.json index 89452f12..a5dce12b 100644 --- a/test/jasmine.json +++ b/test/jasmine.json @@ -1,8 +1,5 @@ { "spec_dir": "test", - "spec_files": [ - "**/*[sS]pec.js" - ], "helpers": [ "helpers/**/*.js" ], diff --git a/test/spec/coreSpec.js b/test/spec/coreSpec.js index a73e3418..a1f5186f 100644 --- a/test/spec/coreSpec.js +++ b/test/spec/coreSpec.js @@ -1,10 +1,4 @@ -var obj; -if (typeof jsonpatch === 'undefined') { - jsonpatch = require('./../../lib/duplex'); -} -if (typeof _ === 'undefined') { - _ = require('underscore'); -} +import * as jsonpatch from '../../module/duplex.js'; describe('jsonpatch.getValueByPointer', function() { it('should retrieve values by JSON pointer from tree - deep object', function() { @@ -493,7 +487,7 @@ describe('root replacement with applyOperation', function() { /* this is just a copy-paste of original specs, but with using applyOperation, to test for non-root patches */ describe('core - using applyOperation', function() { it("shouldn't touch original tree", function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -522,7 +516,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply add', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -647,7 +641,7 @@ describe('core - using applyOperation', function() { }); it('should apply remove', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -679,7 +673,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply replace', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -731,7 +725,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply test', function() { - obj = { + var obj = { foo: { bar: [1, 2, 5, 4] }, @@ -852,7 +846,7 @@ describe('core - using applyOperation', function() { }); it('should apply move', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -907,7 +901,7 @@ describe('core - using applyOperation', function() { }); it('should apply copy', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -970,7 +964,7 @@ describe('core - using applyOperation', function() { describe('core', function() { it("shouldn't touch original tree", function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1001,7 +995,7 @@ describe('core', function() { }); }); it('should apply add', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1123,7 +1117,7 @@ describe('core', function() { var obj = { hello: 'world' }; - newObj = jsonpatch.applyPatch(obj, [ + var newObj = jsonpatch.applyPatch(obj, [ { op: 'add', path: '', @@ -1139,7 +1133,7 @@ describe('core', function() { }); it('should apply remove', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1178,7 +1172,7 @@ describe('core', function() { }); it('should apply replace', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1240,7 +1234,7 @@ describe('core', function() { }); it('should apply test', function() { - obj = { + var obj = { foo: { bar: [1, 2, 5, 4] }, @@ -1388,7 +1382,7 @@ describe('core', function() { }); it('should apply move', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1434,7 +1428,7 @@ describe('core', function() { city: 'Vancouver' } }; - newObj = jsonpatch.applyPatch(obj, [ + var newObj = jsonpatch.applyPatch(obj, [ { op: 'move', from: '/location', @@ -1448,7 +1442,7 @@ describe('core', function() { }); it('should apply copy', function() { - obj = { + var obj = { foo: 1, baz: [ { @@ -1500,7 +1494,7 @@ describe('core', function() { city: 'Vancouver' } }; - newObj = jsonpatch.applyPatch(obj, [ + var newObj = jsonpatch.applyPatch(obj, [ { op: 'copy', from: '/location', @@ -1694,7 +1688,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('remove on element already set to `undefined`, and remove it completely', function() { - obj = { + var obj = { foo: 1, not: undefined }; @@ -1710,7 +1704,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('remove on array element set to `undefined`', function() { - obj = { + var obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1728,7 +1722,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('replace on element set to `undefined`', function() { - obj = { + var obj = { foo: 1, not: undefined }; @@ -1746,7 +1740,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace on array element set to `undefined`', function() { - obj = { + var obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1764,7 +1758,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace element with `undefined` (extension)', function() { - obj = { + var obj = { foo: 1 }; @@ -1780,7 +1774,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace array element with `undefined` (extension)', function() { - obj = { + var obj = { foo: 1, bar: [0, 1, 2, 3] }; @@ -1798,7 +1792,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('test on element set to `undefined`', function() { - obj = { + var obj = { foo: 1, not: undefined }; @@ -1822,7 +1816,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() ).toBe(true); }); it('test on array element set to `undefined`', function() { - obj = { + var obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1856,7 +1850,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('move of `undefined`', function() { - obj = { + var obj = { foo: undefined, baz: 'defined' }; @@ -1886,7 +1880,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('copy of `undefined` as `null` (like `JSON.stringify` does)', function() { - obj = { + var obj = { foo: undefined, baz: 'defined' }; diff --git a/test/spec/duplexSpec.js b/test/spec/duplexSpec.js index 38f53e6c..e4d4e182 100644 --- a/test/spec/duplexSpec.js +++ b/test/spec/duplexSpec.js @@ -1,22 +1,23 @@ var obj, obj2, patches; + +import * as jsonpatch from '../../module/duplex.js'; +import {EventTarget, defineEventAttribute} from "../../node_modules/event-target-shim/dist/event-target-shim.mjs"; + if (typeof window === 'undefined') { - const jsdom = require("jsdom"); - const { JSDOM } = jsdom; - const dom = new JSDOM(); - global.window = dom.window; - global.document = dom.window.document; -} -if (typeof jsonpatch === 'undefined') { - jsonpatch = require('./../../lib/duplex'); -} -if (typeof _ === 'undefined') { - _ = require('underscore'); + global.window = new EventTarget(); } -function trigger(eventName, elem) { - if (typeof document !== 'undefined') { - fireEvent(elem || document.documentElement, eventName); +function trigger(eventName) { + let event; + if (typeof CustomEvent !== 'undefined') { + //browser with real EventTarget + event = new CustomEvent(eventName); } + else { + //browser with real EventTarget + event = { type: eventName }; + } + window.dispatchEvent(event) } function getPatchesUsingGenerate(objFactory, objChanger) { @@ -33,21 +34,6 @@ function getPatchesUsingCompare(objFactory, objChanger) { return jsonpatch.compare(mirror, JSON.parse(JSON.stringify(obj))); } -//http://stackoverflow.com/questions/827716/emulate-clicking-a-link-with-javascript-that-works-with-ie -function fireEvent(obj, evt) { - var fireOnThis = obj; - if (document.createEvent) { - var evObj = document.createEvent( - evt.indexOf('mouse') > -1 ? 'MouseEvents' : 'KeyboardEvent' - ); - evObj.initEvent(evt, true, false); - fireOnThis.dispatchEvent(evObj); - } else if (document.createEventObject) { - var evObj = document.createEventObject(); - fireOnThis.fireEvent('on' + evt, evObj); - } -} - var customMatchers = { /** * This matcher is only needed in Chrome 28 (Chrome 28 cannot successfully compare observed objects immediately after they have been changed. Chrome 30 is unaffected) @@ -67,7 +53,7 @@ var customMatchers = { return { compare: function(actual, expected) { return { - pass: _.isEqual(actual, expected) + pass: jsonpatch._areEquals(actual, expected) }; } }; @@ -374,7 +360,7 @@ describe('duplex', function() { }); it('should generate replace (changes in new array cell, primitive values)', function() { - arr = [1]; + const arr = [1]; var observer = jsonpatch.observe(arr); arr.push(2); @@ -412,7 +398,7 @@ describe('duplex', function() { }); it('should generate replace (changes in new array cell, complex values)', function() { - arr = [ + const arr = [ { id: 1, name: 'Ted' diff --git a/test/spec/json-patch-tests/spec_tests.json b/test/spec/json-patch-tests/spec_tests.json.js similarity index 99% rename from test/spec/json-patch-tests/spec_tests.json rename to test/spec/json-patch-tests/spec_tests.json.js index c160535b..0a064634 100644 --- a/test/spec/json-patch-tests/spec_tests.json +++ b/test/spec/json-patch-tests/spec_tests.json.js @@ -1,4 +1,4 @@ -[ +export default [ { "comment": "4.1. add with missing object", "doc": { "q": { "bar": 2 } }, diff --git a/test/spec/json-patch-tests/tests.json b/test/spec/json-patch-tests/tests.json.js old mode 100755 new mode 100644 similarity index 99% rename from test/spec/json-patch-tests/tests.json rename to test/spec/json-patch-tests/tests.json.js index ec1c0c9c..bde26462 --- a/test/spec/json-patch-tests/tests.json +++ b/test/spec/json-patch-tests/tests.json.js @@ -1,4 +1,4 @@ -[ +export default [ { "comment": "empty list, empty docs", "doc": {}, "patch": [], @@ -189,17 +189,17 @@ "patch": [{"op": "replace", "path": "/foo", "value": "truthy"}], "expected": {"foo": "truthy"}, "comment": "null value should be valid obj property to be replaced with something truthy" }, - + { "doc": {"foo": null}, "patch": [{"op": "move", "from": "/foo", "path": "/bar"}], "expected": {"bar": null}, "comment": "null value should be valid obj property to be moved" }, - + { "doc": {"foo": null}, "patch": [{"op": "copy", "from": "/foo", "path": "/bar"}], "expected": {"foo": null, "bar": null}, "comment": "null value should be valid obj property to be copied" }, - + { "doc": {"foo": null}, "patch": [{"op": "remove", "path": "/foo"}], "expected": {}, diff --git a/test/spec/jsonPatchTestsSpec.js b/test/spec/jsonPatchTestsSpec.js index e515fd61..a81c1f72 100644 --- a/test/spec/jsonPatchTestsSpec.js +++ b/test/spec/jsonPatchTestsSpec.js @@ -1,33 +1,19 @@ -if(typeof jsonpatch == 'undefined') { - var jsonpatch = require('../../lib/duplex') -} +import * as jsonpatch from '../../module/duplex.js'; + +import tests_json from './json-patch-tests/tests.json.js'; +import spec_tests_json from './json-patch-tests/spec_tests.json.js'; var JSONtests = [ { name: 'tests.json', - path: 'spec/json-patch-tests/tests.json' + tests: tests_json }, { name: 'spec_tests.json', - path: 'spec/json-patch-tests/spec_tests.json' + tests: spec_tests_json } ]; -var loadJsonTestSuite; -if (typeof XMLHttpRequest === 'undefined') { - var jsonfile = require('jsonfile'); - loadJsonTestSuite = function(url, callback) { - return jsonfile.readFileSync('test/' + url); - }; -} else { - loadJsonTestSuite = function(url, callback) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, false); - xhr.send(); - return JSON.parse(xhr.responseText); - }; -} - if (typeof Array.prototype.forEach != 'function') { Array.prototype.forEach = function(callback) { for (var i = 0; i < this.length; i++) { @@ -39,7 +25,7 @@ if (typeof Array.prototype.forEach != 'function') { describe('json-patch-tests', function() { JSONtests.forEach(function(jsonTest) { describe(jsonTest.name, function() { - loadJsonTestSuite(jsonTest.path).forEach(function(test) { + jsonTest.tests.forEach(function(test) { if (test.disabled) { return; } @@ -47,7 +33,7 @@ describe('json-patch-tests', function() { if (test.expected) { it('should succeed: ' + testName, function() { const results = jsonpatch.applyPatch(test.doc, test.patch, true); - test.doc = results.newDocument; + test.doc = results.newDocument; expect(test.doc).toEqual(test.expected); }); } else if (test.error || test.patch[0].op === 'test') { @@ -73,4 +59,4 @@ describe('json-patch-tests', function() { }); }); }); -}); +}); \ No newline at end of file diff --git a/test/spec/moduleSpec.js b/test/spec/moduleSpec.js deleted file mode 100644 index ea3af748..00000000 --- a/test/spec/moduleSpec.js +++ /dev/null @@ -1,17 +0,0 @@ -import { applyPatch } from "../../module/core.js"; - -describe('ECMAScript module', function () { - it('should apply patch on an object', function () { - const obj = {}; - - applyPatch(obj, [ - { - op: 'add', - path: '/bar', - value: [1, 2, 3, 4] - } - ]); - - expect(obj.bar).toEqual([1, 2, 3, 4]); - }); -}); \ No newline at end of file diff --git a/test/spec/validateSpec.js b/test/spec/validateSpec.js index 12cdf108..3bfd5123 100644 --- a/test/spec/validateSpec.js +++ b/test/spec/validateSpec.js @@ -1,6 +1,5 @@ -if(typeof jsonpatch == 'undefined') { - var jsonpatch = require('../../lib/duplex') -} +import * as jsonpatch from '../../module/duplex.js'; + describe('validate', function() { it('should return an empty array if the patch is valid', function() { var patch = [ From bb925e13224eb6dd1aea9c7062f630375b4aa15e Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Fri, 2 Aug 2019 13:08:40 +0200 Subject: [PATCH 09/31] use Node 12+ for testing on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7c35fe92..1950c4ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js dist: trusty -node_js: lts/* +node_js: node before_script: - npm install - npm run serve & From 304b1328431bba1784d480ae7cc855cb9770cd84 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Fri, 2 Aug 2019 13:15:32 +0200 Subject: [PATCH 10/31] remove my temporary run-scripts --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 9898d3e9..ce8c9acb 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,6 @@ "test-sauce": "npm run build && node test/Sauce/Runner.js", "test-duplex": "node --experimental-modules jasmine-run.js test/**/*[sS]pec.js", "test-core": "node --experimental-modules jasmine-run.js test/spec/jsonPatchTestsSpec.js test/spec/coreSpec.js test/spec/validateSpec.js", - "test-mini": "node --experimental-modules jasmine-run.js test/spec/validateSpec.js", - "test-mini-brk": "node --inspect-brk --experimental-modules jasmine-run.js test/spec/jsonPatchTestsSpec.js", "bench": "npm run bench-core && npm run bench-duplex", "bench-core": "node test/spec/coreBenchmark.js", "bench-duplex": "node test/spec/coreBenchmark.js && node test/spec/duplexBenchmark.js" From 4f8d50eab44d0bbf45b3d8915194430b259f1932 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Fri, 2 Aug 2019 13:17:43 +0200 Subject: [PATCH 11/31] cleanup redundant comment --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 26b3607f..5156c2ad 100644 --- a/test/index.html +++ b/test/index.html @@ -15,7 +15,7 @@ - --> + From aa3e1db2761102e67f8700a793ef3f891b787092 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Fri, 2 Aug 2019 13:38:47 +0200 Subject: [PATCH 12/31] replace "var" with "const" or "let" --- test/spec/coreBenchmark.js | 38 ++-- test/spec/coreSpec.js | 282 +++++++++++------------ test/spec/duplexBenchmark.js | 86 +++---- test/spec/duplexSpec.js | 389 ++++++++++++++++---------------- test/spec/jsonPatchTestsSpec.js | 10 +- test/spec/validateSpec.js | 122 +++++----- 6 files changed, 464 insertions(+), 463 deletions(-) diff --git a/test/spec/coreBenchmark.js b/test/spec/coreBenchmark.js index d721b126..c4d0f077 100644 --- a/test/spec/coreBenchmark.js +++ b/test/spec/coreBenchmark.js @@ -2,16 +2,16 @@ if (typeof jsonpatch === 'undefined') { jsonpatch = require('./../../lib/duplex'); } if (typeof Benchmark === 'undefined') { - var Benchmark = require('benchmark'); - var benchmarkResultsToConsole = require('./../lib/benchmark_console_reporter.js').benchmarkResultsToConsole; + global.Benchmark = require('benchmark'); + global.benchmarkResultsToConsole = require('./../lib/benchmark_console_reporter.js').benchmarkResultsToConsole; } -var suite = new Benchmark.Suite; -suite.add('add operation', { +const coreSuite = new Benchmark.Suite; +coreSuite.add('add operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -26,9 +26,9 @@ suite.add('add operation', { }]); } }); -suite.add('remove operation', { +coreSuite.add('remove operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -43,9 +43,9 @@ suite.add('remove operation', { }]); } }); -suite.add('replace operation', { +coreSuite.add('replace operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -60,9 +60,9 @@ suite.add('replace operation', { }]); } }); -suite.add('move operation', { +coreSuite.add('move operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -78,9 +78,9 @@ suite.add('move operation', { }]); } }); -suite.add('copy operation', { +coreSuite.add('copy operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -96,9 +96,9 @@ suite.add('copy operation', { }]); } }); -suite.add('test operation', { +coreSuite.add('test operation', { setup: function(){ - var obj = { + const obj = { foo: 1, baz: [{ qux: 'hello' @@ -118,10 +118,10 @@ suite.add('test operation', { // if we are in the browser with benchmark < 2.1.2 if(typeof benchmarkReporter !== 'undefined'){ - benchmarkReporter(suite); + benchmarkReporter(coreSuite); } else { - suite.on('complete', function () { - benchmarkResultsToConsole(suite); + coreSuite.on('complete', function () { + benchmarkResultsToConsole(coreSuite); }); - suite.run(); + coreSuite.run(); } diff --git a/test/spec/coreSpec.js b/test/spec/coreSpec.js index a1f5186f..507dba4c 100644 --- a/test/spec/coreSpec.js +++ b/test/spec/coreSpec.js @@ -2,26 +2,26 @@ import * as jsonpatch from '../../module/duplex.js'; describe('jsonpatch.getValueByPointer', function() { it('should retrieve values by JSON pointer from tree - deep object', function() { - var obj = { + const obj = { person: { name: 'Marilyn' } }; - var name = jsonpatch.getValueByPointer(obj, '/person/name'); + const name = jsonpatch.getValueByPointer(obj, '/person/name'); expect(name).toEqual('Marilyn'); }); it('should retrieve values by JSON pointer from tree - deep array', function() { - var obj = { + const obj = { people: [{ name: 'Marilyn' }, { name: 'Monroe' }] }; - var name = jsonpatch.getValueByPointer(obj, '/people/1/name'); + const name = jsonpatch.getValueByPointer(obj, '/people/1/name'); expect(name).toEqual('Monroe'); }); it('should retrieve values by JSON pointer from tree - root object', function() { - var obj = { + const obj = { people: [{ name: 'Marilyn' }, { name: 'Monroe' }] }; - var retrievedObject = jsonpatch.getValueByPointer(obj, ''); + const retrievedObject = jsonpatch.getValueByPointer(obj, ''); expect(retrievedObject).toEqual({ people: [{ name: 'Marilyn' }, { name: 'Monroe' }] @@ -29,12 +29,12 @@ describe('jsonpatch.getValueByPointer', function() { }); it('should retrieve values by JSON pointer from tree - root array', function() { - var obj = [ + const obj = [ { people: [{ name: 'Marilyn' }, { name: 'Monroe' }] } ]; - var retrievedObject = jsonpatch.getValueByPointer(obj, ''); + const retrievedObject = jsonpatch.getValueByPointer(obj, ''); expect(retrievedObject).toEqual([ { @@ -45,15 +45,15 @@ describe('jsonpatch.getValueByPointer', function() { }); describe('jsonpatch.applyReducer - using with Array#reduce', function() { it('should work with Array.reduce on array of patches', function() { - var obj = { + const obj = { hello: 'world' }; - var patch = [ + const patch = [ { op: 'replace', path: '/hello', value: 1 }, { op: 'add', path: '/bye', value: { testing: 'isGood' } } ]; - obj = patch.reduce(jsonpatch.applyReducer, obj); - expect(obj).toEqual({ + const obj2 = patch.reduce(jsonpatch.applyReducer, obj); + expect(obj2).toEqual({ hello: 1, bye: { testing: 'isGood' } }); @@ -62,13 +62,13 @@ describe('jsonpatch.applyReducer - using with Array#reduce', function() { describe('root replacement with applyOperation', function() { describe('_get operation', function() { it('should get root value', function() { - var obj = [ + const obj = [ { people: [{ name: 'Marilyn' }, { name: 'Monroe' }] } ]; - var patch = { op: '_get', path: '' }; + const patch = { op: '_get', path: '' }; jsonpatch.applyOperation(obj, patch); @@ -79,11 +79,11 @@ describe('root replacement with applyOperation', function() { ]); }); it('should get deep value', function() { - var obj = { + const obj = { people: [{ name: 'Marilyn' }, { name: 'Monroe' }] }; - var patch = { op: '_get', path: '/people/1/name' }; + const patch = { op: '_get', path: '/people/1/name' }; jsonpatch.applyOperation(obj, patch); @@ -92,10 +92,10 @@ describe('root replacement with applyOperation', function() { }); describe('add operation', function() { it('should `add` an object (on a json document of type object)) - in place', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: { @@ -108,10 +108,10 @@ describe('root replacement with applyOperation', function() { }); }); it('should `add` an object (on a json document of type object) - and return', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: { @@ -123,12 +123,12 @@ describe('root replacement with applyOperation', function() { }); }); it('should `add` an object (on a json document of type array) - and return', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: { @@ -140,12 +140,12 @@ describe('root replacement with applyOperation', function() { }); }); it('should `add` an array (on a json document of type array) - in place', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: [ @@ -161,12 +161,12 @@ describe('root replacement with applyOperation', function() { ]); }); it('should `add` an array (on a json document of type array) - and return', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: [ @@ -182,9 +182,9 @@ describe('root replacement with applyOperation', function() { ]); }); it('should `add` an array prop', function() { - var obj = []; + const obj = []; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '/prop', value: 'arrayProp' @@ -193,10 +193,10 @@ describe('root replacement with applyOperation', function() { expect(newObj.prop).toEqual('arrayProp'); }); it('should `replace` an array prop', function() { - var obj = []; + const obj = []; obj.prop = 'oldArrayProp'; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '/prop', value: 'arrayProp' @@ -205,10 +205,10 @@ describe('root replacement with applyOperation', function() { expect(newObj.prop).toEqual('arrayProp'); }); it('should `add` an array (on a json document of type object) - and return', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: [ @@ -224,10 +224,10 @@ describe('root replacement with applyOperation', function() { ]); }); it('should `add` a primitive (on a json document of type object) - and return', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: 1 @@ -235,12 +235,12 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual(1); }); it('should `add` with a primitive (on a json document of type array) - and return', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: 1 @@ -250,10 +250,10 @@ describe('root replacement with applyOperation', function() { }); describe('replace operation', function() { it('should `replace` with an object (on a json document of type object)', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: { @@ -265,12 +265,12 @@ describe('root replacement with applyOperation', function() { }); }); it('should `replace` with an object (on a json document of type array)', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: { @@ -282,12 +282,12 @@ describe('root replacement with applyOperation', function() { }); }); it('should `replace` with an array (on a json document of type array)', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: [ @@ -303,10 +303,10 @@ describe('root replacement with applyOperation', function() { ]); }); it('should `replace` with an array (on a json document of type object)', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: [ @@ -322,10 +322,10 @@ describe('root replacement with applyOperation', function() { ]); }); it('should `replace` with a primitive (on a json document of type object)', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: 1 @@ -333,12 +333,12 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual(1); }); it('should `replace` with a primitive (on a json document of type array)', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: 1 @@ -348,22 +348,22 @@ describe('root replacement with applyOperation', function() { }); describe('remove operation', function() { it('should `remove` root (on a json document of type array)', function() { - var obj = [ + const obj = [ { hello: 'world' } ]; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'remove', path: '' }).newDocument; expect(newObj).toEqual(null); }); it('should `remove` root (on a json document of type object)', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'remove', path: '' }).newDocument; @@ -373,10 +373,10 @@ describe('root replacement with applyOperation', function() { describe('move operation', function() { it('should `move` a child of type object to root (on a json document of type object)', function() { - var obj = { + const obj = { child: { name: 'Charles' } }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'move', from: '/child', path: '' @@ -384,10 +384,10 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual({ name: 'Charles' }); }); it('should `move` a child of type object to root (on a json document of type array)', function() { - var obj = { + const obj = { child: [{ name: 'Charles' }] }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'move', from: '/child/0', path: '' @@ -395,10 +395,10 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual({ name: 'Charles' }); }); it('should `move` a child of type array to root (on a json document of type object)', function() { - var obj = { + const obj = { child: [{ name: 'Charles' }] }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'move', from: '/child', path: '' @@ -408,10 +408,10 @@ describe('root replacement with applyOperation', function() { }); describe('copy operation', function() { it('should `copy` a child of type object to root (on a json document of type object) - and return', function() { - var obj = { + const obj = { child: { name: 'Charles' } }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'copy', from: '/child', path: '' @@ -419,10 +419,10 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual({ name: 'Charles' }); }); it('should `copy` a child of type object to root (on a json document of type array) - and return', function() { - var obj = { + const obj = { child: [{ name: 'Charles' }] }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'copy', from: '/child/0', path: '' @@ -430,10 +430,10 @@ describe('root replacement with applyOperation', function() { expect(newObj).toEqual({ name: 'Charles' }); }); it('should `copy` a child of type array to root (on a json document of type object) - and return', function() { - var obj = { + const obj = { child: [{ name: 'Charles' }] }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'copy', from: '/child', path: '' @@ -443,10 +443,10 @@ describe('root replacement with applyOperation', function() { }); describe('test operation', function() { it('should `test` against root (on a json document of type object) - and return true', function() { - var obj = { + const obj = { hello: 'world' }; - var result = jsonpatch.applyOperation(obj, { + const result = jsonpatch.applyOperation(obj, { op: 'test', path: '', value: { @@ -456,7 +456,7 @@ describe('root replacement with applyOperation', function() { expect(result).toEqual(obj); }); it('should `test` against root (on a json document of type object) - and return false', function() { - var obj = { + const obj = { hello: 'world' }; expect(() => @@ -468,7 +468,7 @@ describe('root replacement with applyOperation', function() { ).toThrow(); }); it('should `test` against root (on a json document of type array) - and return false', function() { - var obj = [ + const obj = [ { hello: 'world' } @@ -487,7 +487,7 @@ describe('root replacement with applyOperation', function() { /* this is just a copy-paste of original specs, but with using applyOperation, to test for non-root patches */ describe('core - using applyOperation', function() { it("shouldn't touch original tree", function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -495,7 +495,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation( + const newObj = jsonpatch.applyOperation( obj, { op: 'add', @@ -516,7 +516,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply add', function() { - var obj = { + let obj = { foo: 1, baz: [ { @@ -524,7 +524,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation(obj, { + let newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '/bar', value: [1, 2, 3, 4] @@ -538,7 +538,7 @@ describe('core - using applyOperation', function() { ], bar: [1, 2, 3, 4] }); - var newObj = jsonpatch.applyOperation(newObj, { + newObj = jsonpatch.applyOperation(newObj, { op: 'add', path: '/baz/0/foo', value: 'world' @@ -562,7 +562,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation(obj, { + newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '/bar', value: true @@ -585,7 +585,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation(obj, { + newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '/bar', value: false @@ -608,7 +608,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation(obj, { + newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '/bar', value: null @@ -625,10 +625,10 @@ describe('core - using applyOperation', function() { }); it('should apply add on root', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'add', path: '', value: { @@ -641,7 +641,7 @@ describe('core - using applyOperation', function() { }); it('should apply remove', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -651,7 +651,7 @@ describe('core - using applyOperation', function() { bar: [1, 2, 3, 4] }; - var newObj = jsonpatch.applyOperation(obj, { + let newObj = jsonpatch.applyOperation(obj, { op: 'remove', path: '/bar' }).newDocument; @@ -663,7 +663,7 @@ describe('core - using applyOperation', function() { } ] }); - var newObj = jsonpatch.applyOperation(newObj, { + newObj = jsonpatch.applyOperation(newObj, { op: 'remove', path: '/baz/0/qux' }).newDocument; @@ -673,7 +673,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply replace', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -681,7 +681,7 @@ describe('core - using applyOperation', function() { } ] }; - var newObj = jsonpatch.applyOperation(obj, { + let newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '/foo', value: [1, 2, 3, 4] @@ -694,7 +694,7 @@ describe('core - using applyOperation', function() { } ] }); - var newObj = jsonpatch.applyOperation(newObj, { + newObj = jsonpatch.applyOperation(newObj, { op: 'replace', path: '/baz/0/qux', value: 'world' @@ -709,10 +709,10 @@ describe('core - using applyOperation', function() { }); }); it('should apply replace on root', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'replace', path: '', value: { @@ -725,7 +725,7 @@ describe('core - using applyOperation', function() { }); }); it('should apply test', function() { - var obj = { + const obj = { foo: { bar: [1, 2, 5, 4] }, @@ -824,7 +824,7 @@ describe('core - using applyOperation', function() { }); it('should apply test on root', function() { - var obj = { + const obj = { hello: 'world' }; expect( @@ -846,7 +846,7 @@ describe('core - using applyOperation', function() { }); it('should apply move', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -855,7 +855,7 @@ describe('core - using applyOperation', function() { ] }; - var newObj = jsonpatch.applyOperation(obj, { + let newObj = jsonpatch.applyOperation(obj, { op: 'move', from: '/foo', path: '/bar' @@ -869,7 +869,7 @@ describe('core - using applyOperation', function() { bar: 1 }); - var newObj = jsonpatch.applyOperation(newObj, { + newObj = jsonpatch.applyOperation(newObj, { op: 'move', from: '/baz/0/qux', path: '/baz/1' @@ -883,13 +883,13 @@ describe('core - using applyOperation', function() { it('should apply move on root', function() { //investigate if this test is right (https://github.com/Starcounter-Jack/JSON-Patch/issues/40) - var obj = { + const obj = { hello: 'world', location: { city: 'Vancouver' } }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'move', from: '/location', path: '' @@ -901,7 +901,7 @@ describe('core - using applyOperation', function() { }); it('should apply copy', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -910,7 +910,7 @@ describe('core - using applyOperation', function() { ] }; - var newObj = jsonpatch.applyOperation(obj, { + let newObj = jsonpatch.applyOperation(obj, { op: 'copy', from: '/foo', path: '/bar' @@ -926,7 +926,7 @@ describe('core - using applyOperation', function() { bar: 1 }); - var newObj = jsonpatch.applyOperation(newObj, { + newObj = jsonpatch.applyOperation(newObj, { op: 'copy', from: '/baz/0/qux', path: '/baz/1' @@ -945,13 +945,13 @@ describe('core - using applyOperation', function() { }); it('should apply copy on root', function() { - var obj = { + const obj = { hello: 'world', location: { city: 'Vancouver' } }; - var newObj = jsonpatch.applyOperation(obj, { + const newObj = jsonpatch.applyOperation(obj, { op: 'copy', from: '/location', path: '' @@ -964,7 +964,7 @@ describe('core - using applyOperation', function() { describe('core', function() { it("shouldn't touch original tree", function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -972,7 +972,7 @@ describe('core', function() { } ] }; - var newObj = jsonpatch.applyPatch( + const newObj = jsonpatch.applyPatch( obj, [ { @@ -995,7 +995,7 @@ describe('core', function() { }); }); it('should apply add', function() { - var obj = { + let obj = { foo: 1, baz: [ { @@ -1114,10 +1114,10 @@ describe('core', function() { }); it('should apply add on root', function() { - var obj = { + const obj = { hello: 'world' }; - var newObj = jsonpatch.applyPatch(obj, [ + const newObj = jsonpatch.applyPatch(obj, [ { op: 'add', path: '', @@ -1133,7 +1133,7 @@ describe('core', function() { }); it('should apply remove', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -1172,7 +1172,7 @@ describe('core', function() { }); it('should apply replace', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -1215,10 +1215,10 @@ describe('core', function() { }); it('should apply replace on root', function() { - var obj = { + const obj = { hello: 'world' }; - var newObject = jsonpatch.applyPatch(obj, [ + const newObject = jsonpatch.applyPatch(obj, [ { op: 'replace', path: '', @@ -1234,7 +1234,7 @@ describe('core', function() { }); it('should apply test', function() { - var obj = { + const obj = { foo: { bar: [1, 2, 5, 4] }, @@ -1354,7 +1354,7 @@ describe('core', function() { }); it('should apply test on root', function() { - var obj = { + const obj = { hello: 'world' }; expect( @@ -1382,7 +1382,7 @@ describe('core', function() { }); it('should apply move', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -1422,13 +1422,13 @@ describe('core', function() { it('should apply move on root', function() { //investigate if this test is right (https://github.com/Starcounter-Jack/JSON-Patch/issues/40) - var obj = { + const obj = { hello: 'world', location: { city: 'Vancouver' } }; - var newObj = jsonpatch.applyPatch(obj, [ + const newObj = jsonpatch.applyPatch(obj, [ { op: 'move', from: '/location', @@ -1442,7 +1442,7 @@ describe('core', function() { }); it('should apply copy', function() { - var obj = { + const obj = { foo: 1, baz: [ { @@ -1488,13 +1488,13 @@ describe('core', function() { }); it('should apply copy on root', function() { - var obj = { + const obj = { hello: 'world', location: { city: 'Vancouver' } }; - var newObj = jsonpatch.applyPatch(obj, [ + const newObj = jsonpatch.applyPatch(obj, [ { op: 'copy', from: '/location', @@ -1508,8 +1508,8 @@ describe('core', function() { }); it('should apply copy, without leaving cross-reference between nodes', function() { - var obj = {}; - var patchset = [ + const obj = {}; + const patchset = [ { op: 'add', path: '/foo', value: [] }, { op: 'add', path: '/foo/-', value: 1 }, { op: 'copy', from: '/foo', path: '/bar' }, @@ -1525,8 +1525,8 @@ describe('core', function() { }); it('should use value object as a reference', function() { - var obj1 = {}; - var patch = [{ op: 'add', path: '/foo', value: [] }]; + const obj1 = {}; + const patch = [{ op: 'add', path: '/foo', value: [] }]; jsonpatch.applyPatch(obj1, patch, false); @@ -1534,7 +1534,7 @@ describe('core', function() { }); describe('returning removed elements >', function() { - var obj; + let obj; beforeEach(function() { obj = { name: 'jack', @@ -1544,7 +1544,7 @@ describe('core', function() { }); it('return removed element when removing from object', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'remove', path: '/name' @@ -1553,7 +1553,7 @@ describe('core', function() { expect(result[0].removed).toEqual('jack'); }); it('return removed element when replacing in object', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'replace', path: '/name', @@ -1563,7 +1563,7 @@ describe('core', function() { expect(result[0].removed).toEqual('jack'); }); it('return removed element when moving in object', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'move', from: '/name', @@ -1574,7 +1574,7 @@ describe('core', function() { }); it('return removed element when removing from array', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'remove', path: '/languages/1' @@ -1583,7 +1583,7 @@ describe('core', function() { expect(result[0].removed).toEqual('haskell'); }); it('return removed element when replacing in array', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'replace', path: '/languages/1', @@ -1593,7 +1593,7 @@ describe('core', function() { expect(result[0].removed).toEqual('haskell'); }); it('return removed element when moving in array', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'move', from: '/hobby', @@ -1603,7 +1603,7 @@ describe('core', function() { expect(result[0].removed).toEqual('haskell'); }); it('return root when removing root', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'remove', path: '' @@ -1616,7 +1616,7 @@ describe('core', function() { }); }); it('return root when replacing root', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'replace', path: '', @@ -1632,7 +1632,7 @@ describe('core', function() { }); }); it('return root when moving to root', function() { - var result = jsonpatch.applyPatch(obj, [ + const result = jsonpatch.applyPatch(obj, [ { op: 'move', from: '/languages', @@ -1651,7 +1651,7 @@ describe('core', function() { describe('undefined - JS to JSON projection / JSON to JS extension', function() { describe('jsonpatch should apply', function() { it('add for properties already set to `undefined` in target JS document', function() { - var obj = { + const obj = { hello: 'world', nothing: undefined }; @@ -1670,7 +1670,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('add for properties with value set to `undefined` (extension)', function() { - var obj = { + const obj = { hello: 'world' }; jsonpatch.applyPatch(obj, [ @@ -1688,7 +1688,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('remove on element already set to `undefined`, and remove it completely', function() { - var obj = { + const obj = { foo: 1, not: undefined }; @@ -1704,7 +1704,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('remove on array element set to `undefined`', function() { - var obj = { + const obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1722,7 +1722,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('replace on element set to `undefined`', function() { - var obj = { + const obj = { foo: 1, not: undefined }; @@ -1740,7 +1740,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace on array element set to `undefined`', function() { - var obj = { + const obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1758,7 +1758,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace element with `undefined` (extension)', function() { - var obj = { + const obj = { foo: 1 }; @@ -1774,7 +1774,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('replace array element with `undefined` (extension)', function() { - var obj = { + const obj = { foo: 1, bar: [0, 1, 2, 3] }; @@ -1792,7 +1792,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); }); it('test on element set to `undefined`', function() { - var obj = { + const obj = { foo: 1, not: undefined }; @@ -1816,7 +1816,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() ).toBe(true); }); it('test on array element set to `undefined`', function() { - var obj = { + const obj = { foo: 1, bar: [0, 1, undefined, 3] }; @@ -1850,7 +1850,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('move of `undefined`', function() { - var obj = { + const obj = { foo: undefined, baz: 'defined' }; @@ -1880,7 +1880,7 @@ describe('undefined - JS to JSON projection / JSON to JS extension', function() }); it('copy of `undefined` as `null` (like `JSON.stringify` does)', function() { - var obj = { + const obj = { foo: undefined, baz: 'defined' }; diff --git a/test/spec/duplexBenchmark.js b/test/spec/duplexBenchmark.js index 7e583793..2a22e874 100644 --- a/test/spec/duplexBenchmark.js +++ b/test/spec/duplexBenchmark.js @@ -11,14 +11,14 @@ if (typeof jsonpatch === 'undefined') { } if (typeof Benchmark === 'undefined') { - var Benchmark = require('benchmark'); - var benchmarkResultsToConsole = require('./../lib/benchmark_console_reporter.js').benchmarkResultsToConsole; + global.Benchmark = require('benchmark'); + global.benchmarkResultsToConsole = require('./../lib/benchmark_console_reporter.js').benchmarkResultsToConsole; } -var suite = new Benchmark.Suite(); -suite.add('generate operation', { +const duplexSuite = new Benchmark.Suite(); +duplexSuite.add('generate operation', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -30,7 +30,7 @@ suite.add('generate operation', { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); }, fn: function() { obj.firstName = 'Joachim'; @@ -38,12 +38,12 @@ suite.add('generate operation', { obj.phoneNumbers[0].number = '123'; obj.phoneNumbers[1].number = '456'; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); } }); -suite.add('generate operation and re-apply', { +duplexSuite.add('generate operation and re-apply', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -55,7 +55,7 @@ suite.add('generate operation and re-apply', { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); }, fn: function() { obj.firstName = 'Joachim'; @@ -63,7 +63,7 @@ suite.add('generate operation and re-apply', { obj.phoneNumbers[0].number = '123'; obj.phoneNumbers[1].number = '456'; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); obj2 = { firstName: 'Albert', lastName: 'Einstein', @@ -80,9 +80,9 @@ suite.add('generate operation and re-apply', { jsonpatch.applyPatch(obj2, patches); } }); -suite.add('compare operation', { +duplexSuite.add('compare operation', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -94,7 +94,7 @@ suite.add('compare operation', { } ] }; - var obj2 = { + const obj2 = { firstName: 'Joachim', lastName: 'Wester', mobileNumbers: [ @@ -108,13 +108,13 @@ suite.add('compare operation', { }; }, fn: function() { - var patches = jsonpatch.compare(obj, obj2); + const patches = jsonpatch.compare(obj, obj2); } }); -suite.add('compare operation same but deep objects', { +duplexSuite.add('compare operation same but deep objects', { setup: function() { - var depth = 10; + const depth = 10; function shallowObj() { return { @@ -132,23 +132,23 @@ suite.add('compare operation same but deep objects', { } }; } - var obj = shallowObj(); - var node = obj; + const obj = shallowObj(); + const node = obj; while (depth-- > 0) { node.nested = shallowObj(); node = node.nested; } - var obj2 = obj; + const obj2 = obj; }, fn: function() { - var patches = jsonpatch.compare(obj, obj2); + const patches = jsonpatch.compare(obj, obj2); } }); // Benchmark generating test operations -suite.add('generate operation, invertible = true', { +duplexSuite.add('generate operation, invertible = true', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -160,7 +160,7 @@ suite.add('generate operation, invertible = true', { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); }, fn: function() { obj.firstName = 'Joachim'; @@ -168,12 +168,12 @@ suite.add('generate operation, invertible = true', { obj.phoneNumbers[0].number = '123'; obj.phoneNumbers[1].number = '456'; - var patches = jsonpatch.generate(observer, true); + const patches = jsonpatch.generate(observer, true); } }); -suite.add('generate operation and re-apply, invertible = true', { +duplexSuite.add('generate operation and re-apply, invertible = true', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -185,7 +185,7 @@ suite.add('generate operation and re-apply, invertible = true', { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); }, fn: function() { obj.firstName = 'Joachim'; @@ -193,7 +193,7 @@ suite.add('generate operation and re-apply, invertible = true', { obj.phoneNumbers[0].number = '123'; obj.phoneNumbers[1].number = '456'; - var patches = jsonpatch.generate(observer, true); + const patches = jsonpatch.generate(observer, true); obj2 = { firstName: 'Albert', lastName: 'Einstein', @@ -210,9 +210,9 @@ suite.add('generate operation and re-apply, invertible = true', { jsonpatch.applyPatch(obj2, patches); } }); -suite.add('compare operation, invertible = true', { +duplexSuite.add('compare operation, invertible = true', { setup: function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -224,7 +224,7 @@ suite.add('compare operation, invertible = true', { } ] }; - var obj2 = { + const obj2 = { firstName: 'Joachim', lastName: 'Wester', mobileNumbers: [ @@ -238,13 +238,13 @@ suite.add('compare operation, invertible = true', { }; }, fn: function() { - var patches = jsonpatch.compare(obj, obj2, true); + const patches = jsonpatch.compare(obj, obj2, true); } }); -suite.add('compare operation same but deep objects, invertible = true', { +duplexSuite.add('compare operation same but deep objects, invertible = true', { setup: function() { - var depth = 10; + const depth = 10; function shallowObj() { return { @@ -262,25 +262,25 @@ suite.add('compare operation same but deep objects, invertible = true', { } }; } - var obj = shallowObj(); - var node = obj; + const obj = shallowObj(); + const node = obj; while (depth-- > 0) { node.nested = shallowObj(); node = node.nested; } - var obj2 = obj; + const obj2 = obj; }, fn: function() { - var patches = jsonpatch.compare(obj, obj2, true); + const patches = jsonpatch.compare(obj, obj2, true); } }); // if we are in the browser with benchmark < 2.1.2 if (typeof benchmarkReporter !== 'undefined') { - benchmarkReporter(suite); + benchmarkReporter(duplexSuite); } else { - suite.on('complete', function() { - benchmarkResultsToConsole(suite); + duplexSuite.on('complete', function() { + benchmarkResultsToConsole(duplexSuite); }); - suite.run(); + duplexSuite.run(); } diff --git a/test/spec/duplexSpec.js b/test/spec/duplexSpec.js index e4d4e182..419de449 100644 --- a/test/spec/duplexSpec.js +++ b/test/spec/duplexSpec.js @@ -1,5 +1,3 @@ -var obj, obj2, patches; - import * as jsonpatch from '../../module/duplex.js'; import {EventTarget, defineEventAttribute} from "../../node_modules/event-target-shim/dist/event-target-shim.mjs"; @@ -21,20 +19,20 @@ function trigger(eventName) { } function getPatchesUsingGenerate(objFactory, objChanger) { - var obj = objFactory(); - var observer = jsonpatch.observe(obj); + const obj = objFactory(); + const observer = jsonpatch.observe(obj); objChanger(obj); return jsonpatch.generate(observer); } function getPatchesUsingCompare(objFactory, objChanger) { - var obj = objFactory(); - var mirror = JSON.parse(JSON.stringify(obj)); + const obj = objFactory(); + const mirror = JSON.parse(JSON.stringify(obj)); objChanger(obj); return jsonpatch.compare(mirror, JSON.parse(JSON.stringify(obj))); } -var customMatchers = { +const customMatchers = { /** * This matcher is only needed in Chrome 28 (Chrome 28 cannot successfully compare observed objects immediately after they have been changed. Chrome 30 is unaffected) * @param obj @@ -104,7 +102,7 @@ describe('duplex', function() { describe('generate', function() { it('should generate replace', function() { - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -117,14 +115,14 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.firstName = 'Joachim'; obj.lastName = 'Wester'; obj.phoneNumbers[0].number = '123'; obj.phoneNumbers[1].number = '456'; - var patches = jsonpatch.generate(observer); - obj2 = { + const patches = jsonpatch.generate(observer); + const obj2 = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -142,7 +140,7 @@ describe('duplex', function() { }); it('should generate replace (escaped chars)', function() { - obj = { + const obj = { '/name/first': 'Albert', '/name/last': 'Einstein', '~phone~/numbers': [ @@ -155,14 +153,14 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj['/name/first'] = 'Joachim'; obj['/name/last'] = 'Wester'; obj['~phone~/numbers'][0].number = '123'; obj['~phone~/numbers'][1].number = '456'; - var patches = jsonpatch.generate(observer); - obj2 = { + const patches = jsonpatch.generate(observer); + const obj2 = { '/name/first': 'Albert', '/name/last': 'Einstein', '~phone~/numbers': [ @@ -184,23 +182,23 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var person1 = { + const person1 = { firstName: 'Alexandra', lastName: 'Galbreath' }; - var person2 = { + const person2 = { firstName: 'Lisa', lastName: 'Mendoza' }; - var observer1 = jsonpatch.observe(person1); - var observer2 = jsonpatch.observe(person2); + const observer1 = jsonpatch.observe(person1); + const observer2 = jsonpatch.observe(person2); person1.firstName = 'Alexander'; person2.firstName = 'Lucas'; - var patch1 = jsonpatch.generate(observer1, testInvertible); - var patch2 = jsonpatch.generate(observer2, testInvertible); + const patch1 = jsonpatch.generate(observer1, testInvertible); + const patch2 = jsonpatch.generate(observer2, testInvertible); expect(patch1).toReallyEqual([ ...insertIf(testInvertible, { @@ -234,7 +232,7 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -247,10 +245,10 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.firstName = 'Marcin'; - var patches = jsonpatch.generate(observer, testInvertible); + let patches = jsonpatch.generate(observer, testInvertible); expect(patches).toReallyEqual([ ...insertIf(testInvertible, { op: "test", @@ -299,7 +297,7 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -312,10 +310,10 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.phoneNumbers[0].number = '123'; - var patches = jsonpatch.generate(observer, testInvertible); + let patches = jsonpatch.generate(observer, testInvertible); expect(patches).toReallyEqual([ ...insertIf(testInvertible, { op: "test", @@ -362,10 +360,10 @@ describe('duplex', function() { it('should generate replace (changes in new array cell, primitive values)', function() { const arr = [1]; - var observer = jsonpatch.observe(arr); + const observer = jsonpatch.observe(arr); arr.push(2); - var patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'add', @@ -376,7 +374,7 @@ describe('duplex', function() { arr[0] = 3; - var patches = jsonpatch.generate(observer); + patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -387,7 +385,7 @@ describe('duplex', function() { arr[1] = 4; - var patches = jsonpatch.generate(observer); + patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -405,13 +403,13 @@ describe('duplex', function() { } ]; - var observer = jsonpatch.observe(arr); + const observer = jsonpatch.observe(arr); arr.push({ id: 2, name: 'Jerry' }); - var patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'add', @@ -425,7 +423,7 @@ describe('duplex', function() { arr[0].id = 3; - var patches = jsonpatch.generate(observer); + patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -436,7 +434,7 @@ describe('duplex', function() { arr[1].id = 4; - var patches = jsonpatch.generate(observer); + patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -447,7 +445,7 @@ describe('duplex', function() { }); it('should generate add', function() { - obj = { + const obj = { lastName: 'Einstein', phoneNumbers: [ { @@ -455,7 +453,7 @@ describe('duplex', function() { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.firstName = 'Joachim'; obj.lastName = 'Wester'; @@ -464,8 +462,8 @@ describe('duplex', function() { number: '456' }); - patches = jsonpatch.generate(observer); - obj2 = { + const patches = jsonpatch.generate(observer); + const obj2 = { lastName: 'Einstein', phoneNumbers: [ { @@ -479,7 +477,7 @@ describe('duplex', function() { }); it('should generate remove', function() { - obj = { + const obj = { lastName: 'Einstein', firstName: 'Albert', phoneNumbers: [ @@ -491,15 +489,15 @@ describe('duplex', function() { } ] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); delete obj.firstName; obj.lastName = 'Wester'; obj.phoneNumbers[0].number = '123'; obj.phoneNumbers.pop(1); - patches = jsonpatch.generate(observer); - obj2 = { + const patches = jsonpatch.generate(observer); + const obj2 = { lastName: 'Einstein', firstName: 'Albert', phoneNumbers: [ @@ -521,15 +519,15 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - obj = { + const obj = { items: ['a', 'b', 'c'] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.items.pop(); obj.items.pop(); - patches = jsonpatch.generate(observer, testInvertible); + const patches = jsonpatch.generate(observer, testInvertible); //array indexes must be sorted descending, otherwise there is an index collision in apply expect(patches).toReallyEqual([ @@ -553,7 +551,7 @@ describe('duplex', function() { }, ]); - obj2 = { + const obj2 = { items: ['a', 'b', 'c'] }; jsonpatch.applyPatch(obj2, patches); @@ -562,14 +560,14 @@ describe('duplex', function() { }); it('should not generate the same patch twice (replace)', function() { - obj = { + const obj = { lastName: 'Einstein' }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.lastName = 'Wester'; - patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -583,14 +581,14 @@ describe('duplex', function() { }); it('should not generate the same patch twice (add)', function() { - obj = { + const obj = { lastName: 'Einstein' }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.firstName = 'Albert'; - patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'add', @@ -604,14 +602,14 @@ describe('duplex', function() { }); it('should not generate the same patch twice (remove)', function() { - obj = { + const obj = { lastName: 'Einstein' }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); delete obj.lastName; - patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'remove', @@ -624,15 +622,14 @@ describe('duplex', function() { }); it('should ignore array properties', function() { - var obj = { + const obj = { array: [1, 2, 3] }; - var patches; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.array.value = 1; - patches = jsonpatch.generate(observer); + let patches = jsonpatch.generate(observer); expect(patches.length).toReallyEqual(0); obj.array.value = 2; @@ -641,9 +638,9 @@ describe('duplex', function() { }); it('should respect toJSON', function() { - var a = {}; + const a = {}; a.self = a; - var obj = { + const obj = { a: a, b: 3, toJSON: function() { @@ -653,16 +650,16 @@ describe('duplex', function() { } }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.b = 5; - patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches.length).toReallyEqual(1); }); it('should respect toJSON in nested objects', function() { - var a = {}; + const a = {}; a.self = a; - var outer = { + const outer = { obj: { a: a, b: 3, @@ -674,9 +671,9 @@ describe('duplex', function() { } }; - var observer = jsonpatch.observe(outer); + const observer = jsonpatch.observe(outer); outer.obj.b = 5; - patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches.length).toReallyEqual(1); expect(patches[0].path).toReallyEqual('/obj/b'); @@ -684,31 +681,31 @@ describe('duplex', function() { }); /*it('should not generate the same patch twice (move)', function() { //"move" is not implemented yet in jsonpatch.generate - obj = { lastName: {str: "Einstein"} }; - var observer = jsonpatch.observe(obj); + const obj = { lastName: {str: "Einstein"} }; + const observer = jsonpatch.observe(obj); obj.lastName2 = obj.lastName; delete obj.lastName; - patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'move', from: '/lastName', to: '/lastName2' } ]); - patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([]); });*/ xdescribe('undefined - JS to JSON projection', function() { it('when value is set to `undefined`, should generate remove (undefined is JSON.stringified to no value)', function() { - var obj = { + const obj = { foo: 'bar' }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.foo = undefined; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'remove', @@ -718,26 +715,26 @@ describe('duplex', function() { }); it('when new property is added, and set to `undefined`, nothing should be generated (undefined is JSON.stringified to no value)', function() { - var obj = { + const obj = { foo: 'bar' }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.baz = undefined; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([]); }); it('when array element is set to `undefined`, should generate replace to `null` (undefined array elements are JSON.stringified to `null`)', function() { - var obj = { + const obj = { foo: [0, 1, 2] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.foo[1] = undefined; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -748,14 +745,14 @@ describe('duplex', function() { }); it('when `undefined` property is set to something, should generate add (undefined is JSON.stringified to no value)', function() { - var obj = { + const obj = { foo: undefined }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.foo = 'something'; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'add', @@ -765,14 +762,14 @@ describe('duplex', function() { ]); }); it('when `undefined` array element is set to something, should generate replace (undefined array elements are JSON.stringified to `null`)', function() { - var obj = { + const obj = { foo: [0, undefined, 2] }; - var observer = jsonpatch.observe(obj); + const observer = jsonpatch.observe(obj); obj.foo[1] = 1; - var patches = jsonpatch.generate(observer); + const patches = jsonpatch.generate(observer); expect(patches).toReallyEqual([ { op: 'replace', @@ -786,42 +783,42 @@ describe('duplex', function() { describe('undefined - JSON to JS extension', function() { describe('should generate empty patch, when', function() { it('when new property is set to `undefined`', function() { - var objFactory = function() { + const objFactory = function() { return { foo: 'bar' }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { obj.baz = undefined; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([]); expect(genereatedPatches).toReallyEqual(comparedPatches); }); it('when an `undefined` property is deleted', function() { - var objFactory = function() { + const objFactory = function() { return { foo: undefined }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { delete obj.foo; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([]); expect(genereatedPatches).toReallyEqual(comparedPatches); @@ -830,21 +827,21 @@ describe('duplex', function() { describe('should generate add, when', function() { it('`undefined` property is set to something', function() { - var objFactory = function() { + const objFactory = function() { return { foo: undefined }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { obj.foo = 'something'; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([ { @@ -859,21 +856,21 @@ describe('duplex', function() { describe('should generate remove, when', function() { it('value is set to `undefined`', function() { - var objFactory = function() { + const objFactory = function() { return { foo: 'bar' }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { obj.foo = undefined; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([ { @@ -887,21 +884,21 @@ describe('duplex', function() { describe('should generate replace, when', function() { it('array element is set to `undefined`', function() { - var objFactory = function() { + const objFactory = function() { return { foo: [0, 1, 2] }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { obj.foo[1] = undefined; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([ { @@ -913,21 +910,21 @@ describe('duplex', function() { expect(genereatedPatches).toReallyEqual(comparedPatches); }); it('`undefined` array element is set to something', function() { - var objFactory = function() { + const objFactory = function() { return { foo: [0, undefined, 2] }; }; - var objChanger = function(obj) { + const objChanger = function(obj) { obj.foo[1] = 1; }; - var genereatedPatches = getPatchesUsingGenerate( + const genereatedPatches = getPatchesUsingGenerate( objFactory, objChanger ); - var comparedPatches = getPatchesUsingCompare(objFactory, objChanger); + const comparedPatches = getPatchesUsingCompare(objFactory, objChanger); expect(genereatedPatches).toReallyEqual([ { @@ -945,10 +942,10 @@ describe('duplex', function() { describe('apply', function() { // https://tools.ietf.org/html/rfc6902#appendix-A.16 it('should add an Array Value', function() { - var obj = { + const obj = { foo: ['bar'] }; - var patches = [ + const patches = [ { op: 'add', path: '/foo/-', @@ -965,9 +962,9 @@ describe('duplex', function() { describe('callback', function() { it('should generate replace', function(done) { - var patches; + let patches; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -992,7 +989,7 @@ describe('duplex', function() { trigger('keyup'); function patchesChanged() { - obj2 = { + const obj2 = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1014,9 +1011,10 @@ describe('duplex', function() { it('should generate replace (double change, shallow object)', function( done ) { - var lastPatches, called = 0; + let lastPatches; + let called = 0; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1083,9 +1081,10 @@ describe('duplex', function() { }); it('should generate replace (double change, deep object)', function(done) { - var lastPatches, called = 0; + let lastPatches; + let called = 0; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1152,9 +1151,11 @@ describe('duplex', function() { }); it('generate should execute callback synchronously', function(done) { - var lastPatches, called = 0, res; + let lastPatches; + let called = 0; + let res; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1167,7 +1168,7 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj, function(patches) { + const observer = jsonpatch.observe(obj, function(patches) { called++; lastPatches = patches; }); @@ -1202,9 +1203,9 @@ describe('duplex', function() { }); it('should unobserve then observe again', function(done) { - var called = 0; + let called = 0; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1217,7 +1218,7 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj, function(patches) { + const observer = jsonpatch.observe(obj, function(patches) { called++; }); @@ -1238,7 +1239,7 @@ describe('duplex', function() { setTimeout(function() { expect(called).toReallyEqual(1); - observer = jsonpatch.observe(obj, function(patches) { + const observer2 = jsonpatch.observe(obj, function(patches) { called++; }); @@ -1254,9 +1255,9 @@ describe('duplex', function() { }); it('should unobserve then observe again (deep value)', function(done) { - var called = 0; + let called = 0; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1269,7 +1270,7 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj, function(patches) { + const observer = jsonpatch.observe(obj, function(patches) { called++; }); @@ -1289,7 +1290,7 @@ describe('duplex', function() { setTimeout(function() { expect(called).toReallyEqual(1); - observer = jsonpatch.observe(obj, function(patches) { + const observer2 = jsonpatch.observe(obj, function(patches) { called++; }); @@ -1308,9 +1309,9 @@ describe('duplex', function() { it('calling unobserve should deliver pending changes synchronously', function( done ) { - var lastPatches = ''; + let lastPatches = ''; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1323,7 +1324,7 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj, function(patches) { + const observer = jsonpatch.observe(obj, function(patches) { lastPatches = patches; }); @@ -1345,13 +1346,13 @@ describe('duplex', function() { it('should handle callbacks that calls observe() and unobserve() internally', function( done ) { - var obj = { + const obj = { foo: 'bar' }; - var observer; - var callbackCalled, count = 0; - var callback = jasmine + let observer; + let count = 0; + const callback = jasmine .createSpy('callback', function() { jsonpatch.unobserve(obj, observer); @@ -1387,12 +1388,12 @@ describe('duplex', function() { }); it('should generate patch after `mouseup` event while observing', function(done) { - obj = { + const obj = { lastName: 'Einstein' }; - var lastPatches; - var callCount = 0; - var observer = jsonpatch.observe(obj, function(patches) { + let lastPatches; + let callCount = 0; + const observer = jsonpatch.observe(obj, function(patches) { callCount++; lastPatches = patches; }); @@ -1422,12 +1423,12 @@ describe('duplex', function() { }); it('should generate patch after `mousedown` event while observing', function(done) { - obj = { + const obj = { lastName: 'Einstein' }; - var lastPatches; - var callCount = 0; - var observer = jsonpatch.observe(obj, function(patches) { + let lastPatches; + let callCount = 0; + const observer = jsonpatch.observe(obj, function(patches) { callCount++; lastPatches = patches; }); @@ -1456,12 +1457,12 @@ describe('duplex', function() { }); it('should generate patch after `keyup` event while observing', function(done) { - obj = { + const obj = { lastName: 'Einstein' }; - var lastPatches; - var callCount = 0; - var observer = jsonpatch.observe(obj, function(patches) { + let lastPatches; + let callCount = 0; + const observer = jsonpatch.observe(obj, function(patches) { callCount++; lastPatches = patches; }); @@ -1490,12 +1491,12 @@ describe('duplex', function() { }); it('should generate patch after `keydown` event while observing', function(done) { - obj = { + const obj = { lastName: 'Einstein' }; - var lastPatches; - var callCount = 0; - var observer = jsonpatch.observe(obj, function(patches) { + let lastPatches; + let callCount = 0; + const observer = jsonpatch.observe(obj, function(patches) { callCount++; lastPatches = patches; }); @@ -1524,12 +1525,12 @@ describe('duplex', function() { }); it('should generate patch after `change` event while observing', function(done) { - obj = { + const obj = { lastName: 'Einstein' }; - var lastPatches; - var callCount = 0; - var observer = jsonpatch.observe(obj, function(patches) { + let lastPatches; + let callCount = 0; + const observer = jsonpatch.observe(obj, function(patches) { callCount++; lastPatches = patches; }); @@ -1566,7 +1567,7 @@ describe('duplex', function() { const objA = ['jack']; const objB = {}; - var patches = jsonpatch.compare(objA, objB, testInvertible); + const patches = jsonpatch.compare(objA, objB, testInvertible); expect(patches).toEqual([ ...insertIf(testInvertible, { op: 'test', @@ -1588,7 +1589,7 @@ describe('duplex', function() { return function () { const arr = ['jack']; const obj = {}; - var patches = jsonpatch.compare({ arr: arr }, { arr: obj }, testInvertible); + const patches = jsonpatch.compare({ arr: arr }, { arr: obj }, testInvertible); expect(patches).toEqual([ ...insertIf(testInvertible, { op: 'test', @@ -1611,7 +1612,7 @@ describe('duplex', function() { const arr = ['jack']; const obj = {}; - var patches = jsonpatch.compare({ arr: { deeperArray: arr } }, { arr: { deeperArray: obj } }, testInvertible); + const patches = jsonpatch.compare({ arr: { deeperArray: arr } }, { arr: { deeperArray: obj } }, testInvertible); expect(patches).toEqual([ ...insertIf(testInvertible, { @@ -1632,12 +1633,12 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: { firstName: 'Albert' } }; - var objB = { + const objB = { user: { firstName: 'Albert', lastName: 'Einstein' @@ -1660,13 +1661,13 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: { firstName: 'Albert', lastName: 'Einstein' } }; - var objB = { + const objB = { user: { firstName: 'Albert' } @@ -1691,13 +1692,13 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: { firstName: 'Albert', lastName: 'Einstein' } }; - var objB = { + const objB = { user: { firstName: 'Albert', lastName: 'Collins' @@ -1724,10 +1725,10 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: null }; - var objB = { + const objB = { user: {} }; @@ -1751,10 +1752,10 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: {} }; - var objB = { + const objB = { user: null }; @@ -1778,10 +1779,10 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: undefined }; - var objB = { + const objB = { user: undefined }; @@ -1794,10 +1795,10 @@ describe('duplex', function() { ['invertible = TRUE', true] ], function (testInvertible) { return function () { - var objA = { + const objA = { user: 0 }; - var objB = { + const objB = { user: '' }; @@ -1819,11 +1820,11 @@ describe('duplex', function() { describe('Registering multiple observers with the same callback', function() { it('should register only one observer', function(done) { - var obj = { + const obj = { foo: 'bar' }; - var callback = jasmine.createSpy('callback'); + const callback = jasmine.createSpy('callback'); jsonpatch.observe(obj, callback); jsonpatch.observe(obj, callback); @@ -1841,30 +1842,30 @@ describe('duplex', function() { }); it('should return the same observer if callback has been already registered)', function() { - var obj = { + const obj = { foo: 'bar' }; - var callback = jasmine.createSpy('callback'); + const callback = jasmine.createSpy('callback'); - var observer1 = jsonpatch.observe(obj, callback); - var observer2 = jsonpatch.observe(obj, callback); + const observer1 = jsonpatch.observe(obj, callback); + const observer2 = jsonpatch.observe(obj, callback); expect(observer1).toBe(observer2); }); it('should return a different observer if callback has been unregistered and registered again', function() { - var obj = { + const obj = { foo: 'bar' }; - var callback = jasmine.createSpy('callback'); + const callback = jasmine.createSpy('callback'); - var observer1 = jsonpatch.observe(obj, callback); + const observer1 = jsonpatch.observe(obj, callback); jsonpatch.unobserve(obj, observer1); - var observer2 = jsonpatch.observe(obj, callback); + const observer2 = jsonpatch.observe(obj, callback); expect(observer1).not.toBe(observer2); }); @@ -1872,9 +1873,9 @@ describe('duplex', function() { it('should not call callback on key and mouse events after unobserve', function( done ) { - var called = 0; + let called = 0; - obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1887,7 +1888,7 @@ describe('duplex', function() { ] }; - var observer = jsonpatch.observe(obj, function(patches) { + const observer = jsonpatch.observe(obj, function(patches) { called++; }); @@ -1918,7 +1919,7 @@ describe('duplex', function() { describe('compare', function() { it('should return patch difference between objects', function() { - var obj = { + const obj = { firstName: 'Albert', lastName: 'Einstein', phoneNumbers: [ @@ -1930,7 +1931,7 @@ describe('duplex', function() { } ] }; - var obj2 = { + const obj2 = { firstName: 'Joachim', lastName: 'Wester', mobileNumbers: [ @@ -1943,7 +1944,7 @@ describe('duplex', function() { ] }; - var patches = jsonpatch.compare(obj, obj2); + const patches = jsonpatch.compare(obj, obj2); expect(patches).toReallyEqual([ { op: 'remove', @@ -1975,7 +1976,7 @@ describe('duplex', function() { }); it('should not modify the source object', function() { - var obj = { + const obj = { foo: 'bar' }; jsonpatch.compare(obj, {}); @@ -1985,8 +1986,8 @@ describe('duplex', function() { it('should work with plain objects', function() { // Objects without Object prototype - var one = Object.create(null); - var two = Object.create(null); + const one = Object.create(null); + const two = Object.create(null); one.onlyOne = Object.create(null); two.onlyTwo = Object.create(null); one.both = Object.create(null); diff --git a/test/spec/jsonPatchTestsSpec.js b/test/spec/jsonPatchTestsSpec.js index a81c1f72..8981ae38 100644 --- a/test/spec/jsonPatchTestsSpec.js +++ b/test/spec/jsonPatchTestsSpec.js @@ -3,7 +3,7 @@ import * as jsonpatch from '../../module/duplex.js'; import tests_json from './json-patch-tests/tests.json.js'; import spec_tests_json from './json-patch-tests/spec_tests.json.js'; -var JSONtests = [ +const JSONtests = [ { name: 'tests.json', tests: tests_json @@ -16,7 +16,7 @@ var JSONtests = [ if (typeof Array.prototype.forEach != 'function') { Array.prototype.forEach = function(callback) { - for (var i = 0; i < this.length; i++) { + for (const i = 0; i < this.length; i++) { callback.apply(this, [this[i], i, this]); } }; @@ -29,7 +29,7 @@ describe('json-patch-tests', function() { if (test.disabled) { return; } - var testName = test.comment || test.error || JSON.stringify(test.patch); + const testName = test.comment || test.error || JSON.stringify(test.patch); if (test.expected) { it('should succeed: ' + testName, function() { const results = jsonpatch.applyPatch(test.doc, test.patch, true); @@ -38,9 +38,9 @@ describe('json-patch-tests', function() { }); } else if (test.error || test.patch[0].op === 'test') { it('should throw an error: ' + testName, function() { - var errors = 0; + let errors = 0; try { - var res = jsonpatch.applyPatch(test.doc, test.patch, true); + const res = jsonpatch.applyPatch(test.doc, test.patch, true); if (res.test === false) { throw new Error('Test failed'); } diff --git a/test/spec/validateSpec.js b/test/spec/validateSpec.js index 3bfd5123..f125e491 100644 --- a/test/spec/validateSpec.js +++ b/test/spec/validateSpec.js @@ -2,7 +2,7 @@ import * as jsonpatch from '../../module/duplex.js'; describe('validate', function() { it('should return an empty array if the patch is valid', function() { - var patch = [ + const patch = [ { op: 'test', path: '/a/b/c', @@ -33,7 +33,7 @@ describe('validate', function() { path: '/a/b/e' } ]; - var error = jsonpatch.validate(patch); + const error = jsonpatch.validate(patch); expect(error).toBeUndefined(); }); @@ -97,7 +97,7 @@ describe('validate', function() { it('should return an empty array if the operation is a valid object', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'add', value: 'foo', @@ -108,30 +108,30 @@ describe('validate', function() { }); it('should return an error if the operation is null', function() { - var error = jsonpatch.validate([null]); + const error = jsonpatch.validate([null]); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error.name).toBe('OPERATION_NOT_AN_OBJECT'); }); it('should return an error which is instance of Error and jsonpatch.JsonPatchError', function() { - var error = jsonpatch.validate({}); + const error = jsonpatch.validate({}); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error instanceof Error).toBe(true); expect(error.name).toBe('SEQUENCE_NOT_AN_ARRAY'); }); it('should return an error that contains the cloned patch and the patched object', function() { - var tree = { + const tree = { name: 'Elvis', cars: [] }; - var sequence = [ + const sequence = [ { op: 'remove', path: '/name/first' } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(JSON.stringify(error.operation)).toBe(JSON.stringify(sequence[0])); expect(JSON.stringify(error.tree)).toBe(JSON.stringify(tree)); @@ -139,19 +139,19 @@ describe('validate', function() { }); it('should return an error if the operation is undefined', function() { - var error = jsonpatch.validate([undefined]); + const error = jsonpatch.validate([undefined]); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error.name).toBe('OPERATION_NOT_AN_OBJECT'); }); it('should return an error if the operation is an array', function() { - var error = jsonpatch.validate([[]]); + const error = jsonpatch.validate([[]]); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error.name).toBe('OPERATION_NOT_AN_OBJECT'); }); it('should return an error if the operation "op" property is not a string', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { path: '/a/b/c' } @@ -161,7 +161,7 @@ describe('validate', function() { }); it('should return an error if the operation "path" property is not a string', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'remove', value: 'foo' @@ -172,7 +172,7 @@ describe('validate', function() { }); it('should return an error if an "add" operation is missing "value" property', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'add', path: '/a/b/c' @@ -183,7 +183,7 @@ describe('validate', function() { }); it('should return an error if an "add" operation "value" property is "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'add', path: '/a/b/c', @@ -195,7 +195,7 @@ describe('validate', function() { }); it('should return an error if a "replace" operation is missing "value" property', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'replace', path: '/a/b/c' @@ -206,7 +206,7 @@ describe('validate', function() { }); it('should return an error if a "replace" operation "value" property is "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'replace', path: '/a/b/c', @@ -218,7 +218,7 @@ describe('validate', function() { }); it('should return an error if a "test" operation is missing "value" property', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'test', path: '/a/b/c' @@ -229,7 +229,7 @@ describe('validate', function() { }); it('should return an error if a "test" operation "value" property is "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'test', path: '/a/b/c', @@ -241,7 +241,7 @@ describe('validate', function() { }); it('should return an error if an "add" operation "value" contains "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'add', path: '/a/b/c', @@ -255,7 +255,7 @@ describe('validate', function() { }); it('should return an error if a "replace" operation "value" contains "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'replace', path: '/a/b/c', @@ -269,7 +269,7 @@ describe('validate', function() { }); it('should return an error if a "test" operation "value" contains "undefined"', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'test', path: '/a/b/c', @@ -285,7 +285,7 @@ describe('validate', function() { }); it('should return an error if a "move" operation is missing "from" property', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'move', path: '/a/b/c' @@ -296,7 +296,7 @@ describe('validate', function() { }); it('should return an error if a "copy" operation is missing "from" property', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'copy', path: '/a/b/c' @@ -307,7 +307,7 @@ describe('validate', function() { }); it('should return an error if the "op" property is invalid', function() { - var error = jsonpatch.validate([ + const error = jsonpatch.validate([ { op: 'foobar', path: '/a/b/c' @@ -318,9 +318,9 @@ describe('validate', function() { }); it('should return error replacing an unexisting path', function() { - var sequence, - error, - tree = { + let sequence; + let error; + const tree = { '': 'empty string is a valid key', name: 'Elvis', cars: [ @@ -363,28 +363,28 @@ describe('validate', function() { }); it('should return error removing an unexisting path', function() { - var tree = { + const tree = { name: 'Elvis', cars: [] }; - var sequence = [ + const sequence = [ { op: 'remove', path: '/name/first' } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error.name).toBe('OPERATION_PATH_UNRESOLVABLE'); }); it('should allow adding property "b" in "a"', function() { - var tree = { + const tree = { a: { foo: 1 } }; - var sequence = [ + const sequence = [ { op: 'add', path: '/a/b', @@ -392,17 +392,17 @@ describe('validate', function() { } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error).toBeUndefined(); }); it('should report error because "a" does not exist', function() { - var tree = { + const tree = { q: { bar: 2 } }; - var sequence = [ + const sequence = [ { op: 'add', path: '/a/b', @@ -410,16 +410,16 @@ describe('validate', function() { } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error instanceof jsonpatch.JsonPatchError).toBe(true); expect(error.name).toBe('OPERATION_PATH_CANNOT_ADD'); }); it('should return error when replacing a removed path', function() { - var tree = { + const tree = { name: 'Elvis' }; - var sequence = [ + const sequence = [ { op: 'remove', path: '/name' @@ -430,15 +430,15 @@ describe('validate', function() { value: 'Freddie' } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error.name).toBe('OPERATION_PATH_UNRESOLVABLE'); }); it('should allow to override validator to add custom validation', function() { - var tree = { + const tree = { password: 'Elvis' }; - var sequence = [ + const sequence = [ { op: 'replace', path: '/password', @@ -465,16 +465,16 @@ describe('validate', function() { tree ); } - var customError = jsonpatch.validate(sequence, tree, validator); + const customError = jsonpatch.validate(sequence, tree, validator); expect(customError.index).toBe(0); expect(customError.name).toBe('OPERATION_VALUE_MUST_NOT_CONTAIN_OLD_VALUE'); }); it('should pass replacing the tree root', function() { - var tree = { + const tree = { password: 'Elvis' }; - var sequence = [ + const sequence = [ { op: 'replace', path: '', @@ -482,43 +482,43 @@ describe('validate', function() { } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error).toBeUndefined(); }); it('should return error moving from an unexisting path', function() { - var tree = { + const tree = { name: 'Elvis' }; - var sequence = [ + const sequence = [ { op: 'move', from: '/a/b/c', path: '/name' } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error.name).toBe('OPERATION_FROM_UNRESOLVABLE'); }); it('should return error copying from an unexisting path', function() { - var tree = { + const tree = { name: 'Elvis' }; - var sequence = [ + const sequence = [ { op: 'copy', from: '/a/b/c', path: '/name' } ]; - var error = jsonpatch.validate(sequence, tree); + const error = jsonpatch.validate(sequence, tree); expect(error.name).toBe('OPERATION_FROM_UNRESOLVABLE'); }); it('should throw OPERATION_PATH_INVALID when applying patch without path', function() { - var a = {}; - var ex = null; + const a = {}; + let ex = null; try { jsonpatch.applyPatch( @@ -539,8 +539,8 @@ describe('validate', function() { }); it('should throw OPERATION_PATH_INVALID when applying patch with an invalid path. Issue #77.', function() { - var a = {}; - var ex = null; + const a = {}; + let ex = null; try { jsonpatch.applyPatch( @@ -561,8 +561,8 @@ describe('validate', function() { }); it('should throw OPERATION_OP_INVALID when applying patch without operation', function() { - var a = {}; - var ex = null; + const a = {}; + let ex = null; try { jsonpatch.applyPatch( @@ -583,8 +583,8 @@ describe('validate', function() { }); it('should throw OPERATION_VALUE_REQUIRED when applying patch without value', function() { - var a = {}; - var ex = null; + const a = {}; + let ex = null; try { jsonpatch.applyPatch( @@ -605,7 +605,7 @@ describe('validate', function() { }); it('should not modify patch value of type array (issue #76)', function () { - var patches = [ + const patches = [ {op: 'add', path: '/foo', value: []}, {op: 'add', path: '/foo/-', value: 1} ]; @@ -618,7 +618,7 @@ describe('validate', function() { }); it('should not modify patch value of type object (issue #76)', function () { - var patches = [ + const patches = [ {op: 'add', path: '/foo', value: {}}, {op: 'add', path: '/foo/bar', value: 1} ]; From 38c1fced485732573126d315d7beaa2ecb578234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Tue, 6 Aug 2019 16:06:01 +0200 Subject: [PATCH 13/31] Export in CommonJS type by default, rename module files to `.mjs` --- module/{core.js => core.mjs} | 2 +- module/{duplex.js => duplex.mjs} | 8 ++++---- module/{helpers.js => helpers.mjs} | 0 package.json | 7 ++++--- tsc-to-mjs.sh | 4 ++++ 5 files changed, 13 insertions(+), 8 deletions(-) rename module/{core.js => core.mjs} (99%) rename module/{duplex.js => duplex.mjs} (96%) rename module/{helpers.js => helpers.mjs} (100%) create mode 100644 tsc-to-mjs.sh diff --git a/module/core.js b/module/core.mjs similarity index 99% rename from module/core.js rename to module/core.mjs index f82f40b0..93dd839b 100644 --- a/module/core.js +++ b/module/core.mjs @@ -1,4 +1,4 @@ -import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers.js'; +import { PatchError, _deepClone, isInteger, unescapePathComponent, hasUndefined } from './helpers.mjs'; export var JsonPatchError = PatchError; export var deepClone = _deepClone; /* We use a Javascript hash to store each diff --git a/module/duplex.js b/module/duplex.mjs similarity index 96% rename from module/duplex.js rename to module/duplex.mjs index df65b7ec..74db144e 100644 --- a/module/duplex.js +++ b/module/duplex.mjs @@ -3,12 +3,12 @@ * (c) 2017 Joachim Wester * MIT license */ -import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers.js'; -import { applyPatch } from './core.js'; +import { _deepClone, _objectKeys, escapePathComponent, hasOwnProperty } from './helpers.mjs'; +import { applyPatch } from './core.mjs'; /* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator, _areEquals } from './core.js'; +export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator, _areEquals } from './core.mjs'; /* export some helpers */ -export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.js'; +export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.mjs'; var beforeDict = new WeakMap(); var Mirror = /** @class */ (function () { function Mirror(obj) { diff --git a/module/helpers.js b/module/helpers.mjs similarity index 100% rename from module/helpers.js rename to module/helpers.mjs diff --git a/package.json b/package.json index ce8c9acb..d50be078 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,9 @@ "url": "http://www.starcounter.com/" }, "license": "MIT", - "main": "module/duplex.js", + "main": "lib/duplex.js", + "module": "module/duplex.mjs", "typings": "module/duplex.d.ts", - "type": "module", "devDependencies": { "benchmark": "^2.1.4", "bluebird": "^3.5.5", @@ -45,7 +45,8 @@ "scripts": { "tsc": "npm run tsc-common && npm run tsc-module", "tsc-common": "tsc", - "tsc-module": "tsc --module esnext --moduleResolution node --outDir \"module/\"", + "tsc-module": "tsc --module esnext --moduleResolution node --outDir \"module/\" && npm run tsc-to-mjs", + "tsc-to-mjs": "bash tsc-to-mjs.sh", "version": "npm run tsc && webpack && git add -A", "build": "npm run tsc && webpack", "serve": "http-server -p 5000 --silent", diff --git a/tsc-to-mjs.sh b/tsc-to-mjs.sh new file mode 100644 index 00000000..d75abde9 --- /dev/null +++ b/tsc-to-mjs.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd module +mv core.js core.mjs && mv duplex.js duplex.mjs && mv helpers.js helpers.mjs +sed -i 's/\.js/\.mjs/g' duplex.mjs core.mjs \ No newline at end of file From e448c0ce7f1021bdd6d6a6e8d9aa3de5ecd21a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Tue, 6 Aug 2019 22:06:20 +0200 Subject: [PATCH 14/31] Use `.mjs` for tests to force ESM module loader --- jasmine-run.js => jasmine-run.mjs | 0 package-lock.json | 2 +- package.json | 4 ++-- test/index.html | 8 ++++---- test/spec/{coreSpec.js => coreSpec.mjs} | 2 +- test/spec/{duplexSpec.js => duplexSpec.mjs} | 2 +- .../{spec_tests.json.js => spec_tests.json.mjs} | 0 .../json-patch-tests/{tests.json.js => tests.json.mjs} | 0 .../{jsonPatchTestsSpec.js => jsonPatchTestsSpec.mjs} | 6 +++--- test/spec/{validateSpec.js => validateSpec.mjs} | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) rename jasmine-run.js => jasmine-run.mjs (100%) rename test/spec/{coreSpec.js => coreSpec.mjs} (99%) rename test/spec/{duplexSpec.js => duplexSpec.mjs} (99%) rename test/spec/json-patch-tests/{spec_tests.json.js => spec_tests.json.mjs} (100%) rename test/spec/json-patch-tests/{tests.json.js => tests.json.mjs} (100%) rename test/spec/{jsonPatchTestsSpec.js => jsonPatchTestsSpec.mjs} (93%) rename test/spec/{validateSpec.js => validateSpec.mjs} (99%) diff --git a/jasmine-run.js b/jasmine-run.mjs similarity index 100% rename from jasmine-run.js rename to jasmine-run.mjs diff --git a/package-lock.json b/package-lock.json index b55a46fc..70ab2b1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3051,7 +3051,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { "brace-expansion": "^1.1.7" diff --git a/package.json b/package.json index d50be078..9e050ded 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "tsc-watch": "tsc -w", "test": "npm run tsc && npm run test-core && npm run test-duplex", "test-sauce": "npm run build && node test/Sauce/Runner.js", - "test-duplex": "node --experimental-modules jasmine-run.js test/**/*[sS]pec.js", - "test-core": "node --experimental-modules jasmine-run.js test/spec/jsonPatchTestsSpec.js test/spec/coreSpec.js test/spec/validateSpec.js", + "test-duplex": "node --experimental-modules jasmine-run.mjs test/**/*[sS]pec.mjs", + "test-core": "node --experimental-modules jasmine-run.mjs test/spec/jsonPatchTestsSpec.mjs test/spec/coreSpec.mjs test/spec/validateSpec.mjs", "bench": "npm run bench-core && npm run bench-duplex", "bench-core": "node test/spec/coreBenchmark.js", "bench-duplex": "node test/spec/coreBenchmark.js && node test/spec/duplexBenchmark.js" diff --git a/test/index.html b/test/index.html index 5156c2ad..5bf9f79d 100644 --- a/test/index.html +++ b/test/index.html @@ -22,10 +22,10 @@ - - - - + + + + diff --git a/test/spec/coreSpec.js b/test/spec/coreSpec.mjs similarity index 99% rename from test/spec/coreSpec.js rename to test/spec/coreSpec.mjs index 507dba4c..39cef245 100644 --- a/test/spec/coreSpec.js +++ b/test/spec/coreSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.js'; +import * as jsonpatch from '../../module/duplex.mjs'; describe('jsonpatch.getValueByPointer', function() { it('should retrieve values by JSON pointer from tree - deep object', function() { diff --git a/test/spec/duplexSpec.js b/test/spec/duplexSpec.mjs similarity index 99% rename from test/spec/duplexSpec.js rename to test/spec/duplexSpec.mjs index 419de449..fefbf1a9 100644 --- a/test/spec/duplexSpec.js +++ b/test/spec/duplexSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.js'; +import * as jsonpatch from '../../module/duplex.mjs'; import {EventTarget, defineEventAttribute} from "../../node_modules/event-target-shim/dist/event-target-shim.mjs"; if (typeof window === 'undefined') { diff --git a/test/spec/json-patch-tests/spec_tests.json.js b/test/spec/json-patch-tests/spec_tests.json.mjs similarity index 100% rename from test/spec/json-patch-tests/spec_tests.json.js rename to test/spec/json-patch-tests/spec_tests.json.mjs diff --git a/test/spec/json-patch-tests/tests.json.js b/test/spec/json-patch-tests/tests.json.mjs similarity index 100% rename from test/spec/json-patch-tests/tests.json.js rename to test/spec/json-patch-tests/tests.json.mjs diff --git a/test/spec/jsonPatchTestsSpec.js b/test/spec/jsonPatchTestsSpec.mjs similarity index 93% rename from test/spec/jsonPatchTestsSpec.js rename to test/spec/jsonPatchTestsSpec.mjs index 8981ae38..c075e69a 100644 --- a/test/spec/jsonPatchTestsSpec.js +++ b/test/spec/jsonPatchTestsSpec.mjs @@ -1,7 +1,7 @@ -import * as jsonpatch from '../../module/duplex.js'; +import * as jsonpatch from '../../module/duplex.mjs'; -import tests_json from './json-patch-tests/tests.json.js'; -import spec_tests_json from './json-patch-tests/spec_tests.json.js'; +import tests_json from './json-patch-tests/tests.json.mjs'; +import spec_tests_json from './json-patch-tests/spec_tests.json.mjs'; const JSONtests = [ { diff --git a/test/spec/validateSpec.js b/test/spec/validateSpec.mjs similarity index 99% rename from test/spec/validateSpec.js rename to test/spec/validateSpec.mjs index f125e491..157230a0 100644 --- a/test/spec/validateSpec.js +++ b/test/spec/validateSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.js'; +import * as jsonpatch from '../../module/duplex.mjs'; describe('validate', function() { it('should return an empty array if the patch is valid', function() { From 04671e531ecb69d86866576bf380a86df8ed4ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Wed, 7 Aug 2019 20:40:18 +0200 Subject: [PATCH 15/31] Remove incorrect __esModule insertion, https://github.com/Starcounter-Jack/JSON-Patch/issues/233 https://github.com/microsoft/TypeScript/issues/14351 --- dist/fast-json-patch.js | 6 ++-- dist/fast-json-patch.min.js | 2 +- lib/core.js | 2 +- lib/duplex.js | 2 +- lib/helpers.js | 2 +- module/core.mjs | 58 +++++++++++++++++-------------------- module/duplex.mjs | 32 +++++++++----------- module/helpers.mjs | 48 ++++++++++-------------------- package.json | 5 ++-- tsc-to-cjs.sh | 3 ++ 10 files changed, 68 insertions(+), 92 deletions(-) create mode 100644 tsc-to-cjs.sh diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index d6ec0eb0..6b675460 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -108,7 +108,7 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); -Object.defineProperty(exports, "__esModule", { value: true }); + var _hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwnProperty(obj, key) { return _hasOwnProperty.call(obj, key); @@ -277,7 +277,7 @@ exports.PatchError = PatchError; /* 1 */ /***/ (function(module, exports, __webpack_require__) { -Object.defineProperty(exports, "__esModule", { value: true }); + var helpers_js_1 = __webpack_require__(0); exports.JsonPatchError = helpers_js_1.PatchError; exports.deepClone = helpers_js_1._deepClone; @@ -717,7 +717,7 @@ exports._areEquals = _areEquals; /* 2 */ /***/ (function(module, exports, __webpack_require__) { -Object.defineProperty(exports, "__esModule", { value: true }); + /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index aab6dc5a..be54040e 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -5,7 +5,7 @@ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0});var o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a obj.length) { throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document); } - var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch + const returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -228,7 +224,7 @@ export function applyOperation(document, operation, validateOperation, mutateDoc key = unescapePathComponent(key); } if (t >= len) { - var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch + const returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -253,9 +249,7 @@ export function applyOperation(document, operation, validateOperation, mutateDoc * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. * @return An array of `{newDocument, result}` after the patch */ -export function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) { - if (mutateDocument === void 0) { mutateDocument = true; } - if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } +export function applyPatch(document, patch, validateOperation, mutateDocument = true, banPrototypeModifications = true) { if (validateOperation) { if (!Array.isArray(patch)) { throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); @@ -264,8 +258,8 @@ export function applyPatch(document, patch, validateOperation, mutateDocument, b if (!mutateDocument) { document = _deepClone(document); } - var results = new Array(patch.length); - for (var i = 0, length_1 = patch.length; i < length_1; i++) { + const results = new Array(patch.length); + for (let i = 0, length = patch.length; i < length; i++) { // we don't need to pass mutateDocument argument because if it was true, we already deep cloned the object, we'll just pass `true` results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i); document = results[i].newDocument; // in case root was replaced @@ -283,7 +277,7 @@ export function applyPatch(document, patch, validateOperation, mutateDocument, b * @return The updated document */ export function applyReducer(document, operation, index) { - var operationResult = applyOperation(document, operation); + const operationResult = applyOperation(document, operation); if (operationResult.test === false) { // failed test throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } diff --git a/module/duplex.mjs b/module/duplex.mjs index 74db144e..1ddcfeb9 100644 --- a/module/duplex.mjs +++ b/module/duplex.mjs @@ -10,20 +10,18 @@ export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, /* export some helpers */ export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.mjs'; var beforeDict = new WeakMap(); -var Mirror = /** @class */ (function () { - function Mirror(obj) { +class Mirror { + constructor(obj) { this.observers = new Map(); this.obj = obj; } - return Mirror; -}()); -var ObserverInfo = /** @class */ (function () { - function ObserverInfo(callback, observer) { +} +class ObserverInfo { + constructor(callback, observer) { this.callback = callback; this.observer = observer; } - return ObserverInfo; -}()); +} function getMirror(obj) { return beforeDict.get(obj); } @@ -51,7 +49,7 @@ export function observe(obj, callback) { beforeDict.set(obj, mirror); } else { - var observerInfo = getObserverFromMirror(mirror, callback); + const observerInfo = getObserverFromMirror(mirror, callback); observer = observerInfo && observerInfo.observer; } if (observer) { @@ -62,10 +60,10 @@ export function observe(obj, callback) { if (callback) { observer.callback = callback; observer.next = null; - var dirtyCheck = function () { + var dirtyCheck = () => { generate(observer); }; - var fastCheck = function () { + var fastCheck = () => { clearTimeout(observer.next); observer.next = setTimeout(dirtyCheck); }; @@ -79,7 +77,7 @@ export function observe(obj, callback) { } observer.patches = patches; observer.object = obj; - observer.unobserve = function () { + observer.unobserve = () => { generate(observer); clearTimeout(observer.next); removeObserverFromMirror(mirror, observer); @@ -97,8 +95,7 @@ export function observe(obj, callback) { /** * Generate an array of patches from an observer */ -export function generate(observer, invertible) { - if (invertible === void 0) { invertible = false; } +export function generate(observer, invertible = false) { var mirror = beforeDict.get(observer.object); _generate(mirror.value, observer.object, observer.patches, "", invertible); if (observer.patches.length) { @@ -153,9 +150,9 @@ function _generate(mirror, obj, patches, path, invertible) { } else { if (invertible) { - patches.push({ op: "test", path: path, value: mirror }); + patches.push({ op: "test", path, value: mirror }); } - patches.push({ op: "replace", path: path, value: obj }); + patches.push({ op: "replace", path, value: obj }); changed = true; } } @@ -172,8 +169,7 @@ function _generate(mirror, obj, patches, path, invertible) { /** * Create an array of patches from the differences in two objects */ -export function compare(tree1, tree2, invertible) { - if (invertible === void 0) { invertible = false; } +export function compare(tree1, tree2, invertible = false) { var patches = []; _generate(tree1, tree2, patches, '', invertible); return patches; diff --git a/module/helpers.mjs b/module/helpers.mjs index 10844fe8..91ef008b 100644 --- a/module/helpers.mjs +++ b/module/helpers.mjs @@ -3,20 +3,7 @@ * (c) 2017 Joachim Wester * MIT license */ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var _hasOwnProperty = Object.prototype.hasOwnProperty; +const _hasOwnProperty = Object.prototype.hasOwnProperty; export function hasOwnProperty(obj, key) { return _hasOwnProperty.call(obj, key); } @@ -144,28 +131,23 @@ export function hasUndefined(obj) { return false; } function patchErrorMessageFormatter(message, args) { - var messageParts = [message]; - for (var key in args) { - var value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print + const messageParts = [message]; + for (const key in args) { + const value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print if (typeof value !== 'undefined') { - messageParts.push(key + ": " + value); + messageParts.push(`${key}: ${value}`); } } return messageParts.join('\n'); } -var PatchError = /** @class */ (function (_super) { - __extends(PatchError, _super); - function PatchError(message, name, index, operation, tree) { - var _newTarget = this.constructor; - var _this = _super.call(this, patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree })) || this; - _this.name = name; - _this.index = index; - _this.operation = operation; - _this.tree = tree; - Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 - _this.message = patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree }); - return _this; +export class PatchError extends Error { + constructor(message, name, index, operation, tree) { + super(patchErrorMessageFormatter(message, { name, index, operation, tree })); + this.name = name; + this.index = index; + this.operation = operation; + this.tree = tree; + Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 + this.message = patchErrorMessageFormatter(message, { name, index, operation, tree }); } - return PatchError; -}(Error)); -export { PatchError }; +} diff --git a/package.json b/package.json index 9e050ded..fc76d977 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,10 @@ }, "scripts": { "tsc": "npm run tsc-common && npm run tsc-module", - "tsc-common": "tsc", - "tsc-module": "tsc --module esnext --moduleResolution node --outDir \"module/\" && npm run tsc-to-mjs", + "tsc-common": "tsc && npm run tsc-to-cjs", + "tsc-module": "tsc --target es6 --module es6 --moduleResolution node --outDir \"module/\" && npm run tsc-to-mjs", "tsc-to-mjs": "bash tsc-to-mjs.sh", + "tsc-to-cjs": "bash tsc-to-cjs.sh", "version": "npm run tsc && webpack && git add -A", "build": "npm run tsc && webpack", "serve": "http-server -p 5000 --silent", diff --git a/tsc-to-cjs.sh b/tsc-to-cjs.sh new file mode 100644 index 00000000..ae735bdd --- /dev/null +++ b/tsc-to-cjs.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd lib +sed -i 's/Object\.defineProperty(exports, "__esModule", { value: true });/ /g' core.js duplex.js helpers.js \ No newline at end of file From 119f0d4dad45a92b14550a1aa7033f7c38f1cf81 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 11:35:27 +0200 Subject: [PATCH 16/31] update importing instructions to reflect the current state --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 70f15b74..abb8146b 100644 --- a/README.md +++ b/README.md @@ -51,22 +51,27 @@ Load the bundled distribution script: Call require to get the instance: ```js -var jsonpatch = require('fast-json-patch/lib'); +var jsonpatch = require('fast-json-patch'); // or, get just a single function: -const { applyOperation } = require('fast-json-patch/lib'); -const applyOperation = require('fast-json-patch/lib').applyOperation; +const { applyOperation } = require('fast-json-patch'); +const applyOperation = require('fast-json-patch').applyOperation; ``` Or use the CommonJS export in ES6 style (Works with Webpack, Babel): ```js -import { applyOperation } from 'fast-json-patch/lib' +// default import does not work: +// import jsonpatch from 'fast-json-patch'; +// use named imports instead: +import { * as jsonpatch } from 'fast-json-patch'; +import { applyOperation } from 'fast-json-patch'; ``` Or use the ECMAScript module (Works with Webpack, Babel, and in Node 12+ with `--experimental-modules` flag): ```js -import { applyOperation } from 'fast-json-patch' +import { * as jsonpatch } from 'fast-json-patch/module/duplex.mjs'; +import { applyOperation } from 'fast-json-patch/module/duplex.mjs'; ``` ## Directories From c465da4e5b5f418869c8d7edf93acb5887d50d51 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 11:43:26 +0200 Subject: [PATCH 17/31] test CommonJS using require and Webpack --- package.json | 4 +- test/spec/commonjs/requireSpec.js | 25 +++++++ test/spec/webpack/importSpec.build.js | 13 ++++ test/spec/webpack/importSpec.src.js | 43 +++++++++++++ webpack.config.js | 93 +++++++++++++++++---------- 5 files changed, 143 insertions(+), 35 deletions(-) create mode 100644 test/spec/commonjs/requireSpec.js create mode 100644 test/spec/webpack/importSpec.build.js create mode 100644 test/spec/webpack/importSpec.src.js diff --git a/package.json b/package.json index fc76d977..2f8ce03e 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,10 @@ "build": "npm run tsc && webpack", "serve": "http-server -p 5000 --silent", "tsc-watch": "tsc -w", - "test": "npm run tsc && npm run test-core && npm run test-duplex", + "test": "npm run tsc && npm run test-core && npm run test-duplex && npm run test-commonjs && npm run test-webpack-import", "test-sauce": "npm run build && node test/Sauce/Runner.js", + "test-commonjs": "jasmine test/spec/commonjs/requireSpec.js", + "test-webpack-import": "webpack --env.NODE_ENV=test && jasmine test/spec/webpack/importSpec.build.js", "test-duplex": "node --experimental-modules jasmine-run.mjs test/**/*[sS]pec.mjs", "test-core": "node --experimental-modules jasmine-run.mjs test/spec/jsonPatchTestsSpec.mjs test/spec/coreSpec.mjs test/spec/validateSpec.mjs", "bench": "npm run bench-core && npm run bench-duplex", diff --git a/test/spec/commonjs/requireSpec.js b/test/spec/commonjs/requireSpec.js new file mode 100644 index 00000000..38e3119c --- /dev/null +++ b/test/spec/commonjs/requireSpec.js @@ -0,0 +1,25 @@ +const jsonpatch = require('../../..'); + +describe('CommonJS', function () { + describe('require', function () { + it('should have the expected structure', function () { + expect(typeof jsonpatch).withContext("result from require() should be an object").toEqual("object"); + expect(typeof jsonpatch).withContext("result from require() should not be a function").not.toEqual("function"); + expect(jsonpatch.applyOperation).withContext("applyOperation should be a method within the object").toBeDefined(); + expect(jsonpatch.applyPatch).withContext("applyPatch should be a method within the object").toBeDefined(); + expect(jsonpatch.applyReducer).withContext("applyReducer should be a method within the object").toBeDefined(); + expect(jsonpatch.getValueByPointer).withContext("getValueByPointer should be a method within the object").toBeDefined(); + expect(jsonpatch.validate).withContext("validate should be a method within the object").toBeDefined(); + expect(jsonpatch.validator).withContext("validator should be a method within the object").toBeDefined(); + expect(jsonpatch._areEquals).withContext("_areEquals should be a method within the object").toBeDefined(); + expect(jsonpatch.JsonPatchError).withContext("JsonPatchError should be a method within the object").toBeDefined(); + expect(jsonpatch.deepClone).withContext("deepClone should be a method within the object").toBeDefined(); + expect(jsonpatch.escapePathComponent).withContext("escapePathComponent should be a method within the object").toBeDefined(); + expect(jsonpatch.unescapePathComponent).withContext("unescapePathComponent should be a method within the object").toBeDefined(); + expect(jsonpatch.unobserve).withContext("unobserve should be a method within the object").toBeDefined(); + expect(jsonpatch.observe).withContext("observe should be a method within the object").toBeDefined(); + expect(jsonpatch.generate).withContext("generate should be a method within the object").toBeDefined(); + expect(jsonpatch.compare).withContext("compare should be a method within the object").toBeDefined(); + }); + }); +}); \ No newline at end of file diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js new file mode 100644 index 00000000..fe62d786 --- /dev/null +++ b/test/spec/webpack/importSpec.build.js @@ -0,0 +1,13 @@ +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return m}),n.d(o,"applyPatch",function(){return y}),n.d(o,"applyReducer",function(){return b}),n.d(o,"getValueByPointer",function(){return w}),n.d(o,"validate",function(){return A}),n.d(o,"validator",function(){return O}),n.d(o,"_areEquals",function(){return _}),n.d(o,"JsonPatchError",function(){return h}),n.d(o,"deepClone",function(){return u}),n.d(o,"escapePathComponent",function(){return c}),n.d(o,"unescapePathComponent",function(){return s}),n.d(o,"unobserve",function(){return P}),n.d(o,"observe",function(){return T}),n.d(o,"generate",function(){return D}),n.d(o,"compare",function(){return j}); +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +const r=Object.prototype.hasOwnProperty;function i(e,t){return r.call(e,t)}function a(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0}function c(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function s(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function f(e,t){const n=[e];for(const e in t){const o="object"==typeof t[e]?JSON.stringify(t[e],null,2):t[e];void 0!==o&&n.push(`${e}: ${o}`)}return n.join("\n")}class h extends Error{constructor(e,t,n,o,r){super(f(e,{name:t,index:n,operation:o,tree:r})),this.name=t,this.index=n,this.operation=o,this.tree=r,Object.setPrototypeOf(this,new.target.prototype),this.message=f(e,{name:t,index:n,operation:o,tree:r})}}const d=h,l={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){let o=w(n,this.path);o&&(o=u(o));const r=m(n,{op:"remove",path:this.from}).removed;return m(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){const o=w(n,this.from);return m(n,{op:"add",path:this.path,value:u(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:_(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}};var v={add:function(e,t,n){return p(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:l.move,copy:l.copy,test:l.test,_get:l._get};function w(e,t){if(""==t)return e;var n={op:"_get",path:t};return m(e,n),n.value}function m(e,t,n=!1,o=!0,r=!0,i=0){if(n&&("function"==typeof n?n(t,0,e,t.path):O(t,0)),""===t.path){let o={newDocument:e};if("add"===t.op)return o.newDocument=t.value,o;if("replace"===t.op)return o.newDocument=t.value,o.removed=e,o;if("move"===t.op||"copy"===t.op)return o.newDocument=w(e,t.from),"move"===t.op&&(o.removed=e),o;if("test"===t.op){if(o.test=_(e,t.value),!1===o.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return o.newDocument=e,o}if("remove"===t.op)return o.removed=e,o.newDocument=null,o;if("_get"===t.op)return t.value=e,o;if(n)throw new d("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return o}{o||(e=u(e));const a=(t.path||"").split("/");let c,f,h=e,w=1,m=a.length,y=void 0;for(f="function"==typeof n?n:O;;){if(c=a[w],r&&"__proto__"==c)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===y&&(void 0===h[c]?y=a.slice(0,w).join("/"):w==m-1&&(y=t.path),void 0!==y&&f(t,0,e,y)),w++,Array.isArray(h)){if("-"===c)c=h.length;else{if(n&&!p(c))throw new d("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);p(c)&&(c=~~c)}if(w>=m){if(n&&"add"===t.op&&c>h.length)throw new d("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);const o=v[t.op].call(t,h,c,e);if(!1===o.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return o}}else if(c&&-1!=c.indexOf("~")&&(c=s(c)),w>=m){const n=l[t.op].call(t,h,c,e);if(!1===n.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return n}h=h[c]}}}function y(e,t,n,o=!0,r=!0){if(n&&!Array.isArray(t))throw new d("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=u(e));const i=new Array(t.length);for(let o=0,a=t.length;o0)throw new d('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new d("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new d("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n{D(n)},i=()=>{clearTimeout(n.next),n.next=setTimeout(r)};"undefined"!=typeof window&&(window.addEventListener("mouseup",i),window.addEventListener("keyup",i),window.addEventListener("mousedown",i),window.addEventListener("keydown",i),window.addEventListener("change",i))}return n.patches=[],n.object=e,n.unobserve=()=>{D(n),clearTimeout(n.next),function(e,t){e.observers.delete(t.callback)}(o,n),"undefined"!=typeof window&&(window.removeEventListener("mouseup",i),window.removeEventListener("keyup",i),window.removeEventListener("mousedown",i),window.removeEventListener("keydown",i),window.removeEventListener("change",i))},o.observers.set(t,new x(t,n)),n}function D(e,t=!1){var n=E.get(e.object);N(n.value,e.object,e.patches,"",t),e.patches.length&&y(n.value,e.patches);var o=e.patches;return o.length>0&&(e.patches=[],e.callback&&e.callback(o)),o}function N(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var p=a(t),s=a(e),f=!1,h=s.length-1;h>=0;h--){var d=e[v=s[h]];if(!i(t,v)||void 0===t[v]&&void 0!==d&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+c(v),value:u(d)}),n.push({op:"remove",path:o+"/"+c(v)}),f=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof d&&null!=d&&"object"==typeof l&&null!=l?N(d,l,n,o+"/"+c(v),r):d!==l&&(!0,r&&n.push({op:"test",path:o+"/"+c(v),value:u(d)}),n.push({op:"replace",path:o+"/"+c(v),value:u(l)}))}}if(f||p.length!=s.length)for(h=0;h { + if(env && env.NODE_ENV === "test") { + return [ + { + entry: './test/spec/webpack/importSpec.src.js', + mode: 'production', + output: { + path: path.resolve(__dirname, 'test/spec/webpack'), + filename: 'importSpec.build.js' + }, + target: 'node', + resolve: { + extensions: ['.js'] + } + } + ]; } -]; + else { + return [ + { + entry: './lib/duplex.js', + mode: 'production', + optimization: { + minimize: false + }, + output: { + filename: 'fast-json-patch.js', + library: 'jsonpatch', + libraryTarget: 'var' + }, + resolve: { + extensions: ['.js'] + }, + plugins: [ + new webpack.BannerPlugin('fast-json-patch, version: ' + package['version']) + ] + }, + { + entry: './lib/duplex.js', + mode: 'production', + output: { + filename: 'fast-json-patch.min.js', + library: 'jsonpatch', + libraryTarget: 'var' + }, + resolve: { + extensions: ['.js'] + }, + plugins: [ + new webpack.BannerPlugin('fast-json-patch, version: ' + package['version']) + ] + } + ]; + } +}; + + + + From f545f13220b7df2180a9b8cada906e497f87bb62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Thu, 8 Aug 2019 13:18:43 +0200 Subject: [PATCH 18/31] Revert "Remove incorrect __esModule insertion," As `__esModule` flag is not a problem, lack of default export is a problem for many users that assumed it exists due to old typescript/webpack conventions This reverts commit 04671e531ecb69d86866576bf380a86df8ed4ea3. --- dist/fast-json-patch.js | 6 ++-- dist/fast-json-patch.min.js | 2 +- lib/core.js | 2 +- lib/duplex.js | 2 +- lib/helpers.js | 2 +- module/core.mjs | 58 ++++++++++++++++++++----------------- module/duplex.mjs | 32 +++++++++++--------- module/helpers.mjs | 48 ++++++++++++++++++++---------- package.json | 5 ++-- tsc-to-cjs.sh | 3 -- 10 files changed, 92 insertions(+), 68 deletions(-) delete mode 100644 tsc-to-cjs.sh diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index 6b675460..d6ec0eb0 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -108,7 +108,7 @@ var __extends = (this && this.__extends) || (function () { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); - +Object.defineProperty(exports, "__esModule", { value: true }); var _hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwnProperty(obj, key) { return _hasOwnProperty.call(obj, key); @@ -277,7 +277,7 @@ exports.PatchError = PatchError; /* 1 */ /***/ (function(module, exports, __webpack_require__) { - +Object.defineProperty(exports, "__esModule", { value: true }); var helpers_js_1 = __webpack_require__(0); exports.JsonPatchError = helpers_js_1.PatchError; exports.deepClone = helpers_js_1._deepClone; @@ -717,7 +717,7 @@ exports._areEquals = _areEquals; /* 2 */ /***/ (function(module, exports, __webpack_require__) { - +Object.defineProperty(exports, "__esModule", { value: true }); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index be54040e..aab6dc5a 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -5,7 +5,7 @@ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a obj.length) { throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", index, operation, document); } - const returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch + var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -224,7 +228,7 @@ export function applyOperation(document, operation, validateOperation = false, m key = unescapePathComponent(key); } if (t >= len) { - const returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch + var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch if (returnValue.test === false) { throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } @@ -249,7 +253,9 @@ export function applyOperation(document, operation, validateOperation = false, m * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. * @return An array of `{newDocument, result}` after the patch */ -export function applyPatch(document, patch, validateOperation, mutateDocument = true, banPrototypeModifications = true) { +export function applyPatch(document, patch, validateOperation, mutateDocument, banPrototypeModifications) { + if (mutateDocument === void 0) { mutateDocument = true; } + if (banPrototypeModifications === void 0) { banPrototypeModifications = true; } if (validateOperation) { if (!Array.isArray(patch)) { throw new JsonPatchError('Patch sequence must be an array', 'SEQUENCE_NOT_AN_ARRAY'); @@ -258,8 +264,8 @@ export function applyPatch(document, patch, validateOperation, mutateDocument = if (!mutateDocument) { document = _deepClone(document); } - const results = new Array(patch.length); - for (let i = 0, length = patch.length; i < length; i++) { + var results = new Array(patch.length); + for (var i = 0, length_1 = patch.length; i < length_1; i++) { // we don't need to pass mutateDocument argument because if it was true, we already deep cloned the object, we'll just pass `true` results[i] = applyOperation(document, patch[i], validateOperation, true, banPrototypeModifications, i); document = results[i].newDocument; // in case root was replaced @@ -277,7 +283,7 @@ export function applyPatch(document, patch, validateOperation, mutateDocument = * @return The updated document */ export function applyReducer(document, operation, index) { - const operationResult = applyOperation(document, operation); + var operationResult = applyOperation(document, operation); if (operationResult.test === false) { // failed test throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', index, operation, document); } diff --git a/module/duplex.mjs b/module/duplex.mjs index 1ddcfeb9..74db144e 100644 --- a/module/duplex.mjs +++ b/module/duplex.mjs @@ -10,18 +10,20 @@ export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, /* export some helpers */ export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.mjs'; var beforeDict = new WeakMap(); -class Mirror { - constructor(obj) { +var Mirror = /** @class */ (function () { + function Mirror(obj) { this.observers = new Map(); this.obj = obj; } -} -class ObserverInfo { - constructor(callback, observer) { + return Mirror; +}()); +var ObserverInfo = /** @class */ (function () { + function ObserverInfo(callback, observer) { this.callback = callback; this.observer = observer; } -} + return ObserverInfo; +}()); function getMirror(obj) { return beforeDict.get(obj); } @@ -49,7 +51,7 @@ export function observe(obj, callback) { beforeDict.set(obj, mirror); } else { - const observerInfo = getObserverFromMirror(mirror, callback); + var observerInfo = getObserverFromMirror(mirror, callback); observer = observerInfo && observerInfo.observer; } if (observer) { @@ -60,10 +62,10 @@ export function observe(obj, callback) { if (callback) { observer.callback = callback; observer.next = null; - var dirtyCheck = () => { + var dirtyCheck = function () { generate(observer); }; - var fastCheck = () => { + var fastCheck = function () { clearTimeout(observer.next); observer.next = setTimeout(dirtyCheck); }; @@ -77,7 +79,7 @@ export function observe(obj, callback) { } observer.patches = patches; observer.object = obj; - observer.unobserve = () => { + observer.unobserve = function () { generate(observer); clearTimeout(observer.next); removeObserverFromMirror(mirror, observer); @@ -95,7 +97,8 @@ export function observe(obj, callback) { /** * Generate an array of patches from an observer */ -export function generate(observer, invertible = false) { +export function generate(observer, invertible) { + if (invertible === void 0) { invertible = false; } var mirror = beforeDict.get(observer.object); _generate(mirror.value, observer.object, observer.patches, "", invertible); if (observer.patches.length) { @@ -150,9 +153,9 @@ function _generate(mirror, obj, patches, path, invertible) { } else { if (invertible) { - patches.push({ op: "test", path, value: mirror }); + patches.push({ op: "test", path: path, value: mirror }); } - patches.push({ op: "replace", path, value: obj }); + patches.push({ op: "replace", path: path, value: obj }); changed = true; } } @@ -169,7 +172,8 @@ function _generate(mirror, obj, patches, path, invertible) { /** * Create an array of patches from the differences in two objects */ -export function compare(tree1, tree2, invertible = false) { +export function compare(tree1, tree2, invertible) { + if (invertible === void 0) { invertible = false; } var patches = []; _generate(tree1, tree2, patches, '', invertible); return patches; diff --git a/module/helpers.mjs b/module/helpers.mjs index 91ef008b..10844fe8 100644 --- a/module/helpers.mjs +++ b/module/helpers.mjs @@ -3,7 +3,20 @@ * (c) 2017 Joachim Wester * MIT license */ -const _hasOwnProperty = Object.prototype.hasOwnProperty; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var _hasOwnProperty = Object.prototype.hasOwnProperty; export function hasOwnProperty(obj, key) { return _hasOwnProperty.call(obj, key); } @@ -131,23 +144,28 @@ export function hasUndefined(obj) { return false; } function patchErrorMessageFormatter(message, args) { - const messageParts = [message]; - for (const key in args) { - const value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print + var messageParts = [message]; + for (var key in args) { + var value = typeof args[key] === 'object' ? JSON.stringify(args[key], null, 2) : args[key]; // pretty print if (typeof value !== 'undefined') { - messageParts.push(`${key}: ${value}`); + messageParts.push(key + ": " + value); } } return messageParts.join('\n'); } -export class PatchError extends Error { - constructor(message, name, index, operation, tree) { - super(patchErrorMessageFormatter(message, { name, index, operation, tree })); - this.name = name; - this.index = index; - this.operation = operation; - this.tree = tree; - Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 - this.message = patchErrorMessageFormatter(message, { name, index, operation, tree }); +var PatchError = /** @class */ (function (_super) { + __extends(PatchError, _super); + function PatchError(message, name, index, operation, tree) { + var _newTarget = this.constructor; + var _this = _super.call(this, patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree })) || this; + _this.name = name; + _this.index = index; + _this.operation = operation; + _this.tree = tree; + Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain, see https://stackoverflow.com/a/48342359 + _this.message = patchErrorMessageFormatter(message, { name: name, index: index, operation: operation, tree: tree }); + return _this; } -} + return PatchError; +}(Error)); +export { PatchError }; diff --git a/package.json b/package.json index 2f8ce03e..c0cdd9b8 100644 --- a/package.json +++ b/package.json @@ -44,10 +44,9 @@ }, "scripts": { "tsc": "npm run tsc-common && npm run tsc-module", - "tsc-common": "tsc && npm run tsc-to-cjs", - "tsc-module": "tsc --target es6 --module es6 --moduleResolution node --outDir \"module/\" && npm run tsc-to-mjs", + "tsc-common": "tsc", + "tsc-module": "tsc --module esnext --moduleResolution node --outDir \"module/\" && npm run tsc-to-mjs", "tsc-to-mjs": "bash tsc-to-mjs.sh", - "tsc-to-cjs": "bash tsc-to-cjs.sh", "version": "npm run tsc && webpack && git add -A", "build": "npm run tsc && webpack", "serve": "http-server -p 5000 --silent", diff --git a/tsc-to-cjs.sh b/tsc-to-cjs.sh deleted file mode 100644 index ae735bdd..00000000 --- a/tsc-to-cjs.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd lib -sed -i 's/Object\.defineProperty(exports, "__esModule", { value: true });/ /g' core.js duplex.js helpers.js \ No newline at end of file From 24766ba692128c940d3daa3a7b73f6c3f0b8d06a Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 13:40:21 +0200 Subject: [PATCH 19/31] clarify about the purpose of the test --- test/spec/webpack/importSpec.build.js | 6 +++--- test/spec/webpack/importSpec.src.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js index fe62d786..25a3c42e 100644 --- a/test/spec/webpack/importSpec.build.js +++ b/test/spec/webpack/importSpec.build.js @@ -1,13 +1,13 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return m}),n.d(o,"applyPatch",function(){return y}),n.d(o,"applyReducer",function(){return b}),n.d(o,"getValueByPointer",function(){return w}),n.d(o,"validate",function(){return A}),n.d(o,"validator",function(){return O}),n.d(o,"_areEquals",function(){return _}),n.d(o,"JsonPatchError",function(){return h}),n.d(o,"deepClone",function(){return u}),n.d(o,"escapePathComponent",function(){return c}),n.d(o,"unescapePathComponent",function(){return s}),n.d(o,"unobserve",function(){return P}),n.d(o,"observe",function(){return T}),n.d(o,"generate",function(){return D}),n.d(o,"compare",function(){return j}); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"validate",function(){return E}),n.d(o,"validator",function(){return A}),n.d(o,"_areEquals",function(){return g}),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester * MIT license */ -const r=Object.prototype.hasOwnProperty;function i(e,t){return r.call(e,t)}function a(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0}function c(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function s(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function f(e,t){const n=[e];for(const e in t){const o="object"==typeof t[e]?JSON.stringify(t[e],null,2):t[e];void 0!==o&&n.push(`${e}: ${o}`)}return n.join("\n")}class h extends Error{constructor(e,t,n,o,r){super(f(e,{name:t,index:n,operation:o,tree:r})),this.name=t,this.index=n,this.operation=o,this.tree=r,Object.setPrototypeOf(this,new.target.prototype),this.message=f(e,{name:t,index:n,operation:o,tree:r})}}const d=h,l={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){let o=w(n,this.path);o&&(o=u(o));const r=m(n,{op:"remove",path:this.from}).removed;return m(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){const o=w(n,this.from);return m(n,{op:"add",path:this.path,value:u(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:_(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}};var v={add:function(e,t,n){return p(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:l.move,copy:l.copy,test:l.test,_get:l._get};function w(e,t){if(""==t)return e;var n={op:"_get",path:t};return m(e,n),n.value}function m(e,t,n=!1,o=!0,r=!0,i=0){if(n&&("function"==typeof n?n(t,0,e,t.path):O(t,0)),""===t.path){let o={newDocument:e};if("add"===t.op)return o.newDocument=t.value,o;if("replace"===t.op)return o.newDocument=t.value,o.removed=e,o;if("move"===t.op||"copy"===t.op)return o.newDocument=w(e,t.from),"move"===t.op&&(o.removed=e),o;if("test"===t.op){if(o.test=_(e,t.value),!1===o.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return o.newDocument=e,o}if("remove"===t.op)return o.removed=e,o.newDocument=null,o;if("_get"===t.op)return t.value=e,o;if(n)throw new d("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return o}{o||(e=u(e));const a=(t.path||"").split("/");let c,f,h=e,w=1,m=a.length,y=void 0;for(f="function"==typeof n?n:O;;){if(c=a[w],r&&"__proto__"==c)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===y&&(void 0===h[c]?y=a.slice(0,w).join("/"):w==m-1&&(y=t.path),void 0!==y&&f(t,0,e,y)),w++,Array.isArray(h)){if("-"===c)c=h.length;else{if(n&&!p(c))throw new d("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);p(c)&&(c=~~c)}if(w>=m){if(n&&"add"===t.op&&c>h.length)throw new d("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);const o=v[t.op].call(t,h,c,e);if(!1===o.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return o}}else if(c&&-1!=c.indexOf("~")&&(c=s(c)),w>=m){const n=l[t.op].call(t,h,c,e);if(!1===n.test)throw new d("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return n}h=h[c]}}}function y(e,t,n,o=!0,r=!0){if(n&&!Array.isArray(t))throw new d("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=u(e));const i=new Array(t.length);for(let o=0,a=t.length;o0)throw new d('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new d("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new d("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n=48&&t<=57))return!1;n++}return!0}function s(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function h(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function d(e,t){var n=[e];for(var o in t){var r="object"==typeof t[o]?JSON.stringify(t[o],null,2):t[o];void 0!==r&&n.push(o+": "+r)}return n.join("\n")}var l=function(e){function t(t,n,o,r,i){var a=this.constructor,u=e.call(this,d(t,{name:n,index:o,operation:r,tree:i}))||this;return u.name=n,u.index=o,u.operation=r,u.tree=i,Object.setPrototypeOf(u,a.prototype),u.message=d(t,{name:n,index:o,operation:r,tree:i}),u}return i(t,e),t}(Error),v=l,w={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){var o=y(n,this.path);o&&(o=c(o));var r=b(n,{op:"remove",path:this.from}).removed;return b(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){var o=y(n,this.from);return b(n,{op:"add",path:this.path,value:c(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:g(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},m={add:function(e,t,n){return f(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:w.move,copy:w.copy,test:w.test,_get:w._get};function y(e,t){if(""==t)return e;var n={op:"_get",path:t};return b(e,n),n.value}function b(e,t,n,o,r,i){if(void 0===n&&(n=!1),void 0===o&&(o=!0),void 0===r&&(r=!0),void 0===i&&(i=0),n&&("function"==typeof n?n(t,0,e,t.path):A(t,0)),""===t.path){var a={newDocument:e};if("add"===t.op)return a.newDocument=t.value,a;if("replace"===t.op)return a.newDocument=t.value,a.removed=e,a;if("move"===t.op||"copy"===t.op)return a.newDocument=y(e,t.from),"move"===t.op&&(a.removed=e),a;if("test"===t.op){if(a.test=g(e,t.value),!1===a.test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a.newDocument=e,a}if("remove"===t.op)return a.removed=e,a.newDocument=null,a;if("_get"===t.op)return t.value=e,a;if(n)throw new v("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return a}o||(e=c(e));var u=(t.path||"").split("/"),p=e,s=1,d=u.length,l=void 0,b=void 0,O=void 0;for(O="function"==typeof n?n:A;;){if(b=u[s],r&&"__proto__"==b)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===l&&(void 0===p[b]?l=u.slice(0,s).join("/"):s==d-1&&(l=t.path),void 0!==l&&O(t,0,e,l)),s++,Array.isArray(p)){if("-"===b)b=p.length;else{if(n&&!f(b))throw new v("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);f(b)&&(b=~~b)}if(s>=d){if(n&&"add"===t.op&&b>p.length)throw new v("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);if(!1===(a=m[t.op].call(t,p,b,e)).test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}}else if(b&&-1!=b.indexOf("~")&&(b=h(b)),s>=d){if(!1===(a=w[t.op].call(t,p,b,e)).test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}p=p[b]}}function O(e,t,n,o,r){if(void 0===o&&(o=!0),void 0===r&&(r=!0),n&&!Array.isArray(t))throw new v("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=c(e));for(var i=new Array(t.length),a=0,u=t.length;a0)throw new v('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new v("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new v("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n{D(n)},i=()=>{clearTimeout(n.next),n.next=setTimeout(r)};"undefined"!=typeof window&&(window.addEventListener("mouseup",i),window.addEventListener("keyup",i),window.addEventListener("mousedown",i),window.addEventListener("keydown",i),window.addEventListener("change",i))}return n.patches=[],n.object=e,n.unobserve=()=>{D(n),clearTimeout(n.next),function(e,t){e.observers.delete(t.callback)}(o,n),"undefined"!=typeof window&&(window.removeEventListener("mouseup",i),window.removeEventListener("keyup",i),window.removeEventListener("mousedown",i),window.removeEventListener("keydown",i),window.removeEventListener("change",i))},o.observers.set(t,new x(t,n)),n}function D(e,t=!1){var n=E.get(e.object);N(n.value,e.object,e.patches,"",t),e.patches.length&&y(n.value,e.patches);var o=e.patches;return o.length>0&&(e.patches=[],e.callback&&e.callback(o)),o}function N(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var p=a(t),s=a(e),f=!1,h=s.length-1;h>=0;h--){var d=e[v=s[h]];if(!i(t,v)||void 0===t[v]&&void 0!==d&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+c(v),value:u(d)}),n.push({op:"remove",path:o+"/"+c(v)}),f=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof d&&null!=d&&"object"==typeof l&&null!=l?N(d,l,n,o+"/"+c(v),r):d!==l&&(!0,r&&n.push({op:"test",path:o+"/"+c(v),value:u(d)}),n.push({op:"replace",path:o+"/"+c(v),value:u(l)}))}}if(f||p.length!=s.length)for(h=0;h0&&(e.patches=[],e.callback&&e.callback(o)),o}function C(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=p(t),a=p(e),f=!1,h=a.length-1;h>=0;h--){var d=e[v=a[h]];if(!u(t,v)||void 0===t[v]&&void 0!==d&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+s(v),value:c(d)}),n.push({op:"remove",path:o+"/"+s(v)}),f=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof d&&null!=d&&"object"==typeof l&&null!=l?C(d,l,n,o+"/"+s(v),r):d!==l&&(!0,r&&n.push({op:"test",path:o+"/"+s(v),value:c(d)}),n.push({op:"replace",path:o+"/"+s(v),value:c(l)}))}}if(f||i.length!=a.length)for(h=0;h Date: Thu, 8 Aug 2019 13:43:48 +0200 Subject: [PATCH 20/31] change installation instructions depending on our proposed priority --- README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index abb8146b..440c35d4 100644 --- a/README.md +++ b/README.md @@ -46,32 +46,36 @@ Load the bundled distribution script: ``` +In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-module), the below code uses this library as a module: + +```html + +``` + ### In Node.js -Call require to get the instance: +In Node 12+ with `--experimental-modules` flag, the below code uses this library as an ECMAScript module: ```js -var jsonpatch = require('fast-json-patch'); -// or, get just a single function: -const { applyOperation } = require('fast-json-patch'); -const applyOperation = require('fast-json-patch').applyOperation; +import { * as jsonpatch } from 'fast-json-patch/module/duplex.mjs'; +import { applyOperation } from 'fast-json-patch/module/duplex.mjs'; ``` -Or use the CommonJS export in ES6 style (Works with Webpack, Babel): +In Webpack (and most surely other transpilers based on Babel), the below code uses this library as an ECMAScript module: ```js -// default import does not work: -// import jsonpatch from 'fast-json-patch'; -// use named imports instead: import { * as jsonpatch } from 'fast-json-patch'; import { applyOperation } from 'fast-json-patch'; ``` -Or use the ECMAScript module (Works with Webpack, Babel, and in Node 12+ with `--experimental-modules` flag): +In standard Node, the below code uses this library as a CommonJS module: ```js -import { * as jsonpatch } from 'fast-json-patch/module/duplex.mjs'; -import { applyOperation } from 'fast-json-patch/module/duplex.mjs'; +const { applyOperation } = require('fast-json-patch'); +const applyOperation = require('fast-json-patch').applyOperation; ``` ## Directories From d594a3dd22b2e104c63c2f1cd51a14d8e7ac0602 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 13:44:25 +0200 Subject: [PATCH 21/31] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 440c35d4..2da022c2 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ import { * as jsonpatch } from 'fast-json-patch/module/duplex.mjs'; import { applyOperation } from 'fast-json-patch/module/duplex.mjs'; ``` -In Webpack (and most surely other transpilers based on Babel), the below code uses this library as an ECMAScript module: +In Webpack (and most surely other bundlers based on Babel), the below code uses this library as an ECMAScript module: ```js import { * as jsonpatch } from 'fast-json-patch'; From c3fc4d948ded3102ebfdafe5b3254095c0f5919a Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 13:51:19 +0200 Subject: [PATCH 22/31] add a new entry point "index", do not re-export "core" methods from "duplex" --- README.md | 8 ++--- dist/fast-json-patch.js | 43 +++++++++++++++++---------- dist/fast-json-patch.min.js | 4 +-- lib/duplex.js | 15 ---------- lib/index.js | 22 ++++++++++++++ module/duplex.mjs | 4 --- module/index.mjs | 6 ++++ package.json | 6 ++-- src/duplex.ts | 6 ---- src/index.ts | 35 ++++++++++++++++++++++ test/spec/coreSpec.mjs | 2 +- test/spec/duplexSpec.mjs | 2 +- test/spec/jsonPatchTestsSpec.mjs | 2 +- test/spec/validateSpec.mjs | 2 +- test/spec/webpack/importSpec.build.js | 2 +- tsc-to-mjs.sh | 4 +-- webpack.config.js | 4 +-- 17 files changed, 109 insertions(+), 58 deletions(-) create mode 100644 lib/index.js create mode 100644 module/index.mjs create mode 100644 src/index.ts diff --git a/README.md b/README.md index 2da022c2..17568850 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu ```html ``` @@ -60,8 +60,8 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu In Node 12+ with `--experimental-modules` flag, the below code uses this library as an ECMAScript module: ```js -import { * as jsonpatch } from 'fast-json-patch/module/duplex.mjs'; -import { applyOperation } from 'fast-json-patch/module/duplex.mjs'; +import { * as jsonpatch } from 'fast-json-patch/module/index.mjs'; +import { applyOperation } from 'fast-json-patch/module/index.mjs'; ``` In Webpack (and most surely other bundlers based on Babel), the below code uses this library as an ECMAScript module: diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index d6ec0eb0..a7516b25 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -717,6 +717,34 @@ exports._areEquals = _areEquals; /* 2 */ /***/ (function(module, exports, __webpack_require__) { +Object.defineProperty(exports, "__esModule", { value: true }); +/* export all core functions and types */ +var core_js_1 = __webpack_require__(1); +exports.applyOperation = core_js_1.applyOperation; +exports.applyPatch = core_js_1.applyPatch; +exports.applyReducer = core_js_1.applyReducer; +exports.getValueByPointer = core_js_1.getValueByPointer; +exports.validate = core_js_1.validate; +exports.validator = core_js_1.validator; +exports._areEquals = core_js_1._areEquals; +/* export all duplex functions */ +var duplex_js_1 = __webpack_require__(3); +exports.unobserve = duplex_js_1.unobserve; +exports.observe = duplex_js_1.observe; +exports.generate = duplex_js_1.generate; +exports.compare = duplex_js_1.compare; +/* export some helpers */ +var helpers_js_1 = __webpack_require__(0); +exports.JsonPatchError = helpers_js_1.PatchError; +exports.deepClone = helpers_js_1._deepClone; +exports.escapePathComponent = helpers_js_1.escapePathComponent; +exports.unescapePathComponent = helpers_js_1.unescapePathComponent; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + Object.defineProperty(exports, "__esModule", { value: true }); /*! * https://github.com/Starcounter-Jack/JSON-Patch @@ -725,21 +753,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); */ var helpers_js_1 = __webpack_require__(0); var core_js_1 = __webpack_require__(1); -/* export all core functions and types */ -var core_js_2 = __webpack_require__(1); -exports.applyOperation = core_js_2.applyOperation; -exports.applyPatch = core_js_2.applyPatch; -exports.applyReducer = core_js_2.applyReducer; -exports.getValueByPointer = core_js_2.getValueByPointer; -exports.validate = core_js_2.validate; -exports.validator = core_js_2.validator; -exports._areEquals = core_js_2._areEquals; -/* export some helpers */ -var helpers_js_2 = __webpack_require__(0); -exports.JsonPatchError = helpers_js_2.PatchError; -exports.deepClone = helpers_js_2._deepClone; -exports.escapePathComponent = helpers_js_2.escapePathComponent; -exports.unescapePathComponent = helpers_js_2.unescapePathComponent; var beforeDict = new WeakMap(); var Mirror = /** @class */ (function () { function Mirror(obj) { diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index aab6dc5a..0aa049e6 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -5,10 +5,10 @@ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0});var o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=_){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=_){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a0&&(e.patches=[],e.callback&&e.callback(n)),n}function f(e,t,r,o,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=n._objectKeys(t),p=n._objectKeys(e),u=!1,s=p.length-1;s>=0;s--){var c=e[h=p[s]];if(!n.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==c&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"remove",path:o+"/"+n.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:o,value:e}),r.push({op:"replace",path:o,value:t}),!0);else{var l=t[h];"object"==typeof c&&null!=c&&"object"==typeof l&&null!=l?f(c,l,r,o+"/"+n.escapePathComponent(h),a):c!==l&&(!0,a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(c)}),r.push({op:"replace",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(l)}))}}if(u||i.length!=p.length)for(s=0;s0&&(e.patches=[],e.callback&&e.callback(n)),n}function s(e,t,r,o,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=n._objectKeys(t),p=n._objectKeys(e),u=!1,c=p.length-1;c>=0;c--){var f=e[h=p[c]];if(!n.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==f&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(f)}),r.push({op:"remove",path:o+"/"+n.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:o,value:e}),r.push({op:"replace",path:o,value:t}),!0);else{var l=t[h];"object"==typeof f&&null!=f&&"object"==typeof l&&null!=l?s(f,l,r,o+"/"+n.escapePathComponent(h),a):f!==l&&(!0,a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(f)}),r.push({op:"replace",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(l)}))}}if(u||i.length!=p.length)for(c=0;c { object: T; patches: Operation[]; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..71fb56a4 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,35 @@ +/* export all core functions and types */ +export { + applyOperation, + applyPatch, + applyReducer, + getValueByPointer, + Operation, + AddOperation, + RemoveOperation, + ReplaceOperation, + MoveOperation, + CopyOperation, + TestOperation, + GetOperation, + validate, + validator, + OperationResult, + _areEquals +} from './core.js'; + +/* export all duplex functions */ +export { + unobserve, + observe, + generate, + compare +} from './duplex.js'; + +/* export some helpers */ +export { + PatchError as JsonPatchError, + _deepClone as deepClone, + escapePathComponent, + unescapePathComponent +} from './helpers.js'; \ No newline at end of file diff --git a/test/spec/coreSpec.mjs b/test/spec/coreSpec.mjs index 39cef245..19d85b8d 100644 --- a/test/spec/coreSpec.mjs +++ b/test/spec/coreSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.mjs'; +import * as jsonpatch from '../../module/index.mjs'; describe('jsonpatch.getValueByPointer', function() { it('should retrieve values by JSON pointer from tree - deep object', function() { diff --git a/test/spec/duplexSpec.mjs b/test/spec/duplexSpec.mjs index fefbf1a9..8eff889d 100644 --- a/test/spec/duplexSpec.mjs +++ b/test/spec/duplexSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.mjs'; +import * as jsonpatch from '../../module/index.mjs'; import {EventTarget, defineEventAttribute} from "../../node_modules/event-target-shim/dist/event-target-shim.mjs"; if (typeof window === 'undefined') { diff --git a/test/spec/jsonPatchTestsSpec.mjs b/test/spec/jsonPatchTestsSpec.mjs index c075e69a..e7d783c7 100644 --- a/test/spec/jsonPatchTestsSpec.mjs +++ b/test/spec/jsonPatchTestsSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.mjs'; +import * as jsonpatch from '../../module/index.mjs'; import tests_json from './json-patch-tests/tests.json.mjs'; import spec_tests_json from './json-patch-tests/spec_tests.json.mjs'; diff --git a/test/spec/validateSpec.mjs b/test/spec/validateSpec.mjs index 157230a0..345b487b 100644 --- a/test/spec/validateSpec.mjs +++ b/test/spec/validateSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/duplex.mjs'; +import * as jsonpatch from '../../module/index.mjs'; describe('validate', function() { it('should return an empty array if the patch is valid', function() { diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js index 25a3c42e..d671a295 100644 --- a/test/spec/webpack/importSpec.build.js +++ b/test/spec/webpack/importSpec.build.js @@ -1,4 +1,4 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"validate",function(){return E}),n.d(o,"validator",function(){return A}),n.d(o,"_areEquals",function(){return g}),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"validate",function(){return E}),n.d(o,"validator",function(){return A}),n.d(o,"_areEquals",function(){return g}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester diff --git a/tsc-to-mjs.sh b/tsc-to-mjs.sh index d75abde9..2b62911a 100644 --- a/tsc-to-mjs.sh +++ b/tsc-to-mjs.sh @@ -1,4 +1,4 @@ #!/bin/bash cd module -mv core.js core.mjs && mv duplex.js duplex.mjs && mv helpers.js helpers.mjs -sed -i 's/\.js/\.mjs/g' duplex.mjs core.mjs \ No newline at end of file +mv index.js index.mjs && mv core.js core.mjs && mv duplex.js duplex.mjs && mv helpers.js helpers.mjs +sed -i 's/\.js/\.mjs/g' duplex.mjs core.mjs index.mjs \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index c28aeff2..6dd512f5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -22,7 +22,7 @@ module.exports = env => { else { return [ { - entry: './lib/duplex.js', + entry: './lib/index.js', mode: 'production', optimization: { minimize: false @@ -40,7 +40,7 @@ module.exports = env => { ] }, { - entry: './lib/duplex.js', + entry: './lib/index.js', mode: 'production', output: { filename: 'fast-json-patch.min.js', From 5f4a77ec170393b13753fa3068e2fd04e1525079 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 14:23:47 +0200 Subject: [PATCH 23/31] remove interface that is redundant in "core" because it is also exported in "duplex" --- src/core.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core.ts b/src/core.ts index bd629efd..c8d743cb 100644 --- a/src/core.ts +++ b/src/core.ts @@ -63,13 +63,6 @@ export interface PatchResult extends Array> { newDocument: T; } -export interface Observer { - object: T; - patches: Operation[]; - unobserve: () => void; - callback: (patches: Operation[]) => void; -} - /* We use a Javascript hash to store each function. Each hash entry (property) uses the operation identifiers specified in rfc6902. From b5f37e76f5d6a319d9ad410a2daea6e9cf8369e9 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 14:24:01 +0200 Subject: [PATCH 24/31] move "index" files to the root directory --- .gitignore | 2 +- README.md | 8 +- dist/fast-json-patch.js | 33 +++----- dist/fast-json-patch.min.js | 2 +- index.d.ts | 8 ++ index.js | 11 +++ index.mjs | 8 ++ index.ts | 8 ++ lib/index.js | 22 ----- module/core.d.ts | 111 ++++++++++++++++++++++++++ module/duplex.d.ts | 23 ++++++ module/helpers.d.ts | 41 ++++++++++ module/index.mjs | 6 -- package.json | 6 +- src/index.ts | 35 -------- test/spec/coreSpec.mjs | 2 +- test/spec/duplexSpec.mjs | 2 +- test/spec/jsonPatchTestsSpec.mjs | 2 +- test/spec/validateSpec.mjs | 2 +- test/spec/webpack/importSpec.build.js | 2 +- tsc-to-mjs.sh | 4 +- webpack.config.js | 4 +- 22 files changed, 239 insertions(+), 103 deletions(-) create mode 100644 index.d.ts create mode 100644 index.js create mode 100644 index.mjs create mode 100644 index.ts delete mode 100644 lib/index.js create mode 100644 module/core.d.ts create mode 100644 module/duplex.d.ts create mode 100644 module/helpers.d.ts delete mode 100644 module/index.mjs delete mode 100644 src/index.ts diff --git a/.gitignore b/.gitignore index 259a81af..34f555c2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ npm-debug.log .idea # Typescript -*.d.ts +lib/*.d.ts # SauceLabs logs *.log \ No newline at end of file diff --git a/README.md b/README.md index 17568850..f64b00da 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu ```html ``` @@ -60,8 +60,8 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu In Node 12+ with `--experimental-modules` flag, the below code uses this library as an ECMAScript module: ```js -import { * as jsonpatch } from 'fast-json-patch/module/index.mjs'; -import { applyOperation } from 'fast-json-patch/module/index.mjs'; +import { * as jsonpatch } from 'fast-json-patch/index.mjs'; +import { applyOperation } from 'fast-json-patch/index.mjs'; ``` In Webpack (and most surely other bundlers based on Babel), the below code uses this library as an ECMAScript module: diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index a7516b25..950de506 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -717,28 +717,17 @@ exports._areEquals = _areEquals; /* 2 */ /***/ (function(module, exports, __webpack_require__) { -Object.defineProperty(exports, "__esModule", { value: true }); -/* export all core functions and types */ -var core_js_1 = __webpack_require__(1); -exports.applyOperation = core_js_1.applyOperation; -exports.applyPatch = core_js_1.applyPatch; -exports.applyReducer = core_js_1.applyReducer; -exports.getValueByPointer = core_js_1.getValueByPointer; -exports.validate = core_js_1.validate; -exports.validator = core_js_1.validator; -exports._areEquals = core_js_1._areEquals; -/* export all duplex functions */ -var duplex_js_1 = __webpack_require__(3); -exports.unobserve = duplex_js_1.unobserve; -exports.observe = duplex_js_1.observe; -exports.generate = duplex_js_1.generate; -exports.compare = duplex_js_1.compare; -/* export some helpers */ -var helpers_js_1 = __webpack_require__(0); -exports.JsonPatchError = helpers_js_1.PatchError; -exports.deepClone = helpers_js_1._deepClone; -exports.escapePathComponent = helpers_js_1.escapePathComponent; -exports.unescapePathComponent = helpers_js_1.unescapePathComponent; +var core = __webpack_require__(1); +Object.assign(exports, core); + +var duplex = __webpack_require__(3); +Object.assign(exports, duplex); + +var helpers = __webpack_require__(0); +exports.JsonPatchError = helpers.PatchError; +exports.deepClone = helpers._deepClone; +exports.escapePathComponent = helpers.escapePathComponent; +exports.unescapePathComponent = helpers.unescapePathComponent; /***/ }), diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index 0aa049e6..cc45307b 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -5,7 +5,7 @@ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0});var o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=_){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=_){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a | RemoveOperation | ReplaceOperation | MoveOperation | CopyOperation | TestOperation | GetOperation; +export interface Validator { + (operation: Operation, index: number, document: T, existingPathFragment: string): void; +} +export interface OperationResult { + removed?: any; + test?: boolean; + newDocument: T; +} +export interface BaseOperation { + path: string; +} +export interface AddOperation extends BaseOperation { + op: 'add'; + value: T; +} +export interface RemoveOperation extends BaseOperation { + op: 'remove'; +} +export interface ReplaceOperation extends BaseOperation { + op: 'replace'; + value: T; +} +export interface MoveOperation extends BaseOperation { + op: 'move'; + from: string; +} +export interface CopyOperation extends BaseOperation { + op: 'copy'; + from: string; +} +export interface TestOperation extends BaseOperation { + op: 'test'; + value: T; +} +export interface GetOperation extends BaseOperation { + op: '_get'; + value: T; +} +export interface PatchResult extends Array> { + newDocument: T; +} +/** + * Retrieves a value from a JSON document by a JSON pointer. + * Returns the value. + * + * @param document The document to get the value from + * @param pointer an escaped JSON pointer + * @return The retrieved value + */ +export declare function getValueByPointer(document: any, pointer: string): any; +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the {newDocument, result} of the operation. + * It modifies the `document` and `operation` objects - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyOperation(document, jsonpatch._deepClone(operation))`. + * + * @param document The document to patch + * @param operation The operation to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return `{newDocument, result}` after the operation + */ +export declare function applyOperation(document: T, operation: Operation, validateOperation?: boolean | Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean, index?: number): OperationResult; +/** + * Apply a full JSON Patch array on a JSON document. + * Returns the {newDocument, result} of the patch. + * It modifies the `document` object and `patch` - it gets the values by reference. + * If you would like to avoid touching your values, clone them: + * `jsonpatch.applyPatch(document, jsonpatch._deepClone(patch))`. + * + * @param document The document to patch + * @param patch The patch to apply + * @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. + * @param mutateDocument Whether to mutate the original document or clone it before applying + * @param banPrototypeModifications Whether to ban modifications to `__proto__`, defaults to `true`. + * @return An array of `{newDocument, result}` after the patch + */ +export declare function applyPatch(document: T, patch: Operation[], validateOperation?: boolean | Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean): PatchResult; +/** + * Apply a single JSON Patch Operation on a JSON document. + * Returns the updated document. + * Suitable as a reducer. + * + * @param document The document to patch + * @param operation The operation to apply + * @return The updated document + */ +export declare function applyReducer(document: T, operation: Operation, index: number): T; +/** + * Validates a single operation. Called from `jsonpatch.validate`. Throws `JsonPatchError` in case of an error. + * @param {object} operation - operation object (patch) + * @param {number} index - index of operation in the sequence + * @param {object} [document] - object where the operation is supposed to be applied + * @param {string} [existingPathFragment] - comes along with `document` + */ +export declare function validator(operation: Operation, index: number, document?: any, existingPathFragment?: string): void; +/** + * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. + * If error is encountered, returns a JsonPatchError object + * @param sequence + * @param document + * @returns {JsonPatchError|undefined} + */ +export declare function validate(sequence: Operation[], document?: T, externalValidator?: Validator): PatchError; +export declare function _areEquals(a: any, b: any): boolean; diff --git a/module/duplex.d.ts b/module/duplex.d.ts new file mode 100644 index 00000000..75f82fb8 --- /dev/null +++ b/module/duplex.d.ts @@ -0,0 +1,23 @@ +import { Operation } from './core.js'; +export interface Observer { + object: T; + patches: Operation[]; + unobserve: () => void; + callback: (patches: Operation[]) => void; +} +/** + * Detach an observer from an object + */ +export declare function unobserve(root: T, observer: Observer): void; +/** + * Observes changes made to an object, which can then be retrieved using generate + */ +export declare function observe(obj: Object | Array, callback?: (patches: Operation[]) => void): Observer; +/** + * Generate an array of patches from an observer + */ +export declare function generate(observer: Observer, invertible?: boolean): Operation[]; +/** + * Create an array of patches from the differences in two objects + */ +export declare function compare(tree1: Object | Array, tree2: Object | Array, invertible?: boolean): Operation[]; diff --git a/module/helpers.d.ts b/module/helpers.d.ts new file mode 100644 index 00000000..034b1a60 --- /dev/null +++ b/module/helpers.d.ts @@ -0,0 +1,41 @@ +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +export declare function hasOwnProperty(obj: any, key: any): any; +export declare function _objectKeys(obj: any): any[]; +/** +* Deeply clone the object. +* https://jsperf.com/deep-copy-vs-json-stringify-json-parse/25 (recursiveDeepCopy) +* @param {any} obj value to clone +* @return {any} cloned obj +*/ +export declare function _deepClone(obj: any): any; +export declare function isInteger(str: string): boolean; +/** +* Escapes a json pointer path +* @param path The raw pointer +* @return the Escaped path +*/ +export declare function escapePathComponent(path: string): string; +/** + * Unescapes a json pointer path + * @param path The escaped pointer + * @return The unescaped path + */ +export declare function unescapePathComponent(path: string): string; +export declare function _getPathRecursive(root: Object, obj: Object): string; +export declare function getPath(root: Object, obj: Object): string; +/** +* Recursively checks whether an object has any undefined values inside. +*/ +export declare function hasUndefined(obj: any): boolean; +export declare type JsonPatchErrorName = 'SEQUENCE_NOT_AN_ARRAY' | 'OPERATION_NOT_AN_OBJECT' | 'OPERATION_OP_INVALID' | 'OPERATION_PATH_INVALID' | 'OPERATION_FROM_REQUIRED' | 'OPERATION_VALUE_REQUIRED' | 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' | 'OPERATION_PATH_CANNOT_ADD' | 'OPERATION_PATH_UNRESOLVABLE' | 'OPERATION_FROM_UNRESOLVABLE' | 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' | 'OPERATION_VALUE_OUT_OF_BOUNDS' | 'TEST_OPERATION_FAILED'; +export declare class PatchError extends Error { + name: JsonPatchErrorName; + index?: number; + operation?: any; + tree?: any; + constructor(message: string, name: JsonPatchErrorName, index?: number, operation?: any, tree?: any); +} diff --git a/module/index.mjs b/module/index.mjs deleted file mode 100644 index 6b0d71ab..00000000 --- a/module/index.mjs +++ /dev/null @@ -1,6 +0,0 @@ -/* export all core functions and types */ -export { applyOperation, applyPatch, applyReducer, getValueByPointer, validate, validator, _areEquals } from './core.mjs'; -/* export all duplex functions */ -export { unobserve, observe, generate, compare } from './duplex.mjs'; -/* export some helpers */ -export { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './helpers.mjs'; diff --git a/package.json b/package.json index 4caeb4e3..7f6cc422 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,9 @@ "url": "http://www.starcounter.com/" }, "license": "MIT", - "main": "lib/index.js", - "module": "module/index.mjs", - "typings": "module/index.d.ts", + "main": "index.js", + "module": "index.mjs", + "typings": "index.d.ts", "devDependencies": { "benchmark": "^2.1.4", "bluebird": "^3.5.5", diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 71fb56a4..00000000 --- a/src/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* export all core functions and types */ -export { - applyOperation, - applyPatch, - applyReducer, - getValueByPointer, - Operation, - AddOperation, - RemoveOperation, - ReplaceOperation, - MoveOperation, - CopyOperation, - TestOperation, - GetOperation, - validate, - validator, - OperationResult, - _areEquals -} from './core.js'; - -/* export all duplex functions */ -export { - unobserve, - observe, - generate, - compare -} from './duplex.js'; - -/* export some helpers */ -export { - PatchError as JsonPatchError, - _deepClone as deepClone, - escapePathComponent, - unescapePathComponent -} from './helpers.js'; \ No newline at end of file diff --git a/test/spec/coreSpec.mjs b/test/spec/coreSpec.mjs index 19d85b8d..b423e072 100644 --- a/test/spec/coreSpec.mjs +++ b/test/spec/coreSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/index.mjs'; +import * as jsonpatch from '../../index.mjs'; describe('jsonpatch.getValueByPointer', function() { it('should retrieve values by JSON pointer from tree - deep object', function() { diff --git a/test/spec/duplexSpec.mjs b/test/spec/duplexSpec.mjs index 8eff889d..c5d53e87 100644 --- a/test/spec/duplexSpec.mjs +++ b/test/spec/duplexSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/index.mjs'; +import * as jsonpatch from '../../index.mjs'; import {EventTarget, defineEventAttribute} from "../../node_modules/event-target-shim/dist/event-target-shim.mjs"; if (typeof window === 'undefined') { diff --git a/test/spec/jsonPatchTestsSpec.mjs b/test/spec/jsonPatchTestsSpec.mjs index e7d783c7..86b3aa2d 100644 --- a/test/spec/jsonPatchTestsSpec.mjs +++ b/test/spec/jsonPatchTestsSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/index.mjs'; +import * as jsonpatch from '../../index.mjs'; import tests_json from './json-patch-tests/tests.json.mjs'; import spec_tests_json from './json-patch-tests/spec_tests.json.mjs'; diff --git a/test/spec/validateSpec.mjs b/test/spec/validateSpec.mjs index 345b487b..41621f93 100644 --- a/test/spec/validateSpec.mjs +++ b/test/spec/validateSpec.mjs @@ -1,4 +1,4 @@ -import * as jsonpatch from '../../module/index.mjs'; +import * as jsonpatch from '../../index.mjs'; describe('validate', function() { it('should return an empty array if the patch is valid', function() { diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js index d671a295..967effc2 100644 --- a/test/spec/webpack/importSpec.build.js +++ b/test/spec/webpack/importSpec.build.js @@ -1,4 +1,4 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"validate",function(){return E}),n.d(o,"validator",function(){return A}),n.d(o,"_areEquals",function(){return g}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"validator",function(){return A}),n.d(o,"validate",function(){return E}),n.d(o,"_areEquals",function(){return g}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester diff --git a/tsc-to-mjs.sh b/tsc-to-mjs.sh index 2b62911a..d75abde9 100644 --- a/tsc-to-mjs.sh +++ b/tsc-to-mjs.sh @@ -1,4 +1,4 @@ #!/bin/bash cd module -mv index.js index.mjs && mv core.js core.mjs && mv duplex.js duplex.mjs && mv helpers.js helpers.mjs -sed -i 's/\.js/\.mjs/g' duplex.mjs core.mjs index.mjs \ No newline at end of file +mv core.js core.mjs && mv duplex.js duplex.mjs && mv helpers.js helpers.mjs +sed -i 's/\.js/\.mjs/g' duplex.mjs core.mjs \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 6dd512f5..e10d4910 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -22,7 +22,7 @@ module.exports = env => { else { return [ { - entry: './lib/index.js', + entry: './index.js', mode: 'production', optimization: { minimize: false @@ -40,7 +40,7 @@ module.exports = env => { ] }, { - entry: './lib/index.js', + entry: './index.js', mode: 'production', output: { filename: 'fast-json-patch.min.js', From 82234a7c00aa379339b98397f949a38edd95474c Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 15:04:31 +0200 Subject: [PATCH 25/31] test typings --- .gitignore | 1 + package.json | 3 ++- test/spec/typings/typingsSpec.ts | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/spec/typings/typingsSpec.ts diff --git a/.gitignore b/.gitignore index 34f555c2..edd2cfb5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ npm-debug.log # Typescript lib/*.d.ts +test/spec/typings/typingsSpec.js # SauceLabs logs *.log \ No newline at end of file diff --git a/package.json b/package.json index 7f6cc422..15583761 100644 --- a/package.json +++ b/package.json @@ -51,10 +51,11 @@ "build": "npm run tsc && webpack", "serve": "http-server -p 5000 --silent", "tsc-watch": "tsc -w", - "test": "npm run tsc && npm run test-core && npm run test-duplex && npm run test-commonjs && npm run test-webpack-import", + "test": "npm run tsc && npm run test-core && npm run test-duplex && npm run test-commonjs && npm run test-webpack-import && npm run test-typings", "test-sauce": "npm run build && node test/Sauce/Runner.js", "test-commonjs": "jasmine test/spec/commonjs/requireSpec.js", "test-webpack-import": "webpack --env.NODE_ENV=test && jasmine test/spec/webpack/importSpec.build.js", + "test-typings": "tsc test/spec/typings/typingsSpec.ts", "test-duplex": "node --experimental-modules jasmine-run.mjs test/**/*[sS]pec.mjs", "test-core": "node --experimental-modules jasmine-run.mjs test/spec/jsonPatchTestsSpec.mjs test/spec/coreSpec.mjs test/spec/validateSpec.mjs", "bench": "npm run bench-core && npm run bench-duplex", diff --git a/test/spec/typings/typingsSpec.ts b/test/spec/typings/typingsSpec.ts new file mode 100644 index 00000000..96e8488f --- /dev/null +++ b/test/spec/typings/typingsSpec.ts @@ -0,0 +1,22 @@ +/** + * Run using `npm run test-typings` + * The sole fact that this file compiles means that typings work + * This follows how DefinitelyTyped tests work + * @see https://stackoverflow.com/questions/49296151/how-to-write-tests-for-typescript-typing-definition + */ + +// import jsonpatch from '../../..'; +import * as jsonpatchStar from '../../..'; +import { applyPatch, Operation } from '../../..'; + +const document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; + +const typedPatch = new Array({ op: "replace", path: "/firstName", value: "Joachim" }); +const untypedPatch = [{ op: "replace", path: "/firstName", value: "Joachim" }]; + +// const test_jsonpatch = jsonpatch.applyPatch(document, typedPatch).newDocument; +const test_jsonpatchStar = jsonpatchStar.applyPatch(document, typedPatch).newDocument; +const test_applyPatch = applyPatch(document, typedPatch).newDocument; + +// the below line would NOT compile with TSC +// const test_applyPatch = applyPatch(document, untypedPatch).newDocument; \ No newline at end of file From 1de6122774251a9688a354e2d23a09029dbefa65 Mon Sep 17 00:00:00 2001 From: Marcin Warpechowski Date: Thu, 8 Aug 2019 15:22:16 +0200 Subject: [PATCH 26/31] add default export, test with Webpack and typings --- index.d.ts | 28 ++++++++++++++++++++++++++- index.mjs | 25 +++++++++++++++++++++++- index.ts | 25 +++++++++++++++++++++++- test/spec/typings/typingsSpec.ts | 4 ++-- test/spec/webpack/importSpec.build.js | 6 +++--- 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/index.d.ts b/index.d.ts index f03bdf1a..3fe97a29 100644 --- a/index.d.ts +++ b/index.d.ts @@ -5,4 +5,30 @@ export { _deepClone as deepClone, escapePathComponent, unescapePathComponent -} from './module/helpers'; \ No newline at end of file +} from './module/helpers'; + + +/** + * Default export for backwards compat + */ +import * as core from './module/core'; +import * as duplex from './module/duplex'; +import { PatchError as JsonPatchError, _deepClone as deepClone, escapePathComponent, unescapePathComponent } from './module/helpers'; +declare const _default: { + JsonPatchError: typeof JsonPatchError; + deepClone: typeof deepClone; + escapePathComponent: typeof escapePathComponent; + unescapePathComponent: typeof unescapePathComponent; + unobserve(root: T, observer: duplex.Observer): void; + observe(obj: Object | T[], callback?: (patches: core.Operation[]) => void): duplex.Observer; + generate(observer: duplex.Observer, invertible?: boolean): core.Operation[]; + compare(tree1: Object | any[], tree2: Object | any[], invertible?: boolean): core.Operation[]; + getValueByPointer(document: any, pointer: string): any; + applyOperation(document: T, operation: core.Operation, validateOperation?: boolean | core.Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean, index?: number): core.OperationResult; + applyPatch(document: T, patch: core.Operation[], validateOperation?: boolean | core.Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean): core.PatchResult; + applyReducer(document: T, operation: core.Operation, index: number): T; + validator(operation: core.Operation, index: number, document?: any, existingPathFragment?: string): void; + validate(sequence: core.Operation[], document?: T, externalValidator?: core.Validator): JsonPatchError; + _areEquals(a: any, b: any): boolean; +}; +export default _default; \ No newline at end of file diff --git a/index.mjs b/index.mjs index 4a821457..b21cf4a6 100644 --- a/index.mjs +++ b/index.mjs @@ -5,4 +5,27 @@ export { _deepClone as deepClone, escapePathComponent, unescapePathComponent -} from './module/helpers.mjs'; \ No newline at end of file +} from './module/helpers.mjs'; + + +/** + * Default export for backwards compat + */ + +import * as core from './module/core.mjs'; +import * as duplex from './module/duplex.mjs'; +import { + PatchError as JsonPatchError, + _deepClone as deepClone, + escapePathComponent, + unescapePathComponent +} from './module/helpers.mjs'; + +export default { + ...core, + ...duplex, + JsonPatchError, + deepClone, + escapePathComponent, + unescapePathComponent +} \ No newline at end of file diff --git a/index.ts b/index.ts index f5b15cb2..10d72781 100644 --- a/index.ts +++ b/index.ts @@ -5,4 +5,27 @@ export { _deepClone as deepClone, escapePathComponent, unescapePathComponent -} from './src/helpers'; \ No newline at end of file +} from './src/helpers'; + + +/** + * Default export for backwards compat + */ + +import * as core from './src/core'; +import * as duplex from './src/duplex'; +import { + PatchError as JsonPatchError, + _deepClone as deepClone, + escapePathComponent, + unescapePathComponent +} from './src/helpers'; + +export default { + ...core, + ...duplex, + JsonPatchError, + deepClone, + escapePathComponent, + unescapePathComponent +} \ No newline at end of file diff --git a/test/spec/typings/typingsSpec.ts b/test/spec/typings/typingsSpec.ts index 96e8488f..ae7f4d8b 100644 --- a/test/spec/typings/typingsSpec.ts +++ b/test/spec/typings/typingsSpec.ts @@ -5,7 +5,7 @@ * @see https://stackoverflow.com/questions/49296151/how-to-write-tests-for-typescript-typing-definition */ -// import jsonpatch from '../../..'; +import jsonpatch from '../../..'; import * as jsonpatchStar from '../../..'; import { applyPatch, Operation } from '../../..'; @@ -14,7 +14,7 @@ const document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; const typedPatch = new Array({ op: "replace", path: "/firstName", value: "Joachim" }); const untypedPatch = [{ op: "replace", path: "/firstName", value: "Joachim" }]; -// const test_jsonpatch = jsonpatch.applyPatch(document, typedPatch).newDocument; +const test_jsonpatch = jsonpatch.applyPatch(document, typedPatch).newDocument; const test_jsonpatchStar = jsonpatchStar.applyPatch(document, typedPatch).newDocument; const test_applyPatch = applyPatch(document, typedPatch).newDocument; diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js index 967effc2..510af010 100644 --- a/test/spec/webpack/importSpec.build.js +++ b/test/spec/webpack/importSpec.build.js @@ -1,13 +1,13 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"JsonPatchError",function(){return l}),n.d(o,"deepClone",function(){return c}),n.d(o,"escapePathComponent",function(){return s}),n.d(o,"unescapePathComponent",function(){return h}),n.d(o,"getValueByPointer",function(){return y}),n.d(o,"applyOperation",function(){return b}),n.d(o,"applyPatch",function(){return O}),n.d(o,"applyReducer",function(){return _}),n.d(o,"validator",function(){return A}),n.d(o,"validate",function(){return E}),n.d(o,"_areEquals",function(){return g}),n.d(o,"unobserve",function(){return D}),n.d(o,"observe",function(){return N}),n.d(o,"generate",function(){return j}),n.d(o,"compare",function(){return R}); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"JsonPatchError",function(){return m}),n.d(o,"deepClone",function(){return y}),n.d(o,"getValueByPointer",function(){return _}),n.d(o,"applyOperation",function(){return A}),n.d(o,"applyPatch",function(){return E}),n.d(o,"applyReducer",function(){return g}),n.d(o,"validator",function(){return x}),n.d(o,"validate",function(){return P}),n.d(o,"_areEquals",function(){return T});var r={};n.r(r),n.d(r,"unobserve",function(){return C}),n.d(r,"observe",function(){return R}),n.d(r,"generate",function(){return I}),n.d(r,"compare",function(){return B});var i={};n.r(i),n.d(i,"JsonPatchError",function(){return w}),n.d(i,"deepClone",function(){return d}),n.d(i,"escapePathComponent",function(){return h}),n.d(i,"unescapePathComponent",function(){return l}),n.d(i,"default",function(){return S}),n.d(i,"getValueByPointer",function(){return _}),n.d(i,"applyOperation",function(){return A}),n.d(i,"applyPatch",function(){return E}),n.d(i,"applyReducer",function(){return g}),n.d(i,"validator",function(){return x}),n.d(i,"validate",function(){return P}),n.d(i,"_areEquals",function(){return T}),n.d(i,"unobserve",function(){return C}),n.d(i,"observe",function(){return R}),n.d(i,"generate",function(){return I}),n.d(i,"compare",function(){return B}); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester * MIT license */ -var r,i=(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),a=Object.prototype.hasOwnProperty;function u(e,t){return a.call(e,t)}function p(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0}function s(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function h(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function d(e,t){var n=[e];for(var o in t){var r="object"==typeof t[o]?JSON.stringify(t[o],null,2):t[o];void 0!==r&&n.push(o+": "+r)}return n.join("\n")}var l=function(e){function t(t,n,o,r,i){var a=this.constructor,u=e.call(this,d(t,{name:n,index:o,operation:r,tree:i}))||this;return u.name=n,u.index=o,u.operation=r,u.tree=i,Object.setPrototypeOf(u,a.prototype),u.message=d(t,{name:n,index:o,operation:r,tree:i}),u}return i(t,e),t}(Error),v=l,w={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){var o=y(n,this.path);o&&(o=c(o));var r=b(n,{op:"remove",path:this.from}).removed;return b(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){var o=y(n,this.from);return b(n,{op:"add",path:this.path,value:c(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:g(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},m={add:function(e,t,n){return f(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:w.move,copy:w.copy,test:w.test,_get:w._get};function y(e,t){if(""==t)return e;var n={op:"_get",path:t};return b(e,n),n.value}function b(e,t,n,o,r,i){if(void 0===n&&(n=!1),void 0===o&&(o=!0),void 0===r&&(r=!0),void 0===i&&(i=0),n&&("function"==typeof n?n(t,0,e,t.path):A(t,0)),""===t.path){var a={newDocument:e};if("add"===t.op)return a.newDocument=t.value,a;if("replace"===t.op)return a.newDocument=t.value,a.removed=e,a;if("move"===t.op||"copy"===t.op)return a.newDocument=y(e,t.from),"move"===t.op&&(a.removed=e),a;if("test"===t.op){if(a.test=g(e,t.value),!1===a.test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a.newDocument=e,a}if("remove"===t.op)return a.removed=e,a.newDocument=null,a;if("_get"===t.op)return t.value=e,a;if(n)throw new v("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return a}o||(e=c(e));var u=(t.path||"").split("/"),p=e,s=1,d=u.length,l=void 0,b=void 0,O=void 0;for(O="function"==typeof n?n:A;;){if(b=u[s],r&&"__proto__"==b)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===l&&(void 0===p[b]?l=u.slice(0,s).join("/"):s==d-1&&(l=t.path),void 0!==l&&O(t,0,e,l)),s++,Array.isArray(p)){if("-"===b)b=p.length;else{if(n&&!f(b))throw new v("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);f(b)&&(b=~~b)}if(s>=d){if(n&&"add"===t.op&&b>p.length)throw new v("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);if(!1===(a=m[t.op].call(t,p,b,e)).test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}}else if(b&&-1!=b.indexOf("~")&&(b=h(b)),s>=d){if(!1===(a=w[t.op].call(t,p,b,e)).test)throw new v("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}p=p[b]}}function O(e,t,n,o,r){if(void 0===o&&(o=!0),void 0===r&&(r=!0),n&&!Array.isArray(t))throw new v("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=c(e));for(var i=new Array(t.length),a=0,u=t.length;a0)throw new v('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new v("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new v("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n=48&&t<=57))return!1;n++}return!0}function h(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function l(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function v(e,t){var n=[e];for(var o in t){var r="object"==typeof t[o]?JSON.stringify(t[o],null,2):t[o];void 0!==r&&n.push(o+": "+r)}return n.join("\n")}var w=function(e){function t(t,n,o,r,i){var a=this.constructor,u=e.call(this,v(t,{name:n,index:o,operation:r,tree:i}))||this;return u.name=n,u.index=o,u.operation=r,u.tree=i,Object.setPrototypeOf(u,a.prototype),u.message=v(t,{name:n,index:o,operation:r,tree:i}),u}return u(t,e),t}(Error),m=w,y=d,b={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){var o=_(n,this.path);o&&(o=d(o));var r=A(n,{op:"remove",path:this.from}).removed;return A(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){var o=_(n,this.from);return A(n,{op:"add",path:this.path,value:d(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:T(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},O={add:function(e,t,n){return s(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:b.move,copy:b.copy,test:b.test,_get:b._get};function _(e,t){if(""==t)return e;var n={op:"_get",path:t};return A(e,n),n.value}function A(e,t,n,o,r,i){if(void 0===n&&(n=!1),void 0===o&&(o=!0),void 0===r&&(r=!0),void 0===i&&(i=0),n&&("function"==typeof n?n(t,0,e,t.path):x(t,0)),""===t.path){var a={newDocument:e};if("add"===t.op)return a.newDocument=t.value,a;if("replace"===t.op)return a.newDocument=t.value,a.removed=e,a;if("move"===t.op||"copy"===t.op)return a.newDocument=_(e,t.from),"move"===t.op&&(a.removed=e),a;if("test"===t.op){if(a.test=T(e,t.value),!1===a.test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a.newDocument=e,a}if("remove"===t.op)return a.removed=e,a.newDocument=null,a;if("_get"===t.op)return t.value=e,a;if(n)throw new m("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return a}o||(e=d(e));var u=(t.path||"").split("/"),p=e,c=1,f=u.length,h=void 0,v=void 0,w=void 0;for(w="function"==typeof n?n:x;;){if(v=u[c],r&&"__proto__"==v)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===h&&(void 0===p[v]?h=u.slice(0,c).join("/"):c==f-1&&(h=t.path),void 0!==h&&w(t,0,e,h)),c++,Array.isArray(p)){if("-"===v)v=p.length;else{if(n&&!s(v))throw new m("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);s(v)&&(v=~~v)}if(c>=f){if(n&&"add"===t.op&&v>p.length)throw new m("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);if(!1===(a=O[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}}else if(v&&-1!=v.indexOf("~")&&(v=l(v)),c>=f){if(!1===(a=b[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}p=p[v]}}function E(e,t,n,o,r){if(void 0===o&&(o=!0),void 0===r&&(r=!0),n&&!Array.isArray(t))throw new m("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=d(e));for(var i=new Array(t.length),a=0,u=t.length;a0)throw new m('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new m("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new m("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n0&&(e.patches=[],e.callback&&e.callback(o)),o}function C(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=p(t),a=p(e),f=!1,h=a.length-1;h>=0;h--){var d=e[v=a[h]];if(!u(t,v)||void 0===t[v]&&void 0!==d&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+s(v),value:c(d)}),n.push({op:"remove",path:o+"/"+s(v)}),f=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof d&&null!=d&&"object"==typeof l&&null!=l?C(d,l,n,o+"/"+s(v),r):d!==l&&(!0,r&&n.push({op:"test",path:o+"/"+s(v),value:c(d)}),n.push({op:"replace",path:o+"/"+s(v),value:c(l)}))}}if(f||i.length!=a.length)for(h=0;h0&&(e.patches=[],e.callback&&e.callback(o)),o}function L(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=f(t),a=f(e),u=!1,p=a.length-1;p>=0;p--){var s=e[v=a[p]];if(!c(t,v)||void 0===t[v]&&void 0!==s&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"remove",path:o+"/"+h(v)}),u=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof s&&null!=s&&"object"==typeof l&&null!=l?L(s,l,n,o+"/"+h(v),r):s!==l&&(!0,r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"replace",path:o+"/"+h(v),value:d(l)}))}}if(u||i.length!=a.length)for(p=0;p Date: Thu, 8 Aug 2019 15:26:24 +0200 Subject: [PATCH 27/31] rename "lib" directory to "commonjs" because there are many directories and the function of "lib" was not clear --- .gitignore | 2 +- README.md | 2 +- {lib => commonjs}/core.js | 0 {lib => commonjs}/duplex.js | 0 {lib => commonjs}/helpers.js | 0 index.js | 6 +++--- test/spec/coreBenchmark.js | 2 +- test/spec/duplexBenchmark.js | 2 +- tsconfig.json | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename {lib => commonjs}/core.js (100%) rename {lib => commonjs}/duplex.js (100%) rename {lib => commonjs}/helpers.js (100%) diff --git a/.gitignore b/.gitignore index edd2cfb5..05939c84 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ npm-debug.log .idea # Typescript -lib/*.d.ts +commonjs/*.d.ts test/spec/typings/typingsSpec.js # SauceLabs logs diff --git a/README.md b/README.md index f64b00da..a87e3cee 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ const applyOperation = require('fast-json-patch').applyOperation; Directories used in this package: - `dist/` - contains ES5 files for a Web browser -- `lib/` - contains CommonJS module and typings +- `commonjs/` - contains CommonJS module and typings - `module/` - contains ECMAScript module and typings - `src/` - contains TypeScript source files diff --git a/lib/core.js b/commonjs/core.js similarity index 100% rename from lib/core.js rename to commonjs/core.js diff --git a/lib/duplex.js b/commonjs/duplex.js similarity index 100% rename from lib/duplex.js rename to commonjs/duplex.js diff --git a/lib/helpers.js b/commonjs/helpers.js similarity index 100% rename from lib/helpers.js rename to commonjs/helpers.js diff --git a/index.js b/index.js index dfa80de5..d53ed04b 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,10 @@ -var core = require("./lib/core.js"); +var core = require("./commonjs/core.js"); Object.assign(exports, core); -var duplex = require("./lib/duplex.js"); +var duplex = require("./commonjs/duplex.js"); Object.assign(exports, duplex); -var helpers = require("./lib/helpers.js"); +var helpers = require("./commonjs/helpers.js"); exports.JsonPatchError = helpers.PatchError; exports.deepClone = helpers._deepClone; exports.escapePathComponent = helpers.escapePathComponent; diff --git a/test/spec/coreBenchmark.js b/test/spec/coreBenchmark.js index c4d0f077..82cf04ef 100644 --- a/test/spec/coreBenchmark.js +++ b/test/spec/coreBenchmark.js @@ -1,5 +1,5 @@ if (typeof jsonpatch === 'undefined') { - jsonpatch = require('./../../lib/duplex'); + jsonpatch = require('./../..'); } if (typeof Benchmark === 'undefined') { global.Benchmark = require('benchmark'); diff --git a/test/spec/duplexBenchmark.js b/test/spec/duplexBenchmark.js index 2a22e874..1f07a6d2 100644 --- a/test/spec/duplexBenchmark.js +++ b/test/spec/duplexBenchmark.js @@ -7,7 +7,7 @@ if (typeof window === 'undefined') { } if (typeof jsonpatch === 'undefined') { - jsonpatch = require('./../../lib/duplex'); + jsonpatch = require('./../..'); } if (typeof Benchmark === 'undefined') { diff --git a/tsconfig.json b/tsconfig.json index 78450648..26eaf38b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es5", - "outDir": "lib/", + "outDir": "commonjs/", "module": "commonjs", "lib": [ "es2016", "dom" From 3970595316a842c93874d1202bbaf7e8beb40996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Fri, 9 Aug 2019 16:44:48 +0200 Subject: [PATCH 28/31] Add extensions in duplex.ts for to imports for default re-export, to fix the merge --- src/duplex.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/duplex.ts b/src/duplex.ts index 33470279..abe7eee8 100644 --- a/src/duplex.ts +++ b/src/duplex.ts @@ -215,8 +215,8 @@ export function compare(tree1: Object | Array, tree2: Object | Array, * Default export for backwards compat */ // import just to re-export as default -import * as core from './core'; -import { PatchError as JsonPatchError, unescapePathComponent } from './helpers'; +import * as core from './core.js'; +import { PatchError as JsonPatchError, unescapePathComponent } from './helpers.js'; export default { ...core, From 14bee2532f1a6d818d7a6d9cdd0c519bf237b763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Fri, 9 Aug 2019 16:45:21 +0200 Subject: [PATCH 29/31] npm install && npm run build && npm test after merge --- commonjs/core.js | 14 +++++++++ commonjs/duplex.js | 26 +++++++++++++++++ dist/fast-json-patch.js | 42 ++++++++++++++++++++++++++- dist/fast-json-patch.min.js | 6 ++-- module/core.d.ts | 15 ++++++++++ module/core.mjs | 14 +++++++++ module/duplex.d.ts | 42 ++++++++++++++++++++++++++- module/duplex.mjs | 26 +++++++++++++++++ package-lock.json | 2 +- test/spec/webpack/importSpec.build.js | 10 ++----- 10 files changed, 183 insertions(+), 14 deletions(-) diff --git a/commonjs/core.js b/commonjs/core.js index c4f67e37..8e13ca8c 100644 --- a/commonjs/core.js +++ b/commonjs/core.js @@ -432,3 +432,17 @@ function _areEquals(a, b) { } exports._areEquals = _areEquals; ; +/** + * Default export for backwards compat + */ +exports.default = { + JsonPatchError: exports.JsonPatchError, + deepClone: exports.deepClone, + getValueByPointer: getValueByPointer, + applyOperation: applyOperation, + applyPatch: applyPatch, + applyReducer: applyReducer, + validator: validator, + validate: validate, + _areEquals: _areEquals +}; diff --git a/commonjs/duplex.js b/commonjs/duplex.js index bb3f14f3..569b23f0 100644 --- a/commonjs/duplex.js +++ b/commonjs/duplex.js @@ -1,3 +1,14 @@ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; Object.defineProperty(exports, "__esModule", { value: true }); /*! * https://github.com/Starcounter-Jack/JSON-Patch @@ -179,3 +190,18 @@ function compare(tree1, tree2, invertible) { return patches; } exports.compare = compare; +/** + * Default export for backwards compat + */ +// import just to re-export as default +var core = require("./core.js"); +var helpers_js_2 = require("./helpers.js"); +exports.default = __assign({}, core, { + // duplex + unobserve: unobserve, + observe: observe, + generate: generate, + compare: compare, + // helpers + JsonPatchError: helpers_js_2.PatchError, deepClone: helpers_js_1._deepClone, escapePathComponent: helpers_js_1.escapePathComponent, + unescapePathComponent: helpers_js_2.unescapePathComponent }); diff --git a/dist/fast-json-patch.js b/dist/fast-json-patch.js index 950de506..4cd50e28 100644 --- a/dist/fast-json-patch.js +++ b/dist/fast-json-patch.js @@ -1,4 +1,4 @@ -/*! fast-json-patch, version: 2.2.0 */ +/*! fast-json-patch, version: 2.2.1 */ var jsonpatch = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache @@ -711,6 +711,20 @@ function _areEquals(a, b) { } exports._areEquals = _areEquals; ; +/** + * Default export for backwards compat + */ +exports.default = { + JsonPatchError: exports.JsonPatchError, + deepClone: exports.deepClone, + getValueByPointer: getValueByPointer, + applyOperation: applyOperation, + applyPatch: applyPatch, + applyReducer: applyReducer, + validator: validator, + validate: validate, + _areEquals: _areEquals +}; /***/ }), @@ -734,6 +748,17 @@ exports.unescapePathComponent = helpers.unescapePathComponent; /* 3 */ /***/ (function(module, exports, __webpack_require__) { +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; Object.defineProperty(exports, "__esModule", { value: true }); /*! * https://github.com/Starcounter-Jack/JSON-Patch @@ -915,6 +940,21 @@ function compare(tree1, tree2, invertible) { return patches; } exports.compare = compare; +/** + * Default export for backwards compat + */ +// import just to re-export as default +var core = __webpack_require__(1); +var helpers_js_2 = __webpack_require__(0); +exports.default = __assign({}, core, { + // duplex + unobserve: unobserve, + observe: observe, + generate: generate, + compare: compare, + // helpers + JsonPatchError: helpers_js_2.PatchError, deepClone: helpers_js_1._deepClone, escapePathComponent: helpers_js_1.escapePathComponent, + unescapePathComponent: helpers_js_2.unescapePathComponent }); /***/ }) diff --git a/dist/fast-json-patch.min.js b/dist/fast-json-patch.min.js index cc45307b..89646f44 100644 --- a/dist/fast-json-patch.min.js +++ b/dist/fast-json-patch.min.js @@ -1,14 +1,14 @@ -/*! fast-json-patch, version: 2.2.0 */ +/*! fast-json-patch, version: 2.2.1 */ var jsonpatch=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=2)}([function(e,t){ /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester * MIT license */ -var r,n=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0});var o=Object.prototype.hasOwnProperty;function a(e,t){return o.call(e,t)}function i(e){if(Array.isArray(e)){for(var t=new Array(e.length),r=0;r=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",l,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",l,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=c([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function c(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||s;for(var a=0;a=48&&t<=57))return!1;r++}return!0},t.escapePathComponent=p,t.unescapePathComponent=function(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")},t._getPathRecursive=u,t.getPath=function(e,t){if(e===t)return"/";var r=u(e,t);if(""===r)throw new Error("Object not found in root");return"/"+r},t.hasUndefined=function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var r=0,n=t.length;r=w){if(p&&"add"===r.op&&O>v.length)throw new t.JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",f,r,e);if(!1===(h=a[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",f,r,e);return h}}else if(O&&-1!=O.indexOf("~")&&(O=n.unescapePathComponent(O)),y>=w){if(!1===(h=o[r.op].call(r,v,O,e)).test)throw new t.JsonPatchError("Test operation failed","TEST_OPERATION_FAILED",f,r,e);return h}v=v[O]}}function u(e,r,o,a,i){if(void 0===a&&(a=!0),void 0===i&&(i=!0),o&&!Array.isArray(r))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");a||(e=n._deepClone(e));for(var u=new Array(r.length),s=0,c=r.length;s0)throw new t.JsonPatchError('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",r,e,a);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new t.JsonPatchError("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",r,e,a);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&n.hasUndefined(e.value))throw new t.JsonPatchError("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",r,e,a);if(a)if("add"==e.op){var p=e.path.split("/").length,u=i.split("/").length;if(p!==u+1&&p!==u)throw new t.JsonPatchError("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",r,e,a)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==i)throw new t.JsonPatchError("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",r,e,a)}else if("move"===e.op||"copy"===e.op){var s=f([{op:"_get",path:e.from,value:void 0}],a);if(s&&"OPERATION_PATH_UNRESOLVABLE"===s.name)throw new t.JsonPatchError("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",r,e,a)}}function f(e,r,o){try{if(!Array.isArray(e))throw new t.JsonPatchError("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(r)u(n._deepClone(r),n._deepClone(e),o||!0);else{o=o||c;for(var a=0;a0&&(e.patches=[],e.callback&&e.callback(n)),n}function s(e,t,r,o,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=n._objectKeys(t),p=n._objectKeys(e),u=!1,c=p.length-1;c>=0;c--){var f=e[h=p[c]];if(!n.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==f&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(f)}),r.push({op:"remove",path:o+"/"+n.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:o,value:e}),r.push({op:"replace",path:o,value:t}),!0);else{var l=t[h];"object"==typeof f&&null!=f&&"object"==typeof l&&null!=l?s(f,l,r,o+"/"+n.escapePathComponent(h),a):f!==l&&(!0,a&&r.push({op:"test",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(f)}),r.push({op:"replace",path:o+"/"+n.escapePathComponent(h),value:n._deepClone(l)}))}}if(u||i.length!=p.length)for(c=0;c0&&(e.patches=[],e.callback&&e.callback(n)),n}function l(e,t,r,n,a){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=o._objectKeys(t),p=o._objectKeys(e),u=!1,s=p.length-1;s>=0;s--){var c=e[h=p[s]];if(!o.hasOwnProperty(t,h)||void 0===t[h]&&void 0!==c&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(a&&r.push({op:"test",path:n+"/"+o.escapePathComponent(h),value:o._deepClone(c)}),r.push({op:"remove",path:n+"/"+o.escapePathComponent(h)}),u=!0):(a&&r.push({op:"test",path:n,value:e}),r.push({op:"replace",path:n,value:t}),!0);else{var f=t[h];"object"==typeof c&&null!=c&&"object"==typeof f&&null!=f?l(c,f,r,n+"/"+o.escapePathComponent(h),a):c!==f&&(!0,a&&r.push({op:"test",path:n+"/"+o.escapePathComponent(h),value:o._deepClone(c)}),r.push({op:"replace",path:n+"/"+o.escapePathComponent(h),value:o._deepClone(f)}))}}if(u||i.length!=p.length)for(s=0;s(sequence: Operation[], document?: T, externalValidator?: Validator): PatchError; export declare function _areEquals(a: any, b: any): boolean; +declare const _default: { + JsonPatchError: typeof PatchError; + deepClone: typeof _deepClone; + getValueByPointer: typeof getValueByPointer; + applyOperation: typeof applyOperation; + applyPatch: typeof applyPatch; + applyReducer: typeof applyReducer; + validator: typeof validator; + validate: typeof validate; + _areEquals: typeof _areEquals; +}; +/** + * Default export for backwards compat + */ +export default _default; diff --git a/module/core.mjs b/module/core.mjs index 93dd839b..1db15f20 100644 --- a/module/core.mjs +++ b/module/core.mjs @@ -424,3 +424,17 @@ export function _areEquals(a, b) { return a !== a && b !== b; } ; +/** + * Default export for backwards compat + */ +export default { + JsonPatchError: JsonPatchError, + deepClone: deepClone, + getValueByPointer: getValueByPointer, + applyOperation: applyOperation, + applyPatch: applyPatch, + applyReducer: applyReducer, + validator: validator, + validate: validate, + _areEquals: _areEquals +}; diff --git a/module/duplex.d.ts b/module/duplex.d.ts index 75f82fb8..3e369304 100644 --- a/module/duplex.d.ts +++ b/module/duplex.d.ts @@ -1,4 +1,10 @@ -import { Operation } from './core.js'; +/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017 Joachim Wester + * MIT license + */ +import { _deepClone, escapePathComponent } from './helpers.js'; +import { applyPatch, Operation } from './core.js'; export interface Observer { object: T; patches: Operation[]; @@ -21,3 +27,37 @@ export declare function generate(observer: Observer, invertible?: boo * Create an array of patches from the differences in two objects */ export declare function compare(tree1: Object | Array, tree2: Object | Array, invertible?: boolean): Operation[]; +/** + * Default export for backwards compat + */ +import * as core from './core.js'; +import { PatchError as JsonPatchError, unescapePathComponent } from './helpers.js'; +declare const _default: { + unobserve: typeof unobserve; + observe: typeof observe; + generate: typeof generate; + compare: typeof compare; + JsonPatchError: typeof JsonPatchError; + deepClone: typeof _deepClone; + escapePathComponent: typeof escapePathComponent; + unescapePathComponent: typeof unescapePathComponent; + getValueByPointer(document: any, pointer: string): any; + applyOperation(document: T, operation: Operation, validateOperation?: boolean | core.Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean, index?: number): core.OperationResult; + applyPatch(document: T, patch: Operation[], validateOperation?: boolean | core.Validator, mutateDocument?: boolean, banPrototypeModifications?: boolean): core.PatchResult; + applyReducer(document: T, operation: Operation, index: number): T; + validator(operation: Operation, index: number, document?: any, existingPathFragment?: string): void; + validate(sequence: Operation[], document?: T, externalValidator?: core.Validator): JsonPatchError; + _areEquals(a: any, b: any): boolean; + default: { + JsonPatchError: typeof JsonPatchError; + deepClone: typeof _deepClone; + getValueByPointer: typeof core.getValueByPointer; + applyOperation: typeof core.applyOperation; + applyPatch: typeof applyPatch; + applyReducer: typeof core.applyReducer; + validator: typeof core.validator; + validate: typeof core.validate; + _areEquals: typeof core._areEquals; + }; +}; +export default _default; diff --git a/module/duplex.mjs b/module/duplex.mjs index b8c5c214..8449eb55 100644 --- a/module/duplex.mjs +++ b/module/duplex.mjs @@ -1,3 +1,14 @@ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester @@ -174,3 +185,18 @@ export function compare(tree1, tree2, invertible) { _generate(tree1, tree2, patches, '', invertible); return patches; } +/** + * Default export for backwards compat + */ +// import just to re-export as default +import * as core from './core.mjs'; +import { PatchError as JsonPatchError, unescapePathComponent } from './helpers.mjs'; +export default __assign({}, core, { + // duplex + unobserve: unobserve, + observe: observe, + generate: generate, + compare: compare, + // helpers + JsonPatchError: JsonPatchError, deepClone: _deepClone, escapePathComponent: escapePathComponent, + unescapePathComponent: unescapePathComponent }); diff --git a/package-lock.json b/package-lock.json index 6a3107c8..85352857 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3051,7 +3051,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" diff --git a/test/spec/webpack/importSpec.build.js b/test/spec/webpack/importSpec.build.js index 510af010..48bc80d9 100644 --- a/test/spec/webpack/importSpec.build.js +++ b/test/spec/webpack/importSpec.build.js @@ -1,13 +1,7 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"JsonPatchError",function(){return m}),n.d(o,"deepClone",function(){return y}),n.d(o,"getValueByPointer",function(){return _}),n.d(o,"applyOperation",function(){return A}),n.d(o,"applyPatch",function(){return E}),n.d(o,"applyReducer",function(){return g}),n.d(o,"validator",function(){return x}),n.d(o,"validate",function(){return P}),n.d(o,"_areEquals",function(){return T});var r={};n.r(r),n.d(r,"unobserve",function(){return C}),n.d(r,"observe",function(){return R}),n.d(r,"generate",function(){return I}),n.d(r,"compare",function(){return B});var i={};n.r(i),n.d(i,"JsonPatchError",function(){return w}),n.d(i,"deepClone",function(){return d}),n.d(i,"escapePathComponent",function(){return h}),n.d(i,"unescapePathComponent",function(){return l}),n.d(i,"default",function(){return S}),n.d(i,"getValueByPointer",function(){return _}),n.d(i,"applyOperation",function(){return A}),n.d(i,"applyPatch",function(){return E}),n.d(i,"applyReducer",function(){return g}),n.d(i,"validator",function(){return x}),n.d(i,"validate",function(){return P}),n.d(i,"_areEquals",function(){return T}),n.d(i,"unobserve",function(){return C}),n.d(i,"observe",function(){return R}),n.d(i,"generate",function(){return I}),n.d(i,"compare",function(){return B}); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);var o={};n.r(o),n.d(o,"JsonPatchError",function(){return m}),n.d(o,"deepClone",function(){return y}),n.d(o,"getValueByPointer",function(){return _}),n.d(o,"applyOperation",function(){return A}),n.d(o,"applyPatch",function(){return E}),n.d(o,"applyReducer",function(){return g}),n.d(o,"validator",function(){return P}),n.d(o,"validate",function(){return x}),n.d(o,"_areEquals",function(){return T}),n.d(o,"default",function(){return D});var r={};n.r(r),n.d(r,"unobserve",function(){return I}),n.d(r,"observe",function(){return L}),n.d(r,"generate",function(){return B}),n.d(r,"compare",function(){return k}),n.d(r,"default",function(){return V});var i={};n.r(i),n.d(i,"JsonPatchError",function(){return w}),n.d(i,"deepClone",function(){return d}),n.d(i,"escapePathComponent",function(){return h}),n.d(i,"unescapePathComponent",function(){return l}),n.d(i,"default",function(){return J}),n.d(i,"getValueByPointer",function(){return _}),n.d(i,"applyOperation",function(){return A}),n.d(i,"applyPatch",function(){return E}),n.d(i,"applyReducer",function(){return g}),n.d(i,"validator",function(){return P}),n.d(i,"validate",function(){return x}),n.d(i,"_areEquals",function(){return T}),n.d(i,"unobserve",function(){return I}),n.d(i,"observe",function(){return L}),n.d(i,"generate",function(){return B}),n.d(i,"compare",function(){return k}); /*! * https://github.com/Starcounter-Jack/JSON-Patch * (c) 2017 Joachim Wester * MIT license */ -var a,u=(a=function(e,t){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}a(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),p=Object.prototype.hasOwnProperty;function c(e,t){return p.call(e,t)}function f(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0}function h(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function l(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function v(e,t){var n=[e];for(var o in t){var r="object"==typeof t[o]?JSON.stringify(t[o],null,2):t[o];void 0!==r&&n.push(o+": "+r)}return n.join("\n")}var w=function(e){function t(t,n,o,r,i){var a=this.constructor,u=e.call(this,v(t,{name:n,index:o,operation:r,tree:i}))||this;return u.name=n,u.index=o,u.operation=r,u.tree=i,Object.setPrototypeOf(u,a.prototype),u.message=v(t,{name:n,index:o,operation:r,tree:i}),u}return u(t,e),t}(Error),m=w,y=d,b={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){var o=_(n,this.path);o&&(o=d(o));var r=A(n,{op:"remove",path:this.from}).removed;return A(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){var o=_(n,this.from);return A(n,{op:"add",path:this.path,value:d(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:T(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},O={add:function(e,t,n){return s(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:b.move,copy:b.copy,test:b.test,_get:b._get};function _(e,t){if(""==t)return e;var n={op:"_get",path:t};return A(e,n),n.value}function A(e,t,n,o,r,i){if(void 0===n&&(n=!1),void 0===o&&(o=!0),void 0===r&&(r=!0),void 0===i&&(i=0),n&&("function"==typeof n?n(t,0,e,t.path):x(t,0)),""===t.path){var a={newDocument:e};if("add"===t.op)return a.newDocument=t.value,a;if("replace"===t.op)return a.newDocument=t.value,a.removed=e,a;if("move"===t.op||"copy"===t.op)return a.newDocument=_(e,t.from),"move"===t.op&&(a.removed=e),a;if("test"===t.op){if(a.test=T(e,t.value),!1===a.test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a.newDocument=e,a}if("remove"===t.op)return a.removed=e,a.newDocument=null,a;if("_get"===t.op)return t.value=e,a;if(n)throw new m("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return a}o||(e=d(e));var u=(t.path||"").split("/"),p=e,c=1,f=u.length,h=void 0,v=void 0,w=void 0;for(w="function"==typeof n?n:x;;){if(v=u[c],r&&"__proto__"==v)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===h&&(void 0===p[v]?h=u.slice(0,c).join("/"):c==f-1&&(h=t.path),void 0!==h&&w(t,0,e,h)),c++,Array.isArray(p)){if("-"===v)v=p.length;else{if(n&&!s(v))throw new m("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);s(v)&&(v=~~v)}if(c>=f){if(n&&"add"===t.op&&v>p.length)throw new m("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);if(!1===(a=O[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}}else if(v&&-1!=v.indexOf("~")&&(v=l(v)),c>=f){if(!1===(a=b[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}p=p[v]}}function E(e,t,n,o,r){if(void 0===o&&(o=!0),void 0===r&&(r=!0),n&&!Array.isArray(t))throw new m("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=d(e));for(var i=new Array(t.length),a=0,u=t.length;a0)throw new m('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new m("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new m("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n0&&(e.patches=[],e.callback&&e.callback(o)),o}function L(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=f(t),a=f(e),u=!1,p=a.length-1;p>=0;p--){var s=e[v=a[p]];if(!c(t,v)||void 0===t[v]&&void 0!==s&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"remove",path:o+"/"+h(v)}),u=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof s&&null!=s&&"object"==typeof l&&null!=l?L(s,l,n,o+"/"+h(v),r):s!==l&&(!0,r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"replace",path:o+"/"+h(v),value:d(l)}))}}if(u||i.length!=a.length)for(p=0;p=48&&t<=57))return!1;n++}return!0}function h(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function l(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function v(e,t){var n=[e];for(var o in t){var r="object"==typeof t[o]?JSON.stringify(t[o],null,2):t[o];void 0!==r&&n.push(o+": "+r)}return n.join("\n")}var w=function(e){function t(t,n,o,r,i){var a=this.constructor,u=e.call(this,v(t,{name:n,index:o,operation:r,tree:i}))||this;return u.name=n,u.index=o,u.operation=r,u.tree=i,Object.setPrototypeOf(u,a.prototype),u.message=v(t,{name:n,index:o,operation:r,tree:i}),u}return u(t,e),t}(Error),m=w,y=d,b={add:function(e,t,n){return e[t]=this.value,{newDocument:n}},remove:function(e,t,n){var o=e[t];return delete e[t],{newDocument:n,removed:o}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:function(e,t,n){var o=_(n,this.path);o&&(o=d(o));var r=A(n,{op:"remove",path:this.from}).removed;return A(n,{op:"add",path:this.path,value:r}),{newDocument:n,removed:o}},copy:function(e,t,n){var o=_(n,this.from);return A(n,{op:"add",path:this.path,value:d(o)}),{newDocument:n}},test:function(e,t,n){return{newDocument:n,test:T(e[t],this.value)}},_get:function(e,t,n){return this.value=e[t],{newDocument:n}}},O={add:function(e,t,n){return s(t)?e.splice(t,0,this.value):e[t]=this.value,{newDocument:n,index:t}},remove:function(e,t,n){return{newDocument:n,removed:e.splice(t,1)[0]}},replace:function(e,t,n){var o=e[t];return e[t]=this.value,{newDocument:n,removed:o}},move:b.move,copy:b.copy,test:b.test,_get:b._get};function _(e,t){if(""==t)return e;var n={op:"_get",path:t};return A(e,n),n.value}function A(e,t,n,o,r,i){if(void 0===n&&(n=!1),void 0===o&&(o=!0),void 0===r&&(r=!0),void 0===i&&(i=0),n&&("function"==typeof n?n(t,0,e,t.path):P(t,0)),""===t.path){var a={newDocument:e};if("add"===t.op)return a.newDocument=t.value,a;if("replace"===t.op)return a.newDocument=t.value,a.removed=e,a;if("move"===t.op||"copy"===t.op)return a.newDocument=_(e,t.from),"move"===t.op&&(a.removed=e),a;if("test"===t.op){if(a.test=T(e,t.value),!1===a.test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a.newDocument=e,a}if("remove"===t.op)return a.removed=e,a.newDocument=null,a;if("_get"===t.op)return t.value=e,a;if(n)throw new m("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",i,t,e);return a}o||(e=d(e));var u=(t.path||"").split("/"),p=e,c=1,f=u.length,h=void 0,v=void 0,w=void 0;for(w="function"==typeof n?n:P;;){if(v=u[c],r&&"__proto__"==v)throw new TypeError("JSON-Patch: modifying `__proto__` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===h&&(void 0===p[v]?h=u.slice(0,c).join("/"):c==f-1&&(h=t.path),void 0!==h&&w(t,0,e,h)),c++,Array.isArray(p)){if("-"===v)v=p.length;else{if(n&&!s(v))throw new m("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",i,t,e);s(v)&&(v=~~v)}if(c>=f){if(n&&"add"===t.op&&v>p.length)throw new m("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",i,t,e);if(!1===(a=O[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}}else if(v&&-1!=v.indexOf("~")&&(v=l(v)),c>=f){if(!1===(a=b[t.op].call(t,p,v,e)).test)throw new m("Test operation failed","TEST_OPERATION_FAILED",i,t,e);return a}p=p[v]}}function E(e,t,n,o,r){if(void 0===o&&(o=!0),void 0===r&&(r=!0),n&&!Array.isArray(t))throw new m("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");o||(e=d(e));for(var i=new Array(t.length),a=0,u=t.length;a0)throw new m('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new m("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new m("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&function e(t){if(void 0===t)return!0;if(t)if(Array.isArray(t)){for(var n=0,o=t.length;n0&&(e.patches=[],e.callback&&e.callback(o)),o}function S(e,t,n,o,r){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var i=f(t),a=f(e),u=!1,p=a.length-1;p>=0;p--){var s=e[v=a[p]];if(!c(t,v)||void 0===t[v]&&void 0!==s&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"remove",path:o+"/"+h(v)}),u=!0):(r&&n.push({op:"test",path:o,value:e}),n.push({op:"replace",path:o,value:t}),!0);else{var l=t[v];"object"==typeof s&&null!=s&&"object"==typeof l&&null!=l?S(s,l,n,o+"/"+h(v),r):s!==l&&(!0,r&&n.push({op:"test",path:o+"/"+h(v),value:d(s)}),n.push({op:"replace",path:o+"/"+h(v),value:d(l)}))}}if(u||i.length!=a.length)for(p=0;p Date: Sat, 10 Aug 2019 21:39:12 +0200 Subject: [PATCH 30/31] Remove redundant default exports from core.ts and duplex.ts, as it is now covered by index.js and index.mjs --- src/core.ts | 17 +---------------- src/duplex.ts | 21 --------------------- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/src/core.ts b/src/core.ts index 91dc427f..c8d743cb 100644 --- a/src/core.ts +++ b/src/core.ts @@ -510,19 +510,4 @@ export function _areEquals(a: any, b: any): boolean { } return a!==a && b!==b; -}; -/** - * Default export for backwards compat - */ - -export default { - JsonPatchError, - deepClone, - getValueByPointer, - applyOperation, - applyPatch, - applyReducer, - validator, - validate, - _areEquals -} +}; \ No newline at end of file diff --git a/src/duplex.ts b/src/duplex.ts index abe7eee8..ba9658b7 100644 --- a/src/duplex.ts +++ b/src/duplex.ts @@ -209,25 +209,4 @@ export function compare(tree1: Object | Array, tree2: Object | Array, var patches = []; _generate(tree1, tree2, patches, '', invertible); return patches; -} - -/** - * Default export for backwards compat - */ -// import just to re-export as default -import * as core from './core.js'; -import { PatchError as JsonPatchError, unescapePathComponent } from './helpers.js'; - -export default { - ...core, - // duplex - unobserve, - observe, - generate, - compare, - // helpers - JsonPatchError, - deepClone:_deepClone, - escapePathComponent, - unescapePathComponent } \ No newline at end of file From 37f292d449d7f8538307bab888e105587ffff707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wytr=C4=99bowicz?= Date: Thu, 22 Aug 2019 11:36:59 +0200 Subject: [PATCH 31/31] Change `import { *...` to `import *...` in README.md, as suggested at https://github.com/Starcounter-Jack/JSON-Patch/pull/232#pullrequestreview-277868952 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a87e3cee..404021fc 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu ```html ``` @@ -60,14 +60,14 @@ In [browsers that support ECMAScript modules](https://caniuse.com/#feat=es6-modu In Node 12+ with `--experimental-modules` flag, the below code uses this library as an ECMAScript module: ```js -import { * as jsonpatch } from 'fast-json-patch/index.mjs'; +import * as jsonpatch from 'fast-json-patch/index.mjs'; import { applyOperation } from 'fast-json-patch/index.mjs'; ``` In Webpack (and most surely other bundlers based on Babel), the below code uses this library as an ECMAScript module: ```js -import { * as jsonpatch } from 'fast-json-patch'; +import * as jsonpatch from 'fast-json-patch'; import { applyOperation } from 'fast-json-patch'; ```