arrow-left
Only this pageAll pages
gitbookPowered by GitBook
1 of 18

Fractale

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Examples

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Introduction

Inspired from Mongoosearrow-up-right, it allows you to modeling your data to be explicit on data format.

It will test value of each fields and link model between them.

hashtag
Installation

npm install --save fractale

hashtag
Documentation

You can found more documentation and examples or .

hashtag
Dependencies

  • Usage of to generate a unique id for model instances.

Optional :

  • Usage of for date.

  • Usage of for color.

  • Usage of for bridge / provider.

  • Usage of for bridge.

hashtag
Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please make sure to update tests as appropriate.

See the and files for details

hashtag
License

This project is licensed under the MIT License - see the file for details

hashtag
Authors

  • Jocelyn Faihy - Web developer and Blob of Internets -

See also the list of who participated in this project.

hashtag
Thanks

herearrow-up-right
wikiarrow-up-right
uuidarrow-up-right
momentarrow-up-right
teintearrow-up-right
mongoosearrow-up-right
prop-typesarrow-up-right
contributingarrow-up-right
code of conductarrow-up-right
LICENSEarrow-up-right
Jochlainarrow-up-right
contributorsarrow-up-right
Thanks BP

Provider

Fractale lets you possibility to save and retrieve values in a storage

// To use Web localStorage
Fractale.memory.setProvider('local');

// To use Web sessionStorage
Fractale.memory.setProvider('session');

// To use Web cookie
Fractale.memory.setProvider('cookie', { expires: 6048e5 });

// To use Web IndexedDB
Fractale.memory.setProvider('idb', { database: 'Æ’_database' });

Options

'use strict';

const Fractale = require('fractale');

Fractale.setOptions({
    use_moment: () => { try { require('moment'); return true; } catch (error) { return false; }}, // Specify to fractale to transform date to moment instance
});

hashtag
Field options

'use strict';

const Fractale = require('fractale');

const Child = Fractale.create('Child', {
    mixed: undefined,
    boolean: Boolean,
    number: Number,
    string: String,
});

const Parent = Fractale.create('Parent', Child, {
    parent: Fractale.with(Fractale.SELF, {
        // Pass number of parent to number of great-parent
        through: ['number'],
    }),
    children: [
        Fractale.with(Child, {
            // Pass number of parent to mixed of child
            // Pass string of parent to string of child
            through: { number: 'mixed', string: 'string' },
        })      
    ],
});

hashtag
Field validators

'use strict';

const Fractale = require('fractale');

const Simple = Fractale.create('Simple', {
    anyway: Fractale.with(undefined, {
        validator: (value) => value !== 'A value'
    }),
    mixed: Fractale.with(undefined, {
        validator: {
            in: ['foo', 'bar', 42]
        }
    }),
    number: Fractale.with(Number, {
        validator: {
            gt: 17,
            gte: 18,
            lt: 51,
            lte: 50,
            between: [18, 50]
        }
    }),
    date: Fractale.with(Date, {
        validator: {
            gt: '2019-11-17',
            gte: new Date('2019-11-18'),
            lte: moment('2019-11-20'),
            lt: moment(),
            between: [18] // If one value is between ... and today or today and ...
        }
    }),
    string: Fractale.with(String, {
        validator: {
            like: /bar$/
        }
    }),
});

Plugin

Fractale add other custom types which need other optional modules

hashtag
Color

Need npm i -S teinte

const Colored = Fractale.create('Colored', {
    color: Fractale.Color
});

const colored = new Colored({ color: '#0f0f0f' });
console.log(colored.hsl());

hashtag
Moment

If moment module is installed Date will be automatically transform to moment instance

Need npm i -S moment

Simple model

hashtag
Models

const Simple = Fractale.create("Simple", {
    mixed: undefined,
    boolean: Boolean,
    number: Number,
    bigint: BigInt,
    string: String,
    color: Color,
    date: Date,
    regexp: RegExp,
    buffer: ArrayBuffer,
    int8: Int8Array,
    uint8: Uint8Array,
    "uint8_clamped": Uint8ClampedArray,
    int16: Int16Array,
    uint16: Uint16Array,
    int32: Int32Array,
    uint32: Uint32Array,
    float32: Float32Array,
    float64: Float64Array,
    bigint64: BigInt64Array,
    biguint64: BigUint64Array
});

hashtag
Run

hashtag
Results

Performance

