Skip to content

Migrate Models to Services ​

Model Classes and Functions have served us well, but are no more. Every Feathers Service now includes implicit model functions which can be extended.

Why Implicit Models? ​

Rather than having to setup every single model, we can take advantage of Vue 3's reactive API, which allows one to dynamically add and remove attributes from reactive objects. Feathers-Pinia 3 takes full advantage of this fact and automatically assumes that every object needs to be a model. So now there is no need to manually create them.

Switch to Implicit Modeling ​

The below tabs allow you to compare previous modeling examples to the latest API. In Feathers-Pinia modeling happens in the services config of createPiniaClient.

ts
// models/user.ts
import { BaseModel } from '../store/store.pinia'

export class User extends BaseModel {
  /* You might have defined default values, here, */
  _id?: string
  name = ''
  email = ''
  password = ''

  // Depending on the Feathers-Pinia version, you may not have written a constructor
  constructor(data: Partial<User> = {}, options: Record<string, any> = {}) {
    super(data, options)
    this.init(data)
  }

  // optional for setting up data objects and/or associations
  static setupInstance(message: Partial<Task>) {
    const { store, models } = this
    return {
      /* default properties used to go here */
    }
  }
}
ts
import type { Users, UsersData, UsersQuery } from 'my-feathers-api'
import { type ModelInstance, useFeathersModel, useInstanceDefaults } from 'feathers-pinia'
import { api } from '../feathers'

const service = api.service('users')

function modelFn(data: ModelInstance<Users>) {
  const withDefaults = useInstanceDefaults({ name: '', email: '', password: '' }, data)
  return withDefaults
}
const User = useFeathersModel<Users, UsersData, UsersQuery, typeof modelFn>(
  { name: 'User', idField: '_id', service },
  modelFn,
)
ts
import { createPiniaClient, useInstanceDefaults } from 'feathers-pinia'
import type { ServiceInstance } from 'feathers-pinia'
import type { Users } from 'my-feathers-api'

const api = createPiniaClient(feathersClient, {
  pinia,
  idField: 'id',
  services: {
    users: {
      setupInstance(data: ServiceInstance<Users>) {
        const withDefaults = useInstanceDefaults({ name: '', email: '', password: '' }, data)
        return withDefaults
      },
    },
  },
})

Important Changes ​

No Model Constructors ​

The Model constructor is now the model function. If you have any constructor logic, move it into the setupInstance method of the service's configuration.

useInstanceDefaults ​

The instanceDefaults static Model function is replaced by the useInstanceDefaults utility.

setupInstance Changes ​

You must return the object from the setupInstance function. If not, you'll run into errors.

Many thanks go to the Vue and FeathersJS communities for keeping software development FUN!