@red-hat-developer-hub/cli
Version:
CLI for developing Backstage plugins and apps
735 lines (727 loc) • 28.2 kB
JavaScript
var getPackages = require('@manypkg/get-packages');
var parsers = require('@yarnpkg/parsers');
var chalk = require('chalk');
var fs = require('fs-extra');
var semver = require('semver');
var child_process = require('child_process');
var node_module = require('node:module');
var path = require('path');
var productionPack = require('../../lib/packager/productionPack.cjs.js');
var paths = require('../../lib/paths.cjs.js');
var tasks = require('../../lib/tasks.cjs.js');
var Lockfile = require('../../lib/versioning/Lockfile.cjs.js');
var backendUtils = require('./backend-utils.cjs.js');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
var fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
var semver__namespace = /*#__PURE__*/_interopNamespaceCompat(semver);
var path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
async function backend(opts) {
const targetRelativePath = "dist-dynamic";
const target = path__namespace.join(paths.paths.targetDir, targetRelativePath);
const yarn = "yarn";
const yarnVersion = child_process.execSync(`${yarn} --version`).toString().trim();
const pkgContent = await fs__namespace.readFile(
paths.paths.resolveTarget("package.json"),
"utf8"
);
const pkg = JSON.parse(pkgContent);
if (pkg.bundled) {
throw new Error(
`Packages exported as dynamic backend plugins should not have the ${chalk__default.default.cyan(
"bundled"
)} field set to ${chalk__default.default.cyan("true")}`
);
}
const derivedPackageName = `${pkg.name}-dynamic`;
const packagesToEmbed = opts.embedPackage || [];
const allowNative = opts.allowNativePackage || [];
const suppressNative = opts.suppressNativePackage || [];
const ignoreVersionCheck = opts.ignoreVersionCheck || [];
const monoRepoPackages = await getPackages.getPackages(paths.paths.targetDir);
const embeddedResolvedPackages = await searchEmbedded(
pkg,
packagesToEmbed,
monoRepoPackages,
node_module.createRequire(path__namespace.join(paths.paths.targetDir, "package.json")),
[]
);
const embeddedPackages = embeddedResolvedPackages.map((e) => e.packageName);
const unusedEmbeddedPackages = packagesToEmbed.filter(
(e) => !embeddedPackages.includes(e)
);
if (unusedEmbeddedPackages.length > 0) {
tasks.Task.log(
chalk__default.default.yellow(
`Some embedded packages are not part of the plugin transitive dependencies:${chalk__default.default.cyan(
["", ...unusedEmbeddedPackages].join("\n- ")
)}`
)
);
}
const stringOrRegexp = (s) => s.startsWith("/") && s.endsWith("/") ? new RegExp(s.slice(1, -1)) : s;
const moveToPeerDependencies = [
/@backstage\//,
...(opts.sharedPackage || []).filter((p) => !p.startsWith("!")).map(stringOrRegexp)
];
const dontMoveToPeerDependencies = (opts.sharedPackage || []).filter((p) => p.startsWith("!")).map((p) => p.slice(1)).map(stringOrRegexp);
dontMoveToPeerDependencies.push(...embeddedPackages);
const sharedPackagesRules = {
include: moveToPeerDependencies,
exclude: dontMoveToPeerDependencies
};
if (opts.clean) {
await fs__namespace.remove(target);
}
await fs__namespace.mkdirs(target);
await fs__namespace.writeFile(
path__namespace.join(target, ".gitignore"),
`
*
${opts.trackDynamicManifestAndLockFile ? `
!package.json
!yarn.lock
` : ""}`
);
if (suppressNative.length > 0) {
for (const toSuppress of suppressNative) {
await fs__namespace.mkdirs(path__namespace.join(target, "embedded", toSuppress));
await fs__namespace.writeFile(
path__namespace.join(target, "embedded", toSuppress, "package.json"),
JSON.stringify(
{
name: toSuppress,
main: "index.js"
},
void 0,
2
)
);
await fs__namespace.writeFile(
path__namespace.join(target, "embedded", toSuppress, "index.js"),
`
throw new Error(
'The package "${toSuppress}" has been marked as a native module and removed from this dynamic plugin package "${derivedPackageName}", as native modules are not currently supported by dynamic plugins'
);`
);
}
}
const embeddedPeerDependencies = {};
for (const embedded of embeddedResolvedPackages) {
const embeddedDestRelativeDir = embeddedPackageRelativePath(embedded);
const embeddedDestDir = path__namespace.join(target, embeddedDestRelativeDir);
if (!embedded.alreadyPacked) {
if (opts.build) {
tasks.Task.log(
`Building embedded package ${chalk__default.default.cyan(
embedded.packageName
)} in ${chalk__default.default.cyan(embedded.dir)}`
);
await tasks.Task.forCommand(`${yarn} build`, {
cwd: embedded.dir,
optional: false
});
}
tasks.Task.log(
`Packing embedded package ${chalk__default.default.cyan(
embedded.packageName
)} in ${chalk__default.default.cyan(embedded.dir)} to ${chalk__default.default.cyan(
embeddedDestRelativeDir
)}`
);
await productionPack.productionPack({
packageDir: embedded.dir,
targetDir: embeddedDestDir
});
} else {
tasks.Task.log(
`Copying embedded package ${chalk__default.default.cyan(
embedded.packageName
)} from ${chalk__default.default.cyan(embedded.dir)} to ${chalk__default.default.cyan(
embeddedDestRelativeDir
)}`
);
fs__namespace.rmSync(embeddedDestDir, { force: true, recursive: true });
fs__namespace.cpSync(embedded.dir, embeddedDestDir, { recursive: true });
}
if (fs__namespace.pathExistsSync(path__namespace.join(embeddedDestDir, "node_modules"))) {
fs__namespace.rmSync(path__namespace.join(embeddedDestDir, "node_modules"), {
force: true,
recursive: true
});
}
tasks.Task.log(
`Customizing embedded package ${chalk__default.default.cyan(
embedded.packageName
)} for dynamic loading`
);
await customizeForDynamicUse({
embedded: embeddedResolvedPackages,
isYarnV1: yarnVersion.startsWith("1."),
monoRepoPackages,
sharedPackages: sharedPackagesRules,
overridding: {
private: true,
version: `${embedded.version}+embedded`
},
after: (embeddedPkg) => {
if (embeddedPkg.peerDependencies) {
Object.entries(embeddedPkg.peerDependencies).forEach(
([name, version]) => {
backendUtils.addToDependenciesForModule({
dependency: { name, version },
dependencies: embeddedPeerDependencies,
ignoreVersionCheck,
module: embeddedPkg.name
});
}
);
}
}
})(path__namespace.join(embeddedDestDir, "package.json"));
}
const embeddedDependenciesResolutions = embeddedResolvedPackages.reduce(
(resolutions, embeddedPkg) => ({
...resolutions,
...{
[embeddedPkg.packageName]: `file:./${embeddedPackageRelativePath(embeddedPkg)}`
}
}),
{}
);
if (opts.build) {
tasks.Task.log(`Building main package`);
await tasks.Task.forCommand(`${yarn} build`, {
cwd: paths.paths.targetDir,
optional: false
});
}
tasks.Task.log(
`Packing main package to ${chalk__default.default.cyan(
path__namespace.join(targetRelativePath, "package.json")
)}`
);
await productionPack.productionPack({
packageDir: "",
targetDir: target
});
if (fs__namespace.pathExistsSync(path__namespace.join(target, "dist-dynamic"))) {
fs__namespace.rmSync(path__namespace.join(target, "dist-dynamic"), {
force: true,
recursive: true
});
}
tasks.Task.log(
`Customizing main package in ${chalk__default.default.cyan(
path__namespace.join(targetRelativePath, "package.json")
)} for dynamic loading`
);
await customizeForDynamicUse({
embedded: embeddedResolvedPackages,
isYarnV1: yarnVersion.startsWith("1."),
monoRepoPackages,
sharedPackages: sharedPackagesRules,
overridding: {
name: derivedPackageName,
bundleDependencies: true,
// We remove scripts, because they do not make sense for this derived package.
// They even bring errors, especially the pre-pack and post-pack ones:
// we want to be able to use npm pack on this derived package to distribute it as a dynamic plugin,
// and obviously this should not trigger the backstage pre-pack or post-pack actions
// which are related to the packaging of the original static package.
scripts: {}
},
additionalResolutions: {
...embeddedDependenciesResolutions,
...suppressNative.map((nativePkg) => ({
[nativePkg]: path__namespace.join("file:./embedded", nativePkg)
})).reduce((prev, curr) => ({ ...prev, ...curr }), {})
},
after(mainPkg) {
if (Object.keys(embeddedPeerDependencies).length === 0) {
return;
}
tasks.Task.log(
`Hoisting peer dependencies of embedded packages to the main package`
);
const mainPeerDependencies = mainPkg.peerDependencies || {};
backendUtils.addToMainDependencies(
embeddedPeerDependencies,
mainPeerDependencies,
ignoreVersionCheck
);
if (Object.keys(mainPeerDependencies).length > 0) {
mainPkg.peerDependencies = mainPeerDependencies;
}
}
})(path__namespace.resolve(target, "package.json"));
const yarnLock = path__namespace.resolve(target, "yarn.lock");
const yarnLockExists = await fs__namespace.pathExists(yarnLock);
if (!yarnLockExists) {
let staticPluginYarnLock;
if (await fs__namespace.pathExists(path__namespace.join(paths.paths.targetDir, "yarn.lock"))) {
staticPluginYarnLock = path__namespace.join(paths.paths.targetDir, "yarn.lock");
} else if (await fs__namespace.pathExists(path__namespace.join(paths.paths.targetRoot, "yarn.lock"))) {
staticPluginYarnLock = path__namespace.join(paths.paths.targetRoot, "yarn.lock");
}
if (!staticPluginYarnLock) {
throw new Error(
`Could not find the static plugin ${chalk__default.default.cyan(
"yarn.lock"
)} file in either the local folder or the monorepo root (${chalk__default.default.cyan(
paths.paths.targetRoot
)})`
);
}
await fs__namespace.copyFile(staticPluginYarnLock, yarnLock);
if (!opts.install) {
tasks.Task.log(
chalk__default.default.yellow(
`Last export step (${chalk__default.default.cyan(
"yarn install"
)} has been disabled: the dynamic plugin package ${chalk__default.default.cyan(
"yarn.lock"
)} file will be inconsistent until ${chalk__default.default.cyan(
"yarn install"
)} is run manually`
)
);
}
}
if (opts.install) {
tasks.Task.log(`Installing private dependencies of the main package`);
const logFile = "yarn-install.log";
const redirect = `> ${logFile}`;
const yarnInstall = yarnVersion.startsWith("1.") ? `${yarn} install --production${yarnLockExists ? " --frozen-lockfile" : ""} ${redirect}` : `${yarn} install${yarnLockExists ? " --immutable" : " --no-immutable"} ${redirect}`;
await tasks.Task.forCommand(yarnInstall, { cwd: target, optional: false });
await fs__namespace.remove(paths.paths.resolveTarget(targetRelativePath, ".yarn"));
tasks.Task.log(`Validating private dependencies`);
const lockFile = await Lockfile.Lockfile.load(yarnLock);
const sharedPackagesInPrivateDeps = [];
for (const key of lockFile.keys()) {
const entry = lockFile.get(key);
if (!entry) {
continue;
}
if (`${pkg.name}-dynamic` === key) {
continue;
}
if (embeddedPackages.includes(key)) {
continue;
}
if (isPackageShared(key, sharedPackagesRules)) {
sharedPackagesInPrivateDeps.push(key);
}
}
if (sharedPackagesInPrivateDeps.length > 0) {
const dynamicPkgContent = await fs__namespace.readFile(
path__namespace.resolve(target, "package.json"),
"utf8"
);
const dynamicPkg = JSON.parse(dynamicPkgContent);
const lockfileContents = await fs__namespace.readFile(yarnLock, "utf8");
let data;
try {
data = parsers.parseSyml(lockfileContents);
} catch (err) {
throw new Error(`Failed parsing ${chalk__default.default.cyan(yarnLock)}: ${err}`);
}
const packagesToProbablyEmbed = [];
for (const dep in dynamicPkg.dependencies || []) {
if (!Object.prototype.hasOwnProperty.call(dynamicPkg.dependencies, dep)) {
continue;
}
const matchingEntry = Object.entries(data).find(([q, _]) => {
return q.startsWith(`${dep}@`) && (q.includes(`@${dynamicPkg.dependencies[dep]}`) || q.includes(`@npm:${dynamicPkg.dependencies[dep]}`));
});
if (matchingEntry) {
const yarnEntry = matchingEntry[1];
if (yarnEntry.dependencies) {
if (Object.keys(yarnEntry.dependencies).some((d) => {
return isPackageShared(d, sharedPackagesRules);
})) {
packagesToProbablyEmbed.push(dep);
}
}
}
}
throw new Error(
`Following shared package(s) should not be part of the plugin private dependencies:${chalk__default.default.cyan(
["", ...sharedPackagesInPrivateDeps].join("\n- ")
)}
Either unshare them with the ${chalk__default.default.cyan(
"--shared-package !<package>"
)} option, or use the ${chalk__default.default.cyan(
"--embed-package"
)} to embed the following packages which use shared dependencies:${chalk__default.default.cyan(
["", ...packagesToProbablyEmbed].join("\n- ")
)}`
);
}
const nativePackages = [];
for await (const nativePkg of backendUtils.gatherNativeModules(target)) {
if (!allowNative.includes(nativePkg)) {
nativePackages.push(nativePkg);
}
}
if (nativePackages.length > 0) {
throw new Error(
`Dynamic plugins do not support native plugins. the following native modules have been transitively detected:${chalk__default.default.cyan(
["", ...nativePackages].join("\n- ")
)}`
);
}
tasks.Task.log(`Validating plugin entry points`);
const validateEntryPointsError = validatePluginEntryPoints(target);
if (validateEntryPointsError) {
throw new Error(validateEntryPointsError);
}
await fs__namespace.remove(paths.paths.resolveTarget(targetRelativePath, logFile));
}
return target;
}
async function searchEmbedded(pkg, packagesToEmbed, monoRepoPackages, req, alreadyResolved) {
const embedded = [...packagesToEmbed];
let regex = void 0;
switch (pkg.backstage?.role) {
case "backend-plugin":
regex = /-backend$/;
break;
case "backend-plugin-module":
regex = /-backend-module-.+$/;
break;
case "node-library":
regex = /-node$/;
break;
}
if (regex) {
const commonPackage = pkg.name.replace(regex, "-common");
if (commonPackage !== pkg.name && !alreadyResolved.find((r) => r.packageName === commonPackage)) {
embedded.push(commonPackage);
}
const nodePackage = pkg.name.replace(regex, "-node");
if (nodePackage !== pkg.name && !alreadyResolved.find((r) => r.packageName === nodePackage)) {
embedded.push(nodePackage);
}
}
const resolved = [];
if (pkg.dependencies) {
for (const dep in pkg.dependencies || []) {
if (!Object.prototype.hasOwnProperty.call(pkg.dependencies, dep)) {
continue;
}
if (embedded.includes(dep)) {
const dependencyVersion = pkg.dependencies[dep];
const relatedMonoRepoPackages = monoRepoPackages.packages.filter(
(p) => p.packageJson.name === dep
);
if (relatedMonoRepoPackages.length > 1) {
throw new Error(
`Two packages named '${dep}' exist in the monorepo structure: this is not supported.`
);
}
if (relatedMonoRepoPackages.length === 0 && dependencyVersion.startsWith("workspace:")) {
throw new Error(
`No package named '${dep}' exist in the monorepo structure.`
);
}
let resolvedPackage;
let resolvedPackageDir;
let alreadyPacked = false;
if (relatedMonoRepoPackages.length === 1) {
const monoRepoPackage = relatedMonoRepoPackages[0];
let isResolved = false;
if (dependencyVersion.startsWith("workspace:")) {
isResolved = checkWorkspacePackageVersion(dependencyVersion, {
dir: monoRepoPackage.dir,
version: monoRepoPackage.packageJson.version
});
} else if (semver__namespace.satisfies(
monoRepoPackage.packageJson.version,
dependencyVersion
)) {
isResolved = true;
}
if (!isResolved) {
throw new Error(
`Monorepo package named '${dep}' at '${monoRepoPackage.dir}' doesn't satisfy dependency version requirement in parent package '${pkg.name}'.`
);
}
resolvedPackage = JSON.parse(
await fs__namespace.readFile(
paths.paths.resolveTarget(
path__namespace.join(monoRepoPackage.dir, "package.json")
),
"utf8"
)
);
resolvedPackageDir = monoRepoPackage.dir;
} else {
const resolvedPackageJson = req.resolve(
path__namespace.join(dep, "package.json")
);
resolvedPackageDir = path__namespace.dirname(resolvedPackageJson);
resolvedPackage = JSON.parse(
await fs__namespace.readFile(resolvedPackageJson, "utf8")
);
if (!semver__namespace.satisfies(resolvedPackage.version, dependencyVersion)) {
throw new Error(
`Resolved package named '${dep}' at '${resolvedPackageDir}' doesn't satisfy dependency version requirement in parent package '${pkg.name}': '${resolvedPackage.version}', '${dependencyVersion}'.`
);
}
alreadyPacked = !resolvedPackage.main?.endsWith(".ts");
}
if (resolvedPackage.bundled) {
throw new Error(
'Packages embedded inside dynamic backend plugins should not have the "bundled" field set to true'
);
}
if (![...alreadyResolved, ...resolved].find(
(p) => p.dir === resolvedPackageDir
)) {
resolved.push({
dir: resolvedPackageDir,
packageName: resolvedPackage.name,
version: resolvedPackage.version ?? "0.0.0",
parentPackageName: pkg.name,
alreadyPacked
});
resolved.push(
...await searchEmbedded(
resolvedPackage,
embedded,
monoRepoPackages,
node_module.createRequire(path__namespace.join(resolvedPackageDir, "package.json")),
[...alreadyResolved, ...resolved]
)
);
}
}
}
}
return resolved;
}
function checkWorkspacePackageVersion(requiredVersionSpec, pkg) {
const versionDetail = requiredVersionSpec.replace(/^workspace:/, "");
return pkg.dir === versionDetail || versionDetail === "*" || versionDetail === "~" || versionDetail === "^" || semver__namespace.satisfies(pkg.version, versionDetail);
}
function customizeForDynamicUse(options) {
return async (dynamicPkgPath) => {
const dynamicPkgContent = await fs__namespace.readFile(dynamicPkgPath, "utf8");
const pkgToCustomize = JSON.parse(
dynamicPkgContent
);
for (const field in options.overridding || {}) {
if (!Object.prototype.hasOwnProperty.call(options.overridding, field)) {
continue;
}
pkgToCustomize[field] = options.overridding[field];
}
pkgToCustomize.files = pkgToCustomize.files?.filter(
(f) => !f.startsWith("dist-dynamic/")
);
if (pkgToCustomize.dependencies) {
for (const dep in pkgToCustomize.dependencies) {
if (!Object.prototype.hasOwnProperty.call(
pkgToCustomize.dependencies,
dep
)) {
continue;
}
const dependencyVersionSpec = pkgToCustomize.dependencies[dep];
if (dependencyVersionSpec.startsWith("workspace:")) {
let resolvedVersion;
const rangeSpecifier = dependencyVersionSpec.replace(
/^workspace:/,
""
);
const embeddedDep = options.embedded.find(
(e) => e.packageName === dep && checkWorkspacePackageVersion(dependencyVersionSpec, e)
);
if (embeddedDep) {
resolvedVersion = embeddedDep.version;
} else if (options.monoRepoPackages) {
const relatedMonoRepoPackages = options.monoRepoPackages.packages.filter(
(p) => p.packageJson.name === dep
);
if (relatedMonoRepoPackages.length > 1) {
throw new Error(
`Two packages named ${chalk__default.default.cyan(
dep
)} exist in the monorepo structure: this is not supported.`
);
}
if (relatedMonoRepoPackages.length === 1 && checkWorkspacePackageVersion(dependencyVersionSpec, {
dir: relatedMonoRepoPackages[0].dir,
version: relatedMonoRepoPackages[0].packageJson.version
})) {
resolvedVersion = rangeSpecifier === "^" || rangeSpecifier === "~" ? rangeSpecifier + relatedMonoRepoPackages[0].packageJson.version : relatedMonoRepoPackages[0].packageJson.version;
}
}
if (!resolvedVersion) {
throw new Error(
`Workspace dependency ${chalk__default.default.cyan(dep)} of package ${chalk__default.default.cyan(
pkgToCustomize.name
)} doesn't exist in the monorepo structure: maybe you should embed it ?`
);
}
pkgToCustomize.dependencies[dep] = resolvedVersion;
}
if (isPackageShared(dep, options.sharedPackages)) {
tasks.Task.log(` moving ${chalk__default.default.cyan(dep)} to peerDependencies`);
pkgToCustomize.peerDependencies ||= {};
pkgToCustomize.peerDependencies[dep] = pkgToCustomize.dependencies[dep];
delete pkgToCustomize.dependencies[dep];
continue;
}
if (options.isYarnV1) {
const embeddedDep = options.embedded.find(
(e) => e.packageName === dep && checkWorkspacePackageVersion(dependencyVersionSpec, e)
);
if (embeddedDep) {
pkgToCustomize.dependencies[dep] = `file:./${embeddedPackageRelativePath(embeddedDep)}`;
}
}
}
}
pkgToCustomize.devDependencies = {};
const overrides = pkgToCustomize.overrides || {};
pkgToCustomize.overrides = {
// The following lines are a workaround for the fact that the @aws-sdk/util-utf8-browser package
// is not compatible with the NPM 9+, so that `npm pack` would not grab the Javascript files.
// This package has been deprecated in favor of @smithy/util-utf8.
//
// See https://github.com/aws/aws-sdk-js-v3/issues/5305.
"@aws-sdk/util-utf8-browser": {
"@smithy/util-utf8": "^2.0.0"
},
...overrides,
...options.additionalOverrides || {}
};
const resolutions = pkgToCustomize.resolutions || {};
pkgToCustomize.resolutions = {
// The following lines are a workaround for the fact that the @aws-sdk/util-utf8-browser package
// is not compatible with the NPM 9+, so that `npm pack` would not grab the Javascript files.
// This package has been deprecated in favor of @smithy/util-utf8.
//
// See https://github.com/aws/aws-sdk-js-v3/issues/5305.
"@aws-sdk/util-utf8-browser": "npm:@smithy/util-utf8@~2",
...resolutions,
...options.additionalResolutions || {}
};
if (options.after) {
options.after(pkgToCustomize);
}
await fs__namespace.writeJson(dynamicPkgPath, pkgToCustomize, {
encoding: "utf8",
spaces: 2
});
};
}
function isPackageShared(pkgName, rules) {
function test(str, expr) {
if (typeof expr === "string") {
return str === expr;
}
return expr.test(str);
}
if ((rules?.exclude || []).some((dontMove) => test(pkgName, dontMove))) {
return false;
}
if ((rules?.include || []).some((move) => test(pkgName, move))) {
return true;
}
return false;
}
function validatePluginEntryPoints(target) {
const dynamicPluginRequire = node_module.createRequire(`${target}/package.json`);
function requireModule(modulePath) {
try {
return dynamicPluginRequire(modulePath);
} catch (e) {
if (e?.code !== "ERR_UNSUPPORTED_DIR_IMPORT" && e?.name !== SyntaxError.name || dynamicPluginRequire.extensions[".ts"] !== void 0) {
throw e;
}
}
tasks.Task.log(
` adding typescript extension support to enable entry point validation`
);
let nodeTransform;
try {
nodeTransform = dynamicPluginRequire.resolve(
"@backstage/cli/config/nodeTransform.cjs"
);
} catch (e) {
tasks.Task.log(
` => unable to find '@backstage/cli/config/nodeTransform.cjs' in the plugin context`
);
}
if (nodeTransform) {
dynamicPluginRequire(nodeTransform);
} else {
tasks.Task.log(
` => searching for 'ts-node' (legacy mode before backage 1.24.0)`
);
let tsNode;
try {
tsNode = dynamicPluginRequire.resolve("ts-node");
} catch (e) {
tasks.Task.log(` => unable to find 'ts-node' in the plugin context`);
}
if (tsNode) {
dynamicPluginRequire(tsNode).register({
transpileOnly: true,
project: path__namespace.resolve(paths.paths.targetRoot, "tsconfig.json"),
compilerOptions: {
module: "CommonJS"
}
});
}
}
return dynamicPluginRequire(modulePath);
}
try {
const pluginModule = requireModule(target);
const alphaPackage = path__namespace.resolve(target, "alpha");
const pluginAlphaModule = fs__namespace.pathExistsSync(alphaPackage) ? requireModule(alphaPackage) : void 0;
if (![pluginAlphaModule, pluginModule].filter((m) => m !== void 0).some(backendUtils.isValidPluginModule)) {
return `Backend plugin is not valid for dynamic loading: it should either export a ${chalk__default.default.cyan(
"BackendFeature"
)} or ${chalk__default.default.cyan(
"BackendFeatureFactory"
)} as default export, or export a ${chalk__default.default.cyan(
"const dynamicPluginInstaller: BackendDynamicPluginInstaller"
)} field as dynamic loading entrypoint`;
}
} catch (e) {
return `Unable to validate plugin entry points: ${e}`;
}
return "";
}
function embeddedPackageRelativePath(p) {
return path__namespace.join(
"embedded",
p.packageName.replace(/^@/, "").replace(/\//, "-")
);
}
exports.backend = backend;
exports.customizeForDynamicUse = customizeForDynamicUse;
//# sourceMappingURL=backend.cjs.js.map
;