Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

crx

oncletom242.9kMIT5.0.1

crx is a utility to package Google Chrome extensions via a Node API and the command line

readme

crx Build Status Build status

crx is a utility to package Google Chrome extensions via a Node API and the command line. It is written purely in JavaScript and does not require OpenSSL!

Packages are available to use crx with:

Massive hat tip to the node-rsa project for the pure JavaScript encryption!

Compatibility: this extension is compatible with node>=10.

Install

$ npm install crx

Module API

Asynchronous functions returns a native ECMAScript Promise.

const fs = require('fs');
const path = require('path');

const ChromeExtension = require('crx');

const crx = new ChromeExtension({
  codebase: 'http://localhost:8000/myExtension.crx',
  privateKey: fs.readFileSync('./key.pem')
});

crx.load( path.resolve(__dirname, './myExtension') )
  .then(crx => crx.pack())
  .then(crxBuffer => {
    const updateXML = crx.generateUpdateXML()

    fs.writeFile('../update.xml', updateXML);
    fs.writeFile('../myExtension.crx', crxBuffer);
  })
  .catch(err=>{
    console.error( err );
  });

ChromeExtension = require("crx")

crx = new ChromeExtension(attrs)

This module exports the ChromeExtension constructor directly, which can take an optional attribute object, which is used to extend the instance.

crx.load(path|files)

Prepares the temporary workspace for the Chrome Extension located at path — which is expected to directly contain manifest.json.

crx.load('/path/to/extension').then(crx => {
  // ...
});

Alternatively, you can pass a list of files — the first manifest.json file to be found will be considered as the root of the application.

crx.load(['/my/extension/manifest.json', '/my/extension/background.json']).then(crx => {
  // ...
});

crx.pack()

Packs the Chrome Extension and resolves the promise with a Buffer containing the .crx file.

crx.load('/path/to/extension')
  .then(crx => crx.pack())
  .then(crxBuffer => {
    fs.writeFile('/tmp/foobar.crx', crxBuffer);
  });

crx.generateUpdateXML()

Returns a Buffer containing the update.xml file used for autoupdate, as specified for update_url in the manifest. In this case, the instance must have a property called codebase.

const crx = new ChromeExtension({ ..., codebase: 'https://autoupdateserver.com/myFirstExtension.crx' });

crx.load('/path/to/extension')
  .then(crx => crx.pack())
  .then(crxBuffer => {
    // ...
    const xmlBuffer = crx.generateUpdateXML();
    fs.writeFile('/foo/bar/update.xml', xmlBuffer);
  });

crx.generateAppId

Generates application id (extension id) from given path.

new crx().generateAppId('/path/to/ext') // epgkjnfaepceeghkjflpimappmlalchn

CLI API

crx pack [directory] [--crx-version number] [-o file] [--zip-output file] [-p private-key]

Pack the specified directory into a .crx package, and output it to stdout. If no directory is specified, the current working directory is used.

Use the --crx-version option to specify which CRX format version to output. Can be either "2" or "3", defaults to "3".

Use the -o option to write the signed extension to a file instead of stdout.

Use the --zip-output option to write the unsigned extension to a file.

Use the -p option to specify an external private key. If this is not used, key.pem is used from within the directory. If this option is not used and no key.pem file exists, one will be generated automatically.

Use the -b option to specify the maximum buffer allowed to generate extension. By default, will rely on node internal setting (~200KB).

crx keygen [directory]

Generate a 2048-bit RSA private key within the directory. This is called automatically if a key is not specified, and key.pem does not exist.

Use the --force option to overwrite an existing private key located in the same given folder.

crx --help

Show information about using this utility, generated by commander.

CLI example

Given the following directory structure:

└─┬ myFirstExtension
  ├── manifest.json
  └── icon.png

run this:

$ cd myFirstExtension
$ crx pack -o

to generate this:

├─┬ myFirstExtension
│ ├── manifest.json
│ ├── icon.png
│ └── key.pem
└── myFirstExtension.crx

You can also name the output file like this:

$ cd myFirstExtension
$ crx pack -o myFirstExtension.crx

to get the same results, or also pipe to the file manually like this.

$ cd myFirstExtension
$ crx pack > ../myFirstExtension.crx

As you can see a key is generated for you at key.pem if none exists. You can also specify an external key. So if you have this:

├─┬ myFirstExtension
│ ├── manifest.json
│ └── icon.png
└── myPrivateKey.pem

you can run this:

