Skip to content

Repository files navigation

MCF-Objects

A lightweight JavaScript library for creating typed objects with built-in validation. Define a schema once, and every read/write to the object's fields is automatically type-checked and validated against the constraints you specify.

Table of contents

Features

  • Simple schema-based object definitions
  • Built-in support for common types: string, number, boolean, array, enum
  • Field-level constraints: required, defaultValue, min / max, minLength / maxLength, availableValues
  • Automatic validation on both instantiation and later assignment
  • Extendable: build your own reusable typed objects on top of DefinedObject (see the included File object)

Installation

Add the next line to your package.json file:

"mcf-objects": "git+https://github.com/DausdasKreuz/mcf-objects.git"

Then run

npm install
npm run dist

Quick start

import { DefinedObject } from 'mcf-objects'

const user = new DefinedObject({
  fields: {
    name:  { TYPE: 'string', required: true, maxLength: 50 },
    age:   { TYPE: 'number', min: 0, max: 120 },
    role:  { TYPE: 'enum', availableValues: ['admin', 'editor', 'viewer'], defaultValue: 'viewer' },
    tags:  { TYPE: 'array' },
    active: { TYPE: 'boolean', defaultValue: true },
  },
  values: {
    name: 'Jane Doe',
    age: 32,
    tags: ['staff', 'backend'],
  },
})

console.log(user.getValue())
// { name: 'Jane Doe', age: 32, role: 'viewer', tags: ['staff', 'backend'], active: true }

user.setValue({ age: 33 })
console.log(user.getValue().age) // 33

user.setValue({ age: -5 })
// Throws: MCF-Objects ==> MCF_Number validation: the value -5 is lower than the minimum defined: 0

Core concepts

Defining an object

A DefinedObject is created from a definition with two parts:

  • fields: the schema — one entry per field, describing its TYPE and constraints.
  • values: the initial values for those fields.
new DefinedObject({
  fields: { /* schema */ },
  values: { /* initial data */ },
})

Supported field types and options

TYPE Options
string required, defaultValue, minLength, maxLength
number required, defaultValue, min, max
boolean required, defaultValue
array required, defaultValue, minLength, maxLength
enum required, defaultValue, availableValues (array of allowed values)

Common options for every field:

  • required: throws if the field is missing when the object is created.
  • defaultValue: value used when none is provided.
  • null: false: throws if the field ends up undefined/null after applying required and defaultValue.

Reading and writing values

user.getValue()          // returns a plain object with the current values of every field
user.setValue({ ... })   // validates and updates one or more fields
user.getDefinition()     // returns the original schema/definition

Any value that fails validation throws a descriptive Error instead of silently applying an invalid value.

Working with array fields

updateArrayField(field, item, mustBeIncluded) adds or removes a single item from an array field without having to rebuild the whole array by hand:

user.updateArrayField('tags', 'frontend', true)  // adds 'frontend' if not already present
user.updateArrayField('tags', 'staff', false)    // removes 'staff' if present

Building reusable typed objects

You can extend DefinedObject to create your own domain objects with a fixed set of fields. The library ships with one example, File:

import { File } from 'mcf-objects'

const file = new File({
  values: {
    name: 'invoice.pdf',
    extension: 'pdf',
    mimeType: 'application/pdf',
  },
})

console.log(file.getValue())
// { name: 'invoice.pdf', extension: 'pdf', mimeType: 'application/pdf', content: '' }

File predefines name (required), extension, mimeType, and content (defaults to ''), while still allowing extra custom fields to be merged in via definition.fields.

Development

Requires Node v12.13.1 (see .nvmrc).

npm install        # install dependencies
npm start          # run webpack-dev-server for local development
npm run dist       # build the production bundle with webpack (outputs to dist/)

The library source lives in src/ and is transpiled with Babel and bundled with Webpack; the compiled output is published to dist/.

Project structure

src/
├── index.js            # public exports
├── definedObject.js    # DefinedObject base class
├── types/              # built-in field types (string, number, boolean, array, enum) + factory
└── objects/            # ready-to-use typed objects (e.g. File)

Contributing

Issues and pull requests are welcome.

License

This project is under Apache Licence

About

Schema-based typed objects and validation library for JavaScript domain models

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages