Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .reaction/run/fs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import fs from 'fs';
import path from 'path';
import Log from './logger';

/**
* Synchronously check if a file or directory exists
* @param {String} searchPath - path to file or directory
* @return {Boolean} - returns true if file or directory exists
*/
export function exists(searchPath) {
try {
fs.statSync(searchPath);
return true;
} catch (e) {
return false;
}
}

/**
* Synchronously check if a file or directory is empty or doesn't exist
* @param {String} searchPath - path to file or directory
* @return {Boolean} returns true if file or directory is empty or missing
*/
export function isEmptyOrMissing(searchPath) {
let stat;
try {
stat = fs.statSync(searchPath);
} catch (e) {
return true;
}
if (stat.isDirectory()) {
const items = fs.readdirSync(searchPath);
return !items || !items.length;
}
const file = fs.readFileSync(searchPath);
return !file || !file.length;
}


/**
* Get an array of directory names in a given path
* @param {String} dir - path to a directory
* @return {Array} returns an array of directory names
*/
export function getDirectories(dir) {
try {
const files = fs.readdirSync(dir).filter((file) => {
return fs.statSync(path.join(dir, file)).isDirectory();
});
return files;
} catch(e) {
Log.error('Directory not found: ' + dir);
Log.error(e);
process.exit(1);
}
}
49 changes: 49 additions & 0 deletions .reaction/run/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Assumes Node 8.x
import _ from "lodash";
import childProcess from "child_process";
import Log from "./logger";
import loadPlugins from "./loadPlugins";
import loadStyles from "./loadStyles";
import provisionAssets from "./provisionAssets";

function run() {
let start, sec, ns;

start = process.hrtime();
Log.info("Setting up plugin imports...\n");
loadPlugins();
[sec, ns] = process.hrtime(start);
Log.info(`Setting up plugin imports took ${sec}s ${ns / 1000000}ms\n`);

start = process.hrtime();
Log.info("Setting up style imports...\n");
loadStyles();
[sec, ns] = process.hrtime(start);
Log.info(`Setting up style imports took ${sec}s ${ns / 1000000}ms\n`);

start = process.hrtime();
Log.info("Provisioning assets...\n");
provisionAssets();
[sec, ns] = process.hrtime(start);
Log.info(`Provisioning assets took ${sec}s ${ns / 1000000}ms\n`);

// Whatever debugging-related command line arguments were passed in to
// the first node process, forward them along through meteor
const inspect = process.argv
.filter((arg) => arg.startsWith("--inspect"))
.join(" ");
let cmd = `meteor run --no-lint --no-release-check --raw-logs ${inspect}`;

Log.info(`Running command: ${cmd}`);
cmd = `REACTION_METEOR_APP_COMMAND_START_TIME=${Date.now()} ${cmd}`;

try {
childProcess.execSync(cmd, { stdio: "inherit" });
} catch (err) {
Log.default(err);
Log.error("\nError: App failed to start");
process.exit(1);
}
}

run();
143 changes: 143 additions & 0 deletions .reaction/run/loadPlugins.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import fs from 'fs';
import path from 'path';
import childProcess from 'child_process';
import _ from 'lodash';
import Log from './logger';
import { exists, getDirectories } from './fs';

// add a message to the top of the plugins import file
const importFileMessage = `
/**
* ***** DO NOT EDIT THIS FILE MANUALLY *****
* This file is generated automatically by the Reaction
* plugin loader and will be reset at each startup.
*/
`;

/**
* Create a plugin imports file on client or server
* @param {String} file - absolute path to file to write
* @param {Array} imports - array of import path strings
* @return {Boolean} returns true if no error
*/
function generateImportsFile(file, imports) {
// create/reset imports file
try {
fs.writeFileSync(file, '');
fs.writeFileSync(file, importFileMessage);
} catch (e) {
Log.error(`Failed to reset plugins file at ${file}`);
process.exit(1);
}

// populate plugins file with imports
imports.forEach((importPath) => {
try {
fs.appendFileSync(file, `import '${importPath}';\n`);
} catch (e) {
Log.error(`Failed to write to plugins file at ${importPath}`);
process.exit(1);
}
});
}


/**
* Import Reaction plugins
* @param {String} baseDirPath - path to a plugins sub-directory (core/included/custom)
* @return {Object} - returns object with client, server, and registry path arrays
*/
function getImportPaths(baseDirPath) {

// get app root path
const appRoot = path.resolve('.').split('.meteor')[0];

// create the import path
const getImportPath = (pluginFile) => {
const importPath = '/' + path.relative(appRoot, pluginFile);
return importPath.replace(/\\/g, '/');
};

// get all plugin directories at provided base path
// (ignore directories starting with a dot '.')
const pluginDirs = _.reject(getDirectories(baseDirPath), (d) => d.charAt(0) === '.');

const clientImportPaths = [];
const serverImportPaths = [];
const registryImportPaths = [];

// read registry.json and require server/index.js if they exist
pluginDirs.forEach((plugin) => {
const clientImport = baseDirPath + plugin + '/client/index.js';
const serverImport = baseDirPath + plugin + '/server/index.js';
const registryImport = baseDirPath + plugin + '/register.js';
const packageDotJson = baseDirPath + plugin + '/package.json';

// import the client files if they exist
if (exists(clientImport)) {
clientImportPaths.push(getImportPath(clientImport.replace('/index.js', '')));
}

// import the server files if they exist
if (exists(serverImport)) {
serverImportPaths.push(getImportPath(serverImport.replace('/index.js', '')));
}

// import plugin registry files
if (exists(registryImport)) {
registryImportPaths.push(getImportPath(registryImport));
}

// run npm install if package.json exists
if (exists(packageDotJson)) {
Log.info(`Installing dependencies for ${plugin}...\n`);

try {
childProcess.execSync(`cd ${baseDirPath}${plugin} && meteor npm i`, { stdio: 'inherit' });
} catch (err) {
Log.error(`Failed to install npm dependencies for plugin: ${plugin}`);
process.exit(1);
}
}
});

return {
client: clientImportPaths,
server: serverImportPaths,
registry: registryImportPaths
};
}


