tipi-cli
Version:
Project scaffolding for the entitled JavaScript developer
76 lines (62 loc) • 2.07 kB
JavaScript
const fs = require('fs');
const os = require('os');
const path = require('path');
const packageJson = require('package-json');
const pIf = require('p-if');
const npa = require('npm-package-arg');
const npdl = require('npmdl');
const values = require('lodash').values;
const semver = require('semver');
module.exports = getTemplate;
function getTemplate(name) {
const isLocalPath = name.charAt(0) === '.';
return Promise.resolve()
.then(pIf(isLocalPath, () => getDirectoryTemplate(name), () => getNpmTemplate(name)));
}
function getDirectoryTemplate(name) {
return Promise.resolve()
.then(() => path.resolve(process.cwd(), name));
}
function getNpmTemplate(name) {
const templateName = `tipi-template-${name}`;
const parsed = npa(templateName);
if (!parsed.type === 'range') {
return Promise.reject(new Error(`only templates hosted on npmjs.org are supported.`));
}
return Promise.resolve(packageJson(parsed.name))
.then(getMatchingVersionManifest(parsed))
.then(getPackageArchive(parsed.name));
}
function getMatchingVersionManifest(parsed) {
return pkg => {
if (parsed.spec in pkg['dist-tags']) {
const version = pkg['dist-tags'][parsed.spec];
return pkg.versions[version];
}
const matching = values(pkg.versions)
.filter(entry => semver.satisfies(entry.version, parsed.spec))
.sort((a, b) => semver.gt(a.version, b.version) ? a : b);
if (!matching.length) {
throw new Error(`${parsed.name} has no versions satisfying ${parsed.spec}. Available: ${Object.keys(matching).join(', ')}`);
}
return matching[0];
};
}
function getPackageArchive(name) {
return manifest => {
return downloadPackage(name, manifest.version);
};
}
function downloadPackage(name, version) {
return new Promise((resolve, reject) => {
const dir = path.resolve(os.tmpdir());
const result = path.resolve(dir, name, version, 'package', 'template');
const manifestPath = path.join('template', 'package.json');
npdl(dir)(name, version, manifestPath, err => {
if (err) {
reject(err);
}
resolve(result);
});
});
}