cakex
v1.0.0
Published
extended functionality for cake
Downloads
8
Readme
cakex
- extended functionality for cake
If you currently use CoffeeScript's cake
utility as a project builder, the cakex
package may be useful to you. It
provides a number of useful functions to make it even easier to script your
builds.
cakex
should be usable with other build tools as well.
using cakex
Add cakex
to your devDependencies
property of your package.json
file.
Once added, you can access cakex
from your Cakefile
with a simple
require invocation:
require "cakex"
globals that cakex
adds
cakex
adds a number of global functions to your running environment.
Adds all of the functions in the
shelljs
package as global functions. Eg, you can usels()
to get a list of files.Adds
fs
,path
, and_
as global variables, whose values arerequire("fs")
,require("path")
, andrequire("underscore")
.Adds the
cakex
exported functions. See below for more on these functionsAdds a function for every "script" in your
node_modules/.bin
directory. Any characters in those script names, which are not valid in JavaScript identifiers, will be converted to underscores, so you can reference them easily. Any script names that still aren't legal JavaScript identifiers will need to be accessed from theglobal
variable. Eg, access the script6to5
asglobal['6to5']
.The script functions are invocations of the
shelljs
functionexec()
with the arguments passed to the functions appended to the script name. For example, if you call:browserify "foo"
it will be invoked as:
exec("node node_modules/.bin/browserify foo")
You may also pass valid additional
exec()
arguments to the script functions. For example, if you call:browserify "foo", {silent: true}
it will be invoked as:
exec("node node_modules/.bin/browserify foo", {silent: true})
cakex
exported functions
The following functions are exported from the cakex
module, but also available
as globals.
log(string)
Writes a string to the console, prefixed by the name of the main program running. When called with no argument, prints a blank line.
watch({files: gazeSpec, run: fn})
The argument to this function should be an object with a files
property and
a run
property.
The files
property should be a gaze
pattern argument (string or array of strings).
The run
property is a function that will be called when a file matching
the files
patterns changes. The function will be called with this
set
to the argument of the watch()
function, and with a
single argument file name of the file that triggered the
watch.
The watch will not respond to any other file changes until after the run
function completes.
You can call watch()
multiple times. There is no way to cancel a watch,
so once you've called watch()
at least once, your cake
invocation will run
forever; or until you break out of it, or the Cakefile
calls exit()
(or
process.exit()
).
daemon.start(handle, program, args, options={})
This function starts a background process with the child_process.spawn()
function, ensuring only one instance of the program
will be running for each unique handle. The first argument should be a handle
to refer to this server, for later use with daemon.start()
or daemon.kill()
.
The remaining arguments are the same as for the child_process
function
spawn()
.
daemon.start()
will first call daemon.kill()
with the same handle
, to
ensure that an earlier invocation of the process is killed before the new
one starts.
daemon.kill(handle, cb)
This function will kill a background process started with daemon.start()
. If
a callback is passed, it will be invoked when the process has been killed (or
as near as we can guess).
defineModuleFunctions(dir)
This function will add scripts from a node_modules/.bin
directory as global
functions, just as is done with with the node_modules/.bin
in your current
directory by default. In fact, those globals are added by invoking
defineModuleFunctions(".")
when cakex
starts.
If you have other node_modules
directories that you'd like to add tools from,
you can do that with this function.
The argument to this function should be the directory that contains the relevant
node_modules
directory.
integration with npm start
To make life easier on your users, if you're using cake
as your build tool,
consider:
- adding
coffee-script
to yourdevDependencies
in yourpackage.json
- adding a
watch
andcake
script to thescripts
in yourpackage.json
- use
npm run watch
during development, which calls thewatch
script from yourpackage.json
, which presumably does acake watch
The reason for structuring things this way is that you won't be dependent on
a global install of the coffee-script
package; that's a terrible way to live!
Here's an examplefrom this package's package.json
"scripts": {
"cake": "cake",
"watch": "cake watch"
},
...
"devDependencies": {
"coffee-script": "1.9.x"
}
example Cakefile
Below is an example Cakefile
that uses cakex
. It defines 3 tasks:
watch
, build
, and serve
.
The watch
task will run the build
and serve
tasks, then start watching
source files for changes. When a source file changes, the build
and serve
tasks are run again. Because the serve
task uses daemon.start()
, the
existing server (if any) is first stopped, and then restarted, presumably
running the new code. So as you're saving files in your editor, and you
have cake watch
(or maybe npm run watch
) running in a terminal window,
you see the build run, and server recycle, and then start waiting for your
next save.
The build
task can be run stand-alone, if you just want to run a "build".
The server
task can also be run stand-alone, if you just want to run the
server.
In addition, if you make changes to the Cakefile
while cake watch
is
running, the cake
invocation will exit. The rationale is that you've changed
the Cakefile
, and so to pick up the changes, you'll need to start over.
# add this to the top of your Cakefile to cakex-ize it
require "cakex"
# I just always do this, often handy to get name, version, etc
pkg = require "./package.json"
#-------------------------------------------------------------------------------
task "watch", "watch for source changes, build, restart server", -> taskWatch()
task "build", "run a build", -> taskBuild()
task "serve", "run the server stand-alone", -> taskServe()
# globs of my source files, to feed to `watch()`
WatchSpec = "lib/**/* www/**/*"
#-------------------------------------------------------------------------------
# gotta have a tmp directory!
#-------------------------------------------------------------------------------
mkdir "-p", "tmp"
#-------------------------------------------------------------------------------
# this build doesn't do much, log a message; runs jshint
#-------------------------------------------------------------------------------
taskBuild = ->
log "linting ..."
jshint "lib/*.js"
#-------------------------------------------------------------------------------
# set up the things to watch, and what to do when the watches fire
#-------------------------------------------------------------------------------
taskWatch = ->
# run the build/serve/whatever steps when starting
watchIter()
# when a source file changes, run the build/serve/whatever steps
watch
files: WatchSpec.split " "
run: watchIter
# when this file changes, kill `cake`; for some reason the gaze lib ends
# up watching other things besides this file, with this spec, so do an extra
# check in the `run` function
watch
files: "Cakefile"
run: (file) ->
return unless file == "Cakefile"
log "Cakefile changed, exiting"
exit 0
#-------------------------------------------------------------------------------
# stuff to do when a source file changes; do a build, restart the server;
# handy to have it as a separate function so I can run it BEFORE watching
# as well
#-------------------------------------------------------------------------------
watchIter = ->
log "in #{path.relative "../..", __dirname}"
taskBuild()
taskServe()
#-------------------------------------------------------------------------------
# start the server; if it's already running, shut it down, restart it
#-------------------------------------------------------------------------------
taskServe = ->
log "restarting server at #{new Date()}"
daemon.start "test server", "node", ["server"]
#-------------------------------------------------------------------------------
# handy utility to clear out build output dirs before a build
#-------------------------------------------------------------------------------
cleanDir = (dir) ->
mkdir "-p", dir
rm "-rf", "#{dir}/*"
hacking
This project uses CoffeeScript's cake
as it's
build tool. To rebuild the project continuously, use the command:
npm run watch
Other cake
commands are available (assuming you are using npm v2) with
the command
npm run cake -- <command here>
Run npm run cake
to see the other commands available in the Cakefile
.
license
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.