Giter VIP home page Giter VIP logo

Comments (8)

sylvainpolletvillard avatar sylvainpolletvillard commented on June 18, 2024

Hello,

Yeah I did not think about nested models when writing this example of SealedModel, but that's an easy fix.

We will consider than when encoutering another nested model in the definition, the parent model is trusting its child model to validate its properties. So if you use SealedModel for child models as well, you should be fine.

Here is the completed SealedModel code:

import { ObjectModel } from "objectmodel";

const SealedModel = def => {
	let model = ObjectModel(def);
	model.sealed = true;
	model.extend = () => {
		throw new Error(`Sealed models cannot be extended`);
	};

	const checkUndeclaredProps = (obj, def, undeclaredProps, path) => {
		Object.keys(obj).forEach(key => {
			let val = obj[key],
				subpath = path ? path + "." + key : key;
			if(def instanceof Model){
				// trust nested model props validation
			} else if (!Object.prototype.hasOwnProperty.call(def, key)) {
				undeclaredProps.push(subpath);
			} else if (val && typeof val === "object" && Object.getPrototypeOf(val) === Object.prototype) {
				checkUndeclaredProps(val, def[key], undeclaredProps, subpath);
			}
		});
	};

	return model.assert(
		function hasNoUndeclaredProps(obj) {
			if (!model.sealed) return true;
			let undeclaredProps = [];
			checkUndeclaredProps(obj, this.definition, undeclaredProps);
			return undeclaredProps.length === 0 ? true : undeclaredProps;
		},
		undeclaredProps =>
			`Undeclared properties in the sealed model definition: ${undeclaredProps}`
	);
};

export default SealedModel;

Thanks for your report, I'll update it on the website as well.

from objectmodel.

eponymous301 avatar eponymous301 commented on June 18, 2024

Excellent, thank you!

from objectmodel.

eponymous301 avatar eponymous301 commented on June 18, 2024

Doc note - missing line import {Model} from 'objectmodel' at top of http://objectmodel.js.org/docs/examples/sealed.js

I noticed an issue when trying to add a nested sealed model as an optional field:

const NameModel = SealedModel({
  first: String,
  last: String
})

const PossiblyAnonymousPersonModel = SealedModel({
  age: Number,
  name: [NameModel]
})

const x = PossiblyAnonymousPersonModel({
  age: 20,
  name: {
	first: 'John',
	last: 'Doe'
  }
})

// TypeError: Undeclared properties in the sealed model definition: name.first,name.last

Omitting the optional nested model altogether works fine:

const y = PossiblyAnonymousPersonModel({
  age: 20
})

Setting the fields in the inner model to optional still produces the undeclared properties message, although only for provided input fields:

const NameModel = SealedModel({
  first: [String],
  last: [String]
})

const PossiblyAnonymousPersonModel = SealedModel({
  age: Number,
  name: [NameModel]
})

const z = PossiblyAnonymousPersonModel({
  age: 20,
  name: {
	first: "John"
  }
})

//  Undeclared properties in the sealed model definition: name.first

from objectmodel.

sylvainpolletvillard avatar sylvainpolletvillard commented on June 18, 2024

Yes, the code of the SealedModel example is perfectible. I updated it , is it better now ?
http://objectmodel.js.org/docs/examples/sealed.js

from objectmodel.

eponymous301 avatar eponymous301 commented on June 18, 2024

Yes, optional nested models working now with SealedModel(). Thank you!

from objectmodel.

eponymous301 avatar eponymous301 commented on June 18, 2024

Ah, sorry, now getting Undeclared properties in the sealed model definition: 0,1,2... appended to errors if I pass in a string, e.g.

const z = PossiblyAnonymousPersonModel('foobar')

// TypeError: expecting {
//         age: Number, 
//         name: [{
//                         first: [String], 
//                         last: [String] 
//                 }] 
// }, got String "foobar"
// Undeclared properties in the sealed model definition: 0,1,2,3,4,5

from objectmodel.

sylvainpolletvillard avatar sylvainpolletvillard commented on June 18, 2024

Oh yeah that's an easy fix, the assertion should not be run at all if the argument is not an object

Add if(typeof obj !== "object") return; at the first line of checkUndeclaredProps assertion, like so:

import { ObjectModel } from "objectmodel";

const SealedModel = def => {
	const model = ObjectModel(def);
	model.sealed = true;
	model.extend = () => {
		throw new Error(`Sealed models cannot be extended`);
	};

	const isPlainObject = obj => typeof obj === "object" && Object.getPrototypeOf(obj) === Object.prototype
	const checkUndeclaredProps = (obj, def, undeclaredProps, path) => {
                if(typeof obj !== "object" || obj === null) return;
		Object.keys(obj).forEach(key => {
			let val = obj[key],
				subpath = path ? path + "." + key : key;
			if(isPlainObject(def) && !Object.prototype.hasOwnProperty.call(def, key)) {
				undeclaredProps.push(subpath);
			} else if (isPlainObject(val) && isPlainObject(def)) {
				checkUndeclaredProps(val, def[key], undeclaredProps, subpath);
			}
		});
	};

	return model.assert(
		function hasNoUndeclaredProps(obj) {
			if (!model.sealed) return true;
			let undeclaredProps = [];
			checkUndeclaredProps(obj, this.definition, undeclaredProps);
			return undeclaredProps.length === 0 ? true : undeclaredProps;
		},
		undeclaredProps =>
			`Undeclared properties in the sealed model definition: ${undeclaredProps}`
	);
};

export default SealedModel;

from objectmodel.

eponymous301 avatar eponymous301 commented on June 18, 2024

That fixed, thank you!

from objectmodel.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.