From a JSON of 10.45M:

  • Deserialization: ~0.895s => 11.68Mo/s

  • Read: ~0.001s

  • Serialization: ~0.304s => 34.37Mo/s

From a JSON of 339.06M:

  • Deserialization: ~3.301s => 102.71Mo/s

  • Read: ~0.001s

  • Serialization: ~1.173s => 289.05Mo/s

From a JSON of 1.27G:

  • Deserialization: ~12.942s => 98.22Mo/s

  • Read: ~0s

  • Serialization: ~6.089s => 208.77Mo/s

const { Simple } = module.exports.get();

const instance = new Simple({
    mixed: 'It\'s dangerous to go alone! Take this.',
    buffer: 'RnJhY3RhbGUgYnVmZmVyIHNhdmU=',
    int8: 'RnJhY3RhbGUgSW50OEFycmF5IHNhdmU=',
    uint8: 'RnJhY3RhbGUgVWludDhBcnJheSBzYXZl',
    uint8_clamped: 'RnJhY3RhbGUgVWludDhDbGFtcGVkQXJyYXkgc2F2ZQ==',
    int16: 'RnJhY3RhbGUgSW50MTZBcnJheSBzYXZl',
    uint16: 'RnJhY3RhbGUgVWludDE2QXJyYXkgdW5pdCB0ZXN0',
    int32: 'RnJhY3RhbGUgSW50MzJBcnJheSB0ZXN0',
    uint32: 'RnJhY3RhbGUgVUludDMyQXJyYXkgdGVzdGluZw==',
    float32: 'RnJhY3RhbGUgRmxvYXQzMkFycmF5IHVuaXRzIHRlc3Q=',
    float64: 'RnJhY3RhbGUgRmxvYXQ2NEFycmF5IHVuaXRzIHRlc3Q=',
    bigint64: 'RnJhY3RhbGUgQmlnSW50NjRBcnJheSB1bml0IHRlc3Q=',
    biguint64: 'RnJhY3RhbGUgQmlnVUludDY0QXJyYXkgdGVzdGluZ3M=',
});

_.test(instance.mixed, 'It\'s dangerous to go alone! Take this.', 'Error on simple accessor with type mixed');
_.test(instance.boolean, false, 'Error on simple accessor with type boolean');
_.test(instance.number, 31, 'Error on simple accessor with type number');
_.test(instance.bigint, 31n, 'Error on simple accessor with type bigint');
_.test(instance.string, 'Lorem ipsum', 'Error on simple accessor with type string');
_.test(instance.color.hex(), '#AA0000', 'Error on simple accessor with type color');
_.test(instance.date.format('DD/MM/YYYY'), '01/01/2000', 'Error on simple accessor with type date');
_.test(instance.regexp.toString(), /toto/g.toString(), 'Error on simple accessor with type bigint');
_.test(base64.encode(instance.buffer), 'RnJhY3RhbGUgYnVmZmVyIHNhdmU=', 'Error on simple accessor with type buffer');
_.test(base64.encode(instance.int8.buffer), 'RnJhY3RhbGUgSW50OEFycmF5IHNhdmU=', 'Error on simple accessor with type int8');
_.test(base64.encode(instance.uint8.buffer), 'RnJhY3RhbGUgVWludDhBcnJheSBzYXZl', 'Error on simple accessor with type uint8');
_.test(base64.encode(instance.uint8_clamped.buffer), 'RnJhY3RhbGUgVWludDhDbGFtcGVkQXJyYXkgc2F2ZQ==', 'Error on simple accessor with type uint8_clamped');
_.test(base64.encode(instance.int16.buffer), 'RnJhY3RhbGUgSW50MTZBcnJheSBzYXZl', 'Error on simple accessor with type int16');
_.test(base64.encode(instance.uint16.buffer), 'RnJhY3RhbGUgVWludDE2QXJyYXkgdW5pdCB0ZXN0', 'Error on simple accessor with type uint16');
_.test(base64.encode(instance.int32.buffer), 'RnJhY3RhbGUgSW50MzJBcnJheSB0ZXN0', 'Error on simple accessor with type int32');
_.test(base64.encode(instance.uint32.buffer), 'RnJhY3RhbGUgVUludDMyQXJyYXkgdGVzdGluZw==', 'Error on simple accessor with type uint32');
_.test(base64.encode(instance.float32.buffer), 'RnJhY3RhbGUgRmxvYXQzMkFycmF5IHVuaXRzIHRlc3Q=', 'Error on simple accessor with type float32');
_.test(base64.encode(instance.float64.buffer), 'RnJhY3RhbGUgRmxvYXQ2NEFycmF5IHVuaXRzIHRlc3Q=', 'Error on simple accessor with type float64');
_.test(base64.encode(instance.bigint64.buffer), 'RnJhY3RhbGUgQmlnSW50NjRBcnJheSB1bml0IHRlc3Q=', 'Error on simple accessor with type bigint64');
_.test(base64.encode(instance.biguint64.buffer), 'RnJhY3RhbGUgQmlnVUludDY0QXJyYXkgdGVzdGluZ3M=', 'Error on simple accessor with type biguint64');

