Giter VIP home page Giter VIP logo

muesli's Introduction

Muesli

Simple, ORM-agnostic domain driven model management

npm version Greenkeeper badge Build Status Code Climate CircleCI dependencies:? devDependencies:?

Installation

npm install muesli

or

yarn add muesli

Usage

Import Model class from muesli package.

import Model from 'muesli';
// or
const Model = require('muesli');

Define your model's props

class Book extends Model {
  
}
Book.props = {
  ISBN: {
    filter: 'string',
    value: '',
    constraints: [],
    validate: (value) => {},
    json: {},
  },
  title: {
    filter: 'string',
  },
  author: {
    filter: (value) => Author.fromJSON(value),
  },
  reference: {
    filter: (ref) => CustomModelStore.findByRef(ref),
  },
};

Add settings for your model

class Book extends Model {
  
}
Book.propsSettings = {
  nameStrategy: 'camel', // currently affected only during json serialization for attributes' keys
  
  strict: false, // if true is set, then model won't accept non schema attributes. It won't throw an error
  throwOnStrictError: false, // if true it will throw an error when `strict` is true and you are trying to set non schema attribute
  
  useGetters: true, // default to true -- give access to direct access to props via model.values object
  useSetters: true, // default to true

  validators: [ // model validators that can validate all object's values
    MuesliValidators.equalProps(['password', 'password-confirmation'], ['validation-group1']),
    MuesliValidators.validDates(['birthdate'], 'validation-group2')
  ]
};
Setting name Default value Possible values Description
nameStrategy <empty string> (camel OR pascal OR title OR snake OR lower OR upper OR constant) Props names' serialization strategy. Look inside package https://www.npmjs.com/package/change-case
strict false true OR false if true is set, then model won't accept non schema props.
throwOnStrictError false true OR false if true is set and strict === true, model will throw an error when model tries to set non schema prop
useGetters true true OR false gives direct access to props values via model.values object
useSetters true true OR false
validators [] array of model validators that can validate through whole model

Model validation

const book = Book.fromJSON({ ISBN: '1232412-123' });

book.validate()
  .then((validationErrors) => {
    if (validationErrors.length) {
      // Model doesn't pass validation constraints
    } else {
      // everything is good
    }
  })
  .catch((error) => {
    // FATAL errors occurred during validation process
    console.error(error);
  });

There is static method to make the same operation quicker

Book.validate({ ISBN: '12345123-123' })
  .then((validationErrors) => {
    if (validationErrors.length) {
      // Model doesn't pass validation constraints
    } else {
      // everything is good
    }
  })
  .catch((error) => {
    // FATAL errors occurred during validation process
    console.error(error);
  });

You can also validate only part of the model using validation group

book.validate(['group1'])
  .then((validationErrors) => {
    if (validationErrors.length) {
      // Model doesn't pass validation constraints
    } else {
      // everything is good
    }
  })
  .catch((error) => {
    // FATAL errors occurred during validation process
    console.error(error);
  });

Custom constraints and validators

Constraints and validators are asynchronous by default, but you not required to use Promises if you don't need to.

const customConstraint = (groups = []) => {
  return (propValue, propName, currentGroup) => {
    return new Promise((resolve, reject) => {
      if (!groups.includes(currentGroup)) {
        // It is very important that you handle validation groups inside custom constraint 
        resolve();
        return;
      }
      if (propValue !== 'custom value') {
        reject(new Error(`${propName} must be equals 'custom value'`));
        return;
      }
      resolve();
    });
  };
};
const customValidator = (groups = []) => {
  return (values, currentGroup) => {
    if (!groups.includes(currentGroup)) {
      // It is very important that you handle validation groups inside custom constraint 
      return;
    }
    if (values.password !== values.password_confirmation) {
      throw new Error('Password and password confirmation must be equal');
    }
    // You don't need to return anything if everything is fine
  };
};

Computed props

class Author extends Model {}
Author.props = {
  firstName: {
    filter: String,
    value: 'Dmytro',
  },
  lastName: {
    filter: String,
  },
  fullName: {
    filter: function (deps = []) {
      return deps.filter((v) => v).join(' ');
    },
    computed: ['firstName', 'lastName'],
  },
};
const author = new Author();

console.log(author.get('fullName')); // output -> 'Dmytro'
author.set('lastName', 'Zelenetskyi');
console.log(author.get('fullName')); // output -> 'Dmytro Zelenetskyi'

Deserializing and serializing model(fromJSON/toJSON)

class Author extends Model {}

Author.props = {
 name: {
   filter: 'string',
   constraints: [MusliConstraints.required()],
 },
 lastName: {
   filter: 'string',
 },
}; 

const horror = Author.fromJSON({
  name: 'Stephen',
  lastName: 'King',
});
console.log(horror instanceof Author);
// outputs `true`
 
console.log(horror.toJSON());
// outputs `{ name: "Stephen", lastName: "King" }`

Using useGetters and useSetters options

if useGetters or/and useSetters options are set to true, then you can use props' values directly via model.values object.

Example:

class Author extends Model {}
Author.props = {
 name: {
   filter: 'string',
   value: 'Default value',
 },
 age: {
   filter: 'number',
   value: 0,
 },
};
Author.propsSettings = {
  useGetters: true,
  useSetters: true,
};

const model = new Author();
console.log(model.values.name); // outputs: 'Default value'
console.log(model.values.age); // outputs: 0

// or you can use setter
model.values.age = 30;
console.log(model.values.age); // outputs: 30

model.values object can't be extended. Only props from schema are available. Setters won't be provided for computed properties.

Model version

With each model mutation model increases it's version, so you can track it.

const author = Author.fromJSON({ name: 'Stephen' });
console.log(model.version); // output: 1
model.set('name', 'Dmytro');
console.log(model.version); // output: 2

Creating ORM-like entities

const pg = require('pg');
const SQL = require('sql-template-strings')

class Entity extends Model {
  static get source() {
    throw new Error('Implement me');
  }
  
  static async findById(id) {
    const rows = await pool.query(SQL`SELECT * FROM "`.append(this.source).append(SQL`" WHERE id=${id}`));
    return this.fromJSON(rows[0]);
  }
}

class UserEntity extends Entity {
  static get source() {
    return 'users';
  }
  
  static get props() {
    return {
      first_name: {
        filter: 'string',
      },
      last_name: {
        filter: 'string',
      },
      password: {
        filter: 'string',
      },
    };
  }
}

const user = UserEntity.findById(1);
console.log(user.get('first_name'));
console.log(user.values);

Events

Model inherits event system from rx-emitter(github link) package that uses rxjs and handles all events as observables.

const book = new Book();

Rx.Observable.combineLatest(
  book.subject('chapter1'),
  book.subject('chapter2'),
)
.subscribe(() => {
  console.log('Two first chapters are ready');
});

book.publish('chapter1');
book.publish('chapter2');

License

Muesli is released under the MIT license.

Donate

muesli's People

Contributors

greenkeeper[bot] avatar zemd avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

muesli's Issues

An in-range update of rollup is breaking the build 🚨

Version 0.47.3 of rollup just got published.

Branch Build failing 🚨
Dependency rollup
Current Version 0.47.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As rollup is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ ci/circleci CircleCI is running your tests Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Commits

The new version differs by 7 commits.

  • 6b94155 -> v0.47.3
  • 586e255 Merge pull request #1551 from rollup/gh-1550
  • c364ec4 deshadow aliased imports (#1550)
  • 1b48335 Merge pull request #1549 from alippai/patch-1
  • a1c19b8 Add appveyor NodeJS 8 builds
  • ae996b7 Add travis for NodeJS 8
  • 3353338 check for process.hrtime, closes #1495

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of rollup is breaking the build 🚨

The devDependency rollup was updated from 1.9.2 to 1.9.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

rollup is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Release Notes for v1.9.3

2019-04-10

Bug Fixes

  • Simplify return expressions that are evaluated before the surrounding function is bound (#2803)

Pull Requests

  • #2803: Handle out-of-order binding of identifiers to improve tree-shaking (@lukastaegert)
Commits

The new version differs by 3 commits.

  • 516a06d 1.9.3
  • a5526ea Update changelog
  • c3d73ff Handle out-of-order binding of identifiers to improve tree-shaking (#2803)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of rollup-plugin-commonjs is breaking the build 🚨

Version 8.1.0 of rollup-plugin-commonjs just got published.

Branch Build failing 🚨
Dependency rollup-plugin-commonjs
Current Version 8.0.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As rollup-plugin-commonjs is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ ci/circleci CircleCI is running your tests Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Commits

The new version differs by 12 commits.

  • f7602d9 -> v8.1.0
  • 60846f5 Merge pull request #212 from rollup/external-from-commonjs
  • 5309d9b update appveyor config
  • d4a14e3 lint
  • d81bca9 handle options.external correctly
  • a5718e2 Merge branch 'master' into external-from-commonjs
  • cb0f14e just test in node 8
  • 078332b failing test for external module imported from commonjs
  • 61157df Merge pull request #195 from calvinmetcalf/top-level-return
  • bcadeb1 Drop extra linebreak from tests (#205)
  • c831ca4 Include a regexp in options' documentation (#197)
  • bb3045d top level return support

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of rxjs is breaking the build 🚨

Version 5.4.3 of rxjs just got published.

Branch Build failing 🚨
Dependency rxjs
Current Version 5.4.2
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

rxjs is a direct dependency of this project this is very likely breaking your project right now. If other packages depend on you it’s very likely also breaking them.
I recommend you give this issue a very high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ ci/circleci CircleCI is running your tests Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of rollup is breaking the build 🚨

Version 0.54.1 of rollup was just published.

Branch Build failing 🚨
Dependency rollup
Current Version 0.54.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

rollup is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… ci/circleci Your tests passed on CircleCI! Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Commits

The new version differs by 4 commits.

  • 4bd7a0a 0.54.1
  • 77e3b44 Update changelog
  • 74de841 Merge pull request #1871 from KingHenne/more-ts-fixes
  • b413df4 Fix two more ts compiler errors based on emitted d.ts files

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of rollup-plugin-commonjs is breaking the build 🚨

Version 9.1.4 of rollup-plugin-commonjs was just published.

Branch Build failing 🚨
Dependency rollup-plugin-commonjs
Current Version 9.1.3
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

rollup-plugin-commonjs is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… ci/circleci: Your tests passed on CircleCI! (Details).
  • ❌ continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

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.