🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

nativemodels

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nativemodels

Native Models for Javascript

Source
npmnpm
Version
1.8.0
Version published
Weekly downloads
38
-48.65%
Maintainers
1
Weekly downloads
 
Created
Source


NativeModels

Version Weekly Downloads License

Open Issues Stars Open PRs

Dependencies DevDependencies PeerDependencies

Install Size Publish Size

Build Status

Code Coverage

Technical Debt Maintainability Coverage

Native Models provides a way to map objects in a clean and typed way. The main goal is to ensure runtime type checking and consistent models for APIs.

Getting Started

const { createModel } = require('nativemodels');
const { array, boolean, computed, date, int, object, string } = require('nativemodels/datatypes');

const photoSchema = {
	ext: string(),
	url: string().required(),
};

const contactSchema = {
	email: string(),
	phone: string(),
	url: string(),
};

const userSchema = {
	accountID: int().nullable(),
	contact: object(contactSchema),
	created: date(),
	firstName: string().required(),
	fullName: computed((record) => `${record.firstName} ${record.lastName}`),
	isAdmin: boolean().nullable(),
	lastName: string().required(),
	photos: array(object(photoSchema)),
	typeID: int().default(2),
};

const userModel = createModel(userSchema);

const johnSmith = userModel({
	contact: {
		email: 'j.smith@example.com',
	},
	firstName: 'John',
	lastName: 'Smith',
	photos: [
		{
			ext: '.jpg',
			url: 'https://example.com/img.jpg',
		},
	],
});
// => { firstName: 'John', lastName: 'Smith', fullName: 'John Smith', ...}

const userRecords = [
	{
		firstName: 'John',
		lastName: 'Smith',
	},
	{
		firstName: 'Jane',
		lastName: 'Doe',
	},
];
const users = userRecords.map(userModel);
// => [{ firstName: 'John', lastName: 'Smith', fullName: 'John Smith', ...}]

const janeDoe = userModel({
	...johnSmith,
	firstName: 'Jane',
	lastName: 'Doe',
});
// => { firstName: 'Jane', lastName: 'Doe', fullName: 'Jane Doe', ...}

Datatype API

Datatype methods that can be chained when defining schema.

datatypes.default(defaultValue)

Sets a default value if no value is set

datatypes.nullable()

Allows the value set to be null (useful for database models)

datatypes.required()

Forces the value to be required. Is ignored if default value is set

datatypes.strict()

Requires the value that is passed in to be the correct datatype instead of coerced

Datatypes

  • array
  • boolean
  • computed
  • date
  • float
  • int
  • object
  • string

Extending Datatypes

const { base } = require('nativemodels/datatypes');

const myCustomDataType = () => ({
	...base,
	parse: (key, value) => `${key}:${value}`,
	requiredCheck(key, value) {
		if (key && value) {
			return true;
		}

		throw new Error(`Property: '${key}' is required`);
	},
	strictCheck: (key, value) => {
		if (typeof value === 'string') {
			return true;
		}

		throw new Error(`Property ${key} is not a customDataType`);
	},
	validate: (key, value) => {
		if (`${key}:${value}` !== ':') {
			return true;
		}

		throw new Error(`Property ${key} is not a customDataType`);
	},
});

module.exports = int;

base.parse(key, value)

Parses the value being set

base.validCheck(key, value)

Returns true if passes your valid check else should throw an erorr

base.requiredCheck(key, value)

Returns true if passes your required check else should throw an error

base.strictCheck(key, value)

Returns true is passes your strict check else should throw an error

Customtypes

Custom types are types that are useful to have and common enough for use to include them in our library. They currently include

  • email
  • enumberable
  • guid
  • phone
  • url

Examples

const { email, enumberable, guid, phone, url } = require('nativemodels/customtypes');

const model = createModel({
	email: email(),
	enumberable: enumberable(['FOO', 'BAR']),
	guid: guid(),
	phone: phone(),
	url: url(),
});

Async / Promise Computed Functions

Sometimes computed values aren't syncronous. To help you deal with that, we have provided the resolver method which will allow you to resolve all computed functions that are promises or async functions.

NOTE: You must return an async function, Promise or syncronous result. Generators will not work with this

WARNING: This is an N+1 unoptimized resolver meaning that for each nested array / object will require an extra iteration.

const { createModel, resolver } = require('nativemodels');
const { boolean, computed } = require('nativemodels/datatypes');

const schema = {
	async: computed(
		(record) =>
			new Promise((succeed, reject) => (record.succeed ? succeed(1) : reject(new Error('Failed to resolve')))),
	),
	succeed: boolean().default(false),
};

const model = createModel(schema);
const data = model({ succeed: true });

const resolvedData = await resolver(data);
// => { async: 1, succeed: true }

Schema Parsing of resolved data

You can provide a second option to resolver() that will allow you to receive back an object that has had the schema applied to it.

const { createModel, resolver } = require('nativemodels');
const { boolean, computed, int } = require('nativemodels/datatypes');

const schema = {
	async: computed(
		(record) =>
			new Promise((succeed, reject) => (record.succeed ? succeed(1) : reject(new Error('Failed to resolve')))),
	),
	succeed: boolean().default(false),
};

const resolvedSchema = {
	async: int(),
	succeed: boolean(),
};

const model = createModel(schema);
const data = model({ succeed: true });

const resolvedData = await resolver(data, resolvedSchema);
// => { async: 1, succeed: true }

Options for createModel

defaultOptions

const defaultOptions = {
	caseSensitive: true, // Ignores case when initializing object from model
	strict: false, // Throws an error if key is not in schema
};

caseSensitive

The caseSensitive option default(true) allows you to turn off caseSensitive matching. This is useful for ignoring and parsing user submitted data into a nice clean format while still maintaining model integrity

const { createModel } = require('nativemodels');
const { string } = require('nativemodels/datatypes');

const options = {
	caseSensitive: false,
};

const schema = {
	foo: string(),
};

const model = createModel(schema, options);
const data = model({ FOO: 'bar' });
// => { foo: 'bar' }

Options are shallow by default, so if you have a deeply nested object, you will need to pass down options by hand.

const { createModel } = require('nativemodels');
const { object, string } = require('nativemodels/datatypes');

const options = {
	caseSensitive: false,
};

const schema = {
	foo: string(),
};

const deepSchema = {
	nested: object(schema, options),
};

const model = createModel(deepSchema, options);
const data = model({ Nested: { FOO: 'bar' } });
// => { nested: { foo: 'bar' } }

strict

The strict option default: false allows you to throw an error if the inital object you are assigning has extra keys. This is useful for validating data structure when coming from an unknown source

const { createModel } = require('nativemodels');
const { string } = require('nativemodels/datatypes');

const options = {
	strict: true,
};

const schema = {
	foo: string(),
};

const model = createModel(schema, options);
const data = model({ faa: 'bar' });
// => throw new Error(`Property: 'faa' is not defined in the schema`);

Options are shallow by default, so if you have a deeply nested object, you will need to pass down options by hand.

const { createModel } = require('nativemodels');
const { object, string } = require('nativemodels/datatypes');

const options = {
	strict: true,
};

const schema = {
	foo: string(),
};

const deepSchema = {
	nested: object(schema, options),
};

const model = createModel(deepSchema, options);
const data = model({ nested: { faa: 'bar' } });
// => throw new Error(`Property: 'faa' is not defined in the schema`);

FAQs

Package last updated on 05 Nov 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts