vuex-jsonschema-validationを作っている

vuex-jsonschema-validationを作っている

November 10, 2019,
tags: vue vuex vuex-plugin


このエントリーをはてなブックマークに追加

GitHub - polidog/vuex-jsonschema-validation: A vuex state validation plugin on change state.
作りました。

これは何をするものなかの?

vuexのstateをjson schemaを使ってvalidationするvuex-pluginです。 schema.jsonでstateの構造を定義して、そのとおりになるかをチェックします。

チェックするタイミングはmutationでstateを変化するときに、json schemaを利用してvalidationを行います。 validationエラーになる場合は、変更前のstateに戻します。 エラーが無ければそのままstateの変更が反映されます。

なぜ作ったのか?

情報の構造を定義するのは言語仕様の型(クラス)を使って表現するべきなのか?
そんな疑問が湧いたところから、情報の構造ならjson schemaで定義するのがいいのでは?という発想で作りました。

Vuexのstateは情報であって、どう振る舞うかを定義する場所ではないと考えました。
(どう振る舞わせるかは、gettersあたりでなにかするのが良いのではと思っています。)  

Stateはシンプルな構造にするべきで、その正しさを守るためにjson schemaを利用してバリデーションをする。
それで丁度いいと僕は思いました。

実装内容について

コード読んでもらえればわかりますが、大したことはしてないです。

subscribeを利用しているので、mutationが実行されてから、変更されたstateが正しいかvalidationを行います。

正しくなければエラーを発生させるのと、store.replaceStore() を使って状態をもとに戻しています。

使い方

README.mdと全く同じですがこんな感じです。

npm install --save vuex-jsonschema-validation
// schema.json

{
  "type": "object",
  "properties": {
    "todos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "text": {
            "type": "string"
          },
          "done": {
            "type": "boolean"
          }
        }
      }
    }
  },
  "additionalProperties": false
}
// store.js

import Vue from 'vue'
import Vuex from 'vuex'
import VuexJsonSceham from 'vuex-jsonschema-validation'
import schema from './schema.json'
const plugin = VuexJsonSceham(schema)

Vue.use(Vuex)


const state = {
  todos: [
    { id: 1, text: 'taskA', done: true },
    { id: 2, text: 'taskB', done: false }
  ]  
}

const actions = {}

const mutations = {
  change(state, { id, done }) {
    const target = state.todos.find(todo => todo.id === id)
    if (target) {
      target.done = done
    }
  },
  add(state, { text }) {
    const lastId = state.todos.slice(-1)[0].id
    state.todos.push({
      id: lastId + 1,
      text,
      done: false
    })
  },
  other() {
    state.abc = 'd'
  }
}

const store = new Vuex.Store({
  strict: process.env.NODE_ENV !== 'production',
  plugins: [plugin],
  state,
  actions,
  mutations
})

export default store

気が向いたらサンプルのアプリを作ります。

最後に

これは非常に実験てきなものであって、どうなるかわかりません。

comments powered by Disqus