instance.mixed = -1;
instance.boolean = true;
instance.number = 42;
instance.bigint = 42n;
instance.string = 'Dolor sit amet';
instance.color = 'rgba(0, 0, 255, 0)';

_.test(instance.mixed, -1, 'Error on simple accessor with type mixed after change');
_.test(instance.boolean, true, 'Error on simple accessor with type boolean after change');
_.test(instance.number, 42, 'Error on simple accessor with type number after change');
_.test(instance.bigint, 42n, 'Error on simple accessor with type number after change');
_.test(instance.string, 'Dolor sit amet', 'Error on simple accessor with type string after change');
_.test(instance.color.hex(), '#0000FF00', 'Error on simple accessor with type string after change');

resolve(instance);
const Article = Fractale.create('Article', {
    content: String,
    created_at: Date,
    updated_at: Date,
});

const article = new Article({
    content: 'This module is awesome',
    created_at: '2000-01-01',
    updated_at: '2000-01-01',
});
console.log(article.created_at.format('DD/MM/YYYY'));
{
    "uuid": "764a4649-6de0-4ae3-ab0c-7009cc16fcc8",
    "mixed": -1,
    "boolean": true,
    "number": 42,
    "bigint": "42",
    "string": "Dolor sit amet",
    "color": "#0000FF00",
    "date": "2000-01-01T02:00:00.000Z",
    "regexp": "/toto/g",
    "buffer": "RnJhY3RhbGUgYnVmZmVyIHNhdmU=",
    "int8": "RnJhY3RhbGUgSW50OEFycmF5IHNhdmU=",
    "uint8": "RnJhY3RhbGUgVWludDhBcnJheSBzYXZl",
    "uint8_clamped": "RnJhY3RhbGUgVWludDhDbGFtcGVkQXJyYXkgc2F2ZQ==",
    "int16": "RnJhY3RhbGUgSW50MTZBcnJheSBzYXZl",
    "uint16": "RnJhY3RhbGUgVWludDE2QXJyYXkgdW5pdCB0ZXN0",
    "int32": "RnJhY3RhbGUgSW50MzJBcnJheSB0ZXN0",
    "uint32": "RnJhY3RhbGUgVUludDMyQXJyYXkgdGVzdGluZw==",
    "float32": "RnJhY3RhbGUgRmxvYXQzMkFycmF5IHVuaXRzIHRlc3Q=",
    "float64": "RnJhY3RhbGUgRmxvYXQ2NEFycmF5IHVuaXRzIHRlc3Q=",
    "bigint64": "RnJhY3RhbGUgQmlnSW50NjRBcnJheSB1bml0IHRlc3Q=",
    "biguint64": "RnJhY3RhbGUgQmlnVUludDY0QXJyYXkgdGVzdGluZ3M="
}

Usage

hashtag
Declaration

hashtag
Instanciation

hashtag
Modification

hashtag
Array helpers

'use strict';

const Fractale = require('fractale');

const KeyValuePair = Fractale.create(
    'KeyValuePair', /* Name of your model (required) */
    { /* Model's schema */
        key: String,
        value: undefined,
    }
);

/* More complete example */
const Model = Fractale.create(
    'Model',
    {
        mixed: undefined,
        boolean: Boolean,
        number: Number,
        string: String,
        date: Date,
        boards: [String],
        metadata: { key: String },
        inception: KeyValuePair,
        collection: [{ key: String, value: null }],
        self: Fractale.SELF, // the Model itself
    }
);

/* Full example */
const Full = Fractale.create(
    'Full',
    Model, // Full inherit Model
    {
        declareAfter: Fractale.from('After'),
        withOption: Fractale.with(String, { validator: { in: ['Foo','Bar'] } }),
    }
);

const After = Fractale.create('After', {
    start: Fractale.with(Date, { required: true, default: '2000-01-01' }),
    end: Date,
});
const instance = new Model({
    mixed: 'Great !',
    boolean: true,
    number: 42,
    string: 'Hello world',
    boards: ['Lorem ipsum', 'dolores sit amet'],
    metadata: { key: 'AZERTYUIOP' },
    inception: { key: 'key', value: 1 },
    collections: [
        { key: 'foo', value: 123 },
        { key: 'bar', value: 456 }
    ]
});

console.log(instance.serialize());
/* 
> { 
    mixed: 'Great !',
    boolean: true,
    number: 42,
    string: 'Hello world',
    boards: ['Lorem ipsum', 'dolores sit amet'],
    metadata: { key: 'AZERTYUIOP' },
    inception: { key: 'key', value: 1 },
    collections: [
        { key: 'foo', value: 123 },
        { key: 'bar', value: 456 }
    ]
}
*/

/* Copy props to another instance */
// Method 1
const full = Full.from(instance);

// Method 2
const serialized = instance.serialize();
delete serialized.uuid;
const clone = new Full(serialized);
/* Array methods use */
instance.collections.push({ key: 'azertyuiop', value: 2 });
instance.collections = instance.collections.concat([{ key: 'new_key', value: 3 }, { key: 'N3W_K3Y', value: 4 }]);
console.log(instance.serialize().collections);
/*
> [
    { key: 'pass', value: 789 },
    { key: 'bar', value: 456 },
    { key: 'qwerty', value: 1 },
    { key: 'new_key', value: 3 },
    { key: 'N3W_K3Y', value: 4 }
]
*/
console.log(instance.mixed); // > true
instance.mixed = 123;
console.log(instance.mixed); // > 123

console.log(instance.boolean); // > true
instance.boolean = false;
console.log(instance.boolean); // > false

console.log(instance.number); // > 42
instance.number = 12;
console.log(instance.number); // > 12

console.log(instance.string); // > 'Hello world'
instance.string = 'Lorem ipsum';
console.log(instance.string); // > 'Lorem ipsum'

console.log(instance.boards[0]); // > 'Lorem ipsum'
instance.boards[0] = 'Hello world';
console.log(instance.boards[0]); // > 'Hello World'

console.log(instance.metadata.key); // > 'AZERTYUIOP' 
instance.metadata.key = 'foo';
console.log(instance.metadata.key); // > 'foo' 

console.log(instance.inception); // > KeyValuePair { key: 'key', value: 1 }
instance.inception = new KeyValuePair({ key: 'new_key', value: 'new_value' });
console.log(instance.inception); // > KeyValuePair { key: 'new_key', value: 'new_value' }

console.log(instance.inception); // > KeyValuePair { key: 'new_key', value: 'new_value' }
instance.inception.value = 'updated_value';
console.log(instance.inception); // > KeyValuePair { key: 'new_key', value: 'updated_value' }

console.log(instance.collections[0].key); // > 'foo'
instance.collections[0].key = 'pass';
instance.collections[0] = { value: 789 };
console.log(instance.collections[0].key); // > 'pass'
console.log(instance.collections[0].value); // > 789

console.log(instance.serialize());
/* 
> { 
    mixed: 123,
    boolean: false,
    number: 12,
    string: 'Lorem ipsum',
    boards: ['Hello world', 'dolores sit amet'],
    metadata: { key: 'foo' },
    collections: [
        { key: 'pass', value: 789 },
        { key: 'bar', value: 456 }
    ],
    inception: { key: 'new_key', value: 'updated_value' }
}
*/

Collection model

hashtag
Models

const Collection_Item = Fractale.create("Collection_Item", {
    value: String
});

const Collection_Category = Fractale.create("Collection_Category", {
    items: [
        Collection_Item
    ]
});

hashtag
Run

hashtag
Results

const { Collection_Category, Collection_Item } = module.exports.get();
const item = new Collection_Item({ value: 'foo' });
const category = new Collection_Category({ items: [item, { value: 'bar' }] });

_.test(category.items[0].value, 'foo', 'Error on collection accessor with brace');
_.test(category.items[1].value, 'bar', 'Error on collection accessor with brace');

let changed = false;
category.addEventListener('change', () => changed = true);
category.items[0].value = 'hello';

