Skip to content

Commit

Permalink
Merge branch 'master' into mvenkov/add-list-angular-template
Browse files Browse the repository at this point in the history
  • Loading branch information
wnvko committed Feb 7, 2018
2 parents 8ea99e5 + 5acf662 commit 1539347
Show file tree
Hide file tree
Showing 15 changed files with 504 additions and 16 deletions.
60 changes: 53 additions & 7 deletions lib/ProjectConfig.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,72 @@
import * as fs from "fs-extra";
import * as os from "os";
import * as path from "path";
import { Util } from "./Util";

export class ProjectConfig {

public static configFile: string = "ignite-ui-cli.json";
public static readonly defaults: Config = require("./config/defaults.json");

public static getConfig(): Config {
/** Returns true if there's a CLI config file in the current working directory */
public static hasLocalConfig(): boolean {
const filePath = path.join(process.cwd(), this.configFile);
return fs.existsSync(filePath);
}

/**
* Get effective CLI configuration (merged defaults, global and local)
* @param global return only global values
*/
public static getConfig(global: boolean = false): Config {
const filePath = path.join(process.cwd(), this.configFile);
const config = {};

Util.merge(config, this.defaults);
Util.merge(config, this.globalConfig());

if (!global) {
Util.merge(config, this.localConfig());
}
return config as Config;
}

/**
* Write a configuration file (either local or global) with given `Config` object.
* Will create or overwrite.
* @param config Config object to set
* @param global Set global values instead
*/
public static setConfig(config: Config, global: boolean = false) {
const basePath = global ? os.homedir() : process.cwd();
const filePath = path.join(basePath, this.configFile);
fs.writeJsonSync(filePath, config, { spaces: 4 });
}

/*** Get local configuration only */
public static localConfig(): Config {
const filePath = path.join(process.cwd(), this.configFile);
let localConfig = {};

if (fs.existsSync(filePath)) {
try {
return JSON.parse(fs.readFileSync(filePath, "utf8")) as Config;
localConfig = JSON.parse(fs.readFileSync(filePath, "utf8"));
} catch (error) {
throw new Error(`The ${this.configFile} file is not parsed correctly. ` +
`The following error has occurred: ${error.message}`);
}
}
return null;
return localConfig as Config;
}
public static setConfig(config: Config) {
const filePath = path.join(process.cwd(), this.configFile);
if (fs.existsSync(filePath)) {
fs.writeJsonSync(filePath, config, { spaces: 4 });

/*** Get global configuration only */
public static globalConfig(): Config {
const globalConfigPath = path.join(os.homedir(), this.configFile);
let globalConfig = {};

if (fs.existsSync(globalConfigPath)) {
globalConfig = require(globalConfigPath);
}
return globalConfig as Config;
}
}
2 changes: 1 addition & 1 deletion lib/PromptSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class PromptSession {
add.templateManager = this.templateManager;

// tslint:disable:object-literal-sort-keys
if (config != null && !config.project.isShowcase) {
if (ProjectConfig.hasLocalConfig() && !config.project.isShowcase) {
projLibrary = this.templateManager.getProjectLibrary(config.project.framework, config.project.projectType);
await this.chooseActionLoop(projLibrary, config.project.theme);
} else {
Expand Down
37 changes: 37 additions & 0 deletions lib/Util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,43 @@ class Util {
public static isAlphanumericExt(name: string) {
return /^[\sa-zA-Z][\w\s\-]+$/.test(name);
}

/**
* Simple object merge - deep nested objects and arrays (of primitive values only)
* @param target Object to merge values into
* @param source Object to merge values from
*/
public static merge(target: any, source: any) {
for (const key of Object.keys(source)) {
if (!target.hasOwnProperty(key) || typeof source[key] !== "object") {
// primitive/new value:
target[key] = source[key];
} else if (Array.isArray(source[key])) {
// skip array merge on target type mismatch:
if (!Array.isArray(target[key])) {
continue;
}
for (const item of source[key]) {
if (target[key].indexOf(item) === -1) {
target[key].push(item);
}
}
} else {
this.merge(target[key], source[key]);
}
}
}

private static propertyByPath(object: any, propPath: string) {
if (!propPath) {
return object;
}
const pathParts = propPath.split(".");
const currentProp = pathParts.shift();
if (currentProp in object) {
return this.propertyByPath(object[currentProp], pathParts.join("."));
}
}
}

export { Util };
4 changes: 4 additions & 0 deletions lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as inquirer from "inquirer";
import * as yargs from "yargs";
import { default as add } from "./commands/add";
import { default as build } from "./commands/build";
import { default as config } from "./commands/config";
import { default as newCommand } from "./commands/new";
import { default as quickstart } from "./commands/quickstart";
import { default as start } from "./commands/start";
Expand All @@ -28,6 +29,7 @@ export async function run(args = null) {
.command(start)
.command(newCommand)
.command(build)
.command(config)
.command(test)
.command(add)
.options({
Expand Down Expand Up @@ -66,6 +68,8 @@ export async function run(args = null) {
case "build":
await build.execute(argv);
break;
case "config":
break;
case "test":
await test.execute(argv);
break;
Expand Down
5 changes: 2 additions & 3 deletions lib/commands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ command = {
return true;
},
async execute(argv) {
//command.template;
const config = ProjectConfig.getConfig();
if (config == null) {
if (!ProjectConfig.hasLocalConfig()) {
Util.error("Add command is supported only on existing project created with igniteui-cli", "red");
return;
}
const config = ProjectConfig.getConfig();
if (config.project.isShowcase) {
Util.error("Showcases and quickstart projects don't support the add command", "red");
return;
Expand Down
122 changes: 122 additions & 0 deletions lib/commands/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Util } from "../Util";
import { ProjectConfig } from "./../ProjectConfig";

const command = {
// tslint:disable:object-literal-sort-keys
command: "config",
desc: "Get or set configuration properties",
builder: yargs => {
yargs.command({
command: "get <property>",
desc: "Get configuration properties",
builder: {
property: {
describe: "Config property to get",
type: "string"
}
},
handler: command.getHandler
}).command({
command: "set <property> <value>",
desc: "Set configuration properties",
builder: {
property: {
describe: "Config property to set",
type: "string"
},
value: {
describe: "New value for the property",
type: "string"
}
},
handler: command.setHandler
}).command({
command: "add <property> <value>",
desc: "Add a value to an existing configuration array",
builder: {
property: {
describe: "Config property to add to",
type: "string"
},
value: {
describe: "New value to add",
type: "string"
}
},
handler: command.addHandler
}).option("global", {
alias: "g",
type: "boolean",
global: true,
describe: "Specify if the global configuration should be used"
})
// at least one command is required
.demand(1, "Please use either get or set command");
},
// tslint:enable:object-literal-sort-keys
getHandler(argv) {
if (!argv.global && !ProjectConfig.hasLocalConfig()) {
Util.error("No configuration file found in this folder!", "red");
return;
}
const config = ProjectConfig.getConfig(argv.global);
if (config[argv.property] !== undefined) {
Util.log(config[argv.property]);
} else {
Util.error(`No value found for "${argv.property}" property`, "red");
}
},
setHandler(argv) {
let config;

if (argv.global) {
config = ProjectConfig.globalConfig();
} else {
if (!ProjectConfig.hasLocalConfig()) {
Util.error("No configuration file found in this folder!", "red");
return;
}
config = ProjectConfig.localConfig();
}

if (config[argv.property]) {
// TODO: Schema/property validation?
}

config[argv.property] = argv.value;
ProjectConfig.setConfig(config, argv.global);
Util.log(`Property "${argv.property}" set.`);
},
addHandler(argv) {
let config;

if (argv.global) {
config = ProjectConfig.globalConfig();
} else {
if (!ProjectConfig.hasLocalConfig()) {
Util.error("No configuration file found in this folder!", "red");
return;
}
config = ProjectConfig.localConfig();
}

// TODO: Schema/property validation?
if (!config[argv.property]) {
config[argv.property] = [];
} else if (!Array.isArray(config[argv.property])) {
Util.error(`Configuration property "${argv.property}" is not an array, use config set instead.`, "red");
return;
}

if (config[argv.property].indexOf(argv.value) !== -1) {
Util.log(`Value already exists in "${argv.property}".`);
return;
}

config[argv.property].push(argv.value);
ProjectConfig.setConfig(config, argv.global);
Util.log(`Property "${argv.property}" updated.`);
}
};

export default command;
2 changes: 1 addition & 1 deletion lib/commands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ command = {
},
template: null,
async execute(argv) {
if (ProjectConfig.getConfig() !== null) {
if (ProjectConfig.hasLocalConfig()) {
return Util.error("There is already an existing project.", "red");
}
if (!argv.name && !argv.type && !argv.theme) {
Expand Down
4 changes: 4 additions & 0 deletions lib/config/defaults.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"igPackageRegistry": "https://packages.infragistics.com/npm/js-licensed/",
"customTemplates": []
}
9 changes: 7 additions & 2 deletions lib/types/Config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ declare interface Config {
igniteuiSource: string;

[key: string]: any;
};
}
build: {
/** This object contains information related to the build configuration
* and server configuration of the project */
//"projectBuild": "tsc",
//"serverType": "webpack"
};
}

/** An array of paths to read custom templates from */
customTemplates: string[];
/** Infragistics package registry Url */
igPackageRegistry: string;
}
Loading

0 comments on commit 1539347

Please sign in to comment.