Skip to content

Commit

Permalink
Add support for Vue 3
Browse files Browse the repository at this point in the history
  • Loading branch information
davestewart committed May 21, 2020
1 parent 1828500 commit 75d55c9
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 695 deletions.
5 changes: 4 additions & 1 deletion build/rollup.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ const umd = {
},
}),
commonjs(),
buble(),
buble({
// @see https://github.com/vuejs/vue-hackernews-2.0/issues/87
objectAssign: 'Object.assign',
}),
],
}

Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vue-class-store",
"description": "Universal Vue stores you write once and use anywhere",
"version": "2.0.3",
"version": "3.0.0",
"author": "Dave Stewart",
"license": "MIT",
"main": "dist/vue-class-store.js",
Expand All @@ -17,11 +17,10 @@
"scripts": {
"dev": "rollup -c build/rollup.js -w",
"build": "rollup -c build/rollup.js",
"stats": "node dev/stats.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"peerDependencies": {
"vue": "^2.6.11"
"vue": "^3.0.0-beta.14"
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.8.3",
Expand All @@ -37,7 +36,7 @@
"rollup-plugin-vue": "^5.1.7",
"tslib": "^2.0.0",
"typescript": "^3.9.2",
"vue": "^2.6.11",
"vue": "^3.0.0-beta.14",
"vue-template-compiler": "^2.6.11"
},
"keywords": [
Expand Down
95 changes: 55 additions & 40 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Vue, { ComponentOptions, VueConstructor } from 'vue'
import { computed, reactive, watch } from 'vue'

type C = { new (...args: any[]): {} }

Expand All @@ -14,69 +14,84 @@ function getDescriptors (model: R) {
return { ...prototypeDescriptors, ...descriptors }
}

export function makeOptions(model: R): ComponentOptions<any> {
// prototype
const prototype = Object.getPrototypeOf(model)
const descriptors = getDescriptors(prototype)
function getValue (value: Record<any, any>, path: string | string[]) {
const segments = typeof path === 'string'
? path.split('.')
: path
const segment: string | undefined = segments.shift()
return segment
? getValue(value[segment], segments)
: value
}

export function makeReactive (model) {
// properties
const descriptors = getDescriptors(model)

// options
const name = prototype.constructor.name
const data: R = {}
const computed: R = {}
const methods: R = {}
const watch: R = {}
const data = {}
const watched = {}

// data, string watches
Object.keys(model).forEach(key => {
Object.keys(model).forEach((key: string) => {
const value = model[key]
if (key.startsWith('on:')) {
watch[key.substring(3)] = value
watched[key.substring(3)] = value
}
else {
data[key] = value
}
})

// function watches, methods, computed
Object.keys(descriptors).forEach(key => {
if (key !== 'constructor' && !key.startsWith('__')) {
const { value, get, set } = descriptors[key]
if (key.startsWith('on:')) {
watch[key.substring(3)] = value
}
else if (value) {
methods[key] = value
}
else if (get && set) {
computed[key] = { get, set }
}
else if (get) {
computed[key] = get
const state = reactive({
...data,
...Object.keys(descriptors).reduce((output, key) => {
if (key !== 'constructor' && !key.startsWith('__')) {
const { value, get, set } = descriptors[key]
// watch
if (key.startsWith('on:')) {
watched[key.substring(3)] = value
}
// method
else if (value) {
output[key] = (...args) => value.call(state, ...args)
}
// computed
else if (get && set) {
output[key] = computed({
set: (value) => set.call(state, value),
get: () => get.call(state),
})
}
else if (get) {
output[key] = computed(() => get.call(state))
}
}
return output
}, {}),
})

// set up watches
Object.keys(watched).forEach(key => {
const callback: Function = typeof watched[key] === 'string'
? model[getValue(model, 'on:' + key)]
: watched[key]
if (typeof callback === 'function') {
watch(() => getValue(state, key), callback.bind(state))
}
})

// return
return {
name,
computed,
methods,
watch,
data,
}
}

export function makeVue<T extends R> (model: T): T {
const options = makeOptions(model)
return (new Vue(options) as unknown) as T
return state
}

export default function VueStore<T extends C> (constructor: T): T {
function construct (...args: any[]) {
const instance = new (constructor as C)(...args)
return makeVue(instance)
return makeReactive(instance)
}
return (construct as unknown) as T
}

VueStore.create = makeVue
VueStore.create = makeReactive
Loading

0 comments on commit 75d55c9

Please sign in to comment.