feathersjs-ecosystem / feathers-vuex

Integration of FeathersJS, Vue, and Nuxt for the artisan developer
https://vuex.feathersjs.com
MIT License
445 stars 108 forks source link

Use BaseModel as default - simplify makeServicePlugin call #271

Open dkebler opened 5 years ago

dkebler commented 5 years ago

just trying to migrate to 2.0. Need some clarification

in the backend a model and service is created like so

// Initializes the `circuits` service on path `/circuits`
const createService = require('feathers-nedb')
const createModel = require('../../helpers/nedb.model')
const hooks = require('./config.hooks')

module.exports = function () {
  const app = this
  const Model = createModel(app, 'config')
  const paginate = app.get('paginate')

  const options = {
    name: 'config',
    Model,
    events: [],  // custom events
    paginate
  }

  // Initialize our service with any options it requires
  app.use('/config', createService(options))

  // Get our initialized service so that we can register hooks and filters
  const service = app.service('config')

  service.hooks(hooks)
}

I am assuming that is how more or less f-v in V1.7 did it as one only had to pass the service name to the plug-in generator.

In 2.0 one now has to make and pass a BaseModel extended class in which static model name is added

Can the mew makeServicePlugin function take care of all this if it sees a string passed (the service name) and not an object (with model and service)

Seems like that function should/could have access to the feathers object from the feathersVuex call and should be able to create the service as well as the baseModel class instance with the model name if that is what is required. This IMO should be as simple as before if one doesn't need changes to the BaseModel

const SERVICES = ['config', 'network', 'hardware', 'circuits', 'switches']
plugins: SERVICES.map(name => service(name))

As it is I have to do this hard coding of an extended Class 6 times for my 6 services. Seems a 'createModel` function should be added equivalent to that in feathers itself. Then internally to makeServicePlugin it could be called.

Ok...so I probably should do a PR right :-). Unfortunately I don't code in typescript (mainly cause of the transpiler step) but I do write in latest ES6-7/ESM if that is any help.

dkebler commented 5 years ago

@marshallswain
This seems to work from https://stackoverflow.com/questions/33605775/es6-dynamic-class-names

const nameIt = (name, cls) => ({ [name]: class extends cls {} })[name]

function createModelClass (name) {
  class Model extends BaseModel {
    constructor (data, options) {
      super(data, options)
      this.modelName = name + 'i'
    }
  static modelName = name
  }
  return nameIt(name, Model)
}
let Test = createModelClass('Test')
console.log('class static modelName', Test.modelName)
console.log('instance modelName', new Test().modelName)
class static modelName Test 
instance modelName iTest

I'll try it in app now

marshallswain commented 5 years ago

This is a pretty cool idea, really. I can see two issues to address.

(1) This shorthand syntax won't support multiple feathers clients. But MOST apps use a single API, so I feel like we should go for it. This is basically a documentation issue. (2) Lack of instanceDefaults support is a bigger issue, since that saves a lot of boilerplate with forms.

dkebler commented 5 years ago

well that worked! Seems worthwile to at least add as a helper function

this version you can specify a custom base if you made one elsewhere otherwise it uses BaseModel. Could include your suggested static method but will need to be able to grab the api name from somewhere

const nameIt = (name, cls) => ({ [name]: class extends cls {} })[name]

function createModelClass (name, Base) {
  if (!Base) Base = BaseModel
  class Model extends Base {
    constructor (data, options) {
      super(data, options)
      this.modelName = name + 'i'
    }
  static modelName = name
  }
  return nameIt(name, Model)
}

So I'm back up and run with 2.0. Now looking forward to refactoring things to take advantage of all the changes in 2.0. @marshallswain so thankful for your continued work on f-v. Anything I can help with other than PRs? Api Docs? I like this project for those https://github.com/onury/docma. Maybe some examples of usage including with Quasar?

dkebler commented 5 years ago

per 1 it could take an api name and if not supplied can use the first (or only) one it can find. per 2 my better version supports an already extended BaseModel which could include your static method installDefaults That one could be an included and exported as say ExtBaseModel which has those suggestions built in.

marshallswain commented 5 years ago

@dkebler I feel like the only thing standing in the way of getting this into 2.x is https://github.com/feathers-plus/feathers-vuex/issues/276. I would be in favor of having your utility automatically used under the hood if a Model is not passed to makeServicePlugin. Fixing that other issue will make it so that instanceDefaults are no longer required.

dkebler commented 5 years ago

Here it is in action https://github.com/feathers-plus/feathers-vuex/issues/252#issuecomment-537601295

dkebler commented 4 years ago

I see many releases since october. Has #276 been resolved?