ng-packagr
Version:
Compile and package Angular libraries in Angular Package Format (APF)
185 lines • 7.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.analyseSourcesTransform = void 0;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const rxjs_1 = require("rxjs");
const typescript_1 = __importDefault(require("typescript"));
const node_1 = require("../../graph/node");
const log_1 = require("../../utils/log");
const path_1 = require("../../utils/path");
const nodes_1 = require("../nodes");
exports.analyseSourcesTransform = (0, rxjs_1.pipe)((0, rxjs_1.map)(graph => {
const entryPoints = graph.filter(nodes_1.isEntryPoint);
const entryPointsMapped = new Map(entryPoints.map(ep => [ep.data.entryPoint.moduleId, ep]));
const packageNode = (0, nodes_1.findPackageNode)(graph);
const primaryModuleId = packageNode.data.primary.moduleId;
for (const entryPoint of entryPoints) {
if (entryPoint.state !== node_1.STATE_DONE) {
analyseEntryPoint(entryPoint, entryPointsMapped, primaryModuleId);
}
}
return graph;
}));
const JS_TO_TS_EXTENSIONS = {
'.js': ['.ts', '.tsx', '.d.ts'],
'.mjs': ['.mts', '.d.mts'],
'.cjs': ['.cts', '.d.cts'],
};
const RESOLUTION_EXTENSIONS = [
'.ts',
'.tsx',
'.mts',
'.cts',
'.d.ts',
'.d.mts',
'.d.cts',
'/index.ts',
'/index.tsx',
'/index.mts',
'/index.cts',
'/index.d.ts',
'/index.d.mts',
'/index.d.cts',
'.js',
'.mjs',
'.cjs',
'/index.js',
'/index.mjs',
'/index.cjs',
];
function checkFile(filePath, fileCache) {
const entry = fileCache.getOrCreate(filePath);
if (entry.exists === undefined) {
const stat = (0, node_fs_1.statSync)(filePath, { throwIfNoEntry: false });
if (stat?.isFile()) {
entry.exists = true;
}
else {
return false;
}
}
return entry.exists;
}
function resolveRelativeSourceFile(dir, moduleName, fileCache) {
const target = (0, node_path_1.resolve)(dir, moduleName);
if (target.includes('/node_modules/') || target.includes('\\node_modules\\')) {
return undefined;
}
const ext = (0, node_path_1.extname)(target);
const tsExtensions = JS_TO_TS_EXTENSIONS[ext];
if (tsExtensions) {
const base = target.slice(0, -ext.length);
for (const tsExt of tsExtensions) {
const candidate = base + tsExt;
if (checkFile(candidate, fileCache)) {
return (0, path_1.ensureUnixPath)(candidate);
}
}
}
if (checkFile(target, fileCache)) {
return (0, path_1.ensureUnixPath)(target);
}
for (const suffix of RESOLUTION_EXTENSIONS) {
const candidate = target + suffix;
if (checkFile(candidate, fileCache)) {
return (0, path_1.ensureUnixPath)(candidate);
}
}
return undefined;
}
/**
* Analyses an entrypoint, searching for TypeScript dependencies and internal package imports.
*
* @param entryPoint Current entry point that should be analysed.
* @param entryPointsMapped Map of all entry points by moduleId.
* @param primaryModuleId The moduleId of the primary entry point.
*/
function analyseEntryPoint(entryPoint, entryPointsMapped, primaryModuleId) {
const { analyseSourcesFileCache } = entryPoint.cache;
const { moduleId, entryFilePath } = entryPoint.data.entryPoint;
(0, log_1.debug)(`Analysing sources for ${moduleId}`);
// Remove previously discovered entry point dependencies in watch mode
for (const dep of entryPoint.dependents) {
if ((0, nodes_1.isEntryPoint)(dep)) {
dep.dependees.delete(entryPoint);
entryPoint.dependents.delete(dep);
}
}
const potentialDependencies = new Set();
const filesToScan = [...(entryPoint.data.tsConfig?.rootNames ?? [entryFilePath])];
const visited = new Set();
while (filesToScan.length > 0) {
const file = filesToScan.pop();
if (!file) {
continue;
}
const currentFile = (0, path_1.ensureUnixPath)(file);
if (visited.has(currentFile)) {
continue;
}
visited.add(currentFile);
const fileEntry = analyseSourcesFileCache.getOrCreate(currentFile);
if (fileEntry.content === undefined) {
try {
fileEntry.content = (0, node_fs_1.readFileSync)(currentFile, 'utf-8');
fileEntry.exists = true;
}
catch {
continue;
}
}
const { importedFiles, typeReferenceDirectives, referencedFiles } = typescript_1.default.preProcessFile(fileEntry.content, true, // readImportFiles
true);
for (const ref of referencedFiles) {
const resolvedPath = resolveRelativeSourceFile((0, node_path_1.dirname)(currentFile), ref.fileName, analyseSourcesFileCache);
if (resolvedPath && !visited.has(resolvedPath)) {
filesToScan.push(resolvedPath);
}
}
for (const ref of [...importedFiles, ...typeReferenceDirectives]) {
const moduleName = ref.fileName;
if (moduleName[0] !== '.') {
if (moduleName === primaryModuleId || moduleName.startsWith(`${primaryModuleId}/`)) {
potentialDependencies.add(moduleName);
}
}
else {
const resolvedPath = resolveRelativeSourceFile((0, node_path_1.dirname)(currentFile), moduleName, analyseSourcesFileCache);
if (resolvedPath && !visited.has(resolvedPath)) {
filesToScan.push(resolvedPath);
}
}
}
}
// If an index file parallel to the entryFilePath is imported it is not valid as index should be reserved as an
// entry file of an entry-point based on node resolution strategy.
if ((0, node_path_1.basename)(entryFilePath) !== 'index.ts') {
const potentialIndexPath = (0, node_path_1.join)((0, node_path_1.dirname)(entryFilePath), 'index.ts');
if (visited.has((0, path_1.ensureUnixPath)(potentialIndexPath))) {
throw new Error(`Entry point '${moduleId}' has an 'index.ts' parallel to the 'entryFilePath'. ` +
`The 'entryFilePath' should be updated to point to the 'index.ts' file.\n` +
`Full path: ${potentialIndexPath}`);
}
}
for (const moduleName of potentialDependencies) {
const dep = entryPointsMapped.get(moduleName);
if (dep) {
(0, log_1.debug)(`Found entry point dependency: ${moduleId} -> ${moduleName}`);
if (moduleId === moduleName) {
throw new Error(`Entry point ${moduleName} has a circular dependency on itself.`);
}
if (dep.dependents.has(entryPoint)) {
throw new Error(`Entry point ${moduleName} has a circular dependency on ${moduleId}.`);
}
entryPoint.dependsOn(dep);
}
else {
throw new Error(`Entry point ${moduleName} which is required by ${moduleId} doesn't exist.`);
}
}
}
//# sourceMappingURL=analyse-sources.transform.js.map