@domoinc/ryuu-angular
Version:
Angular Schematic to add @domoinc/ryuu-proxy support
196 lines (180 loc) • 6.37 kB
text/typescript
import {
Rule,
SchematicContext,
Tree,
mergeWith,
apply,
url,
template,
chain,
forEach,
FileEntry,
} from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import { strings } from '@angular-devkit/core';
import {
addPackageJsonDependency,
NodeDependencyType,
} from '@schematics/angular/utility/dependencies';
import { getProject, getWorkspace, parseJson } from './utils';
export interface Schema {
project?: string;
output?: string;
}
/**
* Retrieves the contents of the tsconfig.json file from the given tree.
* @param {Tree} tree - The tree object representing the file system.
* @returns The contents of the tsconfig.json file as a JSON object, or an empty string if the file does not exist.
*/
const getTsConfig = (tree: Tree) =>
tree.readJson('tsconfig.json') ?? '';
/**
* Retrieves the Angular configuration from the given tree.
* @param {Tree} tree - The tree object representing the file system.
* @returns The Angular configuration object if found, otherwise an empty string.
*/
const getAngularConfig = (tree: Tree) =>
tree.readJson('angular.json') ?? '';
/**
* Updates the tsconfig.json file in the given tree by adding or modifying the compiler options.
* @param {Tree} tree - The tree representing the file system.
* @returns The updated tree.
*/
const updateTSConfig = () => {
return (tree: Tree) => {
const config: any = getTsConfig(tree);
config.compilerOptions = {
...config.compilerOptions,
resolveJsonModule: true,
allowSyntheticDefaultImports: true,
};
tree.overwrite('tsconfig.json', JSON.stringify(config, null, 2));
return tree;
};
};
/**
* Updates the angular.json file with the specified options.
* @param {Schema} options - The options to update the angular.json file with.
* @returns A function that takes in a Tree object and updates the angular.json file.
*/
const updateAngularJSON = (options: Schema) => {
return (tree: Tree) => {
const workspace = getWorkspace(tree);
const project = getProject(workspace, options.project!);
(project.architect!.build!
.builder) = '@angular-builders/custom-webpack:browser';
(project.architect!.serve!
.builder) = '@angular-builders/custom-webpack:dev-server';
(project.architect!.build!.options)['customWebpackConfig'] = {
path: './extra-webpack.config.ts',
};
// Options
const mainSrc = project.architect!.build!.options!.browser ?? 'src/main.ts';
(project.architect!.build!
.options!.main) = mainSrc;
delete project.architect!.build!.options!.browser; // Remove browser option for Custom Webpack
tree.overwrite('angular.json', JSON.stringify(workspace, null, 2));
return tree;
};
};
/**
* Retrieves the version number of the project from the package.json file in the given tree.
* @param {Tree} tree - The tree object representing the project file structure.
* @returns The version number of the project.
*/
const getProjectVersion = (tree: Tree) => {
const packageBuffer = tree.read('package.json') ?? '';
const pack: any = parseJson(packageBuffer.toString());
return pack.version;
};
/**
* Copies Domo files to the specified tree directory.
* @param {Tree} tree - The tree directory to copy the files to.
* @param {Schema} options - The options for copying the files.
* @returns A merged tree with the copied files.
*/
const copyDomoFiles = (tree: Tree, options: Schema) => {
const version = getProjectVersion(tree);
return mergeWith(
apply(url('./files'), [
template({
...options,
version,
...strings,
}),
forEach((file: FileEntry) => {
if (tree.exists(file.path)) return null;
return file;
}),
]),
);
};
/**
* Adds the specified dependencies to the package.json file.
* @param {Tree} tree - The tree object representing the file system.
* @returns A function that takes in a tree object and adds the dependencies to the package.json file.
*/
const addDepsToPackage = () => {
return (tree: Tree) => {
const deps: any = {
'@angular-builders/custom-webpack': '^18.0.0',
'@domoinc/ryuu-proxy': '^4.3.4',
'copy-webpack-plugin': '^11.0.0',
};
Object.keys(deps).forEach((key) => {
addPackageJsonDependency(tree, {
name: key,
type: NodeDependencyType.Dev,
version: deps[key],
});
});
};
};
/**
* Adds helper scripts to the package.json file based on the provided options.
* @param {Schema} options - The options object containing project information.
* @returns {Tree} The updated tree with the modified package.json file.
*/
const addHelperScripts = (options: Schema) => {
return (tree: Tree) => {
const packageBuffer = tree.read('package.json') ?? '';
const pack: any = parseJson(packageBuffer.toString());
const distFolder = options.output ?? `dist/${options.project}`;
pack.scripts = {
...pack.scripts,
'domo:upload': `npm run build && cd ${distFolder} && domo publish`,
'postdomo:upload': `cp ${distFolder}/manifest.json domo/`,
};
tree.overwrite('package.json', JSON.stringify(pack, null, 2));
return tree;
};
};
/**
* Angular schematic rule that adds dependencies and configuration to an Angular project.
* @param {any} _options - The options for the schematic.
* @returns {Rule} - A rule function that modifies the project tree.
*/
export function ngAdd(options: any): Rule {
return (tree: Tree, context: SchematicContext) => {
context.addTask(new NodePackageInstallTask());
// Check for Project Name
if (!options.project) {
const config: any = getAngularConfig(tree);
if (config.projects) {
const projects = Object.keys(config.projects);
const defaultProjectName = projects.length > 0 ? projects[0] : '';
const defaultProject = config.projects[defaultProjectName];
const buildOutput = defaultProject.architect!.build!.options!.outputPath;
options = { ...options, project: defaultProjectName, output: buildOutput };
}
}
console.log('[ngAdd] options', options);
return chain([
addDepsToPackage(),
copyDomoFiles(tree, options),
updateAngularJSON(options),
updateTSConfig(),
addHelperScripts(options),
]);
};
}