Skip to content

Instantly share code, notes, and snippets.

@agonbina
Last active August 29, 2015 14:17
Show Gist options
  • Save agonbina/21e7bdef2e2d3a0a8ded to your computer and use it in GitHub Desktop.
Save agonbina/21e7bdef2e2d3a0a8ded to your computer and use it in GitHub Desktop.
1aim framework
# Framework
A constructor that will hold the global state of an application.
```js
function Framework(options) {
this.version = options.v || 'v1'
}
```
The following sections describe the concepts we can bundle in the Framework.
### SESSION
A session holds the authenticated user data which is used in other parts of the Framework. For example **Events** will use the session to identify each stored event with it.
If we choose to save the messages they will also be related to the current session.
Every **Action** and **Sequence** is also tied in to a session(This also enables us to remotely run commands on behalf of the user, in this specific session).
```js
Framework.session(function(user) {
// Do something with user
})
```
### DATA
----------
There is the concept of a Model and a Collection(similar to Backbone.js). They will deal with validating data(based on type, ex. String or other properties), serializing and deserializing from and to JSON.
```js
// Construct a new instance of a Model
Framework.Model = function() {}
// A list of Models
Framework.Collection = function() {}
```
Models
: create
: read
: update
: delete
Example:
```js
var User = new Framework.Model({
name: { type: String },
email: { type: String, required: true },
age: { type: Number, required: true }
}).relationships({
one: [ 'key' ],
many: [ 'bookings' ]
})
```
##### Choosing a communication transport
This will define how the requests will be performed, ex. via websockets or http. The Model will then route the request accordingly when we call methods like .update, .read etc
```js
user.transport('http') // or
user.transport('ws')
```
##### Creating instances of a Model definition
```js
var user = new User({
name: 'Agon',
email: 'agon_bina@hotmail.com',
age: 24
})
// Manipulating relationships
user.bookings().get().then(function(bookings) {
console.log('Bookings for user id %d', user.id)
console.log(bookings) // [{ id: 1 ...}, { id: 2 ... }]
})
user.key().get().then(...)
```
In Vue.js you might be able to do something like this:
```js
var app = new Vue({
queries: function($resource) {
var user = Users.get().query({ id: 5 })
return [ user, ]
}
})
// This will automatically fetch the user when the app view model is attached to the DOM and assign it to app.user
```
### ACTIONS
----------
Actions run javascript logic that's not coupled to any 3d party library or framework. These libraries can have their own plugins(or mixins in the case of Vue.js) that understand how actions are executed.
##### Defining an action
```js
var createUser = Action({
// Action will not run if this data is invalid(useful when running remote commands?)
data: {
name: { type: String },
email: { type: String, required: true }
},
setup: function() {
// Check if we have a user with this email already?
},
run: function() {
var data = {
name: this.name,
email: this.email
}
User.create(data)
},
revert: function() {
User.delete(...)
}
})
```
##### Actions have a state
```js
createUser.state({ username: 'agonbina', ranAt: new Date() })
```
##### Register an action
Registering an action with the framework will make it available to run remotely.
```js
Framework.action('create:user', createUser)
```
##### Run an action
Calling .run:
```js
createUser.run({ name: 'Agon', email: 'agon_bina@hotmail.com' })
```
Via the Framework:
```js
Framework
.run('create:user', { ...data... })
.then(...success callback...)
.fail(...failure callback...)
```
### SEQUENCES
A sequence is a collection of actions which can run one after another. The sequence can be reverted if one of the actions fails.
##### Defining a sequence
```js
var bookRoom = Sequence([ createUser, makeSandwich, orderBeer ])
bookRoom
.on('error', function(err) {
console.log('Something went wrong: %s', err.message)
console.log('Reverting back ... ')
bookRoom.revert()
})
.on('complete', function() {
console.log('All actions completed')
})
.run()
```
##### Register a sequence
```js
Framework.sequence('user:book_room', bookRoom)
```
#### Example mixin for Vue.js
```js
var app = new Vue({
actions: [ 'create:user' ],
sequences: [ 'user:book_room' ]
})
app.$action('create:user').run({ name: 'Agon', email: '...' })
app.$sequence('user:book_room').run()
```
### EVENTS
----------
The event store will collect snapshots on specific actions or a sequence and send them to the backend to be persisted. All events are attached to a session.
##### Initializing a session
To initialize a session for this specific user you can do this:
```js
Framework.session(function(user) {
user.track('action', data)
user.track('sequence', [])
user.track('event', {
error: 'book.room crashed unexpectedly',
time: new Date().toISOString(),
state: {}
})
})
```
##### Connecting remotely
To enable remote connections to a session and run actions on behalf of the user you can do this:
```js
Framework.session({ remote: true }, function(user) {
// And then listen when these actions are run
user.on('action', command)
user.on('sequence', [ commandOne, commandTwo])
})
```
### COMMUNICATION
A high level API of postal.js so that we're not completely tied in to it. Initially it will just proxy calls to postal.js but should be possible to extend or add new implementations on top of it.
```js
var orders = Framework.channel('orders')
orders.subscribe('created', function(data) {
console.log('New order: %d', data.id)
})
```
Ex. Store the messages if we need to, using websockets or plain HTTP requests.
```js
orders.transport('http')
// Every message makes a request to be saved on the backend
POST /api/messages/{channel}/{topic} { "sessionId": "123", ... }
```
Now you can look up all messages related to a user by a "sessionId".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment