Skip to content

Commit

Permalink
Merge branch 'IGanchev/chart-templates' of https://github.com/IgniteU…
Browse files Browse the repository at this point in the history
…I/igniteui-cli into IGanchev/chart-templates
  • Loading branch information
IvayloG committed Jul 24, 2018
2 parents 2558030 + d55c95e commit a7b6251
Show file tree
Hide file tree
Showing 39 changed files with 2,068 additions and 413 deletions.
17 changes: 12 additions & 5 deletions lib/commands/add.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as path from "path";
import { GoogleAnalytics } from "../GoogleAnalytics";
import { ProjectConfig } from "../ProjectConfig";
import { TemplateManager } from "../TemplateManager";
Expand All @@ -9,7 +10,7 @@ let command: {
[name: string]: any,
templateManager: TemplateManager,
execute: (argv: any) => Promise<void>,
addTemplate: (name: string, template: Template) => Promise<boolean>
addTemplate: (name: string, template: Template, module?: string) => Promise<boolean>
};
// tslint:disable:object-literal-sort-keys
command = {
Expand All @@ -28,6 +29,12 @@ command = {
description: "File name.",
type: "string",
global: true
},
module: {
alias: "m",
description: "The module to which the template is to be added",
type: "string",
global: true
}
},
check: argv => {
Expand Down Expand Up @@ -88,12 +95,12 @@ command = {
cd14: config.project.theme
});

await command.addTemplate(argv.name, selectedTemplate);
await command.addTemplate(argv.name, selectedTemplate, argv.module);
await PackageManager.flushQueue(true);
PackageManager.ensureIgniteUISource(config.packagesInstalled, command.templateManager);
}
},
async addTemplate(name: string, template: Template): Promise<boolean> {
async addTemplate(name: string, template: Template, modulePath?: string): Promise<boolean> {
// trim name to avoid creating awkward paths or mismatches:
name = name.trim();

Expand All @@ -105,9 +112,9 @@ command = {
return false;
}

if (await template.generateFiles(process.cwd(), name)) {
if (await template.generateFiles(process.cwd(), name, { modulePath })) {
//successful
template.registerInProject(process.cwd(), name);
template.registerInProject(process.cwd(), name, { modulePath });
command.templateManager.updateProjectConfiguration(template);
template.packages.forEach(x => PackageManager.queuePackage(x));
Util.log(`${Util.greenCheck()} View '${name}' added.`);
Expand Down
13 changes: 9 additions & 4 deletions lib/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,19 @@ command = {
const browserSync = bs.create("igniteui-cli");
const filePath = path.join(process.cwd(), "bs-config.js");
const bsConfig = require(filePath);
bsConfig.port = argv.port;
if (argv.port) {
bsConfig.port = argv.port;
}

browserSync.init(bsConfig);
break;
case "react":
exec(`npm start -- --port=` + argv.port);
break;
case "angular":
exec(`npm start -- --port=` + argv.port);
if (argv.port) {
exec(`npm start -- --port=` + argv.port);
} else {
exec(`npm start`);
}
break;
default:
break;
Expand Down
229 changes: 121 additions & 108 deletions lib/project-utility/TypeScriptFileUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export class TypeScriptFileUpdate {
private ngMetaEdits: {
declarations: string[],
imports: Array<{ name: string, root: boolean }>,
providers: string[]
providers: string[],
exports: string[]
};

private createdStringLiterals: string[];
Expand Down Expand Up @@ -123,7 +124,7 @@ export class TypeScriptFileUpdate {
return ts.visitNode(rootNode, visitor);
};

this.targetSource = ts.transform(this.targetSource, [ transformer ], {
this.targetSource = ts.transform(this.targetSource, [transformer], {
pretty: true // oh well..
}).transformed[0] as ts.SourceFile;

Expand All @@ -135,14 +136,16 @@ export class TypeScriptFileUpdate {
* Creates `declarations` array if one is not present already.
* @param filePath Path to the file to import
*/
public addDeclaration(filePath: string) {
public addDeclaration(filePath: string, addToExport?: boolean) {
let className: string;
const fileSource = TsUtils.getFileSource(filePath);
const relativePath: string = TsUtils.relativePath(this.targetPath, filePath, true, true);

className = TsUtils.getClassName(fileSource.getChildren());

this.addNgModuleMeta({ declare: className, from: relativePath });
if (addToExport) {
this.addNgModuleMeta({ declare: className, from: relativePath, export: className });
} else {
this.addNgModuleMeta({ declare: className, from: relativePath });
}
}

/**
Expand All @@ -152,7 +155,9 @@ export class TypeScriptFileUpdate {
const copy = {
declare: this.asArray(dep.declare, variables),
import: this.asArray(dep.import, variables),
provide: this.asArray(dep.provide, variables)
provide: this.asArray(dep.provide, variables),
// tslint:disable-next-line:object-literal-sort-keys
export: this.asArray(dep.export, variables)
};

if (dep.from) {
Expand All @@ -172,6 +177,10 @@ export class TypeScriptFileUpdate {
const providers = copy.provide
.filter(x => !this.ngMetaEdits.providers.find(p => p === x));
this.ngMetaEdits.providers.push(...providers);

const exportsArr = copy.export
.filter(x => !this.ngMetaEdits.exports.find(p => p === x));
this.ngMetaEdits.exports.push(...exportsArr);
}

//#region File state
Expand All @@ -183,7 +192,9 @@ export class TypeScriptFileUpdate {
this.ngMetaEdits = {
declarations: [],
imports: [],
providers: []
providers: [],
// tslint:disable-next-line:object-literal-sort-keys
exports: []
};
this.createdStringLiterals = [];
}
Expand Down Expand Up @@ -259,112 +270,113 @@ export class TypeScriptFileUpdate {

/** Transformation to apply edits to existing named import declarations */
protected importsTransformer: ts.TransformerFactory<ts.Node> =
<T extends ts.Node>(context: ts.TransformationContext) => (rootNode: T) => {
const editImports = this.requestedImports.filter(x => x.edit);
<T extends ts.Node>(context: ts.TransformationContext) => (rootNode: T) => {
const editImports = this.requestedImports.filter(x => x.edit);

// https://github.com/Microsoft/TypeScript/issues/14419#issuecomment-307256171
const visitor = (node: ts.Node): ts.Node => {
if (node.kind === ts.SyntaxKind.ImportDeclaration &&
editImports.find(x => x.from === ((node as ts.ImportDeclaration).moduleSpecifier as ts.StringLiteral).text)
) {
// visit just the source file main array (second visit)
return visitImport(node as ts.ImportDeclaration);
} else {
node = ts.visitEachChild(node, visitor, context);
}
return node;
};
function visitImport(node: ts.Node) {
if (node.kind === ts.SyntaxKind.NamedImports) {
const namedImports = node as ts.NamedImports;
const moduleSpecifier = (namedImports.parent.parent.moduleSpecifier as ts.StringLiteral).text;

// https://github.com/Microsoft/TypeScript/issues/14419#issuecomment-307256171
const visitor = (node: ts.Node): ts.Node => {
if (node.kind === ts.SyntaxKind.ImportDeclaration &&
editImports.find(x => x.from === ((node as ts.ImportDeclaration).moduleSpecifier as ts.StringLiteral).text)
) {
// visit just the source file main array (second visit)
return visitImport(node as ts.ImportDeclaration);
} else {
node = ts.visitEachChild(node, visitor, context);
}
return node;
};
function visitImport(node: ts.Node) {
if (node.kind === ts.SyntaxKind.NamedImports) {
const namedImports = node as ts.NamedImports;
const moduleSpecifier = (namedImports.parent.parent.moduleSpecifier as ts.StringLiteral).text;

const existing = ts.visitNodes(namedImports.elements, visitor);
const alreadyImported = existing.map(x => x.name.text);

const editImport = editImports.find(x => x.from === moduleSpecifier);
const newImports = editImport.imports.filter(x => alreadyImported.indexOf(x) === -1);

node = ts.updateNamedImports(namedImports, [
...existing,
...newImports.map(x => ts.createImportSpecifier(undefined, ts.createIdentifier(x)))
]);
} else {
node = ts.visitEachChild(node, visitImport, context);
const existing = ts.visitNodes(namedImports.elements, visitor);
const alreadyImported = existing.map(x => x.name.text);

const editImport = editImports.find(x => x.from === moduleSpecifier);
const newImports = editImport.imports.filter(x => alreadyImported.indexOf(x) === -1);

node = ts.updateNamedImports(namedImports, [
...existing,
...newImports.map(x => ts.createImportSpecifier(undefined, ts.createIdentifier(x)))
]);
} else {
node = ts.visitEachChild(node, visitImport, context);
}
return node;
}
return node;
return ts.visitNode(rootNode, visitor);
}
return ts.visitNode(rootNode, visitor);
}

/** Transformation to apply `this.ngMetaEdits` to `NgModule` metadata properties */
protected ngModuleTransformer: ts.TransformerFactory<ts.Node> =
<T extends ts.Node>(context: ts.TransformationContext) => (rootNode: T) => {
const visitor = (node: ts.Node): ts.Node => {
if (node.kind === ts.SyntaxKind.CallExpression &&
node.parent && node.parent.kind === ts.SyntaxKind.Decorator &&
(node as ts.CallExpression).expression.getText() === "NgModule") {
// found module declaration
// expression: NgModule(arguments)
node = ts.visitEachChild(node, visitNgModule, context);
} else {
node = ts.visitEachChild(node, visitor, context);
}
return node;
};
const visitNgModule = (node: ts.Node): ts.Node => {
const properties: string[] = []; // "declarations", "imports", "providers"
for (const key in this.ngMetaEdits) {
if (this.ngMetaEdits[key].length) {
properties.push(key);
<T extends ts.Node>(context: ts.TransformationContext) => (rootNode: T) => {
const visitor = (node: ts.Node): ts.Node => {
if (node.kind === ts.SyntaxKind.CallExpression &&
node.parent && node.parent.kind === ts.SyntaxKind.Decorator &&
(node as ts.CallExpression).expression.getText() === "NgModule") {
// found module declaration
// expression: NgModule(arguments)
node = ts.visitEachChild(node, visitNgModule, context);
} else {
node = ts.visitEachChild(node, visitor, context);
}
}
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression &&
node.parent &&
node.parent.kind === ts.SyntaxKind.CallExpression) {
return node;
};
const visitNgModule = (node: ts.Node): ts.Node => {
const properties: string[] = []; // "declarations", "imports", "providers"
for (const key in this.ngMetaEdits) {
if (this.ngMetaEdits[key].length) {
properties.push(key);
}
}
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression &&
node.parent &&
node.parent.kind === ts.SyntaxKind.CallExpression) {

let obj = (node as ts.ObjectLiteralExpression);
let obj = (node as ts.ObjectLiteralExpression);

//TODO: test node.parent for ts.CallExpression NgModule
const missingProperties = properties.filter(x => !obj.properties.find(o => o.name.getText() === x));
//TODO: test node.parent for ts.CallExpression NgModule
const missingProperties = properties.filter(x => !obj.properties.find(o => o.name.getText() === x));

// skip visiting if no declaration/imports/providers arrays exist:
if (missingProperties.length !== properties.length) {
obj = ts.visitEachChild(node, visitNgModule, context) as ts.ObjectLiteralExpression;
}
// skip visiting if no declaration/imports/providers arrays exist:
if (missingProperties.length !== properties.length) {
obj = ts.visitEachChild(node, visitNgModule, context) as ts.ObjectLiteralExpression;
}

if (!missingProperties.length) {
return obj;
}
if (!missingProperties.length) {
return obj;
}

const objProperties = ts.visitNodes(obj.properties, visitor);
const newProps = [];
for (const prop of missingProperties) {
let arrayExpr;
switch (prop) {
case "imports":
const importDeps = this.ngMetaEdits.imports;
arrayExpr = ts.createArrayLiteral(
importDeps.map(x => TsUtils.createIdentifier(x.name, x.root ? "forRoot" : ""))
);
break;
case "declarations":
case "providers":
arrayExpr = ts.createArrayLiteral(
this.ngMetaEdits[prop].map(x => ts.createIdentifier(x))
);
break;
const objProperties = ts.visitNodes(obj.properties, visitor);
const newProps = [];
for (const prop of missingProperties) {
let arrayExpr;
switch (prop) {
case "imports":
const importDeps = this.ngMetaEdits.imports;
arrayExpr = ts.createArrayLiteral(
importDeps.map(x => TsUtils.createIdentifier(x.name, x.root ? "forRoot" : ""))
);
break;
case "declarations":
case "providers":
case "exports":
arrayExpr = ts.createArrayLiteral(
this.ngMetaEdits[prop].map(x => ts.createIdentifier(x))
);
break;
}
newProps.push(ts.createPropertyAssignment(prop, arrayExpr));
}
newProps.push(ts.createPropertyAssignment(prop, arrayExpr));
}

return ts.updateObjectLiteral(obj, [
...objProperties,
...newProps
]);
} else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression &&
node.parent.kind === ts.SyntaxKind.PropertyAssignment &&
properties.indexOf((node.parent as ts.PropertyAssignment).name.getText()) !== -1) {
return ts.updateObjectLiteral(obj, [
...objProperties,
...newProps
]);
} else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression &&
node.parent.kind === ts.SyntaxKind.PropertyAssignment &&
properties.indexOf((node.parent as ts.PropertyAssignment).name.getText()) !== -1) {
const initializer = (node as ts.ArrayLiteralExpression);
const props = ts.visitNodes(initializer.elements, visitor);
const alreadyImported = props.map(x => TsUtils.getIdentifierName(x));
Expand All @@ -379,6 +391,7 @@ export class TypeScriptFileUpdate {
break;
case "declarations":
case "providers":
case "exports":
identifiers = this.ngMetaEdits[prop]
.filter(x => alreadyImported.indexOf(x) === -1)
.map(x => ts.createIdentifier(x));
Expand All @@ -390,13 +403,13 @@ export class TypeScriptFileUpdate {
]);

return ts.updateArrayLiteral(initializer, elements);
} else {
node = ts.visitEachChild(node, visitNgModule, context);
}
return node;
};
return ts.visitNode(rootNode, visitor);
}
} else {
node = ts.visitEachChild(node, visitNgModule, context);
}
return node;
};
return ts.visitNode(rootNode, visitor);
}

//#endregion ts.TransformerFactory

Expand Down Expand Up @@ -479,7 +492,7 @@ export class TypeScriptFileUpdate {

/** Return source file formatting options */
private getFormattingOptions(): ts.FormatCodeSettings {
const formatOptions: ts.FormatCodeSettings = {
const formatOptions: ts.FormatCodeSettings = {
indentSize: this.formatOptions.indentSize,
tabSize: 4,
// tslint:disable-next-line:object-literal-sort-keys
Expand Down
Loading

0 comments on commit a7b6251

Please sign in to comment.