diff --git a/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap b/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap index c7158128..0077a803 100644 --- a/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap +++ b/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap @@ -25,7 +25,6 @@ Array [ "type": "string", }, }, - "type": "object", }, Object { "properties": Object { @@ -33,7 +32,6 @@ Array [ "type": "string", }, }, - "type": "object", }, ], "type": "object", @@ -63,7 +61,6 @@ Array [ "type": "string", }, }, - "type": "object", }, Object { "properties": Object { @@ -71,7 +68,6 @@ Array [ "type": "string", }, }, - "type": "object", }, ], "type": "object", diff --git a/src/utils/__tests__/renderSchema.spec.ts b/src/utils/__tests__/renderSchema.spec.ts index 4c7b7cbd..a77a8c18 100644 --- a/src/utils/__tests__/renderSchema.spec.ts +++ b/src/utils/__tests__/renderSchema.spec.ts @@ -10,19 +10,36 @@ jest.mock('../generateId', () => ({ describe('renderSchema util', () => { it.each([ - ['default-schema.json', ''], - ['ref/original.json', 'ref/resolved.json'], - ['combiner-schema.json', ''], - ['array-of-objects.json', ''], - ['array-of-refs.json', ''], - ['array-of-allofs.json', ''], - ['tickets.schema.json', ''], - ])('should match %s', (schema, dereferenced) => { + 'default-schema.json', + 'ref/original.json', + 'combiner-schema.json', + 'array-of-objects.json', + 'array-of-refs.json', + 'array-of-allofs.json', + 'tickets.schema.json', + ])('should match %s', schema => { expect( Array.from(renderSchema(JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf8')))), ).toMatchSnapshot(); }); + it.each([ + 'default-schema.json', + 'ref/original.json', + 'combiner-schema.json', + 'array-of-objects.json', + 'array-of-refs.json', + 'array-of-allofs.json', + 'tickets.schema.json', + ])('should not mutate original object %s', schema => { + const content = fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf8'); + const input = JSON.parse(content); + + Array.from(renderSchema(input)); + + expect(input).toStrictEqual(JSON.parse(content)); + }); + it('given schema with complex types, throws', () => { expect(() => Array.from( diff --git a/src/utils/renderSchema.ts b/src/utils/renderSchema.ts index d7c977e1..c5adbe88 100644 --- a/src/utils/renderSchema.ts +++ b/src/utils/renderSchema.ts @@ -104,10 +104,13 @@ export const renderSchema: Walker = function*(schema, level = 0, meta = { path: if (node.properties !== undefined) { for (const [i, property] of node.properties.entries()) { if ('type' in node) { - property.type = property.type || node.type; + node.properties[i] = { + ...property, + type: property.type || node.type, + }; } - yield* renderSchema(property, level + 1, { + yield* renderSchema(node.properties[i], level + 1, { ...(i !== 0 && { divider: DIVIDERS[node.combiner] }), path: [...path, node.combiner, i], }); diff --git a/src/utils/walk.ts b/src/utils/walk.ts index 88c1a6c2..b6432429 100644 --- a/src/utils/walk.ts +++ b/src/utils/walk.ts @@ -27,10 +27,11 @@ function processNode(node: JSONSchema4): SchemaNode | void { const type = node.type || inferType(node); if (combiner) { + const properties = node[combiner]; return { id: generateId(), combiner, - properties: node[combiner], + properties: Array.isArray(properties) ? properties.slice() : properties, annotations: getAnnotations(node), ...(type !== undefined && { type }), } as ICombinerNode;