nar is a simple application packager utility for node.js that creates self-contained applications that are ready-to-ship-and-run
It provides built-in support for creating, extracting, installing and running node applications easily from a simple configuration through a featured command-line interface and full asynchronous event-based programmatic API
It could be an ideal solution for distributing, deploying, running and testing
private node.js applications that are outside of the npm
ecosystem
Questions? Read the FAQs or open an issue
- Simple and featured command-line interface
- Easy-to-use asynchronous programmatic API
- Fully configurable from package.json
- Tarball with gzip compression/decompression
- Built-in support for archive extraction
- Built-in support for application execution
- Built-in support for installating archives (like npm does)
- Supports downloading and running archives from remote servers
- Supports application pre/post run hooks (like npm scripts)
- Supports installing archives from local and remote servers (like npm does)
- Allow to embed dependencies by type
- Allow to embed global dependencies
- Allow to embed node binary for isolated runtime environments
- Allow to create archives like executables binary-like containers (embedded node)
- Integrable in your development workflow through Grunt or Gulp
- Transparent file checksum integrity verification
It's recommended you install nar as global package
$ npm install -g nar
If you need to use the API, you should install it as package dependency
$ npm install nar --save
Create new archive
$ nar create
Create new executable binary archive
$ nar create --executable
Extract files
$ nar extract app.nar
Or directly run it
$ nar run app.nar
Install (default to node_modules
)
$ nar install http://server.net/app-0.1.0.nar --save
Example package.json
with full configuration
{
"name": "my-package",
"version": "1.0.0",
"archive": {
"binary": true,
"dependencies": true,
"devDependencies": false,
"globalDependencies": ["npm", "grunt-cli", "bower"],
"patterns": ["**", "!test/**"]
},
"scripts": {
"start": "node app --env ${ENV}"
},
"dependencies": {
"some": "~0.1.0"
}
}
Following options can be declared in your application package.json
as
properties members of the archive
object
Packages dependencies names will be taken from package.json
Type: boolean
Default: true
Include runtime dependencies in the archive
Type: boolean
Default: false
Include development dependencies in the archive
Type: boolean
Default: true
Include peer dependencies in the archive
Type: array
Default: null
Include global dependencies in the archive. It should define an array of strings with packages names
nar will resolve globally installed packages (via requireg) and will add them to the archive
Global dependencies will be placed in .node/lib/node
on archive extraction and them will be
available via require
and PATH
environment variable (for binary files)
Type: boolean
Default: false
Include the node binary in the nar archive. This is useful when you want to deploy a fully self-contained application which works in a sandboxed runtime environment
The included node binary will be, by default, the same as the used when your
create the archive (taken from process.execPath
)
Hooks scripts that requires node will use the self-contained binary inside the archive.
It will be also accessible via PATH
environment variable
if you want to call it from hook scripts
Note: as you already know, the node binary is OS and platform specific. Take that into account if you are going to deploy the archive in multiple platforms
Type: string
Default: process.execPath
Custom node
binary path to add into the archive
You must define the binary
option as true
in order to apply this.
You can use interpolated environment variables expressions in
this option, like ${HOME}/binaries/node
Aditionally, you can also define the binaryPath
value from the NAR_BINARY
environment variable
Type: boolean
Default: true
Enable/disable ignore-like files processing in order to load files patterns to discard from the archive
Type: array
Default: ['**']
Glob patterns for matching files to include or exclude in the archive
OS level specific hidden files such as .DS_Store
or Thumbs.db
will be ignored by default
Aditionally, nar will ignore matched patterns defined in ignore-like files
nar
supports application pre/post execution hooks, that are also supported by npm
You should define them from package.json
in the scripts
member (see npm scripts)
Supported hooks (by execution order):
prestart
start
stop
poststop
Configuration example:
{
"name": "app",
"version": "1.0.0",
"scripts": {
"prestart": "mkdir -p temp/logs",
"start": "node app --env ${ENV}",
"stop" "rm -rf cache"
}
}
You can consum environment variables from hook comands using the ${VARNAME}
notation
nar will expose the NODE_NAR
environment variable in the hooks execution contexts and node application
You can make any environment runtime checks if your application needs a different behavior dependending of the runtime environment
nar will find ignore-like files in order to load and match patterns of files to discard
Supported files (by priority):
.narignore
.buildignore
.npmignore
.gitignore
Usage: nar [options] [command]
Commands:
help
Output usage information
create [options] [path]
Create a nar archive
extract [options] <archive>
Extract archive
run [options] <archive>
Run archive files
list [options] <archive>
List archive files
install [options] <archive>
Install archive
get [options] <url>
Download archive from HTTP server
Options:
-h, --help output usage information
-V, --version output the version number
Usage examples:
$ nar create
$ nar run app.nar
$ nar extract app.nar -o some/dir
$ nar list app.nar
$ nar install app.nar --save
$ nar get http://server.net/app.nar
Command specific help:
$ nar <command> --help
Alias: c
Create a new archive from an existent application
$ nar create
$ nar create some/path --debug
$ nar create path/to/package.json -o some/dir
$ nar create --dev-dependencies --global-dependencies 'npm,grunt'
$ nar create --omit-dependencies
$ nar create --verbose
$ nar create --executable
Alias: e
Extract archive files into directory
$ nar extract
$ nar extract app.nar
$ nar extract app.nar -o some-dir
$ nar extract app.nar --debug
Alias: x
Run nar archive application
$ nar run app.nar
$ nar run app.nar --no-hooks
$ nar run app.nar --no-clean --debug
$ nar run app.nar --verbose
$ nar run app.nar --args-start '--env ${ENV}'
$ nar run app.nar --args-stop '--path ${PATH}'
$ nar run http://server.net/app.nar
Alias: i
Install nar archive as dependency (defaults to node_modules
)
$ nar install app.nar --save
$ nar install app.nar -o some/dir --save-dev
$ nar install app.nar --debug
$ nar install http://server.net/app-0.1.0.nar
$ nar install -g http://server.net/app-0.1.0.nar
Alias: g
Download a remote archive
$ nar get http://server.net/app.nar
$ nar get http://server.net/app.nar --user john --password pa$s
$ nar get http://server.net/app.nar --proxy http://proxy:3128
$ nar get http://server.net/app.nar --strict-ssl --timeout 60000
Alias: l
List files from archive
$ nar list app.nar
$ nar list app.nar --no-table
nar provides a full featured programmatic API designed to be easily consumed from other node applications
The API is fully asynchronous event-based, for a better approach
var nar = require('nar')
var options = {
path: 'my/package.json', // defaults to ./package.json
dest: 'build/', // defaults to current directory
binary: true,
dependencies: true,
devDependencies: true,
globalDependencies: ['npm', 'grunt']
}
try {
nar.create(options)
.on('error', function (err) {
throw err
})
.on('info', function (nar) {
console.log(nar.name)
})
.on('entry', function (file) {
console.log('Adding file:', file.name)
})
.on('end', function (path) {
console.log('Archive created in:', path)
})
} catch (e) {
console.error('Cannot create the archive:', e.message)
}
Fired events: end, error, entry, archive, message, info, start
Create new archive from a given package.json
You can pass any configuration options and the following options:
- path
string
Path to package.json or application directory. Required - dest
string
Extract destination path. Default to random temporal directory - file
string
Archive file name. Default to package name + version, taken frompackage.json
- patterns
array
List of glob patterns for matching files to include or exclude
Same as nar.create()
, but this generate an executable binary-like archive
Fired events: end, error, entry, archive, message, info, start
Extract archive files into a output directory
- path
string
Path to nar archive. Required - dest
string
Extract destination path. Default to random temporal directory - tmpdir
string
Temporal directory to use. Default to random temporal directory
Fired events: end, error, entry, archive, command, info, start, stdout, stderr, exit
Read, extract and run an application. It will read command scripts hooks in package.json
- path
string
Path to nar archive. Required - dest
string
Extract destination path. Defaults to random temporal directory - args
object
Aditional argument to pass to hooks. Keys must have the same hook name - hooks
boolean
Enable/disable run command hooks. Defaults totrue
- clean
boolean
Clean app directory on exit. Defaults totrue
Options: path
Fired events: end, error, entry
Read and parse a given .nar archive, emitting the entry
event for each existent file
- path
string
Path to nar archive. Required
Fired events: end, download, downloadEnd, error, entry, start, progress
Install archive as dependency in node_modules
directory.
It can aditionally download the archive from remote server
- path
string
Path to nar archive. Required ifurl
is empty - url
string
URL to download the archive. Required ifpath
is empty - filename
string
Downloaded filename. Defaults taken from URI path - dest
string
Install destination path. Defaults to randomnode_modules
- clean
boolean
Clean downloaded archive after install. Defaults totrue
- proxy
string
Proxy server URL. Default taken from environment variablehttp_proxy
- auth
object
user and password for HTTP basic authentication - timeout
number
HTTP request timeout in ms. Defaults to10000
- headers
object
Define aditional HTTP request headers - strictSSL
boolean
Performs HTTP request with valid SSL servers. Defaults tofalse
- save
boolean
Save installed package as runtime dependency inpackage.json
. Default tofalse
- saveDev
boolean
Save installed package as development dependency inpackage.json
. Default tofalse
- savePeer
boolean
Save installed package as peer dependency inpackage.json
. Default tofalse
- global
boolean
Install package as global dependency. Default tofalse
Alias: download
Fired events: end, error, download, progress
Download archive from remote server. It supports basic HTTP authentication and proxy
- path
string
Path to nar archive. Required ifurl
is empty - url
string
URL to download the archive. Required ifpath
is empty - dest
string
Install destination path. Defaults to randomnode_modules
- filename
string
Downloaded filename. Defaults taken from URI path - clean
boolean
Clean downloaded archive after install. Defaults totrue
- proxy
string
Proxy server URL. Default taken from environment variablehttp_proxy
- auth
object
user and password for HTTP basic authentication - timeout
number
HTTP request timeout in ms. Defaults to10000
- strictSSL
boolean
Performs HTTP request with valid SSL servers. Defaults tofalse
Type: string
Complete list of available events for subscription
- end
([result])
Task was completed successfully - error
(error)
Some error happens and task cannot be completed - entry
(entry)
On read/write file, usually fired from file streams - archive
(archive)
Emit the archive that is being processed - message
(message)
General information status message, useful for debugging purposes - download
()
Starts a download process - command
(command)
Hook command to execute when run an application - info
(config)
Expose the nar archive config - start
(command)
On application start hook command - stdout
(string)
Command execution stdout entry. Emits on every chunk of data - stderr
(string)
Command execution stderr entry. Emits on every chunk of data - exit
(code, hook)
When a hook command process ends
nar archives are just a tarball containers with gzip compression.
It's equivalent to a file with tar.gz
extension, so you can extract
it with tar
, 7zip
or file compression tools ans inspect the archive contents
Example using tar
$ tar xvfz app-0.1.0.nar
No. From version 0.3.0
you can create executable binary-like applications containers
and there is no more required to have previously installed node
or nar
in order
to run, install or extract an application
You must create a executable nar archive
$ nar create --executable
Then you could simply run it like this:
$ ./app-0.1.0.nar [run|extract|install] [options]
If you don't create your archive with this option, you must to have nar
(and consequently node) installed in the target computer
Yes.
If you use the run
command, if the archive was created with the node binary embedded,
your application will run with the self-contained binary
One of the following types will be valid:
application/x-gzip
aplication/x-compress
application/x-compressed
application/octet-stream
Of course. You could use both methods:
Passing credentials via optional flags:
$ nar get https://server.net/archive.nar --user john --password p@s$
Or using the HTTP_USER
and HTTP_PASSWORD
environment variables
$ HTTP_USER=john HTTP_PASSWORD=p@s$ nar get https://server.net/archive.nar
Wanna help? Cool! It will be really apreciated :)
nar
is completely written in LiveScript language.
Take a look to the language documentation if you are new with it.
and follow the LiveScript language conventions defined in the coding style guide
You must add new test cases for any new feature or refactor you do, always following the same design/code patterns that already exist
Only node.js is required for development
Clone/fork this repository
$ git clone https://github.com/h2non/nar.git && cd nar
Install dependencies
$ npm install
Compile code
$ make compile
Run tests
$ make test
Publish a new version
$ make publish
MIT © Tomas Aparicio