/**
* Define base plugin paths
*/
const pluginsPath = path.resolve('.').split('.meteor')[0] + '/imports/plugins/';
const corePlugins = pluginsPath + 'core/';
const includedPlugins = pluginsPath + 'included/';
const customPlugins = pluginsPath + 'custom/';


export default function loadPlugins() {
// get imports from each plugin directory
const core = getImportPaths(corePlugins);
const included = getImportPaths(includedPlugins);
const custom = getImportPaths(customPlugins);

// concat all imports
const clientImports = [].concat(core.client, included.client, custom.client);
const serverImports = [].concat(
core.server,
included.server,
custom.server,
core.registry,
included.registry,
custom.registry
);

const appRoot = path.resolve('.').split('.meteor')[0];

// create import files on client and server and write import statements
generateImportsFile(`${appRoot}/client/plugins.js`, clientImports);
generateImportsFile(`${appRoot}/server/plugins.js`, serverImports);
}
137 changes: 137 additions & 0 deletions .reaction/run/loadStyles.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import fs from 'fs';
import path from 'path';
import Log from './logger';
import { exists, getDirectories } from './fs';

// add a message to the top of the plugins import file
const importFileMessage = `
/**
* ***** DO NOT EDIT THIS FILE MANUALLY *****
* This file is generated automatically by the Reaction
* style loader and will be reset at each startup.
*/
`;

/**
* Create a plugin imports file on client or server
* @param {String} file - absolute path to file to write
* @param {Array} imports - array of import path strings
* @return {Boolean} returns true if no error
*/
function generateImportsFile(file, imports) {
// Don't create a file if there is nothing to import.
// This prevents the need to have to include all
// css preprocessors since CSS / LESS is predominately used
if (imports.length) {
// create/reset imports file
try {
fs.writeFileSync(file, '');
fs.writeFileSync(file, importFileMessage);
} catch (e) {
Log.error(`Failed to reset plugins file at ${file}`);
process.exit(1);
}

// populate plugins file with imports
imports.forEach((importPath) => {
try {
fs.appendFileSync(file, `@import "${importPath}";\n`);
} catch (e) {
Log.error(`Failed to write to plugins file at ${importPath}`);
process.exit(1);
}
});
}
}


/**
* Import Reaction plugins
* @param {String} baseDirPath - path to a plugins sub-directory (core/included/custom)
* @return {Object} - returns object with client, server, and registry path arrays
*/
function getImportPaths(baseDirPath) {

// get app root path
const appRoot = path.resolve('.').split('.meteor')[0];

// create the import path
const getImportPath = (pluginFile) => {
const importPath = '/' + path.relative(appRoot, pluginFile);
return importPath.replace(/\\/g, '/');
};

// get all plugin directories at provided base path
const pluginDirs = getDirectories(baseDirPath);

const cssImportPaths = [];
const lessImportPaths = [];
const stylusImportPaths = [];
const scssImportPaths = [];

// read registry.json and require server/index.js if they exist
pluginDirs.forEach((plugin) => {
const cssImport = baseDirPath + plugin + '/client/index.css';
const lessImport = baseDirPath + plugin + '/client/index.less';
const stylusImport = baseDirPath + plugin + '/client/index.styl';
const scssImport = baseDirPath + plugin + '/client/index.scss';

// import the client CSS files if they exist
if (exists(cssImport)) {
cssImportPaths.push(getImportPath(cssImport));
}

// import the client LESS files if they exist
if (exists(lessImport)) {
lessImportPaths.push(getImportPath(lessImport));
}

// import the client STYLUS files if they exist
if (exists(stylusImport)) {
stylusImportPaths.push(getImportPath(stylusImport));
}

// import the client SCSS files if they exist
if (exists(scssImport)) {
scssImportPaths.push(getImportPath(scssImport));
}
});

return {
css: cssImportPaths,
less: lessImportPaths,
stylus: stylusImportPaths,
scss: scssImportPaths
};
}


/**
* Define base plugin paths
*/
const pluginsPath = path.resolve('.').split('.meteor')[0] + '/imports/plugins/';
const corePlugins = pluginsPath + 'core/';
const includedPlugins = pluginsPath + 'included/';
const customPlugins = pluginsPath + 'custom/';


export default function loadStyles() {
// get style imports from each plugin directory
const core = getImportPaths(corePlugins);
const included = getImportPaths(includedPlugins);
const custom = getImportPaths(customPlugins);

// concat all imports
const cssImports = [].concat(core.css, included.css, custom.css);
const lessImports = [].concat(core.less, included.less, custom.less);
const stylusImports = [].concat(core.stylus, included.stylus, custom.stylus);
const scssImports = [].concat(core.scss, included.scss, custom.scss);

const appRoot = path.resolve('.').split('.meteor')[0];

// create style import files on client and write import statements
generateImportsFile(appRoot + '/client/plugins.css', cssImports);
generateImportsFile(appRoot + '/client/plugins.less', lessImports);
generateImportsFile(appRoot + '/client/plugins.styl', stylusImports);
generateImportsFile(appRoot + '/client/plugins.scss', scssImports);
}
Loading