UNPKG

@o3r/schematics

Version:

Schematics module of the Otter framework

137 lines • 7.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ngAddPackages = ngAddPackages; const node_fs_1 = require("node:fs"); const path = require("node:path"); const schematics_1 = require("@angular-devkit/schematics"); const tasks_1 = require("@angular-devkit/schematics/tasks"); const dependencies_1 = require("@schematics/angular/utility/dependencies"); const index_1 = require("../../utility/index"); const getNgAddSchema = (packageName, context) => { try { const collection = context.engine.createCollection(packageName); return collection.createSchematic('ng-add'); } catch { context.logger.warn(`No ng-add found for ${packageName}`); return undefined; } }; const sortDependencies = (packageJson, depType) => { packageJson[depType] = packageJson[depType] ? Object.fromEntries(Object.entries(packageJson[depType] || {}).sort(([key1, _val1], [key2, _val2]) => key1.localeCompare(key2))) : undefined; }; /** * Install via `ng add` a list of npm packages. * @param packages List of packages to be installed via `ng add` * @param options install options * @param packageJsonPath path of the package json of the project where they will be installed */ function ngAddPackages(packages, options, packageJsonPath = '/package.json') { if (packages.length === 0) { return schematics_1.noop; } const cwd = process.cwd().replace(/[/\\]+/g, '/'); // FileSystem working directory might be different from Tree working directory (when using `yarn workspace` for example) const fsWorkingDirectory = (options?.workingDirectory && !cwd.endsWith(options.workingDirectory)) ? options.workingDirectory : '.'; const versions = Object.fromEntries(packages.map((packageName, index) => [packageName, typeof options?.version === 'object' ? options.version[index] : options?.version])); if (options?.workingDirectory && !packageJsonPath.startsWith(options.workingDirectory)) { packageJsonPath = path.join(options.workingDirectory, packageJsonPath); } const getInstalledVersion = (packageName) => { let versionFound; for (const workingDirectory of new Set([fsWorkingDirectory, '.'])) { try { const fileSystemPackageJson = JSON.parse((0, node_fs_1.readFileSync)(path.join(workingDirectory, 'package.json'), { encoding: 'utf8' })); let version; if (options?.dependencyType === dependencies_1.NodeDependencyType.Dev) { version = fileSystemPackageJson.devDependencies[packageName]; } else if (options?.dependencyType === dependencies_1.NodeDependencyType.Peer) { version = fileSystemPackageJson.peerDependencies[packageName]; } else { version = fileSystemPackageJson.dependencies[packageName]; } if (versionFound && version !== versionFound) { // In case of conflict between package.json files, we consider the package as not installed to force its update return; } versionFound = version; } catch { return; } } return versionFound; }; const getOptions = (schema) => { const schemaOptions = schema.description.schemaJson?.properties || {}; return Object.entries(options || {}).reduce((accOptions, [key, value]) => { if (schemaOptions[key]) { accOptions[key] = value; } return accOptions; }, {}); }; const installedVersions = packages.map((packageName) => getInstalledVersion(packageName)); const packageManager = (0, index_1.getPackageManager)(); const packagesToInstall = packages.filter((packageName, index) => !installedVersions[index] || installedVersions[index] !== versions[packageName]); if (packagesToInstall.length === 0) { return schematics_1.noop; } return (0, schematics_1.chain)([ // Update package.json in tree (tree) => { for (const filePath of new Set([packageJsonPath, './package.json'])) { const packageJson = tree.readJson(filePath); packages.forEach((packageName) => { const version = versions[packageName] || 'latest'; if (options?.dependencyType === dependencies_1.NodeDependencyType.Dev) { packageJson.devDependencies = { ...packageJson.devDependencies, [packageName]: version }; } else if (options?.dependencyType === dependencies_1.NodeDependencyType.Peer) { packageJson.peerDependencies = { ...packageJson.peerDependencies, [packageName]: version }; } else { packageJson.dependencies = { ...packageJson.dependencies, [packageName]: version }; } }); ['dependencies', 'devDependencies', 'peerDependencies'].forEach((depType) => { sortDependencies(packageJson, depType); }); tree.overwrite(filePath, JSON.stringify(packageJson, null, 2)); } }, // Run ng-adds async (tree, context) => { if (options?.skipNgAddSchematicRun) { context.logger.info(`Package(s) '${packagesToInstall.join(', ')}' was(were) installed. The run of 'ng-add' schematics for the package(s) is intentionally skipped. You can do the run standalone, later.`); return schematics_1.noop; } new Set([packageJsonPath, './package.json']).forEach((filePath) => { (0, node_fs_1.mkdirSync)(path.join(process.cwd(), path.dirname(filePath)), { recursive: true }); (0, node_fs_1.writeFileSync)(path.join(process.cwd(), filePath), tree.readText(filePath)); }); context.addTask(new tasks_1.NodePackageInstallTask({ packageManager: packageManager, hideOutput: false, quiet: false })); await new Promise((resolve, reject) => context.engine.executePostTasks().subscribe({ next: () => { }, complete: () => resolve(), error: (errors) => reject(errors) })); const ngAddsToApply = packagesToInstall .map((packageName) => ({ packageName, ngAddCollection: getNgAddSchema(packageName, context) })) .filter(({ packageName, ngAddCollection }) => { if (!ngAddCollection) { context.logger.info(`No ng-add schematic found for: '${packageName}'. Skipping ng add for: ${packageName}${versions[packageName] ? ' with version: ' + versions[packageName] : ''}`); } return !!ngAddCollection; }) .map(({ packageName, ngAddCollection }) => (0, schematics_1.externalSchematic)(packageName, 'ng-add', getOptions(ngAddCollection))); return (0, schematics_1.chain)(ngAddsToApply); } ]); } //# sourceMappingURL=ng-add.helpers.js.map