A light weight set of handy tools for real world program.
Reduce the gap between different systems. Such as watch directory changes on a network file system, operate spawn
on Windows and Linux, handle async IO api with promise, etc.
Rather than help you decide what to do, it is designed to create possibilities. Even this document is generated by nokit itself.
It's one of the core lib of nobone.
- All async functions will return promise.
- All functions are highly lazy designed, minimum boot time.
- Test on Node 0.8 - 0.12 on Mac, Linux and Windows.
- Light weight and self-reference.
As a lib dependency, install it locally: npm i nokit
.
Nokit has provided a cli tool like GNU Make. If you install it globally like this:
npm -g i nokit
, then have fun with your nofile
, it can be js, coffee or livescript. For more information goto the CLI
section.
Here it will automatically lint, compile, compress and cache files by their extensions. You can goto Drives section to see what extensions are supported, or write your own.
kit = require 'nokit'
drives = kit.require 'drives'
kit.warp 'src/**/*.@(jade|less|coffee|ls)'
# # To disable cache.
# .load drives.reader isCache: false
.load drives.auto 'lint'
.load drives.auto 'compile', '.coffee': { bare: false }
.load drives.auto 'compress'
.load concat 'main.js'
.run 'dist/path'
Nokit has already provided some handy example drives, you can check them in the Drives section. It's fairly easy to write your own.
kit = require 'nokit'
coffee = require 'coffee-script'
# A drive for coffee, a simple curried function.
compiler = (opts) -> ->
# Change extension from '.coffee' to '.js'.
@dest.ext = '.js'
@set coffee.compile(@contents, opts)
# A drive to prepend lisence to each file.
# Here "fileInfo.set" is the same with the "@set".
lisencer = (lisence) -> (fileInfo) ->
@set lisence + '\n' + @contents
# A drive to concat all files. It will override the default writer.
concat = (outputFile) ->
all = ''
# Object.assign
kit._.assign ->
all += @contents
, isWriter: true, onEnd: ->
# This will enable the auto-cache.
@deps = kit._.pluck @list, 'path'
@dest = @to + '/' + outputFile
@set all
# Call the overrided writer.
# Call two times and create two output files.
@super().then =>
@dest = @dest + '.info'
@set = '/* info */\n' + all
@super()
kit.warp 'src/**/*.coffee'
.load compiler bare: true
.load lisencer '/* MIT lisence */'
.load concat 'bundle.js'
.run 'dist'
.then ->
kit.log 'Build Done'
By default nokit only supports js, if you want nokit to support coffee, you should install nokit like this:
npm i -g nokit coffee-cache coffee-script
It's recommended to use coffee-cache, since large build project may consume a large portion of your nofile's startup time. Of course, it's optional, you may run
npm i -g nokit coffee-script
without any problem.
Same works with livescript:
npm i -g nokit LiveScript
Remarks: for the sake of boot performance, nokit will only load
coffee-cache coffee-script/register
by default. For livescript or other precompiler, you have to set environment varialbenokitPreload
to what you want, such as on unix:export nokitPreload='LiveScript coffee-script/register'
. Different module names are separated by spaces.
Create a nofile.coffee
(or .js
, .ls
) at your current working directory
or any of its parents directory. The syntax of nofile
is almost the same as the Cakefile, only the option
's first argument is slightly changed.
Assume your file content is:
module.exports = (task, option) ->
kit = require 'nokit'
option '-w, --hello [world]', 'Just a test option', ''
# Define a default task, and it depends on the "clean" task.
task 'default', ['clean'], 'This is a comment info', (opts) ->
kit.log opts.hello
# Use colors.
kit.require 'colors'
kit.log 'print red words'.red
task 'clean', ->
kit.remove 'dist'
# To add alias to a task, just use space to separate names.
# Here 'build' and 'b' are the same task.
task 'build b', ->
kit.require 'drives'
kit.warp 'src/**/*.js'
.load kit.drives.auto 'compile'
.run 'dist'
task 'sequential', ['clean', 'build'], true, ->
kit.log 'Run clean and build non-concurrently.'
Then you can run it in command line: no
. Just that simple, without task
name, no
will try to call the default
task directly.
You can run no -h
to display help info.
Call no build
or no b
to run the build
task.
For real world example, just see the nofile that nokit is using.
For more doc for the option
goto commander.js.
Goto changelog
-
Nokit extends all the functions of nofs. You can use it as same as nofs. For more info, see the doc:
-
example:
kit.readFile('test.txt', 'utf8').then (str) -> console.log str kit.outputFile 'a.txt', 'test' .then -> kit.log 'done' kit.writeJSON 'b.json', { a: 10 } .then -> kit.log 'done' kit.mkdirs 'b.json', { a: 10 } .then -> kit.log 'done'
-
-
The lodash lib.
-
type: { Object }
-
example:
kit._.map [1, 2, 3]
-
-
An throttled version of
Promise.all
, it runs all the tasks under a concurrent limitation. To run tasks sequentially, usekit.flow
.-
param:
limit
{ Int }The max task to run at a time. It's optional. Default is Infinity.
-
param:
list
{ Array | Function }If the list is an array, it should be a list of functions or promises, and each function will return a promise. If the list is a function, it should be a iterator that returns a promise, when it returns
kit.async.end
, the iteration ends. -
param:
saveResults
{ Boolean }Whether to save each promise's result or not. Default is true.
-
param:
progress
{ Function }If a task ends, the resolve value will be passed to this function.
-
return: { Promise }
-
example:
urls = [ 'http://a.com' 'http://b.com' 'http://c.com' 'http://d.com' ] tasks = [ -> kit.request url[0] -> kit.request url[1] -> kit.request url[2] -> kit.request url[3] ] kit.async(tasks).then -> kit.log 'all done!' kit.async(2, tasks).then -> kit.log 'max concurrent limit is 2' kit.async 3, -> url = urls.pop() if url kit.request url else kit.async.end .then -> kit.log 'all done!'
-
-
The browser helper.
-
static:
-
param:
opts
{ Object }The options of the client, defaults:
{ autoReload: kit.isDevelopment() host: '' # The host of the event source. }
-
param:
useJs
{ Boolean }By default use html. Default is false.
-
return: { String }
The code of client helper.
-
example:
When the client code is loaded on the browser, you can use the
nb.log
to log anything to server's terminal. The server will auto-format and log the information to the terminal. It's convinient for mobile development when remote debug is not possible.# The nb is assigned to the "window" object. nb.log { a: 10 } nb.log 10
-
-
The colors lib makes it easier to print colorful info in CLI. You must
kit.require 'colors'
before using it. Sometimes usekit.require 'colors/safe'
will be better.-
type: { Object }
-
example:
cs = kit.require 'colors/safe' kit.log cs.red 'error info'
-
-
A fast file cache helper. It uses hard link to cache files.
-
param:
info
{ Object }Not optional.
{ # The first item is the key path, others are # its dependencies. deps: Array # The path of the output file. # If it's undefined, depsCache will try to get cache. dests: Array cacheDir: '.nokit' }
-
return: { Promise }
Resolve a info object.
{ isNewer: Boolean # { path: mtime } deps: Object # { destPath: cachePath } dests: Object cacheError: undefined | Error }
-
example:
# Set cache kit.depsCache { dests: ['index.css'] deps: ['index.less', 'b.less', 'c.less'] } # Get cache # You don't have to sepecify 'b.less', 'c.less'. kit.depsCache { deps: ['index.less'] } .then (cache) -> if cache.isNewer kit.log 'cache is newer'. kit.log cache.dests
-
-
Daemonize a program. Just a shortcut usage of
kit.spawn
.-
param:
opts
{ Object }Defaults:
{ bin: 'node' args: ['app.js'] stdout: 'stdout.log' # Can also be a fd stderr: 'stderr.log' # Can also be a fd }
-
return: { Porcess }
The daemonized process.
-
-
A simple decrypt helper. Cross-version of node.
-
param:
data
{ Any } -
param:
password
{ String | Buffer } -
param:
algorithm
{ String }Default is 'aes128'.
-
return: { Buffer }
-
-
The warp drives. You must
kit.require 'drives'
before using it. For more information goto theDrives
section.- type: { Object }
-
A simple encrypt helper. Cross-version of node.
-
param:
data
{ Any } -
param:
password
{ String | Buffer } -
param:
algorithm
{ String }Default is 'aes128'.
-
return: { Buffer }
-
-
A error log shortcut for
kit.log(msg, 'error', opts)
-
param:
msg
{ Any } -
param:
opts
{ Object }
-
-
A better
child_process.exec
. Supports multi-line shell script. For supporting old version of node, it will create 3 temp files, the temp files will be removed after the execution.-
param:
cmd
{ String }Shell commands.
-
param:
shell
{ String }Shell name. Such as
bash
,zsh
. Optinal. -
return: { Promise }
Resolves when the process's stdio is drained. The resolve value is like:
{ code: 0 signal: null stdout: 'hello world' stderr: '' }
-
example:
kit.exec(""" a='hello world' echo $a """).then ({code, stdout}) -> kit.log code # output => 0 kit.log stdout # output => "hello world" # Bash doesn't support "**" recusive match pattern. p = kit.exec """ echo **/*.css """, 'zsh' # Get the child process object. p.process.then (proc) -> kit.log proc.pid
-
-
Creates a function that is the composition of the provided functions. Besides, it can also accept async function that returns promise. See
kit.async
, if you need concurrent support.-
param:
fns
{ Function | Array }Functions that return promise or any value. And the array can also contains promises or values other than function. If there's only one argument and it's a function, it will treat as an iterator, when it returns
kit.flow.end
, the iteration ends. -
return: { Function }
(val) -> Promise
A function that will return a promise. -
example:
# It helps to decouple sequential pipeline code logic. createUrl = (name) -> return "http://test.com/" + name curl = (url) -> kit.request(url).then (body) -> kit.log 'get' body save = (str) -> kit.outputFile('a.txt', str).then -> kit.log 'saved' download = kit.flow createUrl, curl, save # same as "download = kit.flow [createUrl, curl, save]" download 'home'
-
example:
Walk through first link of each page.
list = [] iter = (url) -> return kit.flow.end if not url kit.request url .then (body) -> list.push body m = body.match /href="(.+?)"/ m[0] if m walker = kit.flow iter walker 'test.com'
-
-
Format the parsed comments array to a markdown string.
-
param:
comments
{ Array } -
param:
opts
{ Object }Defaults:
{ indent: 0 name: ({ name }) -> name = name.replace 'self.', '' "- \#\#\#\# #{name}\n\n" tag: ({ tagName, name, type }) -> tname = if name then " `#{name}`" else '' ttype = if type then " { _#{type}_ }" else '' "- **<u>#{tagName}</u>**:#{tname}#{ttype}" }
-
return: { String }
-
-
See my project nofs.
-
Fuzzy search a string list by a key word.
-
param:
keys
{ String }The key word.
-
param:
list
{ Array }The list of string to search.
-
param:
opts
{ Object }Defaults:
{ result: (wrappedList) -> wrappedList.min('distance').words threshold: (cOffset, keyLen, cIndex) -> Infinity notFound: (cOffset, keyLen, cIndex) -> Infinity span: (cOffset, keyLen, cIndex) -> cOffset found: (cOffset, keyLen, cIndex) -> (Math.exp(cOffset + 1) - 1) * (keyLen - cIndex) tail: (cOffset, keyLen, cIndex, tailLen) -> tailLen }
-
return: { String }
The best matched one. If not found, return undefined.
-
example:
kit.fuzzySearch 'hw', ['test', 'hello world', 'hey world'] # output => 'hey world' # To get a sortable weighted list. kit.fuzzySearch 'hw', ['test', 'hello world', 'hey world'], { result: (wrappedList) -> wrappedList.value() } # output => [ # { distance: Infinity } # { words: 'hello world', distance: 1110.069 } # { words: 'hey world', distance: 159.849 } # ]
-
-
Generate a list of module paths from a name and a directory.
-
param:
moduleName
{ String }The module name.
-
param:
dir
{ String }The root path. Default is current working dir.
-
param:
modDir
{ String }Default is 'node_modules'.
-
return: { Array }
Paths
-
example:
# Suppose current working directory is '/home/a' kit.genModulePaths 'test' # output => ['/home/a/node_modules/test', '/home/node_modules/test', '/node_modules/test']
-
-
Indent a text block.
-
param:
text
{ String } -
param:
num
{ Int } -
param:
char
{ String } -
param:
reg
{ RegExp }Default is
/^/mg
. -
return: { String }
The indented text block.
-
example:
# Increase kit.indent "one\ntwo", 2 # => " one\n two" # Decrease kit.indent "--one\n--two", 0, '', /^--/mg # => "one\ntwo"
-
-
Nokit use it to check the running mode of the app. Overwrite it if you want to control the check logic. By default it returns the
rocess.env.NODE_ENV == 'development'
.- return: { Boolean }
-
Nokit use it to check the running mode of the app. Overwrite it if you want to control the check logic. By default it returns the
rocess.env.NODE_ENV == 'production'
.- return: { Boolean }
-
A fast helper to hash string or binary file. See my jhash project. You must
kit.require 'jhash'
before using it.-
example:
kit.require 'jhash' kit.jhash.hash 'test' # output => '349o' jhash.hash kit.readFileSync('a.jpg') # Control the hash char set. kit.jhash.setSymbols 'abcdef' kit.jhash.hash 'test' # output => 'decfddfe' # Control the max length of the result hash value. Unit is bit. jhash.setMaskLen 10 jhash.hash 'test' # output => 'ede'
-
-
A better log for debugging, it uses the
kit.xinspect
to log.Use terminal command like
logReg='pattern' node app.js
to filter the log info.Use
logTrace='on' node app.js
to force each log end with a stack trace.-
param:
msg
{ Any }Your log message.
-
param:
action
{ String }'log', 'error', 'warn'.
-
param:
opts
{ Object }Default is same with
kit.xinspect
, but with some extra options:{ isShowTime: true logReg: process.env.logReg and new RegExp process.env.logReg logTrace: process.env.logTrace == 'on' }
-
example:
kit.log 'test' # => '[2015-02-07 08:31:49] test' kit.log 'test', { isShowTime: false } # => 'test' kit.log 'test', { logReg: /a/ } # => '' kit.log '%s %s %d', ['a', 'b', 10] # => '[2015-02-07 08:31:49] a b 10'
-
-
Shortcut for logging multiple strings.
-
param:
args
{ Any }...
-
example:
kit.log 'test1', 'test2', test3' # => [2015-02-07 08:31:49] test1 test2 test3
-
-
Monitor an application and automatically restart it when file changed. Even when the monitored app exit with error, the monitor will still wait for your file change to restart the application. Not only nodejs, but also other programs like ruby or python. It will print useful infomation when it application unexceptedly.
-
param:
opts
{ Object }Defaults:
{ bin: 'node' args: ['index.js'] watchList: [] # By default, the same with the "args". isNodeDeps: true opts: {} # Same as the opts of 'kit.spawn'. # The option of `kit.parseDependency` parseDependency: {} onStart: -> kit.log "Monitor: " + opts.watchList onRestart: (path) -> kit.log "Reload app, modified: " + path onWatchFiles: (paths) -> kit.log 'Watching:' + paths.join(', ') onNormalExit: ({ code, signal }) -> kit.log 'EXIT' + " code: #{code} signal: #{signal}" onErrorExit: ({ code, signal }) -> kit.err 'EXIT' + " code: #{code} signal: #{signal}\n" + 'Process closed. Edit and save the watched file to restart.' sepLine: -> process.stdout.write _.repeat('*', process.stdout.columns) }
-
return: { Promise }
It has a property
process
, which is the monitored child process. Properties:{ process: Object # Call it to stop monitor. stop: -> # Resolve a list of watch handlers. watchPromise: Promise }
-
example:
kit.monitorApp { bin: 'coffee' args: ['main.coffee'] } kit.monitorApp { bin: 'ruby' args: ['app.rb', 'lib/**/*.rb'] isNodeDeps: false }
-
-
Node version. Such as
v0.10.23
is0.1023
,v0.10.1
is0.1001
.- return: { Float }
-
A helper for arguments type based function override.
-
param:
args
{ Array | Object }The arguments to set.
-
param:
defaults
{ Object }The default argument settings. The key value of the setting is the argument name, the value is an object, and the key is the type of the argument, the value is the default value of the argument.
-
return: { Object }
-
example:
foo = -> args = kit.defaultArgs arguments, { name: { String: 'A' } colors: { Array: [] } family: { String: null } isReal: { Boolean: false } fn: { Function: -> 'callback' } } kit.log foo('test', false, ['red'], -> 'nothing') # Here the logged value will deeply equal: { name: 'test', colors: ['red'], family: null, fn: -> 'nothing' }
-
-
A comments parser for javascript and coffee-script. Used to generate documentation from source code automatically. It will traverse through all the comments of a coffee file.
-
param:
code
{ String }Coffee source code.
-
param:
opts
{ Object }Parser options:
{ commentReg: RegExp splitReg: RegExp tagNameReg: RegExp typeReg: RegExp nameReg: RegExp nameTags: ['param', 'property'] descriptionReg: RegExp }
-
return: { Array }
The parsed comments. Each item is something like:
{ name: 'parseComment' description: 'A comments parser for coffee-script.' tags: [ { tagName: 'param' type: 'string' name: 'code' description: 'The name of the module it belongs to.' index: 256 # The target char index in the file. line: 32 # The line number of the target in the file. } ] }
-
-
Parse dependency tree by regex. The dependency relationships is not a tree, but a graph. To avoid dependency cycle, this function only return an linear array of the dependencies, from which you won't get the detail relationshops between files.
-
param:
entryPaths
{ String | Array }The file to begin with.
-
param:
opts
{ Object }Defaults:
{ depReg: /require\s*\(?['"](.+)['"]\)?/gm depRoots: [''] extensions: ['.js', '.coffee', 'index.js', 'index.coffee'] # It will handle all the matched paths. # Return false value if you don't want this match. handle: (path) -> path.replace(/^[\s'"]+/, '').replace(/[\s'";]+$/, '') }
-
return: { Promise }
It resolves the dependency path array.
-
example:
kit.parseDependency 'main.', { depReg: /require\s*\(?['"](.+)['"]\)?/gm handle: (path) -> return path if path.match /^(?:\.|/|[a-z]:)/i } .then (markdownStr) -> kit.log markdownStr
-
-
io.js native module
path
. Seenofs
for more information. -
The promise lib. Now, it uses Yaku as ES5 polyfill. In the future, the Yaku will be replaced with native ES6 Promise. Please don't use any API other than the ES6 spec.
- type: { Object }
-
Convert a callback style function to a promise function.
-
param:
fn
{ Function } -
param:
this
{ Any }this
object of the function. -
return: { Function }
The function will return a promise object.
-
example:
readFile = kit.promisify fs.readFile, fs readFile('a.txt').then kit.log
-
-
Create a getter & setter for an object's property.
-
param:
self
{ Object } -
param:
prop
{ String }The property name.
-
return: { Function }
(v) -> Any
# Two arguments data = { path: 'a.txt' } txt = kit.prop data, 'txt' txt kit.readFile data.path .then -> kit.log data kit.log txt() # Two arguments another form. kit.readFile data.path .then txt .then -> kit.log data # One argument. txt = kit.prop 'default value' kit.log txt() # => "default value" txt 20 kit.log txt() # => 20
-
-
The
proxy
module. You mustkit.require 'proxy'
before using it. For more information goto theProxy
section. -
Much faster than the native require of node, but you should follow some rules to use it safely. Use it to load nokit's internal module.
-
param:
moduleName
{ String }The module path or name.
-
param:
dir
{ String }Current absolute file path. Not optional, expect when requiring nokit's internal modules. On most times, just pass
__dirname
to it is enough. -
param:
loaded
{ Function }Run only the first time after the module loaded.
-
return: { Module }
The module that you require.
-
example:
Use it to load nokit's internal module.
kit.require 'jhash' # Then you can use the module, or it will be null. kit.jhash.hash 'test'
To load a relative path, or you own module, the second parameter 'dir' is required.
mod = kit.require './mod', __dirname # Or load your own 'jhash', rather than nokit's. jhash = kit.require 'jhash', __dirname
-
-
Require an optional package. If not found, it will warn the user to npm install it, and exit the process.
-
param:
name
{ String }Package name
-
param:
dir
{ String }Current absolute file path. Not optional. On most times, just pass
__dirname
to it is enough. -
param:
semver
{ String }Specify what version you need, such as
^0.3.1
or>=1.2.3
, ect. -
return: { Any }
The required package.
-
-
A handy extended combination of
http.request
andhttps.request
.-
param:
opts
{ Object }The same as the http.request, but with some extra options:
{ # String or Url Object. url: String | Object # Other than return `res` with `res.body`,return `body` directly. body: true # Max times of auto redirect. If 0, no auto redirect. redirect: 0 # Timeout of the socket of the http connection. # If timeout happens, the promise will reject. # Zero means no timeout. timeout: 0 # The key of headers should be lowercased. headers: {} protocol: 'http:' or 'https:' agent: null # Set "transfer-encoding" header to 'chunked'. setTE: false # Set null to use buffer, optional. # It supports GBK, ShiftJIS etc. # For more info, see https://github.com/ashtuchkin/iconv-lite resEncoding: 'auto' # It's string, object or buffer, optional. When it's an object, # The request will be 'application/x-www-form-urlencoded'. reqData: null # auto end the request. autoEndReq: true # Readable stream. reqPipe: null # Writable stream. resPipe: null # The progress of the request. reqProgress: (complete, total) -> # The progress of the response. resProgress: (complete, total) -> }
And if set opts as string, it will be treated as the url.
-
return: { Promise }
Contains the http response object, it has an extra
body
property. You can also get the request object by usingPromise.req
. -
example:
p = kit.request 'http://test.com' p.req.on 'response', (res) -> kit.log res.headers['content-length'] p.then (body) -> kit.log body # html or buffer kit.request { url: { protocol: 'https', hostname: 'test.com' port: 8123, path: '/a.mp3?s=1' } body: false resProgress: (complete, total) -> kit.log "Progress: #{complete} / #{total}" } .then (res) -> kit.log res.body.length kit.log res.headers # Send form-data. form = new (require 'form-data') form.append 'image', new Buffer(0), { filename: 'a.jpg', contentType: 'image/jpg' } form.append 'key', 'value' kit.request { url: 'a.com' method: 'POST' headers: form.getHeaders() # Use chunked encoding, so that we don't have to calculate # the 'Content-Length'. setTE: true reqPipe: form } .then (body) -> kit.log body
-
-
The semantic versioner for npm, known as semver. You must
kit.require 'semver'
before using it.- type: { Object }
-
Create a http request handler middleware.
-
param:
opts
{ Object }Same as the sse.
-
return: { Function }
(req, res, next) ->
-
example:
Visit 'http://127.0.0.1:80123', every 3 sec, the page will be reloaded.
http = require 'http' handler = kit.serverHelper() http.createServer (req, res) -> handler req, res, -> res.end kit.browserHelper() .listen 8123, -> kit.log 'listen ' + 8123 setInterval -> handler.sse.emit 'fileModified', 'changed-file-path.js' , 3000
You can also use the
nokit.log
on the browser to log to the remote server.nokit.log { any: 'thing' }
-
-
Sleep for awhile. Works same as the
setTimeout
-
param:
time
{ Integer }Time to sleep, millisecond.
-
return: { Promise }
-
example:
kit.sleep 1000 .then -> kit.log 'wake'
-
-
A safer version of
child_process.spawn
to cross-platform run a process. In some conditions, it may be more convenient to use thekit.exec
. It will automatically addnode_modules/.bin
to thePATH
environment variable.-
param:
cmd
{ String }Path or name of an executable program.
-
param:
args
{ Array }CLI arguments.
-
param:
opts
{ Object }Process options. Same with the Node.js official documentation. Except that it will inherit the parent's stdio.
-
return: { Promise }
The
promise.process
is the spawned child process object. Resolves when the process's stdio is drained and the exit code is either0
or130
. The resolve value is like:{ code: 0 signal: null }
-
example:
kit.spawn 'git', ['commit', '-m', '42 is the answer to everything'] .then ({code}) -> kit.log code
-
-
The
sse
module. You mustkit.require 'sse'
before using it. For more information goto thesse
section. -
Sequencing and executing tasks and dependencies concurrently.
-
param:
name
{ String }The task name.
-
param:
opts
{ Object }Optional. Defaults:
{ deps: String | Array description: String logStart: -> logEnd: -> # Whether to run dependency in a row. isSequential: false }
-
param:
fn
{ Function }(val) -> Promise | Any
The task function. If it is a async task, it should return a promise. It will get its dependency tasks' resolved values. -
property:
run
{ Function }Use it to start tasks. Each task will only run once.
(names = 'default', opts) ->
. Thenames
can be a string or array. The default opts:{ isSequential: false # Will be passed as the first task's argument. init: undefined # To stop the run currently in process. Set the `$stop` # reference to true. It will reject a "runStopped" error. warp: { $stop: false } }
-
property:
list
{ Object }The defined task functions.
-
return: { Promise }
Resolve with the last task's resolved value. When
isSequential == true
, it resolves a value, else it resolves an array. -
example:
kit.task 'default', { deps: 'build' }, -> kit.log 'run defaults...' kit.task 'build', { deps: ['clean'] }, (isFull) -> if isFull 'do something' else 'do something else' kit.task 'clean', (opts) -> if opts.isForce kit.remove 'dist/**', { isForce: true } else kit.remove 'dist/**' kit.task.run() .then -> kit.log 'All Done!'
-
-
The
url
module of io.js. You mustkit.require 'url'
before using it. -
Works much like
gulp.src
, but with Promise instead. The warp control and error handling is more pleasant.-
param:
from
{ String }Glob pattern string.
-
param:
opts
{ Object }It extends the options of
nofs.glob
, but with some extra proptereis. Defaults:{ # The base directory of the pattern. baseDir: String }
-
return: { Object }
The returned warp object has these members:
{ # The drive can also be a promise that will resolve a drive. load: (drive) -> fileInfo | null run: (path) -> Promise }
Each piped drive will recieve a object that extends
nofs
's fileInfo object:{ # Set the contents and return self. set: (String | Buffer) -> fileInfo # The src file path. path: String # The dest root path. to: String baseDir: String # The destination path. # Alter it if you want to change the output file's location. # You can set it to string, warp will auto-convert it to object. # It's "valueOf" will return "kit.path.join dir, name + ext". dest: { root, dir, base, ext, name } # The file content. contents: String | Buffer isDir: Boolean stats: fs.Stats # Alter it to control the left drives dynamically. drives: [Function] # All the globbed files. list: Array driveList: Array # The opts you passed to "kit.warp", it will be extended. opts: Object }
Each drive can have a
onEnd: (fileInfo) -> Any | Promise
function, which will be called after a file's whole warp is ended.The drive can have a
isReader
property, which will make the drive override the default file reader.The drive can have a
isWriter
property, which will make the drive override the default file writer.If a drive overrides another, it can call
fileInfo.super()
to use it again. -
example:
# Define a simple workflow. kit.warp 'src/**/*.js' .load (fileInfo) -> fileInfo.set '/* Lisence Info */' + fileInfo.contents .load jslint() .load minify() .run 'build/minified' # Override warp's file reader with a custom one. myReader = kit._.extend (fileInfo) -> # Note that we can also use "@path", # its the same with "fileInfo.path" here. kit.readFile @path, 'hex' .then @set , { # This will tell warp you want use your own reader. isReader: true } # Override writer. myWriter = kit._.extend (fileInfo) -> return if @dest == 'a.js' # Call the overrided writer. @super() , isWriter: true, onEnd: -> @super() kit.log @list kit.warp 'src/**/*.js' .load myWriter .run 'dist' # Use nokit's built-in warp drives. drives = kit.require 'drives' kit.warp src/**/*.coffee' .load drives.coffee() .run 'dist'
-
-
Same as the unix
which
command. You mustkit.require 'which'
before using it.-
param:
name
{ String }The command.
-
return: { Promise }
-
-
Sync version of
which
. You mustkit.require 'whichSync'
before using it.- type: { Function }
-
For debugging. Dump a colorful object.
-
param:
obj
{ Object }Your target object.
-
param:
opts
{ Object }Options. Default:
{ colors: true, depth: 5 }
-
return: { String }
-
-
Open a thing that your system can recognize. Now only support Windows, OSX or system that installed 'xdg-open'.
-
param:
cmds
{ String | Array }The thing you want to open.
-
param:
opts
{ Object }The options of the node native
child_process.exec
. -
return: { Promise }
When the child process exists.
-
example:
# Open a webpage with the default browser. kit.open 'http://ysmood.org'
-
-
The built-in plguins for warp. It's more like examples to show how to use nokit efficiently.
-
clean-css
-
param:
opts
{ Object } -
return: { Function }
-
-
coffee-script compiler
-
param:
opts
{ Object }Default is
{ bare: true }
. -
return: { Function }
-
-
coffeelint processor
-
param:
opts
{ Object }It extends the default config of coffeelint, properties:
{ colorize: true reporter: 'default' # The json of the "coffeelint.json". # If it's null, coffeelint will try to find # "coffeelint.json" as its content. config: null | JSON | JsonFilePath }
-
return: { Function }
-
-
Parse commment from a js, coffee, or livescript file, and output a markdown string.
-
param:
path
{ String } -
param:
opts
{ Object }Defaults:
{ # Output doc path. out: 'readme.md' # jst template path. tpl: 'readme.jst.md' # Init doc info. doc: {} # Header size. h: 3 parseComment: -> ... formatComment: -> ... }
-
return: { Function }
-
example:
The nofile of nokit shows how to use it.
-
-
Auto-compiler file by extension. It will search through
kit.drives
, and find proper drive to run the task. You can extendkit.drives
to let it support more. For example:kit.drives.myCompiler = kit._.extend -> # your compile logic , compiler: ['.jsx']
-
param:
action
{ String }By default, it can be 'compile' or 'compress' or 'lint'
-
param:
opts
{ Object }{ # If no compiler match. onNotFound: (fileInfo) -> }
-
return: { Function }
-
-
Change dest path with a filter.
-
param:
dir
{ String } -
param:
filter
{ Function }(fileInfo, dir) -> Boolean
-
return: { Function }
-
-
a batch file concat helper
-
param:
name
{ String }The output file path.
-
param:
dir
{ String }Optional. Override the dest of warp's.
-
return: { Function }
-
-
Suffix file name with the hash value of file content.
-
param:
hashMapPath
{ String }The output file name hash map.
-
return: { Function }
-
-
Lint js via
jshint
.-
param:
opts
{ Object }Properties:
{ global: null config: null | JSON | JsonFilePath }
-
return: { Function }
-
-
Compile less.
-
param: { Object }
-
return: { Function }
-
-
LiveScript compiler.
-
param:
opts
{ Object }Default is
{ bare: true }
. -
return: { Function }
-
-
mocha test
-
param:
opts
{ Object }{ timeout: 5000 }
-
return: { Function }
-
-
read file and set
contents
-
param:
opts
{ Object }Defaults:
{ isCache: true encoding: 'utf8' cacheDir: '.nokit/warp' }
-
return: { Function }
-
-
Compile stylus.
-
param:
opts
{ Object }It will use
stylus.set
to iterateopts
and set the key-value, is the value is not a function.{ config: (styl) -> }
-
return: { Function }
-
example:
kit.drives.stylus { compress: true config: (styl) -> styl.define 'jack', 'a persion' }
-
-
uglify-js processor
-
param:
opts
{ Object }Defaults:
{ output: comments: (node, comment) -> text = comment.value type = comment.type if type == "comment2" return /@preserve|@license|@cc_on/i.test text }
-
return: { Function }
-
-
Output file by
contents
anddest
. If the 'ext' or 'name' is not null, the 'base' will be override by the 'ext' and 'name'.- return: { Function }
-
For test, page injection development. A cross-platform programmable Fiddler alternative.
-
Use it to proxy one url to another.
-
param:
req
{ http.IncomingMessage }Also supports Express.js.
-
param:
res
{ http.ServerResponse }Also supports Express.js.
-
param:
url
{ String | Object }The target url forced to. Optional. Such as force 'http://test.com/a' to 'http://test.com/b', force 'http://test.com/a' to 'http://other.com/a', force 'http://test.com' to 'other.com'. It can also be an url object. Such as
{ protocol: 'http:', host: 'test.com:8123', pathname: '/a/b', query: 's=1' }
. -
param:
opts
{ Object }Other options. Default:
{ # Limit the bandwidth byte per second. bps: null # if the bps is the global bps. globalBps: false agent: customHttpAgent # You can hack the headers before the proxy send it. handleReqHeaders: (headers) -> headers handleResHeaders: (headers) -> headers }
-
param:
err
{ Function }Custom error handler.
-
return: { Promise }
-
example:
kit = require 'nokit' kit.require 'proxy' kit.require 'url' http = require 'http' server = http.createServer (req, res) -> url = kit.url.parse req.url switch url.path when '/a' kit.proxy.url req, res, 'a.com', (err) -> kit.log err when '/b' kit.proxy.url req, res, '/c' when '/c' kit.proxy.url req, res, 'http://b.com/c.js' else # Transparent proxy. service.use kit.proxy.url server.listen 8123
-
-
Http CONNECT method tunneling proxy helper. Most times used with https proxing.
-
param:
req
{ http.IncomingMessage } -
param:
sock
{ net.Socket } -
param:
head
{ Buffer } -
param:
host
{ String }The host force to. It's optional.
-
param:
port
{ Int }The port force to. It's optional.
-
param:
err
{ Function }Custom error handler.
-
example:
kit = require 'nokit' kit.require 'proxy' http = require 'http' server = http.createServer() # Directly connect to the original site. server.on 'connect', kit.proxy.connect server.listen 8123
-
-
A Server-Sent Event Manager. For more info see Using server-sent events. It is used to implement the live-reload of web assets.
-
param:
opts
{ Object }Defaults:
{ # The reconnection time to use when attempting to send the event, unit is ms. retry: 1000 }
-
example:
Your server side code may look like this:
http = require 'http' kit = require 'nokit' sse = kit.require 'sse' sseHandler = sse() http.createServer (req, res) -> if req.url == '/sse' sseHandler req, res else res.end() .listen 8080, -> setTimeout -> sseHandler.emit 'test', { test: 'ok' }
You browser code should be something like this:
es = new EventSource('/sse') es.addEventListener('test', (e) -> msg = JSON.parse(e.data) console.log(msg) # => { test: 'ok' }
-
-
The sse middleware for http handler.
-
param:
req
{ http.IncomingMessage }Also supports Express.js.
-
param:
res
{ http.ServerResponse }Also supports Express.js.
-
-
The sessions of connected clients.
- type: { Array }
-
Broadcast a event to all clients.
-
param:
event
{ String }The event name.
-
param:
msg
{ Object | String }The data you want to emit to session.
-
param: { String }
[path] The namespace of target sessions. If not set, broadcast to all clients.
-
-
Create a sse session.
-
param:
req
{ http.IncomingMessage }Also supports Express.js.
-
param:
res
{ http.ServerResponse }Also supports Express.js.
-
return: { SSESession }
-
-
A session object is something like:
{ req # The http req object. res # The http res object. }
-
Emit message to client.
-
param:
event
{ String }The event name.
-
param:
msg
{ Object | String }The message to send to the client.
-
npm test
or npm run no -- test
Run npm run no -- -h
for all command you can use.
Such as run npm run no -- build
to build this project.
Edit the templete of the readme at doc/readme.jst.md
.
MIT