
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A server library tries to understand what developers really need.
The philosophy behind NoBone is providing possibilities rather than telling developers what they should do. All the default behaviors are just examples of how to use NoBone. All the APIs should work together without pain.
Install as an dependency:
npm install nobone
# View a better nobone documentation than Github readme.
node_modules/.bin/nobone --doc
Or you can install it globally:
npm i -g nobone
# View a better nobone documentation than Github readme.
nb -d
Check if the
process.env.NODE_ENVis set todevelopment.
Please delete the
.nobonecache directory, and try again.
If you have installed nobone globally, just execute
nobone --docornobone -d. If you are on Windows or Mac, it will auto open the documentation.
If you have installed nobone with
npm install nobonein current directory, executenode_modules/.bin/nobone -d.
Don't execute
nobonewith a directory path when you want to start it with an entrance file.
jade or less, it doesn't work.These are optinal packages, you have to install them first. For example, if you want nobone to support
jade, please executenpm install -g jade.
There's an option to do this:
nb = nobone null, { checkUpgrade: false }.
process.env.NODE_ENV = 'development'
nobone = require 'nobone'
port = 8219
# If you want to init without a specific module,
# for example 'db' and 'service' module, just exclude them:
# nobone {
# renderer: {}
# }
# By default it only loads two modules: `service` and `renderer`.
nb = nobone {
db: { dbPath: './test.db' }
proxy: {}
renderer: {}
service: {}
lang: {
langPath: 'examples/fixtures/lang'
current: 'cn'
}
}
# Service
nb.service.get '/', (req, res) ->
# Renderer
# It will auto-find the 'examples/fixtures/index.tpl', and render it to html.
# You can also render jade, coffee, stylus, less, sass,markdown,
# or define custom handlers.
# When you modify the `examples/fixtures/index.tpl`, the page will auto-reload.
nb.renderer.render('examples/fixtures/index.html')
.then (tplFn) ->
res.send tplFn({ name: 'nobone' })
# Launch express.js
nb.service.listen port, ->
# Kit
# A smarter log helper.
nb.kit.log 'Listen port ' + port
# Open default browser.
nb.kit.xopen 'http://127.0.0.1:' + port
# Static folder for auto-service of coffeescript and stylus, etc.
nb.service.use nb.renderer.static('examples/fixtures')
# Database
# Nobone has a build-in file database.
# Here we save 'a' as value 1.
nb.db.loaded.then ->
nb.db.exec (db) ->
db.doc.a = 1
db.save('DB OK')
.then (data) ->
nb.kit.log data
# Get data 'a'.
nb.kit.log nb.db.doc.a
# Proxy
# Proxy path to specific url.
nb.service.get '/proxy.*', (req, res) ->
# If you visit "http://127.0.0.1:8013/proxy.js",
# it'll return the "http://127.0.0.1:8013/main.js" from the remote server,
# though here we just use a local server for test.
nb.proxy.url req, res, "http://127.0.0.1:#{port}/main." + req.params[0]
# Globalization
nb.kit.log 'human'.l # -> '人类'
nb.kit.log 'open|formal'.l # -> '开启'
nb.kit.log nb.lang('find %s men', [10], 'jp') # -> '10人が見付かる'
close = ->
# Release all the resources.
nb.close().then ->
nb.kit.log 'Peacefully closed.'
See the examples.
You can use nobone as an alternative of node bin or coffee, it will auto detect file type and run it properly.
Such as nb app.js, nb app.coffee. It will run the script and if
the script changed, it will automatically restart it.
You can use nb -w off app.js to turn off the watcher.
You can pass a json to the watch list nb -w '["a.js", "b.js"]' app.js.
Any of watched file changed, the program will be restarted.
Such as nb /home/, it will open a web server for you to browse the folder content. As you edit the html file in the folder, nobone will live
reload the content for you. For css or image file change, it won't refresh the whole page, only js file change will trigger the page reload.
You can use url query ?source and url hash #L to view a source file.
Such as http://127.0.0.1:8013/app.js?source#L10,
it will open a html page with syntax highlight.
Or full version http://127.0.0.1:8013/app.js?source=javascript#L10
You can use ?gotoDoc to open a dependencies' markdown file. Such as jdb/readme.md?gotoDoc. Nobone will use the node require's algorithm to search for the module recursively.
Install nobone globally: npm install -g nobone
# Help info
nb -h
# Use it as a static file server for current directory.
# Visit 'http://127.0.0.1/nobone' to see a better nobone documentation.
nb
# Use regex to filter the log info.
# Print out all the log if it contains '.ejs'
logReg='.ejs' nb
# Use custom logic to start up.
nb app.js
watchPersistent=off nb app.js
# Scaffolding helper
nb bone -h
This command is inherited from the nokit's.
For more information:
# Run default task
no
# See help
no -h
Here I give a simple instruction. For a real example, see nobone-sync.
NoBone support a simple way to implement npm plugin. And your npm package doesn't have to waist time to install nobone dependencies. The package.json file can only have these properties:
{
"name": "nobone-sample",
"version": "0.0.1",
"description": "A sample nobone plugin.",
"main": "main.coffee"
}
The name of the plugin should prefixed with nobone-.
The main.coffee file may looks like:
{ kit } = require 'nobone'
kit.log 'sample plugin'
Suppose we have published the nobone-sampe plugin with npm.
Other people can use the plugin after installing it with either npm install nobone-sample or npm install -g nobone-sample.
To run the plugin simply use nobone sample.
You can use nb ls to list all installed plugins.
It's highly recommended reading the API doc locally by command nb --doc
NoBone has several modules and a helper lib.
All the modules are optional.
Only the kit lib is loaded by default and is not optional.
Most of the async functions are implemented with [Promise][Promise]. [Promise]: https://github.com/petkaantonov/bluebird
Main constructor.
param: modules { Object }
By default, it only load two modules,
service and renderer:
{
service: {}
renderer: {}
db: null
proxy: null
lang: null
langPath: null # language set directory
}
param: opts { Object }
Defaults:
{
# Whether to auto-check the version of nobone.
checkUpgrade: true
# Whether to enable the sse live reload.
autoReload: true
}
return: { Object }
A nobone instance.
Release the resources.
Get current nobone version string.
Check if nobone need to be upgraded.
The NoBone client 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 nokit.log to log anything to server's terminal.
Nobone server will auto-format and log the information to the terminal.
It's convinient for mobile development when remote debug is not possible.
# The nokit is assigned to the "window" object.
nokit.log { a: 10 }
nokit.log 10
A collection of commonly used functions.
It is just a Express.js wrap.
extends: { Express }
Create a Service instance.
param: opts { Object }
Defaults:
{
autoLog: kit.isDevelopment()
enableSse: kit.isDevelopment()
express: {}
sse: {}
}
return: { Service }
The server object of the express object.
type: { http.Server }
An abstract renderer for any content, such as source code or image files. It automatically uses high performance memory cache. This renderer helps nobone to build a passive compilation architecture. You can run the benchmark to see the what differences it makes. Even for huge project the memory usage is negligible.
extends: { events.EventEmitter }
Create a Renderer instance.
param: opts { Object }
Defaults:
{
enableWatcher: kit.isDevelopment()
autoLog: kit.isDevelopment()
# If renderer detects this pattern, it will auto-inject `noboneClient.js`
# into the page.
injectClientReg: /<html[^<>]*>[\s\S]*</html>/i
cacheDir: '.nobone/rendererCache'
cacheLimit: 1024
fileHandlers: {
'.html': {
default: true
extSrc: ['.tpl','.ejs', '.jade']
# Extra files to watch.
extraWatch: { path1: 'comment1', path2: 'comment2', ... }
encoding: 'utf8' # optional, default is 'utf8'
dependencyReg: {
'.ejs': /<%[\n\r\s]*include\s+([^\r\n]+)\s*%>/g
}
compiler: (str, path, data) -> ...
}
# Simple coffee compiler
'.js': {
extSrc: '.coffee'
compiler: (str, path) -> ...
}
# Browserify a main entrance file.
'.jsb': {
type: '.js'
extSrc: '.coffee'
dependencyReg: /require\s+([^\r\n]+)/g
compiler: (str, path) -> ...
}
'.css': {
extSrc: ['.styl', '.less', '.sass', '.scss']
compiler: (str, path) -> ...
}
'.md': {
type: 'html' # Force type, optional.
extSrc: ['.md', '.markdown']
compiler: (str, path) -> ...
}
}
}
return: { Renderer }
You can access all the fileHandlers here. Manipulate them at runtime.
type: { Object }
example:
{ renderer } = nobone()
renderer.fileHandlers['.css'].compiler = (str, path) ->
stylus = kit.requireOptional 'stylus', __dirname
compile = stylus(str, data).set 'filename', path
# Take advantage of the syntax parser.
this.dependencyPaths = compile.deps()
kit.promisify(compile.render, compile)()
The cache pool of the result of fileHandlers.compiler
type: { Object }
Key is the file path.
Set a service for listing directory content, similar with the serve-index project.
param: opts { String | Object }
If it's a string it represents the rootDir.
return: { Middleware }
Experss.js middleware.
Set a static directory proxy. Automatically compile, cache and serve source files for both deveopment and production.
param: opts { String | Object }
If it's a string it represents the rootDir. of this static directory. Defaults:
{
rootDir: '.'
# Whether enable serve direcotry index.
index: kit.isDevelopment()
injectClient: kit.isDevelopment()
# Useful when mapping a normal path to a hashed file.
# Such as map 'lib/main.js' to 'lib/main-jk2x.js'.
reqPathHandler: decodeURIComponent
# Check path such as '../../../../etc/passwd'.
isMalicious: ->
}
return: { Middleware }
Experss.js middleware.
An extra version of renderer.static.
Better support for markdown and source file.
param: opts { String | Object }
If it's a string it represents the rootDir. of this static directory. Defaults:
{
rootDir: '.'
# Whether enable serve direcotry index.
index: kit.isDevelopment()
injectClient: kit.isDevelopment()
# Useful when mapping a normal path to a hashed file.
# Such as map 'lib/main.js' to 'lib/main-jk2x.js'.
reqPathHandler: decodeURIComponent
}
return: { Middleware }
Experss.js middleware.
Render a file. It will auto-detect the file extension and choose the right compiler to handle the content.
param: path { String | Object }
The file path. The path extension should be the same with the compiled result file. If it's an object, it can contain any number of following params.
param: ext { String }
Force the extension. Optional.
param: data { Object }
Extra data you want to send to the compiler. Optional.
param: isCache { Boolean }
Whether to cache the result, default is true. Optional.
param: reqPath { String }
The http request path. Support it will make auto-reload more efficient.
param: handler { FileHandler }
A custom file handler.
return: { Promise }
Contains the compiled content.
example:
# The 'a.ejs' file may not exists, it will auto-compile
# the 'a.ejs' or 'a.html' to html.
renderer.render('a.html').then (html) -> kit.log(html)
# if the content of 'a.ejs' is '<% var a = 10 %><%= a %>'
renderer.render('a.ejs', '.html').then (html) -> html == '10'
renderer.render('a.ejs').then (str) -> str == '<% var a = 10 %><%= a %>'
Release the resources.
Release memory cache of a file.
path { String }event: { compiled }
param: path { String }
The compiled file.
param: content { String }
Compiled content.
param: handler { FileHandler }
The current file handler.
event: { compileError }
param: path { String }
The error file.
param: err { Error }
The error info.
event: { watchFile }
param: path { String }
The path of the file.
param: curr { fs.Stats }
Current state.
param: prev { fs.Stats }
Previous state.
event: { fileDeleted }
param: path { String }
The path of the file.
event: { fileModified }
param: path { String }
The path of the file.
Set handler cache.
param: handler { FileHandler }
return: { Promise }
Generate a file handler.
param: path { String }
param: handler { FileHandler }
return: { FileHandler }
It use the renderer module to create some handy functions.
The compiler can handle any type of file.
context: { FileHandler }
Properties:
{
ext: String # The current file's extension.
opts: Object # The current options of renderer.
# The file dependencies of current file.
# If you set it in the `compiler`, the `dependencyReg`
# and `dependencyRoots` should be left undefined.
dependencyPaths: Array
# The regex to match dependency path. Regex or Table.
dependencyReg: RegExp
# The root directories for searching dependencies.
dependencyRoots: Array
# The source map informantion.
# If you need source map support, the `sourceMap`property
# must be set during the compile process.
# If you use inline source map, this property shouldn't be set.
sourceMap: String or Object
}
param: str { String }
Source content.
param: path { String }
For debug info.
param: data { Any }
The data sent from the render function.
when you call the render directly. Default is an object:
{
_: lodash
injectClient: kit.isDevelopment()
}
return: { Promise }
Promise that contains the compiled content.
Folder middleware.
param: opts { Object }
return: { Function }
Static middleware.
param: renderer { Renderer }
param: opts { Object }
return: { Function }
Static middleware. Don't use it in production.
param: renderer { Renderer }
param: opts { Object }
return: { Function }
See my [jdb][jdb] project.
Create a JDB instance.
param: opts { Object }
Defaults:
{
dbPath: './nobone.db'
}
return: { Jdb }
A promise object that help you to detect when the db is totally loaded.
See the proxy of nokit https://github.com/ysmood/nokit#proxy-1
Create a Proxy instance.
An string helper for globalization.
It will find the right key/value pair in your defined langSet.
If it cannot find the one, it will output the key directly.
param: cmd { String }
The original text.
param: args { Array }
The arguments for string format. Optional.
param: name { String }
The target language name. Optional.
return: { String }
example:
{ lang } = require('nobone')(lang: {})
lang.langSet =
human:
cn: '人类'
jp: '人間'
open:
cn:
formal: '开启' # Formal way to say 'open'
casual: '打开' # Casual way to say 'open'
'find %s men': '%s人が見付かる'
lang('human', 'cn', langSet) # -> '人类'
lang('open|casual', 'cn', langSet) # -> '打开'
lang('find %s men', [10], 'jp', langSet) # -> '10人が見付かる'
example:
{ lang } = require('nobone')(
lang: { langPath: 'lang.coffee' }
current: 'cn'
)
'human'.l # '人类'
'Good weather.'.lang('jp') # '日和。'
lang.current = 'en'
'human'.l # 'human'
'Good weather.'.lang('jp') # 'Good weather.'
Language collections.
type: { Object }
example:
{ lang } = require('nobone')(lang: {})
lang.langSet = {
'cn': { 'human': '人类' }
}
Current default language.
type: { String }
default:
'en'
Load language set and save them into the langSet.
Besides, it will also add properties l and lang to String.prototype.
param: filePath { String }
js or coffee files.
example:
{ lang } = require('nobone')(lang: {})
lang.load 'assets/lang'
lang.current = 'cn'
log 'test'.l # -> '测试'.
log '%s persons'.lang([10]) # -> '10 persons'
See the doc/changelog.md file.
npm test
Goto see benchmark
Decouple libs.
Better test coverage.
May 2014, Yad Smood
FAQs
A server library tries to understand what developers really need.
The npm package nobone receives a total of 25 weekly downloads. As such, nobone popularity was classified as not popular.
We found that nobone demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.