The PackageCache wraps all package management functions. It also handles initial global state setup.

Usage:

let cache = new PackageCache();
let dir = cache.create('your-cache', 'yarn', '{
  "dependencies": {
    "lodash": "*",
    "ember-cli": "*"
  }
}');
// => process.cwd()/tmp/your-cache-A3B4C6D

This will generate a persistent cache which contains the results of a clean installation of the dependencies as you specified in the manifest argument. It will save the results of these in a temporary folder, returned as dir. On a second invocation (in the same process, or in a subsequent run) PackageCache will first compare the manifest to the previously installed one, using the manifest as the cache key, and make a decision as to the fastest way to get the cache up-to-date. PackageCache guarantees that your cache will always be up-to-date.

If done in the same process, this simply returns the existing cache directory with no change, making the following invocation simply a cache validation check:

let dir2 = cache.create('your-cache', 'yarn', '{
  "dependencies": {
    "lodash": "*",
    "ember-cli": "*"
  }
}');
// => process.cwd()/tmp/your-cache-A3B4C6D

If you wish to modify a cache you can do so using the update API:

let dir3 = cache.update('your-cache', 'yarn', '{
  "dependencies": {
    "": "*",
    "lodash": "*",
    "ember-cli": "*"
  }
}');
// => process.cwd()/tmp/your-cache-A3B4C6D

Underneath the hood create and update are identical–which makes clear the simplicity of this tool. It will always do the right thing. You can think of the outcome of any create or update call as identical to rm -rf node_modules && npm install except as performant as possible.

If you need to make modifications to a cache but wish to retain the original you can invoke the clone command:

let newDir = cache.clone('your-cache', 'modified-cache');
let manifest = fs.readJsonSync(path.join(newDir, 'package.json'));
manifest.dependencies['express'] = '*';
cache.update('modified-cache', 'yarn', JSON.stringify(manifest));
// => process.cwd()/tmp/modified-cache-F8D5C8B

This mental model makes it easy to prevent coding mistakes, state leakage across multiple test runs by making multiple caches cheap, and has tremendous performance benefits.

You can even programatically update a cache:

let CommandGenerator = require('./command-generator');
let yarn = new CommandGenerator('yarn');

let dir = cache.create('your-cache', 'yarn', '{ ... }');

yarn.invoke('add', 'some-addon', { cwd: dir });

The programmatic approach enables the entire set of usecases that the underlying package manager supports while continuing to wrap it in a persistent cache. You should not directly modify any files in the cache other than the manifest unless you really know what you're doing as that can put the cache into a possibly invalid state.

PackageCache also supports linking. If you pass an array of module names to in the fourth position it will ensure that those are linked, and remain linked for the lifetime of the cache. When you link a package it uses the current global link provided by the underlying package manager and invokes their built-in link command.

let dir = cache.create('your-cache', 'yarn', '{ ... }', ['ember-cli']);
// => yarn link ember-cli happens along the way.

Sometimes this global linking behavior is not what you want. Instead you wish to link in some other working directory. PackageCache makes a best effort attempt at supporting this workflow by allowing you to specify an object in the links argument array passed to create.

let dir = cache.create('your-cache', 'yarn', '{ ... }', [ { name: 'ember-cli', path: '/the/absolute/path/to/the/package' }, 'other-package' ]);

This creates a symlink at the named package path to the specified directory. As package managers do different things for their own linking behavior this is "best effort" only. Be sure to review upstream behavior to identify if you rely on those features for your code to function:

As the only caveat, PackageCache is persistent. The consuming code is responsible for ensuring that the cache size does not grow unbounded.

Constructor Summary

Private Constructors
private
PackageCache(rootPath)

The PackageCache wraps all package management functions. It also handles initial global state setup.

Method Summary

Public Methods
public
create(label, type, manifest, links): String

The create method adds a new package cache entry.

public
destroy(label, type)

The destroy method removes all evidence of the package cache.

public
destroy(fromLabel, toLabel)

The clone method duplicates a cache. Some package managers can leverage a pre-existing state to speed up their installation.

public
get(label): String

The get method returns the directory for the cache.

public
update(label, type, manifest, links): String

The update method aliases the create method.

Private Methods
private

The __resetForTesting puts things back in module scope.

private

The __setupForTesting modifies things in module scope.

private
_checkManifest(label, type, manifest): Boolean

The _checkManifest method compares the desired manifest to that which exists in the cache.

private

The _cleanDirs method deals with sync issues between the Configstore and what exists on disk. Non-existent directories are removed from this.dirs.

private
_install(label, type)

The _install method installs the contents of the manifest into the specified package cache.

private
_readManifest(label, type): String

The _readManifest method reads the on-disk manifest for the current cache and returns its value.

private
_removeLinks(label, type)

The _removeLinks method removes from the dependencies of the manifest the assets which will be linked in so that we don't duplicate install. It saves off the values in the internal PackageCache metadata for restoration after linking as those values may be necessary.

private
_restoreLinks(label, type)

The _restoreLinks method restores the dependencies from the internal PackageCache metadata so that the manifest matches its original state after performing the links.

private
_upgrade(label, type)

The _upgrade method guarantees that the contents of the manifest are allowed to drift in a SemVer compatible manner. It ensures that CI is always running against the latest versions of all dependencies.

private
_writeManifest(label, type, manifest)

The _writeManifest method generates the on-disk folder for the package cache and saves the manifest into it. If it is a yarn package cache it will remove the existing lock file.

private
bower(subcommand, [arguments], [options={}])

The bower command helper.

private
npm(subcommand, [arguments], [options={}])

The npm command helper.

private
translate(type, lookup)

The translate command is used to turn a consistent argument into appropriate values based upon the context in which it is used. It's a convenience helper to avoid littering lookups throughout the code.

private
yarn(subcommand, [arguments], [options={}])

The yarn command helper.

Private Constructors

tests/helpers/package-cache.js:102

private PackageCache(rootPath)

Parameters:

Name Type Attribute Description
rootPath String

Root of the directory for PackageCache.

Public Methods

tests/helpers/package-cache.js:578

public create(label, type, manifest, links): String

The create method adds a new package cache entry.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

manifest String

The contents of the manifest file for the cache.

links Array

Packages to omit for install and link.

Return:

String

The directory on disk which contains the cache.

tests/helpers/package-cache.js:644

public destroy(label, type)

The destroy method removes all evidence of the package cache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

tests/helpers/package-cache.js:659

public destroy(fromLabel, toLabel)

The clone method duplicates a cache. Some package managers can leverage a pre-existing state to speed up their installation.

Parameters:

Name Type Attribute Description
fromLabel String

The label for the cache to clone.

toLabel String

The label for the new cache.

The get method returns the directory for the cache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

Return:

String

The directory on disk which contains the cache.

tests/helpers/package-cache.js:619

public update(label, type, manifest, links): String

The update method aliases the create method.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

manifest String

The contents of the manifest file for the cache.

links Array

Packages to elide for install and link.

Return:

String

The directory on disk which contains the cache.

Private Methods

tests/helpers/package-cache.js:264

private __resetForTesting( )

The __resetForTesting puts things back in module scope.

tests/helpers/package-cache.js:253

private __setupForTesting( )

The __setupForTesting modifies things in module scope.

tests/helpers/package-cache.js:483

private _checkManifest(label, type, manifest): Boolean

The _checkManifest method compares the desired manifest to that which exists in the cache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

manifest String

The contents of the manifest file to compare to cache.

Return:

Boolean

true if identical.

tests/helpers/package-cache.js:274

private _cleanDirs( )

The _cleanDirs method deals with sync issues between the Configstore and what exists on disk. Non-existent directories are removed from this.dirs.

tests/helpers/package-cache.js:524

private _install(label, type)

The _install method installs the contents of the manifest into the specified package cache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

tests/helpers/package-cache.js:295

private _readManifest(label, type): String

The _readManifest method reads the on-disk manifest for the current cache and returns its value.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

Return:

String

The manifest file contents on disk.

The _removeLinks method removes from the dependencies of the manifest the assets which will be linked in so that we don't duplicate install. It saves off the values in the internal PackageCache metadata for restoration after linking as those values may be necessary.

It is also responsible for removing these links prior to making any changes to the specified cache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

The _restoreLinks method restores the dependencies from the internal PackageCache metadata so that the manifest matches its original state after performing the links.

It is also responsible for restoring these links into the PackageCache.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

tests/helpers/package-cache.js:542

private _upgrade(label, type)

The _upgrade method guarantees that the contents of the manifest are allowed to drift in a SemVer compatible manner. It ensures that CI is always running against the latest versions of all dependencies.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

tests/helpers/package-cache.js:326

private _writeManifest(label, type, manifest)

The _writeManifest method generates the on-disk folder for the package cache and saves the manifest into it. If it is a yarn package cache it will remove the existing lock file.

Parameters:

Name Type Attribute Description
label String

The label for the cache.

type String

The type of package cache.

manifest String

The contents of the manifest file to write to disk.

tests/helpers/package-cache.js:25

private bower(subcommand, [arguments], [options={}])

The bower command helper.

Parameters:

Name Type Attribute Description
subcommand String

The subcommand to be passed into bower.

arguments String
  • optional
  • multiple

Arguments to be passed into the bower subcommand.

options Object
  • optional
  • default: {}

The options passed into child_process.spawnSync. (https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options)

tests/helpers/package-cache.js:37

private npm(subcommand, [arguments], [options={}])

The npm command helper.

Parameters:

Name Type Attribute Description
subcommand String

The subcommand to be passed into npm.

arguments String
  • optional
  • multiple

Arguments to be passed into the npm subcommand.

options Object
  • optional
  • default: {}

The options passed into child_process.spawnSync. (https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options)

tests/helpers/package-cache.js:88

private translate(type, lookup)

The translate command is used to turn a consistent argument into appropriate values based upon the context in which it is used. It's a convenience helper to avoid littering lookups throughout the code.

Parameters:

Name Type Attribute Description
type String

Either 'bower', 'npm', or 'yarn'.

lookup String

Either 'manifest', 'path', or 'upgrade'.

tests/helpers/package-cache.js:49

private yarn(subcommand, [arguments], [options={}])

The yarn command helper.

Parameters:

Name Type Attribute Description
subcommand String

The subcommand to be passed into yarn.

arguments String
  • optional
  • multiple

Arguments to be passed into the yarn subcommand.

options Object
  • optional
  • default: {}

The options passed into child_process.spawnSync. (https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options)