{"action":"created","issue":{"url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/17","repository_url":"https://api.github.com/repos/vstirbu/fsm-as-promised","labels_url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/17/labels{/name}","comments_url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/17/comments","events_url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/17/events","html_url":"https://github.com/vstirbu/fsm-as-promised/pull/17","id":141208530,"number":17,"title":"allow \"instance\"-style usage","user":{"login":"boneskull","id":924465,"avatar_url":"https://avatars.githubusercontent.com/u/924465?v=3","gravatar_id":"","url":"https://api.github.com/users/boneskull","html_url":"https://github.com/boneskull","followers_url":"https://api.github.com/users/boneskull/followers","following_url":"https://api.github.com/users/boneskull/following{/other_user}","gists_url":"https://api.github.com/users/boneskull/gists{/gist_id}","starred_url":"https://api.github.com/users/boneskull/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boneskull/subscriptions","organizations_url":"https://api.github.com/users/boneskull/orgs","repos_url":"https://api.github.com/users/boneskull/repos","events_url":"https://api.github.com/users/boneskull/events{/privacy}","received_events_url":"https://api.github.com/users/boneskull/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2016-03-16T08:45:55Z","updated_at":"2016-03-22T17:17:47Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/vstirbu/fsm-as-promised/pulls/17","html_url":"https://github.com/vstirbu/fsm-as-promised/pull/17","diff_url":"https://github.com/vstirbu/fsm-as-promised/pull/17.diff","patch_url":"https://github.com/vstirbu/fsm-as-promised/pull/17.patch"},"body":"This needs tests, obviously, but it brings fsm-as-promised more inline with how these composable factories are intended to be used.  PR #15 was simply a refactor; almost no actual API changes were involved.\r\n\r\nWhenever you call a \"stamp\" (a composable factory function) created by Stampit, the first parameter is always going to be an object.  The object returned is, by default, *not* the object you pass as the parameter.  However, the object you pass (henceforth known as an \"instance\") is *mixed in* (via `Object.assign()`, `_.assign()`, etc) to the resulting object, e.g.:\r\n\r\n```js\r\nconst MyStamp = stampit({\r\n  methods: {\r\n    foo () {\r\n      return this.bar;\r\n    }\r\n  }\r\n});\r\n\r\nconst myObj = MyStamp({bar: 'baz'});\r\nmyObj.foo() // baz\r\n```\r\n\r\nfsm-as-promised's API allows mixing in of an instance via the *second* parameter; the first, of course, being simply the configuration.\r\n\r\nWith these changes, we can now compose freely with `fsm-as-promised`.  Before this change, the following would not work as expected:\r\n\r\n```js\r\nconst myObj = StateMachine({\r\n  foo: 'bar',\r\n  events: {}, \r\n  callbacks: {}, \r\n  initial: 'start'});\r\n\r\nmyObj.foo // undefined\r\n```\r\n\r\nAbove, the first parameter is used for configuration, then thrown away.  To get this behavior, you'd need to do:\r\n\r\n```js\r\nconst myObj = StateMachine({\r\n  events: {}, \r\n  callbacks: {}, \r\n  initial: 'start'}, \r\n  {\r\n    foo: 'bar'\r\n  });\r\n\r\nmyObj.foo // 'bar'\r\n```\r\n\r\nNow, the above is *still supported*, but the problem with this is that if you ever wanted to compose *from* `StateMachine`, you're in for pain, because *the first parameter is thrown away*.\r\n\r\n```js\r\nconst MyStamp = stampit({\r\n  methods: {\r\n    foo () {\r\n      return this.bar;\r\n    }\r\n  }\r\n}).compose(StateMachine);\r\n\r\nconst myObj = MyStamp({\r\n  events: {}, \r\n  callbacks: {}, \r\n  initial: 'start'\r\n});\r\n\r\nmyObj.foo() // TypeError: myObj.foo is not a function\r\n```\r\n\r\nOops.  Anyway, the old behavior *is still supported* with some trickery--and it will now \"mix in\" an EventEmitter into the second parameter (`target`) if it has no `emit` function--but now this works as expected:\r\n\r\n```js\r\nconst myObj = StateMachine({\r\n  foo: 'bar',\r\n  events: {}, \r\n  callbacks: {}, \r\n  initial: 'start'});\r\n\r\nmyObj.foo // 'bar'\r\n```\r\n\r\nThis is accomplished by providing a second factory function (`Target`) which creates an instance of `StateMachine` internally, which sets everything up.  `StateMachine` then exposes a `mixin` object for the `Target` to mix into itself via `_.assign()`.\r\n\r\nOf note, when you write:\r\n\r\n```js\r\nvar StateMachine = require('fsm-as-promised');\r\n```\r\n\r\nyou are now no longer using the `StateMachine` factory; you're actually getting `Target`.  For hacking's sake, to get the *actual* `StateMachine` factory, you'd do this:\r\n\r\n```js\r\nvar StateMachine = require('fsm-as-promised').StateMachine;\r\n```\r\n\r\nThis change should be transparent to the user, unless they are vehemently opposed to having an `EventEmitter` mixed in to their target object (second parameter, as per the old API).\r\n\r\n`EventEmittable` is a composable factory function (a \"stamp\") wrapping `EventEmitter`.  To use it, simply call `.compose(EventEmittable)` upon any stamp."},"comment":{"url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/comments/199914013","html_url":"https://github.com/vstirbu/fsm-as-promised/pull/17#issuecomment-199914013","issue_url":"https://api.github.com/repos/vstirbu/fsm-as-promised/issues/17","id":199914013,"user":{"login":"boneskull","id":924465,"avatar_url":"https://avatars.githubusercontent.com/u/924465?v=3","gravatar_id":"","url":"https://api.github.com/users/boneskull","html_url":"https://github.com/boneskull","followers_url":"https://api.github.com/users/boneskull/followers","following_url":"https://api.github.com/users/boneskull/following{/other_user}","gists_url":"https://api.github.com/users/boneskull/gists{/gist_id}","starred_url":"https://api.github.com/users/boneskull/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boneskull/subscriptions","organizations_url":"https://api.github.com/users/boneskull/orgs","repos_url":"https://api.github.com/users/boneskull/repos","events_url":"https://api.github.com/users/boneskull/events{/privacy}","received_events_url":"https://api.github.com/users/boneskull/received_events","type":"User","site_admin":false},"created_at":"2016-03-22T17:17:47Z","updated_at":"2016-03-22T17:17:47Z","body":"Sounds great.  I'll modify this accordingly with the proposed API."}}