fixturify-project

When implementing JS build tooling it is common to have complete projects as fixture data. Unfortunately fixtures committed to disk can be somewhat to maintain and augment.

Usage no npm install needed!

<script type="module">
  import fixturifyProject from 'https://cdn.skypack.dev/fixturify-project';
</script>

README

node-fixturify-project

CI

When implementing JS build tooling it is common to have complete projects as fixture data. Unfortunately fixtures committed to disk can be somewhat to maintain and augment.

Basic Usage

yarn add fixturify-project
const { Project } = require('fixturify-project');
const project = new Project('rsvp', '3.1.4', {
  files: {
    'index.js': 'module.exports = "Hello, World!"',
  },
});

project.addDependency('mocha', '5.2.0');
project.addDependency('chai', '5.2.0');

project.pkg; // => the contents of package.json for the given project
project.files; // => read or write the set of files further

// if you don't set this, a new temp dir will be made for you when you writeSync()
project.baseDir = 'some/root/';

project.writeSync();

// after writeSync(), you can read project.baseDir even if you didn't set it
expect(fs.existsSync(join(project.baseDir, 'index.js'))).to.eql(true);

The above example produces the following files (and most importantly the appropriate file contents:

some/root/package.json
some/root/index.js
some/root/node_modules/mocha/package.json
some/root/node_modules/chai/package.json

Nesting Dependencies

addDependency returns another Project instance, so you can nest arbitrarily deep:

const { Project } = require('fixturify-project');

let project = new Project('rsvp');
let a = project.addDependency('a');
let b = a.addDependency('b');
let c = b.addDependency('c');

project.writeSync();

Which produces:

$TMPDIR/xxx/package.json
$TMPDIR/xxx/index.js
$TMPDIR/xxx/node_modules/a/package.json
$TMPDIR/xxx/node_modules/a/node_modules/b/package.json
$TMPDIR/xxx/node_modules/b/node_modules/b/node_modules/c/package.json

Linking to real dependencies

Instead of creating all packages from scratch, you can link to real preexisting packages. This lets you take a real working package and modify it and its dependencies and watch how it behaves.

const { Project } = require('fixturify-project');

let project = new Project();
let a = project.addDependency('a');

// explicit target
project.linkDependency('b', { target: '/example/b' });

// this will follow node resolution rules to lookup "c" from "../elsewhere"
project.linkDependency('c', { baseDir: '/example' });

// this will follow node resolution rules to lookup "my-aliased-name" from "../elsewhere"
project.linkDependency('d', { baseDir: '/example', resolveName: 'my-aliased-name' });

project.writeSync();

Produces:

$TMPDIR/xxx/package.json
$TMPDIR/xxx/index.js
$TMPDIR/xxx/node_modules/a/package.json
$TMPDIR/xxx/node_modules/a/node_modules/b -> /example/b
$TMPDIR/xxx/node_modules/b/node_modules/c -> /example/node_modules/c
$TMPDIR/xxx/node_modules/b/node_modules/d -> /example/node_modules/my-aliased-name

When constructing a whole Project from a directory, you can choose to link all dependencies instead of copying them in as Projects:

let project = Project.fromDir('./sample-project', { linkDeps: true });
project.files['extra.js'] = '// stuff';
project.write();

This will generate a new copy of sample-project, with symlinks to all its original dependencies, but with "extra.js" added.

By default, linkDeps will only link up dependencies (which is appropriate for libraries). If you want to also include devDependencies (which is appropriate for apps) you can use linkDevDeps instead.