Skip to content

Commit aad09a3

Browse files
author
Fatme
authored
Merge pull request #4686 from NativeScript/fatme/merge-master
chore: merge master branch
2 parents edd0fae + 311fdf2 commit aad09a3

File tree

15 files changed

+187
-56
lines changed

15 files changed

+187
-56
lines changed

docs/man_pages/project/creation/create.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ Template | Command
5151
`Angular - Hello World`, `--ng`, `--angular` | tns create tns-template-hello-world-ng
5252
`Angular - SideDrawer` | tns create tns-template-drawer-navigation-ng
5353
`Angular - Tabs` | tns create tns-template-tab-navigation-ng
54-
`Vue.js`, `--vue`, `--vuejs` | tns create tns-template-blank-vue
54+
`Vue.js - Blank`, `--vue`, `--vuejs` | tns create tns-template-blank-vue
55+
`Vue.js - SideDrawer`, | tns create tns-template-drawer-navigation-vue
5556

5657
### Related Commands
5758

lib/commands/create-project.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { isInteractive } from "../common/helpers";
55
export class CreateProjectCommand implements ICommand {
66
public enableHooks = false;
77
public allowedParameters: ICommandParameter[] = [this.$stringParameter];
8+
private static BlankTemplateKey = "Blank";
9+
private static BlankTemplateDescription = "A blank app";
810
private static HelloWorldTemplateKey = "Hello World";
911
private static HelloWorldTemplateDescription = "A Hello World app";
1012
private static DrawerTemplateKey = "SideDrawer";
@@ -109,11 +111,11 @@ or --js flags.)
109111
let selectedTemplate: string;
110112
switch (flavorSelection) {
111113
case constants.NgFlavorName: {
112-
selectedFlavorTemplates.push(...this.getNgFlavors());
114+
selectedFlavorTemplates.push(...this.getNgTemplates());
113115
break;
114116
}
115117
case constants.VueFlavorName: {
116-
selectedFlavorTemplates.push({ value: "tns-template-blank-vue" });
118+
selectedFlavorTemplates.push(...this.getVueTemplates());
117119
break;
118120
}
119121
case constants.TsFlavorName: {
@@ -178,7 +180,7 @@ or --js flags.)
178180
return templates;
179181
}
180182

