Skip to content

feats/graph-object

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DEPRECATION NOTE:

This project has started a couple of years ago as we intended to create a way to allow developers to focus on building a structured domain based on well defined patterns instead of having the mess of loose uncoupled resolvers.

Unfortunately we haven’t had the proper time to develop this project further, so it has never gained enough momentum. Since then, as well, lots has changed in the ecosystem. A lot of the goals of this project have already been achieved by other projects, such as https://prisma.io.

Prisma is probably the way to go if you look for something mature and reliable. If you feel adventurous, though, you can take a look at our new experiment: https://github.com/zvictor/faugra.


the GraphObject Build Status

Don't let your graph oriented project become a mess. Add structure to it!

Disclaimer

This is an experimental project not ready for production use yet. Part of the features described in this document are still being implemented. The best way to check the features currently implemented is checking out our example app.

We are looking for feedback and are open for discussing the strategy adopted here. Do not hesitate opening an issue and sharing your thoughts with us, it will make us happy. :)

Install

npm install graph-object --save

Models Usage

new MyModel({ field: value })

import { Model } from 'graph-object';

class Author extends Model {
  get name() {
    return `${this.firstName} ${this.lastName}`;
  }
}
> const orwell = new Author({ firstName: 'George', lastName: 'Orwell' });
> orwell.firstName
'George'
> orwell.name
'George Orwell'

Authorization

Allow/Deny Access

allow(object, objectCRUD, fields_RU_)

import { allow, controlAccess } from 'graph-object';

class Post extends Model {
  ...
}

class Author extends Model {
  get posts() {
    return Post.objects.find({ 'author._id': this._id });
  }

  get publicPosts() {
    return controlAccess(
      Post.objects.find({ 'author._id': this._id })
    )
  }

  allowedPosts(context) {
    return controlAccess(
      Post.objects.find({ 'author._id': this._id }), context
    )
  }
}

allow(Post, {
  read(context) { // Post's CRUD permissions could be changed
    return this.author._id === context.userId || !this.private;
  },
}, {
  views: { // `view` field permissions.
           // Only `read` and `update` are available for fields.
    read(context) {
      return this.author._id === context.userId;
    },
    update(context) {
      return false;
    }
  }
});
> // someAuthor only published a private ({private: 1}) post.
> someAuthor.posts
Error: 'read' permission not granted by Post
> someAuthor.public
[]
> someAuthor.allowedPosts({ userId: 1 })
[Post]

Managers Usage

Managers are inspired in the Django's manager concept. More docs to come.

Connectors Setup

In order to retrieve and persist the data from your objects you should connect your models to your prefered storage provider. Graph-object is agnostic about that, so you can use any database and storage engines, as many as you want, as long as there are adapters available for them.

Note: If no connector is specified for a given class, it will by default use a dumb memory store.

The example below will give your managers access to both mongodb and memory stores.

import models from './models';
import adapter from 'graph-object-adapter-waterline';
import memoryAdapter  from 'sails-memory';
import mongoAdapter  from 'sails-mongo';
import { injectConnectors } from 'graph-object';

const persistingModels = injectConnectors(models, adapter({
  default: {
    adapter: mongoAdapter,
    host: 'localhost', // defaults to `localhost` if omitted
    port: 27017, // defaults to 27017 if omitted
    user: 'username_here', // or omit if not relevant
    password: 'password_here', // or omit if not relevant
    database: 'database_name_here' // or omit if not relevant
    identifiers: {
      Author: 'authors',
      Posts: 'posts',
    }
  },
  memory: {
    adapter: memoryAdapter,
    identifiers: {
      Author: 'people',
      Posts: 'posts',
    }
  },
});

export default persistingModels;

Models, Managers and Connectors. What da heck!?!

If these concepts make you confused, this issue could help clarifying it.

GraphQL resolvers

Graph-object models are plug & play to GraphQL servers. Just make sure you run generateResolvers(schema, models) to have the resolvers generated.

import schema from '/domain/schemas';
import persistingModels from './models';
import { apolloExpress } from 'apollo-server';

const resolvers = generateResolvers(schema, persistingModels);
addResolveFunctionsToSchema(schema, resolvers);

...

app.use('/graphql', bodyParser.json(), apolloExpress({
  schema,
  resolvers,
  context: {},
}));

Example

Please check out the Perfect GraphQL Starter for a working example app.

Motivate

If you like this project just give it a star :)

About

An Object Graph Mapper for GraphQL

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published