Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Model #13

Closed
15 tasks done
etsuo opened this issue Dec 1, 2016 · 5 comments
Closed
15 tasks done

@Model #13

etsuo opened this issue Dec 1, 2016 · 5 comments

Comments

@etsuo
Copy link
Member

etsuo commented Dec 1, 2016

Todo:

Proposal

A set of route handlers are setup with an @Routable class:

@Routable()
class SomeSetOfRouteHandlers {

  @Route({
    path: '/',
    method: 'get'
  })
  someGetHandler(req, res) {
  
  }

  @Route({
    path: '/',
    method: 'post'
  })
  somePostHandler(req, res) {
  
  }
}

This class is instantiated by the @Routable decorator and added to the Express router through a call to SakuraApi.instance.route(this);.

Because there's a single instance of this class responsible for route handlers, it's not an appropriate place to represent a model (i.e., there's only one of these @Routable objects handling routes, but each request will be handling different objects that are relevant to various models).

Possible Solution?:

@Model({
  // these get injected as a dbConfig property that can be used when
  // manually writing to the DB
  dbConfig: {
    db: 'someDatabase',
    collection: 'someCollection'
  },
  // if not defined, perhaps look at the configs for a dbModelBindings.json file
  // (db.ModelBindings.dev.json, etc)
  suppressInjection: ['create']
})
class User {

  id: ObjectId; // object Id will have timestamp capabilities 
                       // & uuid generation on instantiation
                       // the id property will automatically be recognized as
                       // being the _id for MongoDB

  // perhaps these decorators create getters and setters that manipulate an
  // injected _propertyName variable and decorate the getter with various
  // functions that implement the Decorator behaviors?

  @Required 
  @json('fname') @db('fn')
  firstName: string;

  @Required
  @json({'name: "fname"', excludeNull: true}) 
  @db({field: 'fn', excludeNull: true})
  lastName: string;

  @Required @Validate(emailValidator)
  @db('em')
  email: string;

  @Private        // i.e., filter this before sending to client
  ssn: string;

  constructor(json: any) {
    json = json || {}; // perhaps this can be done in the @Model logic

    this.firstName = json.firstName || '';
    this.lastName = json.lastName || '';
    this.email = json.email || '';
  }

  save() : Promise<null> {
    // persist to MongoDB
    super.save(); 
    // if nothing's added, you don't have to override the save()
    // method.

    // There will need to be some kind of DataSource definition that binds an
    // @Model to a specific DB / Collection... perhaps that can be done in 
    // the @Model({})
  }

  static getById(id) : Promise<User> {
    // retrieve from MongoDB
  }

  static get(filter:any) : Promise<User[]> {
    // get list from MongoDB
  }

  deleteById(id) : Promise<null> {
    // delete from MongoDB
  }

  emailValidator(email:string) {
    return (...meets some proper condition...) ? true : false;
  }
}

Then, from within the @Routable class @route method:

  @Route({
    path: '/',
    method: 'post',
    model: User
  })
  somePostHandler(req, res) {
    req.model.save();
    // where .model was patched onto req automatically.
  }

  @Route({
    path: '/',
    method: 'get'
  })
  somePostHandler(req, res) {
    res.send(200).json(User.get(req.query.id));
    // this requires a lot more thought... what about error handling, etc?
  }
@etsuo etsuo added this to the 0.3.0 milestone Dec 1, 2016
etsuo added a commit that referenced this issue Dec 8, 2016
@etsuo
Copy link
Member Author

etsuo commented Dec 9, 2016

etsuo added a commit that referenced this issue Dec 10, 2016
etsuo added a commit that referenced this issue Dec 10, 2016
@etsuo etsuo removed the proposal label Dec 10, 2016
@etsuo
Copy link
Member Author

etsuo commented Dec 10, 2016

Default CRUD Method Injection

What methods should be automatically injected with default behavior unless implemented by the user directly, or suppressed with the @model({suppressInjection: []}) property?

Static

  • get(where?: any, limit?: number, skip?: number) ;
  • getById(id: string);
  • delete(where: any);

Instance

  • create()
  • save()
  • delete()

etsuo added a commit that referenced this issue Dec 11, 2016
…r default CRUD methods, moved instance CRUD methods to prototype, added support for suppressInjection option
etsuo added a commit that referenced this issue Dec 11, 2016
@etsuo
Copy link
Member Author

etsuo commented Dec 11, 2016

@Required

What should be the proper behavior of this decorator?

Http Requests through @Routable

  • on save, it returns an HTTP error
  • on create, it returns an HTTP error
  • on update, it returns a HTTP error

Class behavior

It doesn't do anything intrinsically on the class itself. I.e., you can instantiate a class with a property that has @Required and not have the field, and nothing will happen. @Required only kicks in when an HTTP CRUD operation takes place through @Routable. If that's right, then this should probably be separated out into a separate ticket since it won't be possible to implement then until @Model with @Routable.

@etsuo
Copy link
Member Author

etsuo commented Dec 11, 2016

@Default

This is probably not required.

@Model()
SomeClass {
    @Json('sp') @Default(777);
    someProperty = 777;
}

It's not clear to me what benefit @Default would provide... in fact, it seems to just clutter things.

etsuo added a commit that referenced this issue Dec 12, 2016
etsuo added a commit that referenced this issue Dec 13, 2016
etsuo added a commit that referenced this issue Dec 14, 2016
@etsuo etsuo mentioned this issue Dec 16, 2016
26 tasks
@etsuo
Copy link
Member Author

etsuo commented Dec 16, 2016

merged to develop

@etsuo etsuo closed this as completed Dec 18, 2016
@etsuo etsuo mentioned this issue May 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant