Skip to content

Commit

Permalink
feat: add builtin $watch method
Browse files Browse the repository at this point in the history
  • Loading branch information
guyskk committed Mar 19, 2024
1 parent 8f81328 commit 3001094
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"root": true,
"env": {
"node": true,
"browser": true
"browser": true,
"es6": true
},
"extends": [
"eslint:recommended"
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ export const counterStore = hamiVuex.store({
return this.count * 2
},

// define watcher (event listener), similar to Vuex watch
onChange(callback) {
// $watch is builtin method, used for watch changes
// $watch(source: Function, callback: Function): Function
unwatch = this.$watch(() => this.count, (newValue, oldValue) => {
console.log('onChange', newValue, oldValue)
unwatch()
})
}

// define an action, similar to Vuex action
increment() {
// $patch is builtin Vuex mutation, used for update state
Expand Down
6 changes: 3 additions & 3 deletions runtest.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

echo '*** test on vue 2 + vuex 3 ***'
npm install
npm ci
npm run build
npm run test:unit

Expand All @@ -10,12 +10,12 @@ mv package.json package3.json
mv package-lock.json package3-lock.json
mv package4.json package.json
mv package4-lock.json package-lock.json
npm install
npm ci
npm run test:unit

echo '*** switch back vue 2 + vuex 3 ***'
mv package.json package4.json
mv package-lock.json package4-lock.json
mv package3.json package.json
mv package3-lock.json package-lock.json
npm install
npm ci
12 changes: 8 additions & 4 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ declare type Immutable<T> =

declare type StateMutator<S, R> = (this: never, state: S) => R

declare type WatchCallback<T> = (value: T, oldValue: T) => void
declare type WatchStop = () => void

declare type HamiStoreBase<S> = {
readonly $name: string,
readonly $state: Immutable<S>,
$reset(): void,
readonly $name: string
readonly $state: Immutable<S>
$reset(): void
$patch<R>(stateMutator: StateMutator<S, R>): R
$patch(partialState: Partial<S>): void
$watch<T>(source: (() => any), callback: WatchCallback<T>): WatchStop
}

declare type HamiStoreDefine<T> = Immutable<Omit<T, '$name' | '$state'>>
Expand Down Expand Up @@ -62,5 +66,5 @@ declare function createHamiVuex<
VS = {}
>(options?: HamiVuexOptions<VS>): HamiVuex<VS>;

export type { HamiVuex, HamiStore, HamiStoreUsing }
export type { HamiStore, HamiStoreUsing, HamiVuex }
export { createHamiVuex, defineHamiStore }
18 changes: 17 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createVuexStore, installVuexStore, useVuexStore } from './compat'
import { isNil, isFunction } from './helper'
import { isFunction, isNil } from './helper'

const VUEX_STORE_KEY = '$store'

Expand Down Expand Up @@ -115,7 +115,11 @@ function internalDefineHamiStore(options) {
})
),
actions: define.actions.concat([]),
mixins: _defineBuiltinMixins({ vuexStore }),
}
finalDefine.mixins.forEach(([key, handler]) => {
self[key] = handler
})
finalDefine.mutations.forEach(([key]) => {
self[key] = _createMutationMethod(vuexStore, storeName, key)
})
Expand Down Expand Up @@ -216,6 +220,18 @@ function _defineBuiltinMutations({ vuexStore, storeName, stateFunc }) {
})
}

function _defineBuiltinMixins({ vuexStore }) {
return Object.entries({
$watch(source, callback) {
if (!isFunction(source)) {
throw new Error('watch source only accepts a function')
}
const watchSource = () => source.call(undefined)
return vuexStore.watch(watchSource, callback)
},
})
}

function _defineBuiltinGetters({ vuexStore, storeName, self }) {
return Object.entries({
$state() {
Expand Down
23 changes: 19 additions & 4 deletions tests/basic.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { expect, test } from '@jest/globals'
import Vuex from 'vuex'
import { test, expect } from '@jest/globals'
import { createHamiVuex } from '../dist'
import { isNil, isFunction } from './helper'
import { Vue, IS_VUEX_3, createVueApp } from './helper'
import { counterOptions } from './helper'
import { IS_VUEX_3, Vue, counterOptions, createVueApp, isFunction, isNil } from './helper'

if (IS_VUEX_3) {
Vue.use(Vuex)
Expand Down Expand Up @@ -63,6 +61,20 @@ test('hamiVuex.store: counter', async () => {
expect(counterStore.count).toBe(0)
expect(counterStore.double).toBe(0)

expect(() => {
counterStore.$watch('count', () => {})
}).toThrow('watch source only accepts a function')

let watchCallbackCalled = false
const unwatch = counterStore.$watch(
() => counterStore.count,
(newValue, oldValue) => {
unwatch()
watchCallbackCalled = true
expect(newValue).toBe(1)
expect(oldValue).toBe(0)
}
)
const patchResult = counterStore.$patch((state) => {
state.count += 1
return state.count
Expand All @@ -71,6 +83,9 @@ test('hamiVuex.store: counter', async () => {
expect(counterStore.$state.count).toBe(1)
expect(counterStore.count).toBe(1)
expect(counterStore.double).toBe(2)

await new Promise((r) => setTimeout(r, 0))
expect(watchCallbackCalled).toBe(true)
})

test('hamiVuex.store: error', async () => {
Expand Down

0 comments on commit 3001094

Please sign in to comment.