181-
private getNgFlavors() {
183+
private getNgTemplates() {
182184
const templates = [{
183185
key: CreateProjectCommand.HelloWorldTemplateKey,
184186
value: constants.RESERVED_TEMPLATE_NAMES.angular,
@@ -198,6 +200,21 @@ or --js flags.)
198200
return templates;
199201
}
200202

203+
private getVueTemplates() {
204+
const templates = [{
205+
key: CreateProjectCommand.BlankTemplateKey,
206+
value: "tns-template-blank-vue",
207+
description: CreateProjectCommand.BlankTemplateDescription
208+
},
209+
{
210+
key: CreateProjectCommand.DrawerTemplateKey,
211+
value: "tns-template-drawer-navigation-vue",
212+
description: CreateProjectCommand.DrawerTemplateDescription
213+
}];
214+
215+
return templates;
216+
}
217+
201218
public async postCommandAction(args: string[]): Promise<void> {
202219
const { projectDir } = this.createdProjectData;
203220
const relativePath = path.relative(process.cwd(), projectDir);

lib/common/logger/logger.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,31 +158,40 @@ export class Logger implements ILogger {
158158
}
159159

160160
private getLogOptionsForMessage(data: any[]): { data: any[], [key: string]: any } {
161-
const opts = _.keys(LoggerConfigData);
161+
const loggerOptionKeys = _.keys(LoggerConfigData);
162+
const dataToCheck = data.filter(el => {
163+
// objects created with Object.create(null) do not have `hasOwnProperty` function
164+
if (!!el && typeof el === "object" && el.hasOwnProperty && typeof el.hasOwnProperty === "function") {
165+
for (const key of loggerOptionKeys) {
166+
if (el.hasOwnProperty(key)) {
167+
// include only the elements which have one of the keys we've specified as logger options
168+
return true;
169+
}
170+
}
171+
}
162172

163-
const result: any = {};
164-
const cleanedData = _.cloneDeep(data);
173+
return false;
174+
});
165175

166-
// objects created with Object.create(null) do not have `hasOwnProperty` function
167-
const dataToCheck = data.filter(el => typeof el === "object" && el.hasOwnProperty && typeof el.hasOwnProperty === "function");
176+
const result: any = {
177+
data: _.difference(data, dataToCheck)
178+
};
168179

169180
for (const element of dataToCheck) {
170-
if (opts.length === 0) {
181+
if (loggerOptionKeys.length === 0) {
171182
break;
172183
}
173184

174-
const remainingOpts = _.cloneDeep(opts);
185+
const remainingOpts = _.cloneDeep(loggerOptionKeys);
175186
for (const prop of remainingOpts) {
176187
const hasProp = element && element.hasOwnProperty(prop);
177188
if (hasProp) {
178-
opts.splice(opts.indexOf(prop), 1);
189+
loggerOptionKeys.splice(loggerOptionKeys.indexOf(prop), 1);
179190
result[prop] = element[prop];
180-
cleanedData.splice(cleanedData.indexOf(element), 1);
181191
}
182192
}
183193
}
184194

185-
result.data = cleanedData;
186195
return result;
187196
}
188197

lib/common/services/commands-service.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ export class CommandsService implements ICommandsService {
2727
private $staticConfig: Config.IStaticConfig,
2828
private $helpService: IHelpService,
2929
private $extensibilityService: IExtensibilityService,
30-
private $optionsTracker: IOptionsTracker) {
31-
this.$options.setupOptions();
30+
private $optionsTracker: IOptionsTracker,
31+
private $projectDataService: IProjectDataService) {
3232
}
3333

3434
public allCommands(opts: { includeDevCommands: boolean }): string[] {
@@ -105,8 +105,16 @@ export class CommandsService implements ICommandsService {
105105

106106
private async tryExecuteCommandAction(commandName: string, commandArguments: string[]): Promise<boolean | ICanExecuteCommandOutput> {
107107
const command = this.$injector.resolveCommand(commandName);
108-
if (!command || (command && !command.isHierarchicalCommand)) {
109-
this.$options.validateOptions(command ? command.dashedOptions : null);
108+
if (!command || !command.isHierarchicalCommand) {
109+
let projectData = null;
110+
try {
111+
projectData = this.$projectDataService.getProjectData();
112+
} catch (err) {
113+
this.$logger.trace(`Error while trying to get project data. More info: ${err}`);
114+
}
115+
116+
const dashedOptions = command ? command.dashedOptions : null;
117+
this.$options.validateOptions(dashedOptions, projectData);
110118
}
111119

112120
return this.canExecuteCommand(commandName, commandArguments);

lib/common/test/unit-tests/logger.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Yok } from "../../yok";
22
import { Logger } from "../../logger/logger";
33
import * as path from "path";
4+
import * as util from "util";
45
import { assert } from "chai";
56
import * as fileSystemFile from "../../file-system";
7+
import { LoggerConfigData } from "../../../constants";
68

79
const passwordReplacement = "*******";
810
const debugTrace = ["debug", "trace"];
@@ -33,7 +35,11 @@ describe("logger", () => {
3335
fs = testInjector.resolve("fs");
3436
outputs = {
3537
debug: "",
36-
trace: ""
38+
trace: "",
39+
info: "",
40+
error: "",
41+
context: {},
42+
removedContext: {}
3743
};
3844

3945
const log4jsLogger = {
@@ -42,6 +48,18 @@ describe("logger", () => {
4248
},
4349
trace: (...args: string[]) => {
4450
outputs.trace += args.join("");
51+
},
52+
info: (...args: string[]) => {
53+
outputs.info += util.format.apply(null, args);
54+
},
55+
error: (...args: string[]) => {
56+
outputs.error += util.format.apply(null, args);
57+
},
58+
addContext(key: string, value: any): void {
59+
outputs.context[key] = value;
60+
},
61+
removeContext(key: string): void {
62+
outputs.removedContext[key] = true;
4563
}
4664
};
4765

@@ -139,4 +157,67 @@ describe("logger", () => {
139157
assert.deepEqual(outputs.trace, `${request}${requestBody}`, "logger.trace should not obfuscate body of request unless it is towards api/itmstransporter");
140158
});
141159
});
160+
161+
describe("info", () => {
162+
[undefined, null, false, "string value", 42, { obj: 1 }, ["string value 1", "string value 2"]].forEach(value => {
163+
it(`handles formatted message with '${value}' value in one of the args`, () => {
164+
logger.info("test %s", value);
165+
assert.equal(outputs.info, `test ${value}`);
166+
assert.deepEqual(outputs.context, {}, "Nothing should be added to logger context.");
167+
assert.deepEqual(outputs.removedContext, {}, "Removed context should be empty.");
168+
});
169+
170+
it(`handles formatted message with '${value}' value in one of the args and additional values passed to context`, () => {
171+
logger.info("test %s", value, { [LoggerConfigData.skipNewLine]: true });
172+
assert.equal(outputs.info, `test ${value}`);
173+
assert.deepEqual(outputs.context, { [LoggerConfigData.skipNewLine]: true }, `${LoggerConfigData.skipNewLine} should be set with value true.`);
174+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.skipNewLine]: true }, `Removed context should contain ${LoggerConfigData.skipNewLine}`);
175+
});
176+
});
177+
178+
it("sets correct context when multiple logger options are passed in one object", () => {
179+
logger.info("test", { [LoggerConfigData.skipNewLine]: true, [LoggerConfigData.useStderr]: true });
180+
assert.equal(outputs.info, "test");
181+
assert.deepEqual(outputs.context, { [LoggerConfigData.skipNewLine]: true, [LoggerConfigData.useStderr]: true });
182+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.skipNewLine]: true, [LoggerConfigData.useStderr]: true });
183+
});
184+
185+
it("sets correct context when multiple logger options are passed in multiple objects", () => {
186+
logger.info({ [LoggerConfigData.useStderr]: true }, "test", { [LoggerConfigData.skipNewLine]: true });
187+
assert.equal(outputs.info, "test");
188+
assert.deepEqual(outputs.context, { [LoggerConfigData.skipNewLine]: true, [LoggerConfigData.useStderr]: true });
189+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.skipNewLine]: true, [LoggerConfigData.useStderr]: true });
190+
});
191+
});
192+
193+
describe("printMarkdown", () => {
194+
it(`passes markdown formatted text to log4js.info method`, () => {
195+
logger.printMarkdown("header text\n==");
196+
assert.isTrue(outputs.info.indexOf("# header text") !== -1);
197+
});
198+
199+
it(`passes skipNewLine to log4js context`, () => {
200+
logger.printMarkdown("`coloured` text");
201+
assert.isTrue(outputs.info.indexOf("coloured") !== -1);
202+
assert.deepEqual(outputs.context, { [LoggerConfigData.skipNewLine]: true }, `${LoggerConfigData.skipNewLine} should be set with value true.`);
203+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.skipNewLine]: true }, `Removed context should contain ${LoggerConfigData.skipNewLine}`);
204+
});
205+
});
206+
207+
describe("error", () => {
208+
const errorMessage = "this is error message";
209+
it(`passes useStderr to log4js context`, () => {
210+
logger.error(errorMessage);
211+
assert.equal(outputs.error, errorMessage);
212+
assert.deepEqual(outputs.context, { [LoggerConfigData.useStderr]: true }, `${LoggerConfigData.useStderr} should be set with value true.`);
213+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.useStderr]: true }, `Removed context should contain ${LoggerConfigData.useStderr}`);
214+
});
215+
216+
it(`allows overwrite of useStderr`, () => {
217+
logger.error(errorMessage, { [LoggerConfigData.useStderr]: false });
218+
assert.equal(outputs.error, errorMessage);
219+
assert.deepEqual(outputs.context, { [LoggerConfigData.useStderr]: false }, `${LoggerConfigData.useStderr} should be set with value false.`);
220+
assert.deepEqual(outputs.removedContext, { [LoggerConfigData.useStderr]: true }, `Removed context should contain ${LoggerConfigData.useStderr}`);
221+
});
222+
});
142223
});