$ crx pack myFirstExtension -p myPrivateKey.pem -o

to sign your package without keeping the key in the directory.

License

MIT License.

changelog

Change Log

5.0.1 (2019/07/22 09:57 +00:00)

  • #107 fix: loading relative path (@ahwayakchih)

v5.0.0 (2019/04/17 08:00 +00:00)

  • #106 chore: update CHANGELOG (@ahwayakchih)
  • #105 Update dependencies and prepare for new release (v5.0.0) (@ahwayakchih)
  • #104 fix: create private key file outside extension directory by default (@ahwayakchih)
  • #103 Move CLI script to src folder (@arkon)
  • #100 Move CRX2 logic to separate file (@arkon)
  • #102 feat: use manifest.minimum_chrome_version as XML's prodversionmin (@ahwayakchih)
  • #99 docs: add --crx-format to README (@ahwayakchih)
  • #98 feat: add support for CRXv3 (@ahwayakchih)
  • #97 chore: update dependencies (#97) (@ahwayakchih)
  • #78 Add generateAppId sample (#78) (@NN---)

v4.0.1 (2019/02/03 16:17 +00:00)

  • #96 Remove deprecated crx.writeFile() (@oncletom)

v4.0.0 (2019/02/03 15:57 +00:00)

  • #95 Release crx@4 (@oncletom)
  • #93 fix demo code (@g8up)
  • #88 Bump Node.js version requirement (@oncletom)
  • #90 Fix syntax in module usage (@blimmer)
  • #83 Update dependencies (@oncletom)
  • #81 Fix extension ID calculation from path (@oncletom, @conioh)
  • #76 Add Appveyor configuration to test build on Windows (@oncletom)
  • #71 Remove the manifest data from cache on crx.load() (@binhqx)
  • #75 [Snyk Update] New fixes for 1 vulnerable dependency path (@snyk-bot)

v3.2.1 (2016/10/13 13:13 +00:00)

  • #67 Drop iojs from package.engines (@dsblv)

v3.2.0 (2016/09/22 23:25 +00:00)

  • #66 Add the ability to load a list of files in addition to a path. (@oncletom)

v3.1.0 (2016/09/22 14:06 +00:00)

  • #62 Remove intermediate copy and use of temporary files (@oncletom)
  • #63 Add code coverage and add additional tests (@oncletom)

v3.0.4 (2016/09/21 13:00 +00:00)

  • #58 [security fix] Updated archiver dependency; drops support for node 0.8.x (@PavelVanecek)
  • #56 Update CLI documentation with -o instead of deprecated -f (@nhoizey)
  • #52 Generate 2048-bit keys at the keygen CLI (@ngyikp)
  • #50 test crx on node 4.1 and 5 (@joscha)

v3.0.3 (2015/07/22 16:10 +00:00)

  • #47 added .npmignore file (@PavelVanecek)

v3.0.2 (2015/02/06 11:28 +00:00)

  • #39 Do not concatenate a possible null buffer. (@oncletom)
  • #37 fix pack instruction in Module example (@qbarlas)

v2.0.1 (2015/01/15 18:28 +00:00)

  • #34 Fix various issues with CLI and creating .pem and .crx files (@Batterii)
  • #35 destroy() is not used (@okuryu)
  • #26 fixes minor code problems, such as missing semicolons, etc. (@joscha)
  • #29 generatePublicKey promise and generateAppId state (@joscha)
  • #30 use temp module (@joscha)
  • #27 throw error if public key is not set, yet (@joscha)

v2.0.0 (2014/11/29 16:39 +00:00)

  • #24 Unsigned archives (@oncletom)

v1.1.0 (2014/11/29 15:55 +00:00)

  • #25 Pure JavaScript public key (@oncletom)

v1.0.0 (2014/11/25 11:45 +00:00)

  • #22 Remove system ssh-keygen dependency (@oncletom)
  • #20 Promise-based interface (@oncletom)
  • #19 Event 'finished' no longer valid #18 (@yuryoparin)
  • #17 Fix deleting remaining ./tmp directory (@jokesterfr)
  • #16 removed bufferstream dependency (@christian-bromann)
  • #14 Support long private keys in latest Chrome 32 (@vitalets)
  • #10 Windows Compatibility (@adotout)
  • #8 Use proper stdin options in child_process.spawn() instead of passing a file child.stdin.end() (@nkakuev)
  • #3 Added support for maxBuffer (@oncletom)
  • #2 Updated the README example upon crx API (@oncletom)