/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import { JsonObject, Path, isJsonObject, normalize, strings } from '@angular-devkit/core'; import { Rule, SchematicContext, SchematicsException, Tree, apply, applyTemplates, chain, mergeWith, move, url, } from '@angular-devkit/schematics'; import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; import { Schema } from './schema'; function addSchematicToCollectionJson( collectionPath: Path, schematicName: string, description: JsonObject, ): Rule { return (tree: Tree) => { const collectionJson = tree.readJson(collectionPath); if (!isJsonObject(collectionJson) || !isJsonObject(collectionJson.schematics)) { throw new Error('Invalid collection.json; schematics needs to be an object.'); } collectionJson['schematics'][schematicName] = description; tree.overwrite(collectionPath, JSON.stringify(collectionJson, undefined, 2)); }; } export default function (options: Schema): Rule { const schematicsVersion = require('@angular-devkit/schematics/package.json').version; const coreVersion = require('@angular-devkit/core/package.json').version; // Verify if we need to create a full project, or just add a new schematic. return (tree: Tree, context: SchematicContext) => { if (!options.name) { throw new SchematicsException('name option is required.'); } let collectionPath: Path | undefined; try { const packageJson = tree.readJson('/package.json') as { schematics: unknown; }; if (typeof packageJson.schematics === 'string') { const p = normalize(packageJson.schematics); if (tree.exists(p)) { collectionPath = p; } } } catch {} let source = apply(url('./schematic-files'), [ applyTemplates({ ...options, coreVersion, schematicsVersion, dot: '.', camelize: strings.camelize, dasherize: strings.dasherize, }), ]); // Simply create a new schematic project. if (!collectionPath) { collectionPath = normalize('/' + options.name + '/src/collection.json'); source = apply(url('./project-files'), [ move('package.json', 'package.json.template'), applyTemplates({ ...(options as object), coreVersion, schematicsVersion, dot: '.', camelize: strings.camelize, dasherize: strings.dasherize, }), mergeWith(source), move(options.name), ]); context.addTask( new NodePackageInstallTask({ workingDirectory: options.name, packageManager: options.packageManager, }), ); } return chain([ mergeWith(source), addSchematicToCollectionJson(collectionPath, strings.dasherize(options.name), { description: 'A blank schematic.', factory: './' + strings.dasherize(options.name) + '/index#' + strings.camelize(options.name), }), ]); }; }