artillery
Version:
Cloud-scale load testing. https://www.artillery.io
129 lines (128 loc) • 5.02 kB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
if (typeof path === "string" && /^\.\.?\//.test(path)) {
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
});
}
return path;
};
import { createRequire } from 'node:module';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import createDebug from 'debug';
import { BUILTIN_PACKAGES_DIR } from "./builtin-packages.js";
const debug = createDebug('core');
const require = createRequire(import.meta.url);
// Additional paths to load plugins can be set via ARTILLERY_PLUGIN_PATH
// Additional plugin config mafy be set via ARTILLERY_PLUGINS (as JSON)
// Version may be: v1, v2, v3 or any
function loadPluginsConfig(pluginSpecs) {
let additionalPlugins = {};
if (process.env.ARTILLERY_PLUGINS) {
try {
additionalPlugins = JSON.parse(process.env.ARTILLERY_PLUGINS);
}
catch (ignoreErr) {
debug(ignoreErr);
}
}
return Object.assign({}, pluginSpecs, additionalPlugins);
}
async function loadPlugins(pluginSpecs, testScript, _opts) {
// Bare specifier first (user-installed copies win), bundled built-in
// packages second, ARTILLERY_PLUGIN_PATH entries last
let requirePaths = ['', BUILTIN_PACKAGES_DIR];
if (process.env.ARTILLERY_PLUGIN_PATH) {
requirePaths = requirePaths.concat(process.env.ARTILLERY_PLUGIN_PATH.split(':'));
}
pluginSpecs = loadPluginsConfig(pluginSpecs);
const results = {};
for (const [name, config] of Object.entries(pluginSpecs)) {
const result = await loadPlugin(name, config, requirePaths, testScript);
results[name] = result;
}
return results;
}
async function loadPlugin(name, config, requirePaths, testScript) {
// TODO: Take scope in directly - don't need the full script
const pluginConfigScope = config.scope || testScript.config.pluginsScope;
const pluginPrefix = pluginConfigScope
? pluginConfigScope
: 'artillery-plugin-';
const requireString = pluginPrefix + name;
let PluginExport;
let pluginErr;
let loadedFrom;
let version;
for (const p of requirePaths) {
debug('Looking for plugin in:', p);
try {
loadedFrom = path.join(p, requireString);
// Resolve with CJS semantics (bare specifiers, directories via
// package.json "main"), load with import() - handles both CJS
// and ESM plugins, including ESM with top-level await
const resolvedPath = require.resolve(loadedFrom);
const ns = await import(__rewriteRelativeImportExtension(pathToFileURL(resolvedPath).href));
// CJS: default === module.exports; ESM: unwrap default export,
// fall back to the namespace (named exports, e.g. Plugin)
PluginExport = ns.default ?? ns;
if (typeof PluginExport === 'function') {
version = 1;
}
else if (typeof PluginExport === 'object' &&
typeof PluginExport.Plugin === 'function') {
version = 2;
}
else if (typeof ns.Plugin === 'function') {
// ESM plugin with a named Plugin export alongside a
// non-function default export
PluginExport = ns;
version = 2;
} // TODO: Add v3
}
catch (err) {
debug(err);
pluginErr = err;
}
if (typeof PluginExport !== 'undefined') {
break;
}
}
if (!PluginExport) {
let msg;
if (!pluginErr) {
msg = `WARNING: Could not initialize plugin: ${name}`;
}
else {
const err = pluginErr;
if (err.code === 'MODULE_NOT_FOUND') {
msg = `WARNING: Plugin ${name} specified but module ${requireString} could not be found (${err.code})`;
}
else {
msg = `WARNING: Could not initialize plugin: ${name} (${err.message})`;
}
}
return {
name,
isLoaded: false,
isInitialized: false,
msg: msg,
error: pluginErr
};
}
else {
debug('Plugin %s loaded from %s', name, requireString);
return {
name,
isLoaded: true,
isInitialized: false,
PluginExport,
loadedFrom,
version
};
}
}
export { loadPlugins, loadPlugin, loadPluginsConfig };