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 like
img.png
,robots.txt
are copied over with their preserved directory structure.
- Assets like
- 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 = routes: "GET"'/:api(a|b|c|d)' consolelog 'ayyy' if orouteapi is 'a' oserve body: 'woo!' lanceinitializethen -> # 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 = 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 lancerouterget '/:api(a|b|c|d)' ### `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 orouteapi is 'a' consolelog '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()` ### oserve ###This will build the templates then start the server, all depending on the config. ###lanceinitializethen -> # 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.### lancetemplaterinitializethen -> # 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 lancestartthen -> # 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###lancerouterget '/:api(a|b|c|d)''aRouteName' # HTTP request object oreq # HTTP response object ores # Response HTTP code ocode is 200 # Response headers oheaders is 'content-type': 'text/html; charset=utf-8' # Fallback body to respond with if not template is used obody is '' # Sent as JSON for JSON responses ojson is # Relative or absolute path to a template otemplateview is '' # Local variable for the template otemplatedata is # Optional lance.Templater instance otemplatetemplater is olancetemplater # Redirects to this as a path if set oredirect is '' # Used as a GET response query if redirecting oredirectQuery is # Parsed query, whether it be GET, POST etc. oquery is test: a: '1' # Any files ofiles 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 omethod is 'GET' oroute is path : api: 'b' splats : name : 'aRouteName' callback : ThisFunction pattern : '/:api(a|b|c|d)' regex : /./ # Final regex from pattern opath is oroutepath osplats is oroutesplats ocookies is 'cookies' oreqores # These properties above are also passed into a template, accessable under the "o" property template = view: './someTemplate'data: woo: 1 template is otemplate oserve template oserve ### 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 templater: templater: ext: '.jade' engine: require 'jade' options: # Supplied to the engine on instantiation # Uses ECT.js if `ect` is installed templater: templater:
Optional modules
For these features to become avaliable, simply make sure they're installed.
browserify
for bundling coffee/jscoffee-reactify
for embedding JSX into Coffeecoffeeify
only normal coffeescript
ect
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
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.*
__
/ /___ _____ ________
/ / __ `/ __ \/ ___/ _ \
/ / /_/ / / / / /__/ __/
/_/\__/_/_/ /_/\___/\___/