if (!changed) {
    throw new Error('Error on collection change event');
}
_.test(category.items[0].value, 'hello', 'Error on collection accessor with brace after change');
_.test(category.items.first.value, 'hello', 'Error on collection method first accessor');

category.items.push({ value: 'world' });

_.test(category.items.last.value, 'world', 'Error on collection method last accessor');
_.test(category.items.map(item => item.value).join(', '), 'hello, bar, world', 'Error on array method map accessor');
_.test(category.items.filter(item => item.value === 'hello').map(item => item.value).join(', '), 'hello', 'Error on array method filter accessor');
_.test(category.items.reduce((accu, item) => `${accu} ${item.value}`, '').trim(), 'hello bar world', 'Error on array method reduce accessor');

category.items.remove(item);
if (category.items.length !== 2) throw new Error('Error on array method remove accessor');

resolve(category);
{
    "uuid": "269189c4-9f16-47db-bfe0-094ed8a2a676",
    "items": [
        {
            "uuid": "6edf2663-1fb9-4b76-8c4d-724f5ef70da1",
            "value": "bar"
        },
        {
            "uuid": "522ec9e9-2920-415d-a239-79fb620227fa",
            "value": "world"
        }
    ]
}

Inception model

hashtag
Models

const Inception_Parent = Fractale.create("Inception_Parent", {
    value: String
});

const Inception_Child = Fractale.create("Inception_Child", {
    parent: Inception_Parent,
    value: String
});

hashtag
Run

const { Inception_Child } = module.exports.get();
const child = new Inception_Child({
    parent: { value: 'foo' },
    value: 'bar',
});

_.test(child.parent.value, 'foo', 'Error on inception setter with dot');

const parent = child.parent;
const value = 'hello world';
parent.value = value;
_.test(child.parent.value, value, 'Error on inception setter with dot');

child.parent.value = 'foo';
_.test(child.parent.value, 'foo', 'Error on deep setter with dot');

resolve(child);

hashtag
Results

{
    "uuid": "d2dd4dd1-f369-4ed8-821e-5040deed075b",
    "parent": {
        "uuid": "33ba3961-cc86-4dbc-9945-b0691bd36d93",
        "value": "foo"
    },
    "value": "bar"
}

Metadata model

hashtag
Models

const Metadata = Fractale.create("Metadata", {
    metadata: {
        key: String,
        data: {
            key: String,
            value: undefined
        }
    }
});

hashtag
Run

hashtag
Results

Self-reference model

hashtag
Models

hashtag
Run

const { Metadata } = module.exports.get();
const instance = new Metadata({
    metadata: { key: 'Foo', data: { key: 'Bar', value: 12 } }
});

_.test(instance.metadata.key, 'Foo', 'Error on metadata accessor');

const metadata = instance.metadata;
metadata.key = 'decomposition';

_.test(instance.metadata.key, 'decomposition', 'Error on metadata accessor with decomposition');

instance.metadata.key = 'dot';
_.test(instance.metadata.key, 'dot', 'Error on metadata accessor with dot');

instance.metadata = { key: 'assign' };
_.test(instance.metadata.key, 'assign', 'Error on metadata accessor with assign');
_.test(instance.metadata.data.key, 'Bar', 'Error on metadata accessor with assign');

instance.metadata = { data: { key: 'after', value: 13 } };
_.test(instance.metadata.key, 'assign', 'Error on metadata accessor with bracket');
_.test(instance.metadata.data.key, 'after', 'Error on metadata accessor with bracket');
_.test(instance.metadata.data.value, 13, 'Error on metadata accessor with bracket');

resolve(instance);
{
    "uuid": "6c63fcf6-323a-4cb7-8bd1-afdb4d73c086",
    "metadata": {
        "uuid": "daf1d856-b57c-41a7-9a5e-407188f5f24f",
        "key": "assign",
        "data": {
            "uuid": "c22f5b47-3434-45cb-86e7-fba5134347d5",
            "key": "after",
            "value": 13
        }
    }
}
hashtag
Results
const Self = Fractale.create("Self", {
    self: Self,
    value: String
});
const { Self } = module.exports.get();
const instance_1 = new Self({ value: 'foo' });
const instance_2 = new Self({ self: { self: instance_1, value: 'bar' }, value: 'hello' });

