common-schema
Advanced tools
Comparing version 4.7.1 to 4.7.2
@@ -160,2 +160,4 @@ import { Normalizer } from './normalizer.js'; | ||
_getObjPathSubschemaValue(value: any, subschema: SubschemaType, pathParts: string[], partsIdx: number): any; | ||
setObjectPath(obj: any, path: string, newValue: any): void; | ||
_setObjPathSubschemaValue(value: any, subschema: SubschemaType, pathParts: string[], partsIdx: number, newValue: any): void; | ||
/** | ||
@@ -162,0 +164,0 @@ * Traverses a schema along with an object, calling onField for each field defined by the schema. |
@@ -219,2 +219,42 @@ import { SchemaError } from './schema-error.js'; | ||
} | ||
setObjectPath(obj, path, newValue) { | ||
this._setObjPathSubschemaValue(obj, this.getData(), path.split('.'), 0, newValue); | ||
} | ||
// If partsIdx === pathParts.length - 1 (last part): Set the field [part] to the value at the current container. Throw if current value is not a container. | ||
// Otherwise, recurse into value[part]. If value[part] does not exist, create it. If value[part] is not a container, throw. | ||
_setObjPathSubschemaValue(value, subschema, pathParts, partsIdx, newValue) { | ||
if (value === null || value === undefined) | ||
throw new Error('Cannot set field on undefined or null object'); | ||
if (partsIdx >= pathParts.length) | ||
throw new Error('Invalid path'); | ||
const part = pathParts[partsIdx]; | ||
if (!subschema) | ||
throw new Error('No subschema for object path ' + pathParts.join('.')); | ||
const schemaType = this._getType(subschema.type); | ||
if (!schemaType.isContainer(value, subschema, this)) | ||
throw new Error('Subschema is not container for path ' + pathParts.join('.')); | ||
if (partsIdx === pathParts.length - 1) { | ||
// This is last path component, need to set the value | ||
schemaType.setValueSubfield(value, subschema, part, newValue, this); | ||
} | ||
else { | ||
// Not the last component; descend into or create container | ||
let subvalue = schemaType.getValueSubfield(value, subschema, part, this); | ||
const subsubschema = schemaType.getFieldValueSubschema(value, subschema, part, this); | ||
if (!subsubschema) | ||
throw new Error('No subschema for object path ' + pathParts.join('.')); | ||
const subschemaType = this._getType(subsubschema.type); | ||
if (subvalue === null || subvalue === undefined) { | ||
try { | ||
const newContainer = subschemaType.newEmptyContainer(null, subsubschema, this); | ||
schemaType.setValueSubfield(value, subschema, part, newContainer, this); | ||
subvalue = newContainer; | ||
} | ||
catch (e) { | ||
throw new Error('Cannot create empty container for setting value ' + pathParts.join('.')); | ||
} | ||
} | ||
this._setObjPathSubschemaValue(subvalue, subsubschema, pathParts, partsIdx + 1, newValue); | ||
} | ||
} | ||
/** | ||
@@ -221,0 +261,0 @@ * Traverses a schema along with an object, calling onField for each field defined by the schema. |
@@ -69,2 +69,62 @@ import { expect } from 'chai'; | ||
}); | ||
it('#setObjectPath A', function () { | ||
const schema = createSchema({ | ||
foo: { | ||
bar: { | ||
baz: String | ||
} | ||
} | ||
}); | ||
const obj = { | ||
foo: { | ||
bar: {} | ||
} | ||
}; | ||
schema.setObjectPath(obj, 'foo.bar.baz', 'value'); | ||
expect(obj.foo.bar.baz).to.equal('value'); | ||
}); | ||
it('#setObjectPath B', function () { | ||
const schema = createSchema({ | ||
foo: { | ||
bar: { | ||
baz: String | ||
} | ||
} | ||
}); | ||
const obj = { | ||
foo: {} | ||
}; | ||
schema.setObjectPath(obj, 'foo.bar.baz', 'value'); | ||
expect(obj.foo.bar.baz).to.equal('value'); | ||
}); | ||
it('#setObjectPath C', function () { | ||
const schema = createSchema({ | ||
foo: 'string' | ||
}); | ||
const obj = { | ||
foo: {} | ||
}; | ||
schema.setObjectPath(obj, 'foo', 'value'); | ||
expect(obj.foo).to.equal('value'); | ||
}); | ||
it('#setObjectPath D', function () { | ||
const schema = createSchema({ | ||
arr: [ | ||
{ | ||
foo: 'string' | ||
} | ||
] | ||
}); | ||
const obj = { | ||
arr: [ | ||
{ | ||
foo: 'a' | ||
} | ||
] | ||
}; | ||
schema.setObjectPath(obj, 'arr.0.foo', 'b'); | ||
schema.setObjectPath(obj, 'arr.1.foo', 'c'); | ||
expect(obj.arr[0].foo).to.equal('b'); | ||
expect(obj.arr[1].foo).to.equal('c'); | ||
}); | ||
it('#setSubschemaOption', function () { | ||
@@ -71,0 +131,0 @@ let schema = createSchema({ |
@@ -292,2 +292,37 @@ import { SchemaError } from './schema-error.js'; | ||
setObjectPath(obj: any, path: string, newValue: any): void { | ||
this._setObjPathSubschemaValue(obj, this.getData(), path.split('.'), 0, newValue); | ||
} | ||
// If partsIdx === pathParts.length - 1 (last part): Set the field [part] to the value at the current container. Throw if current value is not a container. | ||
// Otherwise, recurse into value[part]. If value[part] does not exist, create it. If value[part] is not a container, throw. | ||
_setObjPathSubschemaValue(value: any, subschema: SubschemaType, pathParts: string[], partsIdx: number, newValue: any): void { | ||
if (value === null || value === undefined) throw new Error('Cannot set field on undefined or null object'); | ||
if (partsIdx >= pathParts.length) throw new Error('Invalid path'); | ||
const part: string = pathParts[partsIdx]; | ||
if (!subschema) throw new Error('No subschema for object path ' + pathParts.join('.')); | ||
const schemaType: SchemaType = this._getType(subschema.type); | ||
if (!schemaType.isContainer(value, subschema, this)) throw new Error('Subschema is not container for path ' + pathParts.join('.')); | ||
if (partsIdx === pathParts.length - 1) { | ||
// This is last path component, need to set the value | ||
schemaType.setValueSubfield(value, subschema, part, newValue, this); | ||
} else { | ||
// Not the last component; descend into or create container | ||
let subvalue: any = schemaType.getValueSubfield(value, subschema, part, this); | ||
const subsubschema = schemaType.getFieldValueSubschema(value, subschema, part, this); | ||
if (!subsubschema) throw new Error('No subschema for object path ' + pathParts.join('.')); | ||
const subschemaType: SchemaType = this._getType(subsubschema.type); | ||
if (subvalue === null || subvalue === undefined) { | ||
try { | ||
const newContainer = subschemaType.newEmptyContainer(null, subsubschema, this); | ||
schemaType.setValueSubfield(value, subschema, part, newContainer, this); | ||
subvalue = newContainer; | ||
} catch (e) { | ||
throw new Error('Cannot create empty container for setting value ' + pathParts.join('.')); | ||
} | ||
} | ||
this._setObjPathSubschemaValue(subvalue, subsubschema, pathParts, partsIdx + 1, newValue); | ||
} | ||
} | ||
/** | ||
@@ -294,0 +329,0 @@ * Traverses a schema along with an object, calling onField for each field defined by the schema. |
{ | ||
"name": "common-schema", | ||
"version": "4.7.1", | ||
"version": "4.7.2", | ||
"description": "Schema-handling utilities, including schema validators and checkers.", | ||
@@ -5,0 +5,0 @@ "main": "./dist/lib/index.js", |
@@ -79,2 +79,69 @@ import { expect } from 'chai'; | ||
it('#setObjectPath A', function() { | ||
const schema = createSchema({ | ||
foo: { | ||
bar: { | ||
baz: String | ||
} | ||
} | ||
}); | ||
const obj: any = { | ||
foo: { | ||
bar: { | ||
} | ||
} | ||
}; | ||
schema.setObjectPath(obj, 'foo.bar.baz', 'value'); | ||
expect(obj.foo.bar.baz).to.equal('value'); | ||
}); | ||
it('#setObjectPath B', function() { | ||
const schema = createSchema({ | ||
foo: { | ||
bar: { | ||
baz: String | ||
} | ||
} | ||
}); | ||
const obj: any = { | ||
foo: { | ||
} | ||
}; | ||
schema.setObjectPath(obj, 'foo.bar.baz', 'value'); | ||
expect(obj.foo.bar.baz).to.equal('value'); | ||
}); | ||
it('#setObjectPath C', function() { | ||
const schema = createSchema({ | ||
foo: 'string' | ||
}); | ||
const obj: any = { | ||
foo: { | ||
} | ||
}; | ||
schema.setObjectPath(obj, 'foo', 'value'); | ||
expect(obj.foo).to.equal('value'); | ||
}); | ||
it('#setObjectPath D', function() { | ||
const schema = createSchema({ | ||
arr: [ | ||
{ | ||
foo: 'string' | ||
} | ||
] | ||
}); | ||
const obj: any = { | ||
arr: [ | ||
{ | ||
foo: 'a' | ||
} | ||
] | ||
}; | ||
schema.setObjectPath(obj, 'arr.0.foo', 'b'); | ||
schema.setObjectPath(obj, 'arr.1.foo', 'c'); | ||
expect(obj.arr[0].foo).to.equal('b'); | ||
expect(obj.arr[1].foo).to.equal('c'); | ||
}); | ||
it('#setSubschemaOption', function() { | ||
@@ -81,0 +148,0 @@ let schema = createSchema({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
596713
12422