Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

class extends Store #344

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"browser": true,
"es6": true
},
"parser": "babel-eslint",
"ecmaFeatures": {
"modules": true,
"jsx": true
Expand Down
47 changes: 47 additions & 0 deletions foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Alt, { Store } from './'

const alt = new Alt()

const actions = alt.generateActions('foo')

//class MyStore extends Store {
// constructor(one, two, three) {
// super()
//
// this.state = { x: 1 }
//
// this.bindAction(actions.foo, () => {
// this.setState({ x: this.state.x + 1 })
// })
// }
//}
//const store = alt.register(1, 2, 3)(MyStore)

class MyStore {
constructor() {
this.state = { x: 1 }
this.bindActions(actions)
this.exportPublicMethods({
bar: this.bar.bind(this)
})
}

foo() {
this.setState({ x: this.state.x + 1 })
}

bar() {
return this.state.x
}
}

const store = alt.createStore(MyStore)

console.log(store.bar())

store.listen(state => console.log('CHANGED', state))

actions.foo()
actions.foo()
actions.foo()
actions.foo()
90 changes: 51 additions & 39 deletions src/alt/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { Dispatcher } from 'flux'

import * as StateFunctions from './utils/StateFunctions'
import * as fn from '../utils/functions'
import * as store from './store'
import * as utils from './utils/AltUtils'
import makeAction from './actions'

import registerStore from './store/register'

import Store from './store'

class Alt {
constructor(config = {}) {
this.config = config
Expand All @@ -27,44 +30,6 @@ class Alt {
this.batchingFunction(() => this.dispatcher.dispatch({ action, data, details }))
}

createUnsavedStore(StoreModel, ...args) {
const key = StoreModel.displayName || ''
store.createStoreConfig(this.config, StoreModel)
const Store = store.transformStore(this.storeTransforms, StoreModel)

return fn.isFunction(Store)
? store.createStoreFromClass(this, Store, key, ...args)
: store.createStoreFromObject(this, Store, key)
}

createStore(StoreModel, iden, ...args) {
let key = iden || StoreModel.displayName || StoreModel.name || ''
store.createStoreConfig(this.config, StoreModel)
const Store = store.transformStore(this.storeTransforms, StoreModel)

if (this.stores[key] || !key) {
if (this.stores[key]) {
utils.warn(
`A store named ${key} already exists, double check your store ` +
`names or pass in your own custom identifier for each store`
)
} else {
utils.warn('Store name was not specified')
}

key = utils.uid(this.stores, key)
}

const storeInstance = fn.isFunction(Store)
? store.createStoreFromClass(this, Store, key, ...args)
: store.createStoreFromObject(this, Store, key)

this.stores[key] = storeInstance
StateFunctions.saveInitialSnapshot(this, key)

return storeInstance
}

generateActions(...actionNames) {
const actions = { name: 'global' }
return this.createActions(actionNames.reduce((obj, action) => {
Expand All @@ -77,6 +42,51 @@ class Alt {
return makeAction(this, 'global', name, implementation, obj)
}

createUnsavedStore(StoreModel, ...args) {
StoreModel.config = fn.assign({
invisible: true
}, StoreModel.config)
return this.createStore(StoreModel, null, ...args)
}

createStore(StoreModel, iden, ...args) {
// pull all prototype methods out
const proto = utils.getInternalMethods(StoreModel, true)

// force inheritance on store
utils.inherit(StoreModel, Store, Object.keys(proto).reduce((obj, name) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work if StoreModel extends another class? Looks like getInternalMethods might have to walk up the prototype chain for StoreModel for this to work.

I think it'd be easier just to pull out the constructor functionality on the base Store class into an #init() method, then invoke that (in both Store#constructor and for this), without messing with StoreModel's prototype.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah it doesn't it should walk up the proto chain.

I doubt this will work with proper ES6 classes anyway, I may just nuke this. This was just a fun experiment :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW my thought with using the base Store effectively as a mixin is that you fully control that, so you know that it doesn't have any superclasses (or if it does, you know how they're set up), whereas you can't assume anything about whatever crazy thing the user passes in to createStore.

obj[name] = {
value: StoreModel.prototype[name],
enumerable: false,
writable: true,
configurable: true
}
return obj
}, {}))

// setup the a container store which will call Store first
// then your store
function FauxStore() {
Store.prototype.constructor.apply(this, arguments)
StoreModel.prototype.constructor.apply(this, arguments)
}
utils.inherit(FauxStore, StoreModel)

if (iden) FauxStore.displayName = iden
return this.register(...args)(FauxStore)
}

register(...args) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intended syntax something like alt.register(ctorArg1, ctorArg2)(Store)? I feel like alt.register(Store, ctorArg1, ctorArg2) looks a bit better. Although that wouldn't work as a decorator... but I can't think of a good reason to write code that looks like

@alt.register(arg1, arg2)
class MyStore extends Store { ... }

With the latter above I think you just naturally get

@alt.register
class MyStore extends Store { ... }

which ought to be good enough for any sane use case.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 reasonable.

return (Class) => {
const instance = new Class(...args)
if (instance instanceof Store) {
return registerStore(this, instance, Class)
} else {
throw new Error('wtf')
}
}
}

createActions(ActionsClass, exportObj = {}, ...argsForConstructor) {
const actions = {}
const key = utils.uid(
Expand Down Expand Up @@ -212,6 +222,8 @@ class Alt {
}
return alt
}

static Store = Store
}

export default Alt
94 changes: 0 additions & 94 deletions src/alt/store/AltStore.js

This file was deleted.

Loading