What is asar?
The 'asar' npm package is used to create and manage ASAR (Atom Shell Archive) files, which are essentially archives used by Electron applications to package their resources. ASAR files are similar to tar files but are optimized for use with Electron.
What are asar's main functionalities?
Creating an ASAR archive
This feature allows you to create an ASAR archive from a source directory. The code sample demonstrates how to use the 'createPackage' method to create an ASAR archive from the contents of 'path/to/source' and save it to 'path/to/output.asar'.
const asar = require('asar');
asar.createPackage('path/to/source', 'path/to/output.asar').then(() => {
console.log('ASAR archive created successfully');
}).catch(err => {
console.error('Error creating ASAR archive:', err);
});
Extracting an ASAR archive
This feature allows you to extract the contents of an ASAR archive to a specified directory. The code sample demonstrates how to use the 'extractAll' method to extract the contents of 'path/to/archive.asar' to 'path/to/destination'.
const asar = require('asar');
asar.extractAll('path/to/archive.asar', 'path/to/destination').then(() => {
console.log('ASAR archive extracted successfully');
}).catch(err => {
console.error('Error extracting ASAR archive:', err);
});
Listing files in an ASAR archive
This feature allows you to list the files contained within an ASAR archive. The code sample demonstrates how to use the 'listPackage' method to list the files in 'path/to/archive.asar'.
const asar = require('asar');
asar.listPackage('path/to/archive.asar').then(files => {
console.log('Files in ASAR archive:', files);
}).catch(err => {
console.error('Error listing files in ASAR archive:', err);
});
Other packages similar to asar
tar
The 'tar' npm package is used for working with tar archives. It provides functionality to create, extract, and list files in tar archives. While 'tar' is a general-purpose tool for tar files, 'asar' is specifically optimized for Electron applications and their resource packaging needs.
zip
The 'zip' npm package allows for creating and extracting zip archives. Similar to 'asar', it provides methods to compress and decompress files, but it uses the zip format instead of the ASAR format. 'zip' is more widely used for general file compression and decompression tasks.
node-tar
The 'node-tar' package is another tool for handling tar archives in Node.js. It offers a range of features for creating, extracting, and manipulating tar files. Compared to 'asar', 'node-tar' is more versatile for general tar file operations but lacks the specific optimizations for Electron applications.
asar - Electron Archive
Asar is a simple extensive archive format, it works like tar
that concatenates
all files together without compression, while having random access support.
Features
- Support random access
- Use JSON to store files' information
- Very easy to write a parser
Command line utility
Install
This module requires Node 10 or later.
$ npm install --engine-strict asar
Usage
$ asar --help
Usage: asar [options] [command]
Commands:
pack|p <dir> <output>
create asar archive
list|l <archive>
list files of asar archive
extract-file|ef <archive> <filename>
extract one file from archive
extract|e <archive> <dest>
extract archive
Options:
-h, --help output usage information
-V, --version output the version number
Excluding multiple resources from being packed
Given:
app
(a) ├── x1
(b) ├── x2
(c) ├── y3
(d) │ ├── x1
(e) │ └── z1
(f) │ └── x2
(g) └── z4
(h) └── w1
Exclude: a, b
$ asar pack app app.asar --unpack-dir "{x1,x2}"
Exclude: a, b, d, f
$ asar pack app app.asar --unpack-dir "**/{x1,x2}"
Exclude: a, b, d, f, h
$ asar pack app app.asar --unpack-dir "{**/x1,**/x2,z4/w1}"
Using programatically
Example
const asar = require('asar');
const src = 'some/path/';
const dest = 'name.asar';
await asar.createPackage(src, dest);
console.log('done.');
Please note that there is currently no error handling provided!
Transform
You can pass in a transform
option, that is a function, which either returns
nothing, or a stream.Transform
. The latter will be used on files that will be
in the .asar
file to transform them (e.g. compress).
const asar = require('asar');
const src = 'some/path/';
const dest = 'name.asar';
function transform (filename) {
return new CustomTransformStream()
}
await asar.createPackageWithOptions(src, dest, { transform: transform });
console.log('done.');
Using with grunt
There is also an unofficial grunt plugin to generate asar archives at bwin/grunt-asar.
Format
Asar uses Pickle to safely serialize binary value to file, there is
also a node.js binding of Pickle
class.
The format of asar is very flat:
| UInt32: header_size | String: header | Bytes: file1 | ... | Bytes: file42 |
The header_size
and header
are serialized with Pickle class, and
header_size
's Pickle object is 8 bytes.
The header
is a JSON string, and the header_size
is the size of header
's
Pickle
object.
Structure of header
is something like this:
{
"files": {
"tmp": {
"files": {}
},
"usr" : {
"files": {
"bin": {
"files": {
"ls": {
"offset": "0",
"size": 100,
"executable": true,
"integrity": {
"algorithm": "SHA256",
"hash": "...",
"blockSize": 1024,
"blocks": ["...", "..."]
}
},
"cd": {
"offset": "100",
"size": 100,
"executable": true,
"integrity": {
"algorithm": "SHA256",
"hash": "...",
"blockSize": 1024,
"blocks": ["...", "..."]
}
}
}
}
}
},
"etc": {
"files": {
"hosts": {
"offset": "200",
"size": 32,
"integrity": {
"algorithm": "SHA256",
"hash": "...",
"blockSize": 1024,
"blocks": ["...", "..."]
}
}
}
}
}
}
offset
and size
records the information to read the file from archive, the
offset
starts from 0 so you have to manually add the size of header_size
and
header
to the offset
to get the real offset of the file.
offset
is a UINT64 number represented in string, because there is no way to
precisely represent UINT64 in JavaScript Number
. size
is a JavaScript
Number
that is no larger than Number.MAX_SAFE_INTEGER
, which has a value of
9007199254740991
and is about 8PB in size. We didn't store size
in UINT64
because file size in Node.js is represented as Number
and it is not safe to
convert Number
to UINT64.
integrity
is an object consisting of a few keys:
- A hashing
algorithm
, currently only SHA256
is supported. - A hex encoded
hash
value representing the hash of the entire file. - An array of hex encoded hashes for the
blocks
of the file. i.e. for a blockSize of 4KB this array contains the hash of every block if you split the file into N 4KB blocks. - A integer value
blockSize
representing the size in bytes of each block in the blocks
hashes above