Skip to content

Releases: feathersjs-ecosystem/feathers-vuex

Remove straggling stories.js file in `dist` folder

31 Jan 21:51
Compare
Choose a tag to compare

Just what it says on the label.

Prevent stories from getting copied to `dist` folder.

31 Jan 21:47
Compare
Choose a tag to compare

The TypeScript compiler was still copying the stories from src to dist, which interferes with project Storybook configurations. To keep project config simple, the stories are now moved into the ./stories folder. This will keep them from getting copied to dist.

Add src/*.stories.js to `.npmignore`

31 Jan 21:46
Compare
Choose a tag to compare

This prevents Storybook stories in the src folder from getting published to npm.

🎁 Adds the `FeathersVuexInputWrapper`

31 Jan 21:26
Compare
Choose a tag to compare

This release adds the new, renderless FeathersVuexInputWrapper component which makes quick work of "edit-in-place" inputs:

<template>
  <div class="p-3">
    <FeathersVuexInputWrapper :item="user" prop="email">
      <template #default="{ current, prop, createClone, handler }">
        <input v-model="current[prop]" type="text" @focus="createClone" @blur="e => handler(e, save)" />
      </template>
    </FeathersVuexInputWrapper>

    <!-- Simple readout to show that it's working. -->
    <pre class="bg-black text-white text-xs mt-2 p-1">{{user}}</pre>
  </div>
</template>

<script>
export default {
  name: 'InputWrapperExample',
  props: {
    user: {
      type: Object,
      required: true
    }
  },
  methods: {
    // Optionally make the event handler async.
    async save({ event, clone, prop, data }) {
      const user = clone.commit()
      return user.patch(data)
    }
  }
}
</script>

Improve `makeFindMixin` usability & efficiency when `local` option is used.

14 Jan 03:01
Compare
Choose a tag to compare

The makeFindMixin now allows using the mixed-in find${Resources} utility (e.g. findTodos for a todos service) when the local option is provided. It also updates the mixin so that the watchers are not created when using the local option, since the watchers only function is to re-run the API query when something changes. This change will avoid some useless processing that was occurring in local mode.

Includes Fixes from: #394
And this PR: #407

🎁 Hydration API for Nuxt, FeathersVuexGet supports params

08 Jan 00:56
Compare
Choose a tag to compare

New APIs are available which allow for hydrating data in the Nuxt client. See https://vuex.feathersjs.com/nuxt.html#server-side-hydration

FeathersVuexGet now supports params and fetchParams props, which allows passing custom params to the server using hooks like paramsForServer and paramsFromClient.

🐜 Fixes the equality check for the event handlers

22 Dec 18:52
Compare
Choose a tag to compare

This fixes a mistake that was made checking for removed in the event handlers. It was using the assignment operator = instead of the equality operator ===.

🎁 Add `user` and `isAuthenticated` getters to the Auth plugin

22 Dec 18:50
Compare
Choose a tag to compare

This addresses a problem where the user state of the auth module is no longer reactive after destructuring. To fix this issue, two getters have been added to the auth state. They are available when a userService is provided to the makeAuthPlugin options.

  • user: returns the reactive, logged-in user from the userService specified in the options.
  • isAuthenticated: an easy to remember boolean attribute for if the user is logged in.

If you depend on a reactive, logged-in user in your apps, here is how to fix the reactivity:

Replace any reference to store.state.auth.user with store.state.getters('auth/user').
Because the user state is no longer reactive, it is logical for it to be removed in the next version. It will likely be replaced by a userId attribute in Feathers-Vuex 4.0.

For more clarity on 3.2.0, the user in state is actually reactive UNLESS you destructure.

const { user } = store.state.auth
if (user === null) {
  // congrats, you just lost reactivity because it's a primitive
} else {
  // the properties of the user record will be reactive.
}

As soon as null is returned (when there's no user) the reactivity is broken. Of course it works this way because a primitive can't have any reactivity on its own. The new user getter will always be reactive, whether it's null or an actual user.

const user = store.getters['auth/user']
if (user === null) {
  // user itself is still reactive
} else {
  // user continues to be reactive
}

Reactivity doesn't work on objects because it requires either

  • the use of ES5 accessor properties (getters and setters on objects) or...
  • the use of Proxy objects (like in Vue 3)

Either way, if it's not an object it can't be reactive. And I mean a real object. I thought I better clarify since typeof null === 'object', which I'm sure has to make sense for somebody.

Fix bug in the 'removed' event handler.

22 Dec 01:46
Compare
Choose a tag to compare

The event handler for removed was mistakenly calling the non-existent removeItem action instead of the correct removeItem mutation. This is now fixed.

🎁 Custom Handlers for FeathersJS Events

21 Dec 01:34
Compare
Choose a tag to compare

As of version 3.1, you can customize the behavior of the event handlers, or even perform side effects based on the event data. This is handled through the new handleEvents option on the service plugin. Here is an example of how you might use this:

handleEvents: {
  created: (item, { model, models }) => {
    // Perform a side effect to remove any record with the same `name`
    const existing = Model.findInStore({ query: { name: item.name }}).data[0]
    if (existing) {
      existing.remove()
    }

    // Perform side effects with other models.
    const { SomeModel } = models.api
    new SomeModel({ /* some custom data */ }).save()

    // Access the store through model.store
    const modelState = model.store.state[model.namespace]
    if (modelState.keyedById[5]) {
      console.log('we accessed the vuex store')
    }

    // If true, the new item will be stored.
    return true
  },
  updated: () => false, // Ignore `updated` events.
  patched: item => item.hasPatchedAttribute && item.isWorthKeeping,
  removed: item => true // The default value, will remove the record from the store
}

As shown above, each handler has two possible uses:

  1. Control the default behavior of the event by returning a boolean.
  • For created, patched, and updated a truthy return will add or update the item in the store.
  • For removed a truthy return will remove the item from the store, if present.
  1. Perform side effects using the current service model or with other models. The models object is the same as the $FeathersVuex object in the Vue plugin.

Each handler receives the following arguments:

  • item: the record sent from the API server
  • utils: an object containing the following properties
    • model The current service's Model class.
    • models The same as the $FeathersVuex object, gives you access to each api with their respective model classes.