UNPKG

@o3r/schematics

Version:

Schematics module of the Otter framework

185 lines • 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setupDependencies = exports.getPackageInstallConfig = exports.hasSetupInformation = void 0; const tslib_1 = require("tslib"); const node_fs_1 = require("node:fs"); const path = tslib_1.__importStar(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 semver = tslib_1.__importStar(require("semver")); const dependencies_2 = require("../../utility/dependencies"); const loaders_1 = require("../../utility/loaders"); const package_manager_runner_1 = require("../../utility/package-manager-runner"); const editor_config_1 = require("../editor-config"); /** * Determine if the context has information regarding the setup dependencies process * @param context Schematic context */ const hasSetupInformation = (context) => { return !!context.setupDependencies; }; exports.hasSetupInformation = hasSetupInformation; /** * Retrieve the package install configuration * This is a workaround to ng-add to add the dependency to the sub-package * @param packageJsonPath Path to the module package.json file * @param tree Tree to read the file * @param projectName Name of the project * @param devDependencyOnly If true, the dependency will be added as devDependency * @param exactO3rVersion Use a pinned version of the o3r package */ const getPackageInstallConfig = (packageJsonPath, tree, projectName, devDependencyOnly, exactO3rVersion) => { if (!projectName) { return {}; } const packageJson = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, { encoding: 'utf8' })); const workspaceProject = projectName ? (0, loaders_1.getWorkspaceConfig)(tree)?.projects[projectName] : undefined; return { [packageJson.name]: { inManifest: [{ range: `${exactO3rVersion ? '' : '~'}${packageJson.version}`, types: devDependencyOnly ? [dependencies_1.NodeDependencyType.Dev] : (0, loaders_1.getProjectNewDependenciesTypes)(workspaceProject) }], requireInstall: true, ngAddOptions: { exactO3rVersion: exactO3rVersion } } }; }; exports.getPackageInstallConfig = getPackageInstallConfig; /** * Setup dependency to a repository. * Will run manually the ngAdd schematics according to the parameters and install the packages if required * @param options */ const setupDependencies = (options) => { return () => { const ngAddToRun = new Set(Object.keys(options.dependencies) .filter((dep) => options.ngAddToRun?.some((pattern) => typeof pattern === 'string' ? pattern === dep : pattern.test(dep)))); const isInstallRequired = Object.values(options.dependencies).some(({ requireInstall }) => requireInstall); const isInstallNeeded = () => { const needsInstall = Array.from(ngAddToRun).some((packageName) => !(0, package_manager_runner_1.isPackageInstalled)(packageName)); return needsInstall || (options.skipInstall === undefined ? (ngAddToRun.size > 0 || isInstallRequired) : !options.skipInstall); }; const editPackageJson = (packageJsonPath, packageToInstall, dependency, updateLists) => { return (tree, context) => { if (!tree.exists(packageJsonPath)) { context.logger.warn(`The file ${packageJsonPath} does not exist, the dependency ${packageToInstall} will not be added`); return tree; } const packageJsonContent = tree.readJson(packageJsonPath); dependency.inManifest.forEach(({ range, types }) => { const isTildeRangeEnforced = dependency.enforceTildeRange === undefined ? (options.enforceTildeRange === undefined || options.enforceTildeRange) : dependency.enforceTildeRange; if (isTildeRangeEnforced) { range = (0, dependencies_2.enforceTildeRange)(range); } (types || [dependencies_1.NodeDependencyType.Default]).forEach((depType) => { if (packageJsonContent[depType]?.[packageToInstall]) { if (range && semver.validRange(range)) { const currentMinimalVersion = semver.minVersion(packageJsonContent[depType]?.[packageToInstall]); const myRangeMinimalVersion = semver.minVersion(range); if (currentMinimalVersion && myRangeMinimalVersion && semver.gt(myRangeMinimalVersion, currentMinimalVersion)) { context.logger.debug(`The dependency ${packageToInstall} (${depType}@${range}) will be added in ${packageJsonPath}`); packageJsonContent[depType][packageToInstall] = range; } else { if (updateLists) { ngAddToRun.delete(packageToInstall); } context.logger.debug(`The dependency ${packageToInstall} (${depType}) is already in ${packageJsonPath}, it will not be added.`); context.logger.debug(`Because its range is inferior or included to the current one (${range} < ${packageJsonContent[depType][packageToInstall]}) in targeted ${packageJsonPath}`); } } else { if (updateLists) { ngAddToRun.delete(packageToInstall); } context.logger.warn(`The dependency ${packageToInstall} (${depType}) will not added ` + `because there is already this dependency with a defined range (${packageJsonContent[depType][packageToInstall]}) in targeted ${packageJsonPath}`); } } else { packageJsonContent[depType] ||= {}; packageJsonContent[depType][packageToInstall] = range; context.logger.debug(`The dependency ${packageToInstall} (${depType}@${range}) will be added in ${packageJsonPath}`); } packageJsonContent[depType] = Object.keys(packageJsonContent[depType]) .toSorted() .reduce((acc, key) => { acc[key] = packageJsonContent[depType][key]; return acc; }, {}); }); }); const content = JSON.stringify(packageJsonContent, null, 2); tree.overwrite(packageJsonPath, content); }; }; const addDependencies = (tree) => { const workspaceConfig = (0, loaders_1.getWorkspaceConfig)(tree); const workspaceProject = (options.projectName && workspaceConfig?.projects?.[options.projectName]) || undefined; const projectDirectory = workspaceProject?.root; return (0, schematics_1.chain)(Object.entries(options.dependencies) .map(([packageName, dependencyDetails]) => { const shouldRunInSubPackage = projectDirectory && !dependencyDetails.toWorkspaceOnly; const rootPackageRule = editPackageJson('package.json', packageName, dependencyDetails, !shouldRunInSubPackage); if (shouldRunInSubPackage) { return (0, schematics_1.chain)([ rootPackageRule, editPackageJson(path.posix.join(projectDirectory, 'package.json'), packageName, dependencyDetails, true) ]); } return rootPackageRule; })); }; const runNgAddSchematics = (_, context) => { const packageManager = options.packageManager || (0, package_manager_runner_1.getPackageManager)(); const installId = isInstallNeeded() ? [ context.addTask(new tasks_1.NodePackageInstallTask({ packageManager, quiet: true, workingDirectory: options.workingDirectory }), options.runAfterTasks) ] : undefined; if (installId !== undefined) { context.logger.debug(`Schedule the installation of the workspace (${ngAddToRun.size > 0 ? 'for: ' + [...ngAddToRun].join(', ') : (options.skipInstall ? 'skipped' : 'forced')})`); } const getOptions = (packageName, schema) => { const schemaOptions = schema?.description.schemaJson?.properties; return Object.fromEntries(Object.entries({ projectName: options.projectName, ...options.ngAddOptions, ...options.dependencies[packageName].ngAddOptions }) .filter(([key]) => !schemaOptions || !!schemaOptions[key])); }; const finalTaskIds = [...ngAddToRun] .map((packageName) => { let schematic; try { const collection = context.engine.createCollection(packageName); schematic = collection.createSchematic('ng-add'); } catch (e) { context.logger.warn(`The package ${packageName} was not installed, the options check will be skipped`, e); } const schematicOptions = getOptions(packageName, schematic); return { packageName, schematicOptions }; }) .reduce((ids, { packageName, schematicOptions }) => { context.logger.debug(`Schedule the schematic ng-add for ${packageName}`); return [...ids, context.addTask(new tasks_1.RunSchematicTask(packageName, 'ng-add', schematicOptions), ids)]; }, [...(installId || []), ...(options.runAfterTasks || [])]); if ((0, exports.hasSetupInformation)(context)) { context.setupDependencies.taskIds.push(...finalTaskIds); } else { context.setupDependencies = { taskIds: finalTaskIds }; } if (options.scheduleTaskCallback) { options.scheduleTaskCallback(finalTaskIds); } }; return (0, schematics_1.chain)([ addDependencies, runNgAddSchematics, (0, editor_config_1.applyEditorConfig)(['json']) ]); }; }; exports.setupDependencies = setupDependencies; //# sourceMappingURL=dependencies.js.map