ultimate-jekyll-manager
Version:
Ultimate Jekyll dependency manager
374 lines (310 loc) • 10.6 kB
JavaScript
// Libraries
const Manager = new (require('../build.js'));
const logger = Manager.logger('setup');
const argv = Manager.getArguments();
const path = require('path');
const jetpack = require('fs-jetpack');
const version = require('wonderful-version');
const fetch = require('wonderful-fetch');
const { execute, template, force } = require('node-powertools');
const NPM = require('npm-api');
const glob = require('glob').globSync;
const { minimatch } = require('minimatch');
// Load package
const package = Manager.getPackage('main');
const project = Manager.getPackage('project');
const config = Manager.getConfig('project');
// Dependency MAP
const DEPENDENCY_MAP = {
'gulp': 'dev',
}
module.exports = async function (options) {
// Fix options
options = options || {};
options.checkManager = force(options.checkManager || true, 'boolean');
options.checkNode = force(options.checkNode || true, 'boolean');
options.checkBundler = force(options.checkBundler || true, 'boolean');
options.checkRuby = force(options.checkRuby || true, 'boolean');
options.checkPeerDependencies = force(options.checkPeerDependencies || true, 'boolean');
options.setupScripts = force(options.setupScripts || true, 'boolean');
options.createCname = force(options.createCname || true, 'boolean');
options.fetchFirebaseAuth = force(options.fetchFirebaseAuth || true, 'boolean');
options.checkLocality = force(options.checkLocality || true, 'boolean');
options.updateBundle = force(options.updateBundle || true, 'boolean');
// Log
logger.log(`Welcome to ${package.name} v${package.version}!`);
logger.log(`options`, options);
// Prefix project
project.dependencies = project.dependencies || {};
project.devDependencies = project.devDependencies || {};
try {
// Log current working directory
await logCWD();
// Ensure this package is up-to-date
if (options.checkManager) {
await updateManager();
}
// Ensure proper node version
if (options.checkNode) {
await ensureNodeVersion();
}
// Ensure proper bundler version
if (options.checkBundler) {
await ensureBundlerVersion();
}
// Ensure proper ruby version
if (options.checkRuby) {
await ensureRubyVersion();
}
// Run the setup
if (options.checkPeerDependencies) {
await ensurePeerDependencies();
}
// Setup scripts
if (options.setupScripts) {
await setupScripts();
}
// Copy all files from src/defaults/dist on first run
// await copyDefaultDistFiles();
// Create CNAME
if (options.createCname) {
await createCname();
}
// Fetch firebase-auth files
if (options.fetchFirebaseAuth) {
await fetchFirebaseAuth();
}
// Check which locality we are using
if (options.checkLocality) {
await checkLocality();
}
// Check which locality we are using
if (options.updateBundle && !Manager.isServer()) {
await updateBundle();
}
} catch (e) {
// Throw error
throw e;
}
};
async function logCWD() {
logger.log('Current working directory:', process.cwd());
// logger.log('Current working directory 2:', await execute('pwd'));
// logger.log('Current working directory 3:', await execute('ls -al'));
}
async function updateManager() {
const npm = new NPM();
// Get the latest version
const installedVersion = project.devDependencies[package.name];
const latestVersion = await npm.repo(package.name)
.package()
.then((pkg) => {
return pkg.version;
}, (e) => {
return '0.0.0';
});
const isUpToDate = version.is(installedVersion, '>=', latestVersion);
const levelDifference = version.levelDifference(installedVersion, latestVersion);
// Log
logVersionCheck(package.name, installedVersion, latestVersion, isUpToDate);
// Quit if local
if (installedVersion.startsWith('file:')) {
return;
}
// Check if we need to update
if (!isUpToDate) {
// Quit if major version difference
if (levelDifference === 'major') {
return logger.error(`Major version difference detected. Please update to ${latestVersion} manually.`);
}
// Install the latest version
await install(package.name, latestVersion);
}
}
async function ensureNodeVersion() {
const installedVersion = version.clean(process.version);
const requiredVersion = version.clean(package.engines.node);
const isUpToDate = version.is(installedVersion, '>=', requiredVersion);
// Log
logVersionCheck('Node.js', installedVersion, requiredVersion, isUpToDate);
// Check if we need to update
if (!isUpToDate) {
throw new Error(`Node version is out-of-date. Required version is ${requiredVersion}.`);
}
}
async function ensureBundlerVersion() {
const installedVersion = version.clean(
(await execute('bundler -v', { log: false })).match(/(\d+\.\d+\.\d+)/)[0]
);
const requiredVersion = version.clean(package.engines.bundler);
const isUpToDate = version.is(installedVersion, '>=', requiredVersion);
// Log
logVersionCheck('Bundler', installedVersion, requiredVersion, isUpToDate);
// Check if we need to update
if (!isUpToDate) {
throw new Error(`Bundler version is out-of-date. Required version is ${requiredVersion}.`);
}
}
async function ensureRubyVersion() {
const installedVersion = version.clean(
(await execute('ruby -v', { log: false })).match(/(\d+\.\d+\.\d+)/)[0]
);
const requiredVersion = version.clean(package.engines.ruby);
const isUpToDate = version.is(installedVersion, '>=', requiredVersion);
// Log
logVersionCheck('Ruby', installedVersion, requiredVersion, isUpToDate);
// Check if we need to update
if (!isUpToDate) {
throw new Error(`Ruby version is out-of-date. Required version is ${requiredVersion}.`);
}
}
async function ensurePeerDependencies() {
const requiredPeerDependencies = package.peerDependencies || {};
// Loop through and make sure project has AT LEAST the required version
for (let [dependency, ver] of Object.entries(requiredPeerDependencies)) {
const projectDependencyVersion = version.clean(project?.dependencies?.[dependency] || project?.devDependencies?.[dependency]);
const location = DEPENDENCY_MAP[dependency] === 'dev' ? '--save-dev' : '';
const isUpToDate = version.is(projectDependencyVersion, '>=', ver);
// Clean version if needed
ver = version.clean(ver);
// Log
// logger.log('Checking peer dep:', dependency, '-->', projectDependencyVersion, '>=', ver);
logVersionCheck(dependency, projectDependencyVersion, ver, isUpToDate);
// Install if not found
if (
// Not found
!projectDependencyVersion
// Not the right version
|| !isUpToDate
) {
await install(dependency, ver, location);
}
}
}
function setupScripts() {
// Setup the scripts
project.scripts = project.scripts || {};
// Setup the scripts
Object.keys(package.projectScripts).forEach((key) => {
project.scripts[key] = package.projectScripts[key];
});
// Save the project
jetpack.write(path.join(process.cwd(), 'package.json'), project);
}
function checkLocality() {
const installedVersion = project.devDependencies[package.name];
if (installedVersion.startsWith('file:')) {
logger.warn(`⚠️⚠️⚠️ You are using the local version of ${package.name}. This WILL NOT WORK when published. ⚠️⚠️⚠️`);
}
}
async function updateBundle() {
// Log
logger.log('Running bundle install...');
await execute('bundle install', { log: true })
// Log
logger.log('Running bundle update...');
await execute('bundle update', { log: true })
}
function install(package, ver, location) {
// Default to latest
ver || 'latest';
// Clean version if needed
ver = ver === 'latest' ? ver : version.clean(ver);
// Build the command
let command = `npm install ${package}@${ver} ${location || '--save'}`;
// Log
logger.log('Installing:', command);
// Execute
return execute(command, { log: true })
.then(async () => {
// Read new project
const projectUpdated = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
// Log
logger.log('Installed:', package, ver);
// Update package object
project.dependencies = projectUpdated.dependencies;
project.devDependencies = projectUpdated.devDependencies;
});
}
// Create CNAME
async function createCname() {
// Get the CNAME
const url = config.url || 'https://template.itwcreativeworks.com';
const host = new URL(url).host
// Write to file
jetpack.write('dist/CNAME', host);
// Log
logger.log('Created CNAME');
}
// Fetch firebase-auth files
async function fetchFirebaseAuth() {
const managerConfig = config.settings['manager-configuration'];
const firebase = eval(`(${managerConfig})`)?.libraries?.firebase_app?.config;
const projectId = firebase.projectId || 'ultimate-jekyll';
const base = `https://${projectId}.firebaseapp.com`;
const files = [
{
remote: '__/auth/handler',
filename: 'handler.html',
},
{
remote: '__/auth/handler.js',
},
{
remote: '__/auth/experiments.js',
},
{
remote: '__/auth/iframe',
filename: 'iframe.html',
},
{
remote: '__/auth/iframe.js',
},
{
remote: '__/firebase/init.json',
}
]
const promises = [];
const output = './dist';
// Loop through files
files.forEach((file) => {
// Get the remote URL
const url = `${base}/${file.remote}`;
// Get the local path
const fileName = file.filename
? path.basename(file.filename)
: path.basename(file.remote);
const filePath = path.join(path.dirname(file.remote), fileName);
const finalPath = path.join(output, filePath);
// Push to promises
promises.push(
fetch(url, {
response: 'text',
tries: 3,
// log: true,
})
.then((r) => {
// Write to file
jetpack.write(finalPath,
'---\n'
+ `permalink: /${file.remote}\n`
+ '---\n'
+ '\n'
+ r
)
})
);
});
// Await all promises
await Promise.all(promises);
// Log
logger.log('Fetched firebase-auth files');
}
function logVersionCheck(name, installedVersion, latestVersion, isUpToDate) {
// Quit if local
if (installedVersion.startsWith('file:')) {
isUpToDate = true;
}
// Log
logger.log(`Checking if ${name} is up to date (${logger.format.bold(installedVersion)} >= ${logger.format.bold(latestVersion)}): ${isUpToDate ? logger.format.green('Yes') : logger.format.red('No')}`);
}