_.test(instance_1.value, 'foo', 'Error on deep accessor variable name');
_.test(instance_2.self.value, 'bar', 'Error on self-reference accessor');
_.test(instance_2.self.self.value, 'foo', 'Error on double self-reference accessor');
_.test(instance_2.self.self.self, undefined, 'Error infinite self-reference accessor');

resolve(instance_2);
{
    "uuid": "9ad98dd3-6e65-41e0-a592-998c68aafe95",
    "self": {
        "uuid": "3365521f-4db8-4856-a5a2-5dacda8648ba",
        "self": {
            "uuid": "49e72f5e-faa3-4948-a162-3f4abdb792f6",
            "value": "foo"
        },
        "value": "bar"
    },
    "value": "hello"
}

Form usage

hashtag
Models

const Form_Parent = Fractale.create("Form_Parent", {
    value: String
});

const Form_Child = Fractale.create("Form_Child", {
    parent: Form_Parent,
    value: String
});

hashtag
Run

const { Form_Parent, Form_Child } = module.exports.get();
const parent = new Form_Parent({ value: 'foo' });
const child = new Form_Child({ parent: parent.uuid, value: 'bar' });

_.test(child.value, 'bar', 'Error on form setter');
_.test(child.parent.value, 'foo', 'Error on form setter');

resolve(child);

hashtag
Results

{
    "uuid": "250940e8-d1a4-4476-89e9-fcc882f55c64",
    "parent": {
        "uuid": "ab7cde95-30ed-4bdf-8872-0b03a537e3a2",
        "value": "foo"
    },
    "value": "bar"
}

Inheritance model

hashtag
Models

const Inheritance_Child = Fractale.create("Inheritance_Child", {
    value: String
});

const Inheritance_Parent = Fractale.create("Inheritance_Parent", Inheritance_Child, {
    children: [
        Inheritance_Child
    ]
});

hashtag
Run

const { Inheritance_Parent } = module.exports.get();
const instance = new Inheritance_Parent({
    value: 'Hello',
    children: [
        { value: 'world' },
        { value: 'you' },
    ]
});

_.test(instance.sayHelloTo(0), 'Hello world', `Expected "Hello world" got "${instance.sayHelloTo(0)}"`);
_.test(instance.sayHelloTo(1), 'Hello you', 'Error on parent method call');
_.test(instance.toUpperCase(), 'HELLO', 'Error on method inheritance');

resolve(instance);

hashtag
Results

{
    "uuid": "095ee570-53b7-418e-856d-1cb869b7f8cd",
    "value": "Hello",
    "children": [
        {
            "uuid": "d01623e5-8c49-4fc9-b7a8-94ae79a87dff",
            "value": "world"
        },
        {
            "uuid": "2c54c27b-b05b-4344-9e49-29985e8b8383",
            "value": "you"
        }
    ]
}

RegExp key model

hashtag
Models

const ModelWithRegExpAsKey = Fractale.create("ModelWithRegExpAsKey", {
    "/item_\\d+/i": String
});

hashtag
Run

const { ModelWithRegExpAsKey } = module.exports.get();
const instance = new ModelWithRegExpAsKey({
    item_1: 'Foo',
    item_2: 'Bar',
});

_.test(instance.item_1, 'Foo', 'Error on regexp key accessor with type string');
_.test(instance.item_2, 'Bar', 'Error on regexp key accessor with type string');

resolve(instance);

hashtag
Results

Global options

hashtag
Models

const Global_Options = Fractale.create("Global_Options", {
    transformed: Number
});

hashtag
Run

const { Global_Options } = module.exports.get();

const instance = new Global_Options({
    transformed: 39,
});

_.test(instance.transformed, 39, 'Error on global option transform accessor with type percentage');

instance.transformed = '10%';

_.test(instance.transformed, 0.1, 'Error on global option transform accessor with type percentage');

resolve(instance);

hashtag
Results

{
    "uuid": "1e35cacd-193c-4cff-bbbb-d687f6023426",
    "item_1": "Foo",
    "item_2": "Bar"
}
{
    "uuid": "325dda13-7f10-4bc1-a212-c7eaa7e9beb6",
    "transformed": 0.1
}

Philosophy

Bridge

/! Experimental

Fractale lets you possibility to transform models to other types

hashtag
Transform to Mongoose Model

Need npm i -S mongoose

const model = Model.toMongoose();

hashtag
Transform to PropTypes

Need npm i -S prop-types

const propTypes = Model.toPropTypes();
Graph - Complexity x Rate
Graph - Size x Rate