From 6239df4c43fde2d59c877e679045af149f3e4b4c Mon Sep 17 00:00:00 2001 From: Eric Martindale Date: Mon, 26 Jan 2015 23:48:25 -0500 Subject: [PATCH] Add further documentation. --- docs/index.md | 26 +++++++++++ docs/resources.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/docs/index.md b/docs/index.md index f41256dc..8c2648ab 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,12 @@ ## Welcome to Maki. +### Architecture +Maki's architecture is Resource-centric. All aspects of the datastore, its query pipeline, the business logic, and view layer are derived from the definition of the Resources your application exposes. + +![Maki Architecture Overview](public/img/maki-architecture.png?raw=true) + +TODO: explanation here. + ### [Resources](/resources) Resources are the heart and soul of Maki, which exists solely to provide a reasonable framework for automation surrounding their definition, as they apply @@ -9,3 +16,22 @@ to your application. Resources are exposed by Maki in the form of Services. A prime example of a Service would be the `http` service, which provides Resources to web clients in the form of JSON or even HTML. + +### Default Directory Structure +Maki is meant to be understood without context or documentation, and as such the directory structure [and the code itself, for that matter] _should_ be fairly self-explanatory. Nevertheless, here's an explicit declaration for each of the default folders and their intended use. +```bash +. +├── config # configuration files (generally overridden by environment variables) +├── data # data files for use in various places. +├── lib # various classes / prototypes +├── locales # strings for translations +├── private # resources not exposed to the client (LESS, etc.). This is a 1:1 map of the public folder +│   └── css # contains the LESS files used to generate the **public** CSS files (currently, autogenerated using asset-rack) +├── public # resources exposed to the client (images, CSS, etc) +│   ├── css # CSS +│   ├── fonts # Fonts (.woff, etc.) +│   ├── img # Images +│   └── js # JavaScript +├── tests # Tests. Write them. +└── views # composable elements for rendering HTML, JSON, or XML +``` diff --git a/docs/resources.md b/docs/resources.md index 4b858e30..eb672c30 100644 --- a/docs/resources.md +++ b/docs/resources.md @@ -72,6 +72,113 @@ The default datastore for these uploads is the datastore – in the current version of Maki (0.2.0 as of time of writing), this is a GridFS filestore that **never touches disk**. +### Methods +All Maki Resources expose exactly five (5) methods: + +- **query** to select a list of documents, +- **get** to get a single instance of a document by its identifier (ID), +- **create** to create a new instance of a document, +- **update** to change properties of a document, and +- **destroy** to remove a document. + +These methods can be used to construct any more complex behavior, such as when +multiple Resources might need to be involved. The ideal place for these types +of behaviors is in the Pipeline. + +### Pipeline +The Methods exposed by Maki Resource are subject to a pipeline of "transformer" +functions, which can be used to perform authorization, transformation, or any +other number of things. Pipeline functions can be of two types; `pre` or +`post`. + +```javascript +var Person = maki.define('Person', { + attributes: { name: String } +}); + +Person.pre('create', function(done) { + var person = this; + + // trim any whitespace from the individual's name. + person.name = person.name.trim(); + + done(); +}); + +Person.post('create', function(done) { + var person = this; + // create some sort of entry somewhere... + Activity.create({ ref: person._id } , done ); +}); + +``` + +### Events +All Maki Resources also emit events when certain operations take place – and +they even describe the specifics of those operations in an atomic fashion. + +```javascript +var Person = maki.define('Person', { + attributes: { name: String } +}); + +Person.on('create', function( data ) { + console.log('A Person was created!', data ); +}); +``` + +#### PubSub +When using the HTTP service (enabled by default), a pub/sub architecture is +exposed via the WebSocket protocol. This is, by default, **completely +routable:** + +**Server** +```javascript +var Person = maki.define('Person', { + attributes: { name: String } +}); +``` +**Client** +```javascript +var ws = new WebSocket('ws://example.com/people'); +ws.onmessage = function( data ) { + console.log('new event received!', data ); +}; +``` + +These WebSockets speak JSON-RPC, and specifically expose these methods: +- `ping`, which should be responded to with a "pong" result. +- `patch`, which provides an array of operations to execute on a resource (via + [the JSON-PATCH specification][json patch]) +- `subscribe` will expect a `channel` parameter that matches the "collection" +name of the expected resource (see below). +- `unsubscribe` is the inverse of `subscribe`, as you've surely gathered. + + +##### Multiplexing +WebSockets are not limited to a single resource – you can submit a `subscribe` +(or an `unsubscribe`) RPC call to add additional subscriptions to an existing +connection: + +```javascript +var ws = new WebSocket('ws://localhost:9200/people'); +ws.on('open', function() { + + var JSONRPCEvent = { + jsonrpc: '2.0', + method: 'subscribe', + data: { + channel: '/examples' + } + }; + + ws.send( JSON.stringify( JSONRPCEvent ) ); +}); +``` + +The `ws` connection will now receive updates to both the `Example` and the +`People` Resources. + ### Sources Resources can automatically be collected from outside sources, including local files and even remote HTTP services. This is useful for querying APIs, or @@ -90,6 +197,9 @@ then collect the data and cache it locally. Currently, this is done _one time_, at Maki startup. The data is never again queried, and the in-memory version is kept until the worker restarts. +**Important:** Resources currently bypass any middleware. Do not expect hooks +to work on static content. + #### Mappers Sourced data can have a transformation function, or a `mapper`, applied to it at runtime: @@ -128,3 +238,4 @@ maki.define('Release', { will likely include the ability to pass a function in this field. [procure]: https://www.npmjs.com/package/procure +[json patch]: https://tools.ietf.org/html/rfc6902