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!