Skip to content

Commit 25fe40b

Browse files
committed
Merge master
2 parents 6fdc25c + fff9bbe commit 25fe40b

35 files changed

+1051
-312
lines changed

lib/bootstrap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,5 @@ $injector.requireCommand("resources|generate|splashes", "./commands/generate-ass
167167
$injector.requirePublic("assetsGenerationService", "./services/assets-generation/assets-generation-service");
168168

169169
$injector.require("filesHashService", "./services/files-hash-service");
170+
$injector.require("iOSLogParserService", "./services/ios-log-parser-service");
171+
$injector.require("iOSDebuggerPortService", "./services/ios-debugger-port-service");

lib/commands/debug.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,15 @@ export class DebugIOSCommand implements ICommand {
143143
private $injector: IInjector,
144144
private $projectData: IProjectData,
145145
private $platformsData: IPlatformsData,
146-
$iosDeviceOperations: IIOSDeviceOperations) {
146+
$iosDeviceOperations: IIOSDeviceOperations,
147+
$iOSSimulatorLogProvider: Mobile.IiOSSimulatorLogProvider) {
147148
this.$projectData.initializeProjectData();
148149
// Do not dispose ios-device-lib, so the process will remain alive and the debug application (NativeScript Inspector or Chrome DevTools) will be able to connect to the socket.
149150
// In case we dispose ios-device-lib, the socket will be closed and the code will fail when the debug application tries to read/send data to device socket.
150151
// That's why the `$ tns debug ios --justlaunch` command will not release the terminal.
151152
// In case we do not set it to false, the dispose will be called once the command finishes its execution, which will prevent the debugging.
152153
$iosDeviceOperations.setShouldDispose(false);
154+
$iOSSimulatorLogProvider.setShouldDispose(false);
153155
}
154156

155157
public execute(args: string[]): Promise<void> {

lib/constants.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export const enum DebugTools {
137137
export const enum TrackActionNames {
138138
Build = "Build",
139139
CreateProject = "Create project",
140+
UsingTemplate = "Using Template",
140141
Debug = "Debug",
141142
Deploy = "Deploy",
142143
LiveSync = "LiveSync",
@@ -145,6 +146,8 @@ export const enum TrackActionNames {
145146
CheckEnvironmentRequirements = "Check Environment Requirements"
146147
}
147148

149+
export const AnalyticsEventLabelDelimiter = "__";
150+
148151
export const enum BuildStates {
149152
Clean = "Clean",
150153
Incremental = "Incremental"
@@ -189,3 +192,16 @@ export class SubscribeForNewsletterMessages {
189192
public static ReviewPrivacyPolicyMsg = `You can review the Progress Software Privacy Policy at \`${PROGRESS_PRIVACY_POLICY_URL}\``;
190193
public static PromptMsg = "Input your e-mail address to agree".green + " or " + "leave empty to decline".red.bold + ":";
191194
}
195+
196+
export class TemplateVersions {
197+
public static v1 = "v1";
198+
public static v2 = "v2";
199+
}
200+
201+
export class ProjectTemplateErrors {
202+
public static InvalidTemplateVersionStringFormat = "The template '%s' has a NativeScript version '%s' that is not supported. Unable to create project from it.";
203+
}
204+
205+
export class Hooks {
206+
public static createProject = "createProject";
207+
}

lib/declarations.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,9 @@ interface ISocketProxyFactory extends NodeJS.EventEmitter {
643643
createWebSocketProxy(factory: () => Promise<any>, deviceIdentifier: string): Promise<any>;
644644
}
645645

646-
interface IiOSNotification {
646+
interface IiOSNotification extends NodeJS.EventEmitter {
647647
getWaitForDebug(projectId: string): string;
648-
getAttachRequest(projectId: string): string;
648+
getAttachRequest(projectId: string, deviceId: string): string;
649649
getAppLaunching(projectId: string): string;
650650
getReadyForAttach(projectId: string): string;
651651
getAttachAvailabilityQuery(projectId: string): string;
@@ -843,4 +843,4 @@ interface IAssetsGenerationService {
843843
* @returns {Promise<void>}
844844
*/
845845
generateSplashScreens(splashesGenerationData: ISplashesGenerationData): Promise<void>;
846-
}
846+
}

lib/definitions/debug.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ interface IDebugOptions {
8787
* Defines if the iOS App Inspector should be used instead of providing URL to debug the application with Chrome DevTools
8888
*/
8989
inspector?: boolean;
90+
/**
91+
* Defines if should print all availableDevices
92+
*/
93+
availableDevices?: boolean;
9094
}
9195

9296
/**
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
interface IIOSDebuggerPortInputData {
2+
deviceId: string;
3+
appId: string;
4+
}
5+
6+
interface IIOSDebuggerPortData extends IIOSDebuggerPortInputData {
7+
port: number;
8+
}
9+
10+
interface IIOSDebuggerPortStoredData {
11+
port: number;
12+
timer?: NodeJS.Timer;
13+
}
14+
15+
interface IIOSDebuggerPortService {
16+
/**
17+
* Gets iOS debugger port for specified deviceId and appId
18+
* @param {IIOSDebuggerPortInputData} data - Describes deviceId and appId
19+
*/
20+
getPort(data: IIOSDebuggerPortInputData): Promise<number>;
21+
/**
22+
* Attaches on DEBUGGER_PORT_FOUND event and STARTING_IOS_APPLICATION events
23+
* In case when DEBUGGER_PORT_FOUND event is emitted, stores the port and clears the timeout if such.
24+
* In case when STARTING_IOS_APPLICATION event is emiited, sets the port to null and add timeout for 5000 miliseconds which checks if port is null and prints a warning.
25+
* @param {Mobile.IDevice} device - Describes the device which logs should be parsed.
26+
*/
27+
attachToDebuggerPortFoundEvent(device: Mobile.IDevice): void;
28+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
interface IIOSLogParserService extends NodeJS.EventEmitter {
2+
/**
3+
* Starts looking for debugger port. Attaches on device logs and processes them. In case when port is found, DEBUGGER_PORT_FOUND event is emitted.
4+
* @param {Mobile.IDevice} device - Describes the device which logs will be processed.
5+
*/
6+
startParsingLog(device: Mobile.IDevice): void;
7+
}

lib/definitions/platform.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,5 +381,5 @@ interface IUpdateAppOptions extends IOptionalFilesToSync, IOptionalFilesToRemove
381381
}
382382

383383
interface IPlatformEnvironmentRequirements {
384-
checkEnvironmentRequirements(platform?: string): Promise<boolean>;
384+
checkEnvironmentRequirements(platform?: string, projectDir?: string): Promise<boolean>;
385385
}

lib/definitions/project.d.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
/**
2-
* Describes available settings when creating new NativeScript application.
3-
*/
4-
interface IProjectSettings {
1+
interface IProjectName {
2+
projectName: string;
3+
}
4+
5+
interface IProjectSettingsBase extends IProjectName {
56
/**
67
* Name of the newly created application.
78
*/
89
projectName: string;
910

11+
/**
12+
* Defines whether the `npm install` command should be executed with `--ignore-scripts` option.
13+
* When it is passed, all scripts (postinstall for example) will not be executed.
14+
*/
15+
ignoreScripts?: boolean;
16+
1017
/**
1118
* Selected template from which to create the project. If not specified, defaults to hello-world template.
1219
* Template can be any npm package, local dir, github url, .tgz file.
@@ -19,7 +26,19 @@ interface IProjectSettings {
1926
* Application identifier for the newly created application. If not specified, defaults to org.nativescript.<projectName>.
2027
*/
2128
appId?: string;
29+
}
30+
31+
/**
32+
* Describes information passed to project creation hook (createProject).
33+
*/
34+
interface IProjectCreationSettings extends IProjectSettingsBase, IProjectDir {
35+
36+
}
2237

38+
/**
39+
* Describes available settings when creating new NativeScript application.
40+
*/
41+
interface IProjectSettings extends IProjectSettingsBase {
2342
/**
2443
* Path where the project will be created. If not specified, defaults to current working dir.
2544
*/
@@ -29,17 +48,8 @@ interface IProjectSettings {
2948
* Defines if invalid application name can be used for project creation.
3049
*/
3150
force?: boolean;
32-
33-
/**
34-
* Defines whether the `npm install` command should be executed with `--ignore-scripts` option.
35-
* When it is passed, all scripts (postinstall for example) will not be executed.
36-
*/
37-
ignoreScripts?: boolean;
3851
}
3952

40-
interface IProjectName {
41-
projectName: string;
42-
}
4353

4454
interface ICreateProjectData extends IProjectDir, IProjectName {
4555

@@ -201,6 +211,11 @@ interface IImageDefinitionsStructure {
201211
android: IImageDefinitionGroup;
202212
}
203213

214+
interface ITemplateData {
215+
templatePath: string;
216+
templateVersion: string;
217+
}
218+
204219
/**
205220
* Describes working with templates.
206221
*/
@@ -211,13 +226,22 @@ interface IProjectTemplatesService {
211226
* In case templateName is a special word, validated from us (for ex. typescript), resolve the real template name and add it to npm cache.
212227
* In any other cases try to `npm install` the specified templateName to temp directory.
213228
* @param {string} templateName The name of the template.
214-
* @return {string} Path to the directory where extracted template can be found.
229+
* @return {ITemplateData} Data describing the template - location where it is installed and its NativeScript version.
230+
*/
231+
prepareTemplate(templateName: string, projectDir: string): Promise<ITemplateData>;
232+
233+
/**
234+
* Gives information for the nativescript specific version of the template, for example v1, v2, etc.
235+
* Defaults to v1 in case there's no version specified.
236+
* @param {string} templatePath Full path to the template.
237+
* @returns {string} The version, for example v1 or v2.
215238
*/
216-
prepareTemplate(templateName: string, projectDir: string): Promise<string>;
239+
getTemplateVersion(templatePath: string): string;
217240
}
218241

219242
interface IPlatformProjectServiceBase {
220243
getPluginPlatformsFolderPath(pluginData: IPluginData, platform: string): string;
244+
getFrameworkVersion(projectData: IProjectData): string;
221245
}
222246

223247
interface IBuildForDevice {
@@ -270,7 +294,7 @@ interface ILocalBuildService {
270294

271295
interface ICleanNativeAppData extends IProjectDir, IPlatform { }
272296

273-
interface IPlatformProjectService extends NodeJS.EventEmitter {
297+
interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectServiceBase {
274298
getPlatformData(projectData: IProjectData): IPlatformData;
275299
validate(projectData: IProjectData): Promise<void>;
276300
createProject(frameworkDir: string, frameworkVersion: string, projectData: IProjectData, config: ICreateProjectOptions): Promise<void>;

lib/device-sockets/ios/notification.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
export class IOSNotification implements IiOSNotification {
1+
import { EventEmitter } from "events";
2+
import { ATTACH_REQUEST_EVENT_NAME } from "../../common/constants";
3+
4+
export class IOSNotification extends EventEmitter implements IiOSNotification {
25
private static WAIT_FOR_DEBUG_NOTIFICATION_NAME = "WaitForDebugger";
36
private static ATTACH_REQUEST_NOTIFICATION_NAME = "AttachRequest";
47
private static APP_LAUNCHING_NOTIFICATION_NAME = "AppLaunching";
@@ -11,8 +14,11 @@ export class IOSNotification implements IiOSNotification {
1114
return this.formatNotification(IOSNotification.WAIT_FOR_DEBUG_NOTIFICATION_NAME, projectId);
1215
}
1316

14-
public getAttachRequest(projectId: string): string {
15-
return this.formatNotification(IOSNotification.ATTACH_REQUEST_NOTIFICATION_NAME, projectId);
17+
public getAttachRequest(appId: string, deviceId: string): string {
18+
// It could be too early to emit this event, but we rely that if you construct attach request,
19+
// you will execute it immediately.
20+
this.emit(ATTACH_REQUEST_EVENT_NAME, { deviceId, appId });
21+
return this.formatNotification(IOSNotification.ATTACH_REQUEST_NOTIFICATION_NAME, appId);
1622
}
1723

1824
public getAppLaunching(projectId: string): string {

lib/device-sockets/ios/socket-proxy-factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class SocketProxyFactory extends EventEmitter implements ISocketProxyFact
9595
err.deviceIdentifier = deviceIdentifier;
9696
this.$logger.trace(err);
9797
this.emit(CONNECTION_ERROR_EVENT_NAME, err);
98-
this.$errors.failWithoutHelp("Cannot connect to device socket.");
98+
this.$errors.failWithoutHelp(`Cannot connect to device socket. The error message is ${err.message}`);
9999
}
100100

101101
this.$logger.info("Backend socket created.");

lib/device-sockets/ios/socket-request-executor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class IOSSocketRequestExecutor implements IiOSSocketRequestExecutor {
6161
const readyForAttachSocket = await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getReadyForAttach(projectId), constants.IOS_OBSERVE_NOTIFICATION_COMMAND_TYPE);
6262
const readyForAttachPromise = this.$iOSNotificationService.awaitNotification(deviceIdentifier, +readyForAttachSocket, readyForAttachTimeout);
6363

64-
await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getAttachRequest(projectId));
64+
await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getAttachRequest(projectId, deviceIdentifier));
6565
await readyForAttachPromise;
6666
} catch (e) {
6767
this.$logger.trace("Launch request error:");
@@ -76,7 +76,7 @@ export class IOSSocketRequestExecutor implements IiOSSocketRequestExecutor {
7676
// before we send the PostNotification.
7777
const readyForAttachSocket = await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getReadyForAttach(projectId), constants.IOS_OBSERVE_NOTIFICATION_COMMAND_TYPE);
7878
const readyForAttachPromise = this.$iOSNotificationService.awaitNotification(deviceIdentifier, +readyForAttachSocket, timeout);
79-
await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getAttachRequest(projectId));
79+
await this.$iOSNotificationService.postNotification(deviceIdentifier, this.$iOSNotification.getAttachRequest(projectId, deviceIdentifier));
8080
await readyForAttachPromise;
8181
} catch (e) {
8282
this.$errors.failWithoutHelp(`The application ${projectId} timed out when performing the socket handshake.`);

lib/helpers/livesync-command-helper.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
1010
private $platformsData: IPlatformsData,
1111
private $analyticsService: IAnalyticsService,
1212
private $bundleValidatorHelper: IBundleValidatorHelper,
13-
private $errors: IErrors) {
13+
private $errors: IErrors,
14+
private $iOSSimulatorLogProvider: Mobile.IiOSSimulatorLogProvider) {
1415
this.$analyticsService.setShouldDispose(this.$options.justlaunch || !this.$options.watch);
1516
}
1617

@@ -53,6 +54,7 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
5354
const shouldKeepProcessAlive = this.$options.watch || !this.$options.justlaunch;
5455
if (workingWithiOSDevices && shouldKeepProcessAlive) {
5556
this.$iosDeviceOperations.setShouldDispose(false);
57+
this.$iOSSimulatorLogProvider.setShouldDispose(false);
5658
}
5759

5860
if (this.$options.release) {

lib/services/android-project-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
133133
this.validatePackageName(projectData.projectId);
134134
this.validateProjectName(projectData.projectName);
135135

136-
await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName);
136+
await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
137137
this.$androidToolsInfo.validateTargetSdk({ showWarningsAsErrors: true });
138138
}
139139

@@ -605,7 +605,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
605605
}
606606

607607
public stopServices(projectRoot: string): Promise<ISpawnResult> {
608-
return this.executeCommand(projectRoot, ["--stop", "--quiet"]);
608+
return this.executeCommand(projectRoot, ["--stop", "--quiet"], {stdio: "pipe"});
609609
}
610610

611611
public async cleanProject(projectRoot: string, projectData: IProjectData): Promise<void> {

lib/services/doctor-service.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ class DoctorService implements IDoctorService {
1717
private $terminalSpinnerService: ITerminalSpinnerService,
1818
private $versionsService: IVersionsService) { }
1919

20-
public async printWarnings(configOptions?: { trackResult: boolean }): Promise<void> {
20+
public async printWarnings(configOptions?: { trackResult: boolean , projectDir?: string }): Promise<void> {
2121
const infos = await this.$terminalSpinnerService.execute<NativeScriptDoctor.IInfo[]>({
2222
text: `Getting environment information ${EOL}`
23-
}, () => doctor.getInfos());
23+
}, () => doctor.getInfos({ projectDir: configOptions && configOptions.projectDir }));
2424

2525
const warnings = infos.filter(info => info.type === constants.WARNING_TYPE_NAME);
2626
const hasWarnings = warnings.length > 0;
@@ -48,7 +48,7 @@ class DoctorService implements IDoctorService {
4848
this.$logger.error("Cannot get the latest versions information from npm. Please try again later.");
4949
}
5050

51-
await this.$injector.resolve("platformEnvironmentRequirements").checkEnvironmentRequirements(null);
51+
await this.$injector.resolve("platformEnvironmentRequirements").checkEnvironmentRequirements(null, configOptions && configOptions.projectDir);
5252
}
5353

5454
public async runSetupScript(): Promise<ISpawnResult> {
@@ -81,12 +81,12 @@ class DoctorService implements IDoctorService {
8181
});
8282
}
8383

84-
public async canExecuteLocalBuild(platform?: string): Promise<boolean> {
84+
public async canExecuteLocalBuild(platform?: string, projectDir?: string): Promise<boolean> {
8585
await this.$analyticsService.trackEventActionInGoogleAnalytics({
8686
action: TrackActionNames.CheckLocalBuildSetup,
8787
additionalData: "Starting",
8888
});
89-
const infos = await doctor.getInfos({ platform });
89+
const infos = await doctor.getInfos({ platform, projectDir });
9090

9191
const warnings = this.filterInfosByType(infos, constants.WARNING_TYPE_NAME);
9292
const hasWarnings = warnings.length > 0;

0 commit comments

Comments
 (0)