Skip to content

Commit

Permalink
Merge pull request #309 from goatslacker/0.17.0-rebased
Browse files Browse the repository at this point in the history
Working 0.17.0 release
  • Loading branch information
goatslacker committed Jun 7, 2015
2 parents 3acf5af + 0dc3d56 commit 021fbc6
Show file tree
Hide file tree
Showing 29 changed files with 257 additions and 326 deletions.
69 changes: 69 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,74 @@
# Changelog

## 0.17.0

### Breaking Changes

* Removed Symbol

**Upgrade Guide**

- Remove all references to Symbol, Symbol.keyFor, etc.
- Get access to the action's unique id via `myAction.id`

* Removed `getEventEmitter()`

**Upgrade Guide**

- You can no longer access the internal event emitter to dispatch your own custom events. This is usually an anti-pattern.
- If you still need this behavior you can create your own event emitter in your store.

```js
class TodoStore {
constructor() {
this.eventEmitter = new EventEmitter()

this.exportPublicMethods({
getEventEmitter: () => this.eventEmitter
});
}
}
```

* Removed `_storeName`.

**Upgrade Guide**

- `_storeName` was an internal property to the store where the store's name was kept.
- You can now use `displayName` instead which is a public API.

* Removed `stateKey`. [commit](https://github.com/goatslacker/alt/commit/40830ea)

**Upgrade Guide**

- A `stateKey` property was configurable on stores as well as app level.
- This has now been removed.
- This key was mostly used so you can use the react-like API of `this.state`, now this is being supported first-class.

```js
// old behavior
class MyStore {
static config = { stateKey = 'state' }

constructor() {
this.state = {}
}
}
```

Now you can just use `this.state` directly. If it exists it'll be picked up.

```js
// old behavior
class MyStore {
constructor() {
this.state = {}
}
}
```

The old behavior of assigning state directly as instance properties will continue to be supported. However, this new behavior will be favored in the docs.

## 0.16.10

### Added
Expand Down
17 changes: 1 addition & 16 deletions docs/createStore.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,6 @@ Available configuration options:
`getState` receives the current state and returns a copy of it. You can override this function to provide your own implementation.

#### stateKey

`stateKey` is a string that controls where state should be defined at this particular store's level. For example:

```js
class TodoStore {
static config = {
stateKey: 'state'
}
constructor() {
this.state = { todos: {} }
}
}
```

#### onSerialize

`onSerialize` is also called before the store's state is serialized. You may optionally return an object, which will be used directly as the snapshot data for the store. If you do not return anything, the default, [`MyStore#getState()`](stores.md#storegetstate) is used for the snapshot data. See the [serialization](serialization.md) for an example.
Expand Down Expand Up @@ -302,7 +287,7 @@ class MyStore {
}
```

## StoreModel#_storeName
## StoreModel#displayName

This is a reference to the store's internal name. This is either the identifier you provided to `createStore` or StoreModel's class name.

Expand Down
25 changes: 0 additions & 25 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,31 +65,6 @@ This controls how store data is serialized in snapshots. By default alt uses `JS

This controls how store data is deserialized from snapshot/bootstrap data. By default alt uses `JSON.parse`, but you can provide your own function to deserialize data.

#### stateKey

`stateKey` is a string that controls where state should be defined at the store level. For example:

```js
var alt = new Alt({
stateKey: 'cherry'
});

class MyStore {
constructor() {
// state now goes in this.cherry
this.cherry = {
a: 1,
b: 2,
c: 3
};

// instance properties declared below do not go into state
this.isPrivate = 'yes'
this.yay = true
}
}
```

#### stateTransforms

This is an array of functions you can provide which will be executed every time `createStore` or `createUnsavedStore` is ran. It will iterate through the array applying each function to your store. This can be useful if you wish to perform any pre-processing or transformations to your store before it's created.
Expand Down
15 changes: 5 additions & 10 deletions mixins/Subscribe.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
'use strict'
var Symbol = require('es-symbol')
var MIXIN_REGISTRY = Symbol('alt store listeners')

var Subscribe = {
create: function (context) {
context[MIXIN_REGISTRY] = context[MIXIN_REGISTRY] || []
context._AltMixinRegistry = context._AltMixinRegistry || []
},

add: function (context, store, handler) {
context[MIXIN_REGISTRY].push({ store: store, handler: handler })
store.listen(handler)
context._AltMixinRegistry.push(store.listen(handler))
},

destroy: function (context) {
context[MIXIN_REGISTRY].forEach(function (x) {
x.store.unlisten(x.handler)
})
context[MIXIN_REGISTRY] = []
context._AltMixinRegistry.forEach(function (f) { f() })
context._AltMixinRegistry = []
},

listeners: function (context) {
return context[MIXIN_REGISTRY]
return context._AltMixinRegistry
}
}

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
"description": "A flux implementation",
"main": "lib",
"dependencies": {
"es-symbol": "1.1.2",
"eventemitter3": "0.1.6",
"flux": "2.0.3"
"flux": "2.0.3",
"transmitter": "1.0.2"
},
"devDependencies": {
"alt-search-docs": "1.0.6",
Expand Down
53 changes: 29 additions & 24 deletions src/alt/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
import Symbol from 'es-symbol'

import * as Sym from '../symbols/symbols'
import * as fn from '../../utils/functions'
import * as utils from '../utils/AltUtils'

class AltAction {
constructor(alt, name, action, actions, actionDetails) {
this[Sym.ACTION_UID] = name
this[Sym.ACTION_HANDLER] = action.bind(this)
constructor(alt, id, action, actions, actionDetails) {
this.id = id
this._dispatch = action.bind(this)
this.actions = actions
this.actionDetails = actionDetails
this.alt = alt
}

dispatch(data) {
this.alt.dispatch(this[Sym.ACTION_UID], data, this.actionDetails)
this.dispatched = true
this.alt.dispatch(this.id, data, this.actionDetails)
}
}

export default function makeAction(alt, namespace, name, implementation, obj) {
// make sure each Symbol is unique
const actionId = utils.uid(alt[Sym.ACTIONS_REGISTRY], `${namespace}.${name}`)
alt[Sym.ACTIONS_REGISTRY][actionId] = 1
const actionSymbol = Symbol.for(`alt/${actionId}`)

const data = {
namespace,
name,
id: actionId,
symbol: actionSymbol
}
const id = utils.uid(alt._actionsRegistry, `${namespace}.${name}`)
alt._actionsRegistry[id] = 1

const data = { id, namespace, name }

// Wrap the action so we can provide a dispatch method
const newAction = new AltAction(alt, actionSymbol, implementation, obj, data)
const newAction = new AltAction(alt, id, implementation, obj, data)

const dispatch = (payload) => alt.dispatch(id, payload, data)

// the action itself
const action = newAction[Sym.ACTION_HANDLER]
const action = (...args) => {
newAction.dispatched = false
const result = newAction._dispatch(...args)
if (!newAction.dispatched && result !== undefined) {
if (fn.isFunction(result)) {
result(dispatch)
} else {
dispatch(result)
}
}
return result
}
action.defer = (...args) => {
setTimeout(() => {
newAction[Sym.ACTION_HANDLER].apply(null, args)
newAction._dispatch.apply(null, args)
})
}
action[Sym.ACTION_KEY] = actionSymbol
action.id = id
action.data = data

// ensure each reference is unique in the namespace
const container = alt.actions[namespace]
const id = utils.uid(container, name)
container[id] = action
const namespaceId = utils.uid(container, name)
container[namespaceId] = action

return action
}
25 changes: 12 additions & 13 deletions src/alt/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { Dispatcher } from 'flux'

import * as StateFunctions from './utils/StateFunctions'
import * as Sym from './symbols/symbols'
import * as fn from '../utils/functions'
import * as store from './store'
import * as utils from './utils/AltUtils'
Expand All @@ -18,9 +17,9 @@ class Alt {
this.actions = { global: {} }
this.stores = {}
this.storeTransforms = config.storeTransforms || []
this[Sym.ACTIONS_REGISTRY] = {}
this[Sym.INIT_SNAPSHOT] = {}
this[Sym.LAST_SNAPSHOT] = {}
this._actionsRegistry = {}
this._initSnapshot = {}
this._lastSnapshot = {}
}

dispatch(action, data, details) {
Expand Down Expand Up @@ -80,7 +79,7 @@ class Alt {
createActions(ActionsClass, exportObj = {}, ...argsForConstructor) {
const actions = {}
const key = utils.uid(
this[Sym.ACTIONS_REGISTRY],
this._actionsRegistry,
ActionsClass.displayName || ActionsClass.name || 'Unknown'
)

Expand Down Expand Up @@ -121,23 +120,23 @@ class Alt {

// generate a constant
const constant = utils.formatAsConstant(actionName)
exportObj[constant] = exportObj[actionName][Sym.ACTION_KEY]
exportObj[constant] = exportObj[actionName].id
}, [actions])
return exportObj
}

takeSnapshot(...storeNames) {
const state = StateFunctions.snapshot(this, storeNames)
fn.assign(this[Sym.LAST_SNAPSHOT], state)
fn.assign(this._lastSnapshot, state)
return this.serialize(state)
}

rollback() {
StateFunctions.setAppState(
this,
this.serialize(this[Sym.LAST_SNAPSHOT]),
this.serialize(this._lastSnapshot),
storeInst => {
storeInst[Sym.LIFECYCLE].emit('rollback')
storeInst.lifecycle('rollback')
storeInst.emitChange()
}
)
Expand All @@ -147,16 +146,16 @@ class Alt {
const initialSnapshot = storeNames.length
? StateFunctions.filterSnapshots(
this,
this[Sym.INIT_SNAPSHOT],
this._initSnapshot,
storeNames
)
: this[Sym.INIT_SNAPSHOT]
: this._initSnapshot

StateFunctions.setAppState(
this,
this.serialize(initialSnapshot),
(storeInst) => {
storeInst[Sym.LIFECYCLE].emit('init')
storeInst.lifecycle('init')
storeInst.emitChange()
}
)
Expand All @@ -170,7 +169,7 @@ class Alt {

bootstrap(data) {
StateFunctions.setAppState(this, data, (storeInst) => {
storeInst[Sym.LIFECYCLE].emit('bootstrap')
storeInst.lifecycle('bootstrap')
storeInst.emitChange()
})
}
Expand Down
Loading

0 comments on commit 021fbc6

Please sign in to comment.