lib/common/verify-node-version.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ var util = require("util");
1010
// These versions cannot be used with CLI due to bugs in the node itself.
1111
// We are absolutely sure we cannot work with them, so inform the user if he is trying to use any of them and exit the process.
1212
var versionsCausingFailure = ["0.10.34", "4.0.0", "4.2.0", "5.0.0"];
13-
var minimumRequiredVersion = "6.0.0";
13+
var minimumRequiredVersion = "8.0.0";
1414

1515
interface INodeVersionOpts {
1616
supportedVersionsRange: string;
@@ -22,7 +22,7 @@ interface INodeVersionOpts {
2222
function getNodeVersionOpts(): INodeVersionOpts {
2323
var supportedVersionsRange = require("../../package.json").engines.node;
2424
var cliName = "NativeScript";
25-
var deprecatedVersions = ["^6.0.0", "^7.0.0"];
25+
var deprecatedVersions = ["^8.0.0", "^9.0.0"];
2626
var nodeVer = process.version.substr(1);
2727
return {
2828
supportedVersionsRange: supportedVersionsRange,
@@ -49,15 +49,14 @@ export function verifyNodeVersion(): void {
4949

5050
var nodeWarning = getNodeWarning();
5151
if (nodeWarning && nodeWarning.message) {
52-
console.warn((`${os.EOL}${nodeWarning.message}${os.EOL}`).yellow.bold);
52+
console.warn((os.EOL + nodeWarning.message + os.EOL).yellow.bold);
5353
}
5454
}
5555

56-
var isGetNodeWarningCalled = false;
56+
var nodeWarn: ISystemWarning = undefined;
5757
export function getNodeWarning(): ISystemWarning {
58-
if (!isGetNodeWarningCalled) {
59-
isGetNodeWarningCalled = true;
60-
58+
if (nodeWarn === undefined) {
59+
nodeWarn = null;
6160
var verificationOpts = getNodeVersionOpts();
6261
var cliName = verificationOpts.cliName;
6362
var supportedVersionsRange = verificationOpts.supportedVersionsRange;
@@ -83,13 +82,13 @@ export function getNodeWarning(): ISystemWarning {
8382
}
8483

8584
if (warningMessage) {
86-
return {
85+
nodeWarn = {
8786
message: warningMessage,
8887
severity: SystemWarningsSeverity.medium
8988
};
9089
}
91-
92-
return null;
9390
}
91+
92+
return nodeWarn;
9493
}
9594
/* tslint:enable */

lib/declarations.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ interface IAndroidBundleOptions {
490490

491491
interface IOptions extends IRelease, IDeviceIdentifier, IJustLaunch, IAvd, IAvailableDevices, IProfileDir, IHasEmulatorOption, IBundleString, IHasEmulatorOption, IClean, IProvision, ITeamIdentifier, IAndroidReleaseOptions, IAndroidBundleOptions, INpmInstallConfigurationOptions, IPort, IEnvOptions, IPluginSeedOptions, IGenerateOptions {
492492
argv: IYargArgv;
493-
validateOptions(commandSpecificDashedOptions?: IDictionary<IDashedOption>): void;
493+
validateOptions(commandSpecificDashedOptions?: IDictionary<IDashedOption>, projectData?: IProjectData): void;
494494
options: IDictionary<IDashedOption>;
495495
shorthands: string[];
496496
/**
@@ -557,7 +557,6 @@ interface IOptions extends IRelease, IDeviceIdentifier, IJustLaunch, IAvd, IAvai
557557
analyticsLogFile: string;
558558
performance: Object;
559559
cleanupLogFile: string;
560-
setupOptions(): void;
561560
}
562561

563562
interface IEnvOptions {

lib/definitions/project.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ interface IAssetItem {
204204
idiom: string;
205205
resizeOperation?: string;
206206
overlayImageScale?: number;
207+
rgba?: boolean;
207208
}
208209

209210
interface IAssetSubGroup {

lib/options.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ export class Options {
2121

2222
public options: IDictionary<IDashedOption>;
2323

24-
public setupOptions(): void {
24+
public setupOptions(projectData: IProjectData, commandSpecificDashedOptions?: IDictionary<IDashedOption>): void {
25+
if (commandSpecificDashedOptions) {
26+
_.extend(this.options, commandSpecificDashedOptions);
27+
this.setArgv();
28+
}
29+
2530
if (this.argv.release && this.argv.hmr) {
2631
this.$errors.failWithoutHelp("The options --release and --hmr cannot be used simultaneously.");
2732
}
@@ -154,12 +159,8 @@ export class Options {
154159
return this.argv[optionName];
155160
}
156161

157-
public validateOptions(commandSpecificDashedOptions?: IDictionary<IDashedOption>): void {
158-
if (commandSpecificDashedOptions) {
159-
_.extend(this.options, commandSpecificDashedOptions);
160-
this.setArgv();
161-
}
162-
162+
public validateOptions(commandSpecificDashedOptions?: IDictionary<IDashedOption>, projectData?: IProjectData): void {
163+
this.setupOptions(projectData, commandSpecificDashedOptions);
163164
const parsed = Object.create(null);
164165
// DO NOT REMOVE { } as when they are missing and some of the option values is false, the each stops as it thinks we have set "return false".
165166
_.each(_.keys(this.argv), optionName => {

0 commit comments

Comments
 (0)