|
@@ -0,0 +1,62 @@
|
|
|
+const Ajv = require('ajv')
|
|
|
+
|
|
|
+
|
|
|
+module.exports = (obj={}, inSchema, outSchema) => {
|
|
|
+ if (!inSchema) throw new ReferenceError('input schema not defined')
|
|
|
+
|
|
|
+ const inValidate = (new Ajv()).compile(inSchema)
|
|
|
+ let outValidate;
|
|
|
+
|
|
|
+ if (outSchema){
|
|
|
+ outSchema = {...outSchema}
|
|
|
+ outSchema.additionalProperties = false
|
|
|
+ outValidate = (new Ajv()).compile(outSchema)
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Proxy(obj, {
|
|
|
+ get(obj, prop){
|
|
|
+ if (outValidate && !outValidate(obj)){
|
|
|
+ if (outValidate.errors.find(({instancePath}) => instancePath.slice(1).startsWith(prop)) ||
|
|
|
+ (outValidate.errors[0].keyword === 'additionalProperties' && outValidate.errors[0].params.additionalProperty === prop)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return obj[prop]
|
|
|
+ },
|
|
|
+ set(obj, prop, value){
|
|
|
+ const newObject = {...obj, [prop]: value}
|
|
|
+ if (!inValidate(newObject)){
|
|
|
+ throw new TypeError(JSON.stringify([inValidate.errors, prop, value], null, 4))
|
|
|
+ }
|
|
|
+ obj[prop] = value
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const schema = {
|
|
|
+ type: "object",
|
|
|
+ properties: {
|
|
|
+ foo: {type: "integer"},
|
|
|
+ bar: {type: "string"}
|
|
|
+ },
|
|
|
+ required: ["foo"],
|
|
|
+ additionalProperties: false
|
|
|
+}
|
|
|
+
|
|
|
+const outSchema = {
|
|
|
+ type: "object",
|
|
|
+ properties: {
|
|
|
+ foo: {type: "integer"},
|
|
|
+ },
|
|
|
+ required: ["foo"],
|
|
|
+ additionalProperties: false
|
|
|
+}
|
|
|
+
|
|
|
+let validated = module.exports({}, schema, outSchema)
|
|
|
+
|
|
|
+validated.foo = 5;
|
|
|
+validated.bar = "string";
|
|
|
+console.log(validated.foo)
|
|
|
+console.log(validated.bar)
|
|
|
+console.log({...validated})
|
|
|
+//validated.bar = 100500;
|