Skip to content

Instantly share code, notes, and snippets.

@ciwchris
Created July 6, 2018 05:35
Show Gist options
  • Save ciwchris/805596370f6d71fcd05be04d4059cb61 to your computer and use it in GitHub Desktop.
Save ciwchris/805596370f6d71fcd05be04d4059cb61 to your computer and use it in GitHub Desktop.
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import { JsonAstNode, JsonAstObject, JsonParseMode, parseJsonAst } from '@angular-devkit/core';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
const pkgJsonPath = '/package.json';
export const latestVersions = {
StcuExternalStyles: '^2.22.2'
};
export interface NodeDependency {
name: string;
version: string;
}
export function myComponent(): Rule {
return (tree: Tree, _context: SchematicContext) => {
addPackageJsonDependency(_context, tree, {
name: 'moment',
version: latestVersions.StcuExternalStyles
});
_context.addTask(new NodePackageInstallTask());
return tree;
};
}
function _readPackageJson(tree: Tree): JsonAstObject {
const buffer = tree.read(pkgJsonPath);
if (buffer === null) {
throw new SchematicsException('Could not read package.json.');
}
const content = buffer.toString();
const packageJson = parseJsonAst(content, JsonParseMode.Strict);
if (packageJson.kind != 'object') {
throw new SchematicsException('Invalid package.json. Was expecting an object');
}
return packageJson;
}
function addPackageJsonDependency(
_context: SchematicContext,
tree: Tree,
dependency: NodeDependency
): void {
const packageJsonAst = _readPackageJson(tree);
const recorder = tree.beginUpdate(pkgJsonPath);
let depsNode = findPropertyInAstObject(packageJsonAst, 'dependencies');
if (!depsNode) {
throw new SchematicsException("Did not find 'dependencies' node");
} else {
let node = depsNode as JsonAstObject;
// Insert comma.
const last = node.properties[node.properties.length - 1];
recorder.insertRight(last.start.offset + last.text.replace(/\s+$/, '').length, ',');
recorder.insertLeft(
node.end.offset - 1,
' ' + `"${dependency.name}": "${dependency.version}"`
);
}
tree.commitUpdate(recorder);
}
function findPropertyInAstObject(node: JsonAstObject, propertyName: string): JsonAstNode | null {
let maybeNode: JsonAstNode | null = null;
for (const property of node.properties) {
if (property.key.value == propertyName) {
maybeNode = property.value;
}
}
return maybeNode;
}
/*
function appendPropertyInAstObject(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
value: JsonValue,
indent: number
) {
const indentStr = _buildIndent(indent);
if (node.properties.length > 0) {
// Insert comma.
const last = node.properties[node.properties.length - 1];
recorder.insertRight(last.start.offset + last.text.replace(/\s+$/, '').length, ',');
}
recorder.insertLeft(
node.end.offset - 1,
' ' +
`"${propertyName}": ${JSON.stringify(value, null, 2).replace(/\n/g, indentStr)}` +
indentStr.slice(0, -2)
);
}
export function insertPropertyInAstObjectInOrder(
recorder: UpdateRecorder,
node: JsonAstObject,
propertyName: string,
value: JsonValue,
indent: number
) {
if (node.properties.length === 0) {
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
return;
}
// Find insertion info.
let insertAfterProp: JsonAstKeyValue | null = null;
let prev: JsonAstKeyValue | null = null;
let isLastProp = false;
const last = node.properties[node.properties.length - 1];
for (const prop of node.properties) {
if (prop.key.value > propertyName) {
if (prev) {
insertAfterProp = prev;
}
break;
}
if (prop === last) {
isLastProp = true;
insertAfterProp = last;
}
prev = prop;
}
if (isLastProp) {
appendPropertyInAstObject(recorder, node, propertyName, value, indent);
return;
}
const indentStr = _buildIndent(indent);
const insertIndex =
insertAfterProp === null ? node.start.offset + 1 : insertAfterProp.end.offset + 1;
recorder.insertRight(
insertIndex,
indentStr +
`"${propertyName}": ${JSON.stringify(value, null, 2).replace(/\n/g, indentStr)}` +
','
);
}
function _buildIndent(count: number): string {
return '\n' + new Array(count + 1).join(' ');
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment