From 0b557d32138043480cc185564a6ab99e2601918e Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Tue, 30 Jan 2018 18:39:57 -0800 Subject: [PATCH 1/3] Expect that $$ref will be on patch destinations and not on sources --- test/resolver.js | 4 +--- test/specmap/all-of.js | 2 -- test/specmap/index.js | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/resolver.js b/test/resolver.js index c86dab181..19129ea08 100644 --- a/test/resolver.js +++ b/test/resolver.js @@ -447,7 +447,6 @@ describe('resolver', () => { }, definitions: { Category: { - $$ref: '#/definitions/Category', // FIXME: benign, but this should not be present type: 'object', properties: { id: { @@ -460,14 +459,13 @@ describe('resolver', () => { } }, Pet: { - $$ref: '#/definitions/Pet', type: 'object', required: [ 'category' ], properties: { category: { - $$ref: '#/definitions/Category', // FIXME: benign, but this should not be present + $$ref: '#/definitions/Category', type: 'object', properties: { id: { diff --git a/test/specmap/all-of.js b/test/specmap/all-of.js index 8c5293c6f..60de3e514 100644 --- a/test/specmap/all-of.js +++ b/test/specmap/all-of.js @@ -128,7 +128,6 @@ describe('allOf', function () { errors: [], spec: { Pet: { - $$ref: '#/Pet', type: 'object', properties: { name: { @@ -137,7 +136,6 @@ describe('allOf', function () { } }, Cat: { - $$ref: '#/Cat', properties: { meow: { type: 'string' diff --git a/test/specmap/index.js b/test/specmap/index.js index d8cf9afd9..2d341fc98 100644 --- a/test/specmap/index.js +++ b/test/specmap/index.js @@ -549,6 +549,7 @@ describe('specmap', function () { }) .then((res) => { expect(res.spec.one.$$ref).toEqual('#/two') + expect(res.spec.two.$$ref).toEqual(undefined) }) }) From f76371f0910f514588b5ed69c978ac964cf0d62a Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Wed, 31 Jan 2018 14:10:43 -0800 Subject: [PATCH 2/3] Use latest fast-json-patch; don't attach $$ref's to origin --- package.json | 4 +-- src/specmap/index.js | 5 ++- src/specmap/lib/index.js | 68 ++++++++++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 21adf40c1..aad454ba9 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "cross-fetch": "0.0.8", "deep-extend": "^0.4.1", "encode-3986": "^1.0.0", - "fast-json-patch": "1.1.8", + "fast-json-patch": "^1.2.2", "isomorphic-form-data": "0.0.1", "js-yaml": "^3.8.1", "lodash": "^4.16.2", @@ -77,4 +77,4 @@ "utf8-bytes": "0.0.1", "utfstring": "^2.0.0" } -} \ No newline at end of file +} diff --git a/src/specmap/index.js b/src/specmap/index.js index fcf1431e8..ace50efeb 100644 --- a/src/specmap/index.js +++ b/src/specmap/index.js @@ -212,8 +212,11 @@ class SpecMap { } updateMutations(patch) { - if (lib.applyPatch(this.state, patch, {allowMetaPatches: this.allowMetaPatches})) { + const result = lib.applyPatch(this.state, patch, {allowMetaPatches: this.allowMetaPatches}) + console.log('SPECMAP RESULT', result) + if (result) { this.mutations.push(patch) + this.state = result } } diff --git a/src/specmap/lib/index.js b/src/specmap/lib/index.js index cbd865f79..8d7d814c7 100644 --- a/src/specmap/lib/index.js +++ b/src/specmap/lib/index.js @@ -30,22 +30,25 @@ export default { } function applyPatch(obj, patch, opts) { + console.log('original obj', obj, "\n\n") + opts = opts || {} patch = Object.assign({}, patch, { path: patch.path && normalizeJSONPath(patch.path) }) + console.log('patch', patch, "\n\n") + if (patch.op === 'merge') { - const valPatch = _get(patch.path) - jsonPatch.apply(obj, [valPatch]) - Object.assign(valPatch.value, patch.value) + const newValue = getInByJsonPath(obj, patch.path) + Object.assign(newValue, patch.value) + jsonPatch.applyPatch(obj, [replace(patch.path, newValue)]) } else if (patch.op === 'mergeDeep') { - const valPatch = _get(patch.path) - jsonPatch.apply(obj, [valPatch]) - const origValPatchValue = Object.assign({}, valPatch.value) - deepExtend(valPatch.value, patch.value) + const currentValue = getInByJsonPath(obj, patch.path) + const origValPatchValue = Object.assign({}, currentValue) + deepExtend(currentValue, patch.value) // deepExtend doesn't merge arrays, so we will do it manually for (const prop in patch.value) { @@ -53,23 +56,51 @@ function applyPatch(obj, patch, opts) { const propVal = patch.value[prop] if (Array.isArray(propVal)) { const existing = origValPatchValue[prop] || [] - valPatch.value[prop] = existing.concat(propVal) + currentValue[prop] = existing.concat(propVal) } } } } - else { - jsonPatch.apply(obj, [patch]) + else if (patch.op === 'add' && patch.path === '' && isObject(patch.value)) { + // { op: 'add', path: '', value: { a: 1, b: 2 }} + // has no effect: json patch refuses to do anything. + // so let's break that patch down into a set of patches, + // one for each key in the intended root value. + + const patches = Object.keys(patch.value) + .reduce((arr, key) => { + arr.push({ + op: 'add', + path: `/${normalizeJSONPath(key)}`, + value: patch.value[key] + }) + return arr + }, []) + + console.log('segmented patches', patches, "\n\n") + jsonPatch.applyPatch(obj, patches) + } else if(patch.op === 'replace' && patch.path === '') { + let value = patch.value + + if (opts.allowMetaPatches && patch.meta && isAdditiveMutation(patch) && + (Array.isArray(patch.value) || isObject(patch.value))) { + value = Object.assign({}, value, patch.meta) + } + obj = value + } else { + jsonPatch.applyPatch(obj, [patch]) // Attach metadata to the resulting value. if (opts.allowMetaPatches && patch.meta && isAdditiveMutation(patch) && (Array.isArray(patch.value) || isObject(patch.value))) { - const valPatch = _get(patch.path) - jsonPatch.apply(obj, [valPatch]) - Object.assign(valPatch.value, patch.meta) + const currentValue = getInByJsonPath(obj, patch.path) + const newValue = Object.assign({}, currentValue, patch.meta) + jsonPatch.applyPatch(obj, [replace(patch.path, newValue)]) } } + console.log('final obj', obj, "\n\n") + return obj } @@ -302,3 +333,14 @@ function isContextPatch(patch) { function isPatch(patch) { return patch && typeof patch === 'object' } + +function getInByJsonPath(obj, jsonPath) { + console.log('getInByJsonPath', jsonPath) + try { + return jsonPatch.getValueByPointer(obj, jsonPath) + } + catch (e) { + console.error(e) + return {} + } +} From e5b530e94ed60b757fc027bc2bcca6c190717e7b Mon Sep 17 00:00:00 2001 From: Kyle Shockey Date: Wed, 31 Jan 2018 14:12:53 -0800 Subject: [PATCH 3/3] ESLint fixes --- src/specmap/index.js | 1 - src/specmap/lib/index.js | 18 ++++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/specmap/index.js b/src/specmap/index.js index ace50efeb..c18c03247 100644 --- a/src/specmap/index.js +++ b/src/specmap/index.js @@ -213,7 +213,6 @@ class SpecMap { updateMutations(patch) { const result = lib.applyPatch(this.state, patch, {allowMetaPatches: this.allowMetaPatches}) - console.log('SPECMAP RESULT', result) if (result) { this.mutations.push(patch) this.state = result diff --git a/src/specmap/lib/index.js b/src/specmap/lib/index.js index 8d7d814c7..26d23a241 100644 --- a/src/specmap/lib/index.js +++ b/src/specmap/lib/index.js @@ -30,16 +30,12 @@ export default { } function applyPatch(obj, patch, opts) { - console.log('original obj', obj, "\n\n") - opts = opts || {} patch = Object.assign({}, patch, { path: patch.path && normalizeJSONPath(patch.path) }) - console.log('patch', patch, "\n\n") - if (patch.op === 'merge') { const newValue = getInByJsonPath(obj, patch.path) Object.assign(newValue, patch.value) @@ -77,9 +73,9 @@ function applyPatch(obj, patch, opts) { return arr }, []) - console.log('segmented patches', patches, "\n\n") - jsonPatch.applyPatch(obj, patches) - } else if(patch.op === 'replace' && patch.path === '') { + jsonPatch.applyPatch(obj, patches) + } + else if (patch.op === 'replace' && patch.path === '') { let value = patch.value if (opts.allowMetaPatches && patch.meta && isAdditiveMutation(patch) && @@ -87,7 +83,8 @@ function applyPatch(obj, patch, opts) { value = Object.assign({}, value, patch.meta) } obj = value - } else { + } + else { jsonPatch.applyPatch(obj, [patch]) // Attach metadata to the resulting value. @@ -99,8 +96,6 @@ function applyPatch(obj, patch, opts) { } } - console.log('final obj', obj, "\n\n") - return obj } @@ -335,12 +330,11 @@ function isPatch(patch) { } function getInByJsonPath(obj, jsonPath) { - console.log('getInByJsonPath', jsonPath) try { return jsonPatch.getValueByPointer(obj, jsonPath) } catch (e) { - console.error(e) + console.error(e) // eslint-disable-line no-console return {} } }