Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
}
export class TestScript<a> extends Script {
name = 'test-script';
blueprint() {
// eslint-disable-next-line
return {} as $FixMe;
}
}
// Use core package since resources are located here
export const BEEMO_APP_PATH = Path.resolve('..', __dirname);
// Use a folder that should not cause issues / contain much code
export const BEEMO_TEST_ROOT = Path.resolve('../../../tests', __dirname);
export function mockTool(argv: Argv = []): Beemo {
const tool = new Beemo(argv, '', true);
Object.assign(tool.options, {
appName: 'beemo',
appPath: BEEMO_APP_PATH.path(),
root: BEEMO_TEST_ROOT.path(),
workspaceRoot: BEEMO_TEST_ROOT.path(),
});
tool.config = stubToolConfig({
configure: {
cleanup: false,
parallel: true,
},</a>
export function mockTool<
P extends ToolPluginRegistry = TestToolPlugins,
C extends ToolConfig = TestToolConfig
>(options?: Partial, config?: Partial, injectPlugin: boolean = true): Tool {
const tool = new Tool({
appName: 'test-boost',
// Match fixtures path
appPath: new Path(process.cwd(), 'tests/__fixtures__/app').path(),
...options,
});
// Register default plugins
if (injectPlugin) {
// @ts-ignore Ignore this for convenience
tool.registerPlugin('plugin', Plugin);
}
// Stub out standard objects
tool.args = stubArgs();
tool.config = stubToolConfig(config);
tool.package = stubPackageJson();
// Stub out methods
tool.debug = mockDebugger();
async execute(oldContext: ScriptContext, script: Script): Promise {
const context = oldContext.clone();
// Set the context so tasks inherit it
this.setContext(context);
// Update the cwd to point to the package root
if (this.options.packageRoot) {
context.cwd = new Path(this.options.packageRoot);
}
const { argv } = context;
this.debug('Executing script with args "%s"', argv.join(' '));
await script.onBeforeExecute.emit([context, argv]);
const args = parseArgs(argv, script.args());
let result = null;
try {
result = await script.execute(context, args);
// Queue and run sub-tasks
const queue = result as ExecuteQueue;
if (!importedModule || !moduleName) {
throw new Error(
this.tool.msg('errors:moduleImportFailed', {
modules: modulesToAttempt.join(', '),
typeName,
}),
);
}
if (!this.contract) {
return importedModule;
}
// An instance was returned instead of the class definition
if (instanceOf(importedModule, this.contract)) {
throw new TypeError(
this.tool.msg('errors:moduleClassInstanceExported', {
appName,
moduleName,
typeName,
}),
);
} else if (typeof importedModule !== 'function') {
throw new TypeError(this.tool.msg('errors:moduleClassDefRequired', { moduleName, typeName }));
}
const ModuleClass = importedModule as ConcreteConstructor;
const module = new ModuleClass(...args);
if (!instanceOf(module, this.contract)) {
throw new TypeError(
if (!module) {
throw new Error(this.msg('errors:moduleConfigMissing', { configName }));
}
// Allow for local development
if (module === '@local') {
this.debug('Using %s configuration module', chalk.yellow('@local'));
this.moduleRoot = new Path(process.cwd());
return this.moduleRoot;
}
// Reference a node module
const rootPath = Path.resolve(`node_modules/${module}`);
if (!rootPath.exists()) {
throw new Error(this.msg('errors:moduleMissing', { configName, module }));
}
this.debug('Found configuration module root path: %s', chalk.cyan(rootPath));
this.moduleRoot = rootPath;
return rootPath;
}
}
const { configName } = this.options;
const { module } = this.config;
this.debug('Locating configuration module root');
if (!module) {
throw new Error(this.msg('errors:moduleConfigMissing', { configName }));
}
// Allow for local development
if (module === '@local') {
this.debug('Using %s configuration module', chalk.yellow('@local'));
this.moduleRoot = new Path(process.cwd());
return this.moduleRoot;
}
// Reference a node module
const rootPath = Path.resolve(`node_modules/${module}`);
if (!rootPath.exists()) {
throw new Error(this.msg('errors:moduleMissing', { configName, module }));
}
this.debug('Found configuration module root path: %s', chalk.cyan(rootPath));
this.moduleRoot = rootPath;
return rootPath;
let name: string;
let plugin: Plugin;
let priority: number | undefined;
// Module name
if (typeof setting === 'string') {
name = setting;
plugin = this.loader.load(setting, options);
// Module name with options
} else if (Array.isArray(setting)) {
[name, , priority] = setting;
plugin = this.loader.load(name, setting[1] || options);
// Plugin directly
} else if (isObject(setting)) {
if (setting.name) {
name = setting.name;
plugin = setting;
priority = setting.priority;
} else {
throw new Error('Plugin object or class instance found without a `name` property.');
}
// Unknown setting
} else {
throw new Error(`Unknown plugin setting: ${setting}`);
}
this.register(plugin.name || name, plugin, { priority }, tool);
return plugin;
parseAndExtend(fileOrConfig: ConfigPathOrObject): ConfigLike {
let config: ConfigLike;
let baseDir = '';
// Parse out the object if a file path
if (fileOrConfig instanceof Path) {
config = this.parseFile(fileOrConfig);
baseDir = fileOrConfig.parent().path();
} else {
config = fileOrConfig;
}
// Verify we're working with an object
if (!isObject(config)) {
throw new Error(this.tool.msg('errors:configInvalid'));
}
const { extends: extendPaths } = config;
// Nothing to extend, so return the current config
if (!extendPaths || extendPaths.length === 0) {
return config;
}
// Resolve extend paths and inherit their config
const nextConfig = {};
const resolvedPaths = this.resolveExtendPaths(extendPaths, baseDir);
resolvedPaths.forEach(extendPath => {
if (this.parsedFiles.has(extendPath.path())) {
Object.keys(this).forEach(key => {
const prop = key as keyof this;
let value: any = this[prop];
if (Array.isArray(value)) {
value = [...value];
} else if (value instanceof Map) {
value = new Map(value);
} else if (value instanceof Set) {
value = new Set(value);
} else if (value instanceof Date) {
value = new Date(value.getTime());
} else if (isObject(value)) {
// Dont dereference instances, only plain objects
if (value.constructor === Object) {
value = { ...value };
}
}
context[prop] = value;
});
importModule(name: string | Path, args: any[] = []): Tm {
const { typeName } = this;
const { appName, scoped } = this.tool.options;
// Determine modules to attempt to load
const modulesToAttempt = [];
let isFilePath = false;
let importedModule: any = null;
let moduleName;
// File path
if (name instanceof Path || name.match(/^\.|\/|\\|[A-Z]:/u)) {
this.debug('Locating %s from path %s', typeName, color.filePath(name));
modulesToAttempt.push(Path.create(name).path());
isFilePath = true;
// Module name
} else {
this.debug('Locating %s module %s', typeName, color.moduleName(name));
if (scoped) {
modulesToAttempt.push(formatModuleName(appName, typeName, name, true));
}
modulesToAttempt.push(formatModuleName(appName, typeName, name));
// Additional scopes to load
this.scopes.forEach(otherScope => {
modulesToAttempt.push(
formatModuleName(otherScope, typeName, name, true),