Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
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;
});
importModuleFromOptions(baseOptions: OptionsObject, args: any[] = []): Tm {
const { typeName } = this;
const options = { ...baseOptions };
const module = options[typeName];
delete options[typeName];
if (!module || typeof module !== 'string') {
throw new TypeError(this.tool.msg('errors:moduleOptionMissingKey', { typeName }));
}
const nextArgs = [...args];
if (nextArgs.length === 0) {
nextArgs.push(options);
} else if (isObject(nextArgs[0])) {
nextArgs[0] = {
...nextArgs[0],
...options,
};
}
return this.importModule(module, nextArgs);
}
loadModule(module: string | OptionsObject | Tm, args: any[] = []): Tm {
if (this.contract && instanceOf(module, this.contract)) {
return module as Tm;
} else if (typeof module === 'string') {
return this.importModule(module, args);
} else if (isObject(module)) {
return this.importModuleFromOptions(module, args);
}
throw new TypeError(this.tool.msg('errors:moduleTypeInvalid', { typeName: this.typeName }));
}
register(name: ModuleName, plugin: Plugin, options?: PluginOptions, tool?: Tool): this {
if (!name.match(MODULE_NAME_PATTERN)) {
throw new Error(`A fully qualified module name is required for ${this.pluralName}.`);
}
if (!isObject(plugin)) {
throw new TypeError(
`Expected an object or class instance for the ${
this.singularName
}, found ${typeof plugin}.`,
);
}
this.debug('Validating plugin "%s"', name);
this.options.validate(plugin);
this.debug('Registering plugin "%s" with defined tool and triggering startup', name);
this.triggerStartup(plugin, tool);
this.plugins.push({
value = JSON5.parse(fs.readFileSync(filePath.path(), 'utf8'));
} else if (ext === '.js') {
value = requireModule(filePath);
if (typeof value === 'function') {
if (options.errorOnFunction) {
throw new Error(this.tool.msg('errors:configNoFunction', { name }));
} else {
value = value(...args);
}
}
} else {
throw new Error(this.tool.msg('errors:configUnsupportedExt', { ext }));
}
if (!isObject(value)) {
throw new Error(this.tool.msg('errors:configInvalidNamed', { name }));
}
this.parsedFiles.add(filePath.path());
return value;
}