lance v2.10.14
Lance
The alpha-strike web framework.
A framework with sane defaults, aiming to handle everything for you as automatically as possible.
API Stability: Semi-Unstable
Minimal API
new Lance( config )
lance.initailize()
What just happened:
- An HTTP server was started
- Compiled, minified, bundled and watched Stylus, CoffeeScript, CJSX, CSS, JS + Saved to the static directory
- Populated the static asset directory at
./static
+ Assets likeimg.png
,robots.txt
are copied over with their preserved directory structure. - Set up request routing
- Began serving static assets from
./static
- Began utlizing a templating engine in
./views
- Began parsing http requests; forms, file transfers
All parts of Lance can be utilized outside of the config. Lance always utilizes promises for async operations.
See the ./config - effectively an API reference.
The minimal example:
Lance = require 'lance'
lance = new Lance {
routes: [
[ "GET", '/:api(a|b|c|d)', (o) ->
console.log 'ayyy' if o.route.api is 'a'
o.serve { body: 'woo!' }
]
]
}
lance.initialize().then -> # Server is up!
The full example:
###
The directory structure:
/project/
/static/
/views/
index.jade
style.styl
app.coffee
/images/
image.png
server.coffee (this)
###
Lance = require 'lance'
lance = new Lance {
server:
host: '0.0.0.0'
port: 1337
static: './static' # Automatically intercepts and serves static content
templater:
findIn: './views'
saveTo: './static'
###
Bundle up all Stylus/Css or Coffee/Js dependencies into a single file
by utilizing Stylus and browserify.
###
bundle:
# destination : source
"my/css/here.css": "style.styl"
"app.js": "app.coffee"
templater:
ext: '.jade'
engine: require 'jade'
}
# Routes can be defined after instantiation, outside of the config, too
lance.router.get '/:api(a|b|c|d)', (o) ->
###
`o` is a special options object containing request information in a pre-parsed manner. `o` is passed to all route requests in place of `req` and `res`.
More info on this later.
###
if o.route.api is 'a'
console.log 'ayyy'
# This will resolve to our ./project/views/index.jade file
o.template.view = 'index'
###
o.serve() serves a response based on either arguements passed to it or depending on properties in `o`.
if `o.template.view` is set, the template will be rendered
if `o.redirect` is set, a redirection will occur
if neither are set, Lance serves JSON by default.
You may also instead call `o.serveTemplate()`, `o.serveHttpCode()`, `o.serveJson()`, `o.serveRedirect()` or a basic `o.respond()`
###
o.serve()
###
This will build the templates then start the server, all depending on the config.
###
lance.initialize().then ->
# we're ready
###
Alternitavely...
There is a choice between `lance.initialize()`, which initializes everything in order, and manually initializing aspects of lance for more control.
###
lance.templater.initialize().then ->
# The bundles have been compiled to:
# ./projectDirectory/static/style.css
# ./projectDirectory/static/app.js
# from the ./projectDirectory/views directory.
# and will be watched for changes (and any of their dependencies)
# then recompiled automatically
lance.start().then ->
# we're ready
###
The new directory structure:
/project/
/static/
/my/
/css/
here.css
app.js
/images/
image.png
/views/
index.jade
style.styl
app.coffee
/images/
image.png
server.coffee (this)
###
Requests
Requests from a http server normally use response
and request
parameters. Lance supplies an object as outlined below:
###
Assuming you visited:
GET http://yourdomain.com/b?test.a=1
###
lance.router.get '/:api(a|b|c|d)', 'aRouteName', (o) ->
# HTTP request object
o.req
# HTTP response object
o.res
# Response HTTP code
o.code is 200
# Response headers
o.headers is { 'content-type': 'text/html; charset=utf-8' }
# Fallback body to respond with if not template is used
o.body is ''
# Sent as JSON for JSON responses
o.json is {}
# Relative or absolute path to a template
o.template.view is ''
# Local variable for the template
o.template.data is {}
# Optional lance.Templater instance
o.template.templater is o.lance.templater
# Redirects to this as a path if set
o.redirect is ''
# Used as a GET response query if redirecting
o.redirectQuery is {}
# Parsed query, whether it be GET, POST etc.
o.query is {
test: {
a: '1'
}
}
# Any files
o.files is {
# Example file
'exampleFile': {
field : 'exampleFile'
filename : 'file.txt'
encoding : 'utf8'
mimetype : 'text/plain'
ext : 'txt'
# Temporary file path, saved to the OS's temp directory
# Will be auto deleted after a timer
file : tempFilePath
# Call this to delete the temporary file
delete : [Function]
truncated : false
}
}
o.method is 'GET'
o.route is {
path : { api: 'b' }
splats : []
name : 'aRouteName'
callback : [ThisFunction]
pattern : '/:api(a|b|c|d)'
regex : /./ # Final regex from pattern
}
o.path is o.route.path
o.splats is o.route.splats
o.cookies is new require('cookies')( o.req, o.res )
# These properties above are also passed into a template, accessable under the "o" property
template = { view: './someTemplate', data: { woo: 1 } }
template is o.template
o.serve template
o.serve()
###
When `o.serve` is called without parameters it will execute this logic:
if o.redirect
o.serveRedirect( o.redirect, o.redirectQuery )
else
if o.template.view
o.serveTemplate()
else
o.serveJson()
###
Templating
You can specify your own templater middleware. If none are specified, then Lance will default to checking whether ect
is installed and will use that.
# Uses Jade
new Lance {
templater:
templater:
ext: '.jade'
engine: require 'jade'
options: {} # Supplied to the engine on instantiation
}
# Uses ECT.js if `ect` is installed
new Lance {
templater:
templater: {}
}
Optional modules
For these features to become avaliable, simply make sure they're installed.
browserify
for bundling coffee/js +coffee-reactify
for embedding JSX into Coffee +coffeeify
only normal coffeescriptect
fallback templaterstylus
coffee-script
uglify-js
for js compressionlactate
for static file serving
Stylus
Stylus is compulsary if you're going to bundle css assets; because Stylus can exist as pure css with the benefit of the @require()
and @import
bundling syntax. Any plain CSS file is concatenated, it is not resolved to an @import
.
Static assets
Lance handles these mostly automatically:
- CSS and Stylus
- CoffeeScript, CJSX and Javascript
- Static assets such as images, json, robots.txt etc.
On initialization:
- Bundles are rendered to the static directory
- Bundles are watched for changes, then rerendered
- Assets files are copied over to the static directory
- Assets files are watched for changes, then resaved
- Directories are watched for new directories and files
By default all static assets that match the regexp (found in the config's templater.assets.match
) will be copied over to the static directory.
- For some filetypes, such as images, this means they can also be optimized. + TODO: Impliment asset stream hooking
new Lance {
templater:
findIn: './views'
saveTo: './static'
###
true by default, this causes `assets` to keep their directory structure inside the saveTo folder.
###
preserveDirectory: true
bundle:
# destination : source
"style.css" : "style.styl"
"app.js" : "app.coffee"
}
The result is that the static directory will always have only what you want to make public, in one place, with a directory structure that will mirror your views.
Tests
Cloned via the github repo, tests are manual in nature at the moment. Due to the complexity of a web server, they consist of scenarios for which must be manually tested and interacted with in the browser, currently.
All dependencies have unit tests.
Upgrading from 1.x.x
- Replacements
+
clone.merge.hard
toclone
+clone.merge
toclone
+slugify
toformat.slugify
- Removals
+
toArray
+helpers.promisify
helpers.*
__
/ /___ _____ ________
/ / __ `/ __ \/ ___/ _ \
/ / /_/ / / / / /__/ __/
/_/\__/_/_/ /_/\___/\___/
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago