@routineless/nx-aws-cdk
Version:
Nx plugin for AWS CDK
165 lines (160 loc) • 6.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildEsbuildOptions = void 0;
const tslib_1 = require("tslib");
const devkit_1 = require("@nx/devkit");
const fs_1 = require("fs");
const path = tslib_1.__importStar(require("path"));
const esbuild_1 = require("../../../utils/esbuild");
const workspace_1 = require("../../../utils/workspace");
const buildEsbuildOptions = (options, context) => {
const outExtension = '.js';
const esbuildOptions = {
entryNames: '[dir]/[name]',
bundle: false,
platform: 'node',
target: 'esnext',
tsconfig: options.tsConfig,
format: 'cjs',
outExtension: {
'.js': outExtension,
},
outdir: options.outputPath,
};
const entryPoints = [options.main];
// When target platform Node and target format is CJS, then also transpile workspace libs used by the app.
// Provide a `require` override in the main entry file so workspace libs can be loaded when running the app.
const paths = (0, workspace_1.getTsConfigCompilerPaths)(context);
const entryPointsFromProjects = (0, esbuild_1.getEntryPoints)(context.projectName, context, {
initialTsConfigFileName: options.tsConfig,
initialEntryPoints: entryPoints,
recursive: true,
excludeImplicit: true,
});
esbuildOptions.entryPoints = [
// Write a main entry file that registers workspace libs and then calls the user-defined main.
writeTmpEntryWithRequireOverrides(paths, outExtension, options, context),
...entryPointsFromProjects.map((f) => {
/**
* Maintain same directory structure as the workspace, so that other workspace libs may be used by the project.
* dist
* └── apps
* └── demo
* ├── apps
* │ └── demo
* │ └── src
* │ └── main.js (requires '@acme/utils' which is mapped to libs/utils/src/index.js)
* ├── libs
* │ └── utils
* │ └── src
* │ └── index.js
* └── main.js (entry with require overrides)
*/
const { dir, name } = path.parse(f);
return {
in: f,
out: path.join(dir, name),
};
}),
];
return esbuildOptions;
};
exports.buildEsbuildOptions = buildEsbuildOptions;
const writeTmpEntryWithRequireOverrides = (paths, outExtension, options, context) => {
const project = context.projectGraph.nodes[context.projectName];
// Write a temp main entry source that registers workspace libs.
const tmpPath = path.join(context.root, 'tmp', project.name);
(0, fs_1.mkdirSync)(tmpPath, { recursive: true });
const { name: mainFileName, dir: mainPathRelativeToDist } = path.parse(options.main);
const mainWithRequireOverridesInPath = path.join(tmpPath, `main-with-require-overrides.js`);
(0, fs_1.writeFileSync)(mainWithRequireOverridesInPath, getRegisterFileContent(paths, `./${path.join(mainPathRelativeToDist, `${mainFileName}${outExtension}`)}`, outExtension));
let mainWithRequireOverridesOutPath;
if (mainPathRelativeToDist === '' || mainPathRelativeToDist === '.') {
// If the user customized their entry such that it is not inside `src/` folder
throw new Error(`There is a conflict between Nx-generated main file and the project's main file. Main file should be under src/ folder.`);
}
else {
mainWithRequireOverridesOutPath = path.parse(mainFileName).name;
}
return {
in: mainWithRequireOverridesInPath,
out: mainWithRequireOverridesOutPath,
};
};
const getRegisterFileContent = (paths, mainFile, outExtension) => {
mainFile = (0, devkit_1.normalizePath)(mainFile);
// Sort by longest prefix so imports match the most specific path.
const sortedKeys = Object.keys(paths).sort((a, b) => getPrefixLength(b) - getPrefixLength(a));
const manifest = sortedKeys.reduce((acc, k) => {
let exactMatch;
// Nx generates a single path entry.
// If more sophisticated setup is needed, we can consider tsconfig-paths.
const pattern = paths[k][0];
const manifestEntry = { module: k, pattern };
if (/.[cm]?ts$/.test(pattern)) {
// Path specifies a single entry point e.g. "a/b/src/index.ts".
// This is the default setup.
const { dir, name } = path.parse(pattern);
exactMatch = (0, devkit_1.joinPathFragments)(dir, `${name}${outExtension}`);
if (exactMatch) {
manifestEntry.exactMatch = exactMatch;
}
}
acc.push(manifestEntry);
return acc;
}, []);
return `
/**
* IMPORTANT: Do not modify this file.
* This file allows the app to run without bundling in workspace libraries.
* Must be contained in the ".nx" folder inside the output path.
*/
const Module = require('module');
const path = require('path');
const fs = require('fs');
const originalResolveFilename = Module._resolveFilename;
const distPath = __dirname;
const manifest = ${JSON.stringify(manifest)};
Module._resolveFilename = function(request, parent) {
let found;
for (const entry of manifest) {
if (request === entry.module && entry.exactMatch) {
const entry = manifest.find((x) => request === x.module || request.startsWith(x.module + "/"));
const candidate = path.join(distPath, entry.exactMatch);
if (isFile(candidate)) {
found = candidate;
break;
}
} else {
const re = new RegExp(entry.module.replace(/\\*$/, "(?<rest>.*)"));
const match = request.match(re);
if (match?.groups) {
const candidate = path.join(distPath, entry.pattern.replace("*", ""), match.groups.rest + ".js");
if (isFile(candidate)) {
found = candidate;
}
}
}
}
if (found) {
const modifiedArguments = [found, ...[].slice.call(arguments, 1)];
return originalResolveFilename.apply(this, modifiedArguments);
} else {
return originalResolveFilename.apply(this, arguments);
}
};
function isFile(s) {
try {
return fs.statSync(s).isFile();
} catch (_e) {
return false;
}
}
// Call the user-defined main.
require('${mainFile}');
`;
};
const getPrefixLength = (pattern) => {
return pattern.substring(0, pattern.indexOf('*')).length;
};
//# sourceMappingURL=build-esbuild-options.js.map