Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mobx-decorated-models

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobx-decorated-models - npm Package Compare versions

Comparing version 0.1.2 to 0.2.0

95

dist/build.full.js

@@ -105,3 +105,12 @@ (function (global, factory) {

belongsTo: function belongsTo(model) {
return serializr.object(serializr.getDefaultModelSchema(model));
var defaultSerializer = serializr.object(serializr.getDefaultModelSchema(model));
return {
deserializer: defaultSerializer.deserializer,
serializer: function serializer(belongsTo, name, parent) {
if (parent.$nonSerializable && -1 !== parent.$nonSerializable.indexOf(name)) {
return undefined;
}
return defaultSerializer.serializer(belongsTo);
}
};
}

@@ -126,3 +135,3 @@ };

var classDecorator = function (model) {
function modelDecorator(model) {
Object.assign(model.prototype, MixedInInstanceMethods);

@@ -172,3 +181,3 @@ Object.assign(model, MixedInClassMethods);

}
};
}

@@ -245,2 +254,54 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {

var setupModel = mobx.action(function (attrs, modelClass, array, defaultAttributes, inverseOf, parentModel) {
if (defaultAttributes) {
if (typeof defaultAttributes === 'function') {
defaultAttributes = defaultAttributes.call(parentModel, array, parentModel);
}
Object.keys(defaultAttributes).forEach(function (key) {
if (!attrs[key]) {
attrs[key] = defaultAttributes[key];
}
});
}
if (inverseOf) {
attrs[inverseOf] = parentModel;
}
var model = modelClass && !(attrs instanceof modelClass) ? new modelClass(attrs) : attrs;
model.$nonSerializable = model.$nonSerializable || [];
model.$nonSerializable.push(inverseOf);
return model;
});
function buildInterceptor(_ref, parentModel) {
var modelClass = _ref.modelClass,
className = _ref.className,
defaultAttributes = _ref.defaults,
inverseOf = _ref.inverseOf;
return function (change) {
if (!change.newValue) {
change.newValue = {};
}
if (!modelClass) {
modelClass = findModel(className);
}
if (change.type === 'splice') {
for (var i = 0; i < change.added.length; i += 1) {
change.added[i] = setupModel(change.added[i], modelClass, change.object, defaultAttributes, inverseOf, parentModel);
}
} else if (change.type === 'update') {
change.newValue = setupModel(change.newValue, modelClass, change.object, defaultAttributes, inverseOf, parentModel);
}
return change;
};
}
function buildCollection(options, parentModel) {
var ary = mobx.observable.array([]);
if (options.className || options.modelClass) {
ary.intercept(buildInterceptor(options, parentModel));
}
return ary;
}
var Initializers = {

@@ -250,5 +311,3 @@ object: function object$$1() {

},
array: function array() {
return mobx.observable.array([]);
}
array: buildCollection
};

@@ -261,3 +320,10 @@

function getInitializer(type, options) {
return TypeInitializers[type] || Initializers[options.type];
var fn = TypeInitializers[type] || Initializers[options.type];
if (!fn) {
return undefined;
}
return function () {
// eslint-disable-line func-names
return fn(options, this);
};
}

@@ -273,3 +339,4 @@

}
return mobx.observable(target, property, descriptor);
var definition = mobx.observable(target, property, descriptor);
return definition;
}

@@ -320,2 +387,3 @@

};
var hasMany = function hasMany() {

@@ -329,4 +397,7 @@ for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {

exports.model = classDecorator;
exports.identifier = identifier$1;
exports.registerModel = registerModel;
exports.findModel = findModel;
exports.rememberModelUsing = rememberModelUsing;
exports.lookupModelUsing = lookupModelUsing;
exports.modelDecorator = modelDecorator;
exports.field = field;

@@ -336,4 +407,4 @@ exports.session = session;

exports.hasMany = hasMany;
exports.lookupModelUsing = lookupModelUsing;
exports.rememberModelUsing = rememberModelUsing;
exports.identifier = identifier$1;
exports.buildCollection = buildCollection;

@@ -340,0 +411,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

import { createModelSchema, deserialize, getDefaultModelSchema, identifier, list, map, object, primitive, serialize, update } from 'serializr';
import { observable } from 'mobx';
import { action, observable } from 'mobx';

@@ -102,3 +102,12 @@ var ModelsMap = new Map();

belongsTo: function belongsTo(model) {
return object(getDefaultModelSchema(model));
var defaultSerializer = object(getDefaultModelSchema(model));
return {
deserializer: defaultSerializer.deserializer,
serializer: function serializer(belongsTo, name, parent) {
if (parent.$nonSerializable && -1 !== parent.$nonSerializable.indexOf(name)) {
return undefined;
}
return defaultSerializer.serializer(belongsTo);
}
};
}

@@ -123,3 +132,3 @@ };

var classDecorator = function (model) {
function modelDecorator(model) {
Object.assign(model.prototype, MixedInInstanceMethods);

@@ -169,3 +178,3 @@ Object.assign(model, MixedInClassMethods);

}
};
}

@@ -242,2 +251,54 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {

var setupModel = action(function (attrs, modelClass, array, defaultAttributes, inverseOf, parentModel) {
if (defaultAttributes) {
if (typeof defaultAttributes === 'function') {
defaultAttributes = defaultAttributes.call(parentModel, array, parentModel);
}
Object.keys(defaultAttributes).forEach(function (key) {
if (!attrs[key]) {
attrs[key] = defaultAttributes[key];
}
});
}
if (inverseOf) {
attrs[inverseOf] = parentModel;
}
var model = modelClass && !(attrs instanceof modelClass) ? new modelClass(attrs) : attrs;
model.$nonSerializable = model.$nonSerializable || [];
model.$nonSerializable.push(inverseOf);
return model;
});
function buildInterceptor(_ref, parentModel) {
var modelClass = _ref.modelClass,
className = _ref.className,
defaultAttributes = _ref.defaults,
inverseOf = _ref.inverseOf;
return function (change) {
if (!change.newValue) {
change.newValue = {};
}
if (!modelClass) {
modelClass = findModel(className);
}
if (change.type === 'splice') {
for (var i = 0; i < change.added.length; i += 1) {
change.added[i] = setupModel(change.added[i], modelClass, change.object, defaultAttributes, inverseOf, parentModel);
}
} else if (change.type === 'update') {
change.newValue = setupModel(change.newValue, modelClass, change.object, defaultAttributes, inverseOf, parentModel);
}
return change;
};
}
function buildCollection(options, parentModel) {
var ary = observable.array([]);
if (options.className || options.modelClass) {
ary.intercept(buildInterceptor(options, parentModel));
}
return ary;
}
var Initializers = {

@@ -247,5 +308,3 @@ object: function object$$1() {

},
array: function array() {
return observable.array([]);
}
array: buildCollection
};

@@ -258,3 +317,10 @@

function getInitializer(type, options) {
return TypeInitializers[type] || Initializers[options.type];
var fn = TypeInitializers[type] || Initializers[options.type];
if (!fn) {
return undefined;
}
return function () {
// eslint-disable-line func-names
return fn(options, this);
};
}

@@ -270,3 +336,4 @@

}
return observable(target, property, descriptor);
var definition = observable(target, property, descriptor);
return definition;
}

@@ -317,2 +384,3 @@

};
var hasMany = function hasMany() {

@@ -326,3 +394,3 @@ for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {

export { classDecorator as model, identifier$1 as identifier, field, session, belongsTo, hasMany, lookupModelUsing, rememberModelUsing };
export { registerModel, findModel, rememberModelUsing, lookupModelUsing, modelDecorator, field, session, belongsTo, hasMany, identifier$1 as identifier, buildCollection };
//# sourceMappingURL=build.module.js.map

17

index.js

@@ -1,14 +0,3 @@

import model from './lib/class-decorator';
import { lookupModelUsing, rememberModelUsing } from './lib/model-lookup';
import { field, session, belongsTo, hasMany, identifier } from './lib/property-decorators';
export {
model,
identifier,
field,
session,
belongsTo,
hasMany,
lookupModelUsing,
rememberModelUsing,
};
export * from './lib/model-lookup';
export * from './lib/class-decorator';
export * from './lib/property-decorators';

@@ -49,3 +49,14 @@ import {

hasMany: modelRef => list(object(modelRef)),
belongsTo: model => object(getDefaultModelSchema(model)),
belongsTo: model => {
const defaultSerializer = object(getDefaultModelSchema(model));
return {
deserializer: defaultSerializer.deserializer,
serializer: (belongsTo, name, parent) => {
if (parent.$nonSerializable && -1 !== parent.$nonSerializable.indexOf(name)){
return undefined;
}
return defaultSerializer.serializer(belongsTo);
}
}
}
};

@@ -74,3 +85,3 @@

export default function (model) {
export function modelDecorator(model) {
Object.assign(model.prototype, MixedInInstanceMethods);

@@ -77,0 +88,0 @@ Object.assign(model, MixedInClassMethods);

import {
observable,
action,
} from 'mobx';
import { findModel } from './model-lookup';
import getModelSchema from './schema';
const setupModel = action(function(attrs, modelClass, array, defaultAttributes, inverseOf, parentModel) {
if (defaultAttributes) {
if (typeof defaultAttributes === 'function') {
defaultAttributes = defaultAttributes.call(parentModel, array, parentModel);
}
Object.keys(defaultAttributes).forEach((key) => {
if (!attrs[key]) {
attrs[key] = defaultAttributes[key];
}
});
}
if (inverseOf) {
attrs[inverseOf] = parentModel;
}
const model = (modelClass && !(attrs instanceof modelClass)) ? new modelClass(attrs) : attrs;
model.$nonSerializable = model.$nonSerializable || [];
model.$nonSerializable.push(inverseOf);
return model;
});
function buildInterceptor({ modelClass, className, defaults: defaultAttributes, inverseOf }, parentModel) {
return (change) => {
if (!change.newValue) {
change.newValue = {};
}
if (!modelClass) {
modelClass = findModel(className);
}
if (change.type === 'splice') {
for (let i = 0; i < change.added.length; i += 1) {
change.added[i] = setupModel(change.added[i], modelClass, change.object,
defaultAttributes, inverseOf, parentModel);
}
} else if (change.type === 'update') {
change.newValue = setupModel(change.newValue, modelClass, change.object,
defaultAttributes, inverseOf, parentModel);
}
return change;
};
}
function buildCollection(options, parentModel) {
const ary = observable.array([]);
if (options.className || options.modelClass) {
ary.intercept(buildInterceptor(options, parentModel));
}
return ary;
}
const Initializers = {
object: () => observable.map({}),
array: () => observable.array([]),
array: buildCollection,
};

@@ -17,3 +69,7 @@

function getInitializer(type, options) {
return TypeInitializers[type] || Initializers[options.type];
const fn = TypeInitializers[type] || Initializers[options.type];
if (!fn) { return undefined; }
return function () { // eslint-disable-line func-names
return fn(options, this);
};
}

@@ -27,3 +83,4 @@

}
return observable(target, property, descriptor);
const definition = observable(target, property, descriptor);
return definition;
}

@@ -45,4 +102,5 @@

addAttribute(type, target, property, descriptor, options);
const hasMany = (...args) => buildAttributeDecorator('hasMany', args, hasManyBuilder);
export { field, session, belongsTo, hasMany, identifier };
export { field, session, belongsTo, hasMany, identifier, buildCollection };
{
"name": "mobx-decorated-models",
"version": "0.1.2",
"version": "0.2.0",
"description": "Decorators to make using Mobx for model type structures easier",

@@ -13,3 +13,3 @@ "main": "dist/build.full.js",

"mobx": "^3.0.2",
"serializr": "^1.1.9"
"serializr": "https://github.com/nathanstitt/serializr#serializer-args"
},

@@ -16,0 +16,0 @@ "scripts": {

@@ -29,3 +29,3 @@ # Decorators for creating model type structures with mobx

@model
@modelDecorator
export class Box {

@@ -62,3 +62,3 @@ @identifier id;

By default, the class `@model` decorator uses the `name` property of each class as a lookup key so
By default, the class `@modelDecorator` uses the `name` property of each class as a lookup key so
that `hasMany` and `belongsTo` relation ships can be established.

@@ -72,5 +72,5 @@

import { model, belongsTo } from 'mobx-decorated-models';
import { modelDecorator, belongsTo } from 'mobx-decorated-models';
@model
@modelDecorator
class Chair {

@@ -84,3 +84,3 @@ belongsTo 'table'

@model
@modelDecorator
class Table {

@@ -112,3 +112,3 @@ hasMany({ model: 'Chair' }) 'seats'

@model
@modelDecorator
class ATestingModel {

@@ -119,3 +119,3 @@ static identifiedBy = 'test';

@model
@modelDecorator
class Document {

@@ -186,9 +186,41 @@ static identifiedBy = 'document';

Makes a property as belonging to an array of model. Sets the default value to an observable array
Marks a property as belonging to an mobx observable array of models.
Sets the default value to an empty observable array
As in `belongsTo`, can be optionally given an option object with a `className` property to control the mapping.
`hasMany` also accepts `inverseOf` and `defaults` properties. If an inverseOf is provided,
when a model is added to the array, it will have the property named by `inverseOf` to the parent model
If `defaults` are provided the new model's attributes will be defaulted to them. `defaults` may
also be a function, which will be called and it's return values used.
```javascript
class Tire {
@session numberInSet;
@belongsTo vehicle; // will be autoset by the `inverseOf: auto` on Car
}
class Car {
@belongsTo home;
@session color;
@hasMany({ className: 'Tire', inverseOf: 'vehicle', defaults: {numberInSet: 4} }) tires;
}
class Garage {
@session owner;
@hasMany({
className: 'Car',
inverseOf: 'home',
defaults(collection, parent) {
return { color: this.owner.favoriteColor };
}
}) cars;
}
```
# Future plans
* Sessions: properties that will be set from JSON but won't be serialized. https://github.com/mobxjs/serializr/pull/32 is needed before this can be supported

@@ -58,10 +58,12 @@ import { Container, Box } from './test-models';

const container = new Container({ id: 1, name: 'C23', location: 'z1' });
container.boxes.push(new Box({ id: 1, width: 8, depth: 12, height: 8 }));
container.boxes.push(new Box({ id: 2, width: 3, depth: 12, height: 4 }));
container.boxes[1].x = 4;
container.boxes.push(new Box());
container.boxes.push(new Box());
container.boxes[1].width = 4;
// hasMany sets the inverseOf, but it isn't serialized
expect(container.boxes[0].container).toBe(container);
expect(container.serialize()).toEqual({
id: undefined, location: undefined, name: undefined, tags: [],
id: 1, location: 'z1', name: 'C23', tags: [],
boxes: [
{ container: undefined, depth: 1, height: 1, id: undefined, metadata: {}, width: 1 },
{ container: undefined, depth: 1, height: 1, id: undefined, metadata: {}, width: 1 },
{ depth: 1, height: 1, metadata: {}, width: 1 },
{ depth: 1, height: 1, metadata: {}, width: 4 },
],

@@ -68,0 +70,0 @@ });

import { Container, Box } from './test-models';
import { model as modelDecorator } from '../index';
import { modelDecorator } from '../index';
import * as ModelLookup from '../lib/model-lookup';

@@ -4,0 +4,0 @@

@@ -36,2 +36,15 @@ import { Box, Container } from './test-models';

it('sets defaults for hasMany', () => {
const container = Container.deserialize({ color: 'blue' });
container.boxes.push({});
expect(container.boxes[0].color).toEqual('blue');
});
it('sets an inverse', () => {
const container = Container.deserialize({ id: 1, name: 'Bob', location: 'water' });
container.boxes.push({});
expect(container.boxes[0]).toBeInstanceOf(Box);
expect(container.boxes[0].container).toEqual(container);
});
xit('merges both attributes and session props', () => {

@@ -42,3 +55,3 @@ const box = Box.deserialize({ width: 3, isVisible: true });

it('can objserve associations', () => {
it('can observe associations', () => {
const container = Container.deserialize({ id: 1, name: 'Bob', location: 'water' });

@@ -50,4 +63,4 @@ const spy = jest.fn();

expect(container.areaInUse).toEqual(0);
container.boxes.push(Box.deserialize({ id: 1, width: 8, depth: 12, height: 8 }));
container.boxes.push(Box.deserialize({ id: 2, width: 3, depth: 12, height: 4 }));
container.boxes.push({ id: 1, width: 8, depth: 12, height: 8 });
container.boxes.push({ id: 2, width: 3, depth: 12, height: 4 });
container.boxes[1].width = 4;

@@ -54,0 +67,0 @@ expect(container.areaInUse).toEqual(960);

import { observable, computed } from 'mobx';
import { model, field, session, belongsTo, hasMany, identifier } from '../index';
import { modelDecorator, field, session, belongsTo, hasMany, identifier } from '../index';
class RectangularCuboid {
constructor() {
constructor(attrs) {
Object.assign(this, attrs);
this.isCuboid = true;

@@ -10,3 +11,3 @@ }

@model
@modelDecorator
export class Box extends RectangularCuboid {

@@ -18,5 +19,6 @@ @identifier id;

@field depth = 1;
@field({ type: 'object' }) metadata;
@session color;
@computed get volume() {

@@ -29,3 +31,3 @@ return this.width * this.height * this.depth;

@model
@modelDecorator
export class Container extends RectangularCuboid {

@@ -36,5 +38,6 @@ @identifier id;

@field location;
@field({ type: 'array' }) tags = [];
@session color;
@computed get description() {

@@ -44,3 +47,9 @@ return `${this.name} ${this.location}`;

@hasMany({ className: 'Box', inverseOf: 'container' }) boxes;
@hasMany({
className: 'Box',
inverseOf: 'container',
defaults() {
return { color: this.color };
},
}) boxes;

@@ -47,0 +56,0 @@ @computed get areaInUse() {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc