Skip to content

Commit 5bd4130

Browse files
Martin Bektchievdtopuzov
Martin Bektchiev
authored andcommittedJan 10, 2018
Merge release to master (#3299)
* Generate debug port in range for Chrome DevTools websocket - iOS (#3275) * fix generating port for debug socket when debugging ios with chrome devtools When generating a port to start a websocket on, use the same logic as is present in the android debug service - get the first available available port in a range, and reuse it for the next debug session of the same application if it is still available * fix(device-socket): iOS Socket proxy should listen on IPv4 localhost adapter Check for available port is done on this adapter and by default server is launched on "::" which is IPv6's any adapter * Fix debug device/web socket closing (#2897) When we close the websocket we have to destroy the device socket as well. We need to wait the close event on the device socket instead of end. * fix(ios-inspector): Correctly update cached inspector package to latest compatible version (#3302) * Currently it is never updated and is left at the first version ever installed in `~/.local`. As a result newly published inspector packages are not used unless the user installs them explicitly in the project or deletes the cache manually. * The iOS inspector package version must be determined according to project's iOS runtime version instead of the version of CLI as it has been till now
1 parent a02f9c2 commit 5bd4130

File tree

6 files changed

+164
-130
lines changed

6 files changed

+164
-130
lines changed
 

‎lib/declarations.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ interface INpmInstallationManager {
3838
install(packageName: string, packageDir: string, options?: INpmInstallOptions): Promise<any>;
3939
getLatestVersion(packageName: string): Promise<string>;
4040
getNextVersion(packageName: string): Promise<string>;
41-
getLatestCompatibleVersion(packageName: string): Promise<string>;
41+
getLatestCompatibleVersion(packageName: string, referenceVersion?: string): Promise<string>;
4242
getInspectorFromCache(inspectorNpmPackageName: string, projectDir: string): Promise<string>;
4343
}
4444

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class SocketProxyFactory extends EventEmitter implements ISocketProxyFact
7474

7575
public async createWebSocketProxy(factory: () => Promise<net.Socket>): Promise<ws.Server> {
7676
// NOTE: We will try to provide command line options to select ports, at least on the localhost.
77-
const localPort = await this.$net.getFreePort();
77+
const localPort = await this.$net.getAvailablePortInRange(41000);
7878

7979
this.$logger.info("\nSetting up debugger proxy...\nPress Ctrl + C to terminate, or disconnect.\n");
8080

@@ -85,6 +85,7 @@ export class SocketProxyFactory extends EventEmitter implements ISocketProxyFact
8585

8686
const server = new ws.Server(<any>{
8787
port: localPort,
88+
host: "localhost",
8889
verifyClient: async (info: any, callback: Function) => {
8990
this.$logger.info("Frontend client connected.");
9091
let _socket;
@@ -131,12 +132,13 @@ export class SocketProxyFactory extends EventEmitter implements ISocketProxyFact
131132
deviceSocket.on("close", () => {
132133
this.$logger.info("Backend socket closed!");
133134
if (!this.$options.watch) {
134-
process.exit(0);
135+
webSocket.close();
135136
}
136137
});
137138

138139
webSocket.on("close", () => {
139140
this.$logger.info('Frontend socket closed!');
141+
deviceSocket.destroy();
140142
if (!this.$options.watch) {
141143
process.exit(0);
142144
}

‎lib/npm-installation-manager.ts

+33-23
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export class NpmInstallationManager implements INpmInstallationManager {
99
private $options: IOptions,
1010
private $settingsService: ISettingsService,
1111
private $fs: IFileSystem,
12-
private $staticConfig: IStaticConfig) {
12+
private $staticConfig: IStaticConfig,
13+
private $projectDataService: IProjectDataService) {
1314
}
1415

1516
public async getLatestVersion(packageName: string): Promise<string> {
@@ -20,23 +21,21 @@ export class NpmInstallationManager implements INpmInstallationManager {
2021
return await this.getVersion(packageName, constants.PackageVersion.NEXT);
2122
}
2223

23-
public async getLatestCompatibleVersion(packageName: string): Promise<string> {
24-
const configVersion = this.$staticConfig.version;
25-
const isPreReleaseVersion = semver.prerelease(configVersion) !== null;
26-
let cliVersionRange = `~${semver.major(configVersion)}.${semver.minor(configVersion)}.0`;
27-
if (isPreReleaseVersion) {
28-
// if the user has some 0-19 pre-release version, include pre-release versions in the search query.
29-
cliVersionRange = `~${configVersion}`;
30-
}
31-
24+
public async getLatestCompatibleVersion(packageName: string, referenceVersion?: string): Promise<string> {
25+
referenceVersion = referenceVersion || this.$staticConfig.version;
26+
const isPreReleaseVersion = semver.prerelease(referenceVersion) !== null;
27+
// if the user has some v.v.v-prerelease-xx.xx pre-release version, include pre-release versions in the search query.
28+
const compatibleVersionRange = isPreReleaseVersion
29+
? `~${referenceVersion}`
30+
: `~${semver.major(referenceVersion)}.${semver.minor(referenceVersion)}.0`;
3231
const latestVersion = await this.getLatestVersion(packageName);
33-
if (semver.satisfies(latestVersion, cliVersionRange)) {
32+
if (semver.satisfies(latestVersion, compatibleVersionRange)) {
3433
return latestVersion;
3534
}
3635

3736
const data = await this.$npm.view(packageName, { "versions": true });
3837

39-
const maxSatisfying = semver.maxSatisfying(data, cliVersionRange);
38+
const maxSatisfying = semver.maxSatisfying(data, compatibleVersionRange);
4039
return maxSatisfying || latestVersion;
4140
}
4241

@@ -59,21 +58,32 @@ export class NpmInstallationManager implements INpmInstallationManager {
5958
const inspectorPath = path.join(projectDir, constants.NODE_MODULES_FOLDER_NAME, inspectorNpmPackageName);
6059

6160
// local installation takes precedence over cache
62-
if (!this.inspectorAlreadyInstalled(inspectorPath)) {
63-
const cachePath = path.join(this.$settingsService.getProfileDir(), constants.INSPECTOR_CACHE_DIRNAME);
64-
this.prepareCacheDir(cachePath);
65-
const pathToPackageInCache = path.join(cachePath, constants.NODE_MODULES_FOLDER_NAME, inspectorNpmPackageName);
66-
67-
if (!this.$fs.exists(pathToPackageInCache)) {
68-
const version = await this.getLatestCompatibleVersion(inspectorNpmPackageName);
69-
await this.$childProcess.exec(`npm install ${inspectorNpmPackageName}@${version} --prefix ${cachePath}`);
61+
if (this.inspectorAlreadyInstalled(inspectorPath)) {
62+
return inspectorPath;
63+
}
64+
65+
const cachePath = path.join(this.$settingsService.getProfileDir(), constants.INSPECTOR_CACHE_DIRNAME);
66+
this.prepareCacheDir(cachePath);
67+
const pathToPackageInCache = path.join(cachePath, constants.NODE_MODULES_FOLDER_NAME, inspectorNpmPackageName);
68+
const iOSFrameworkNSValue = this.$projectDataService.getNSValue(projectDir, constants.TNS_IOS_RUNTIME_NAME);
69+
const version = await this.getLatestCompatibleVersion(inspectorNpmPackageName, iOSFrameworkNSValue.version);
70+
let shouldInstall = !this.$fs.exists(pathToPackageInCache);
71+
72+
if (!shouldInstall) {
73+
try {
74+
const installedVersion = this.$fs.readJson(path.join(pathToPackageInCache, constants.PACKAGE_JSON_FILE_NAME)).version;
75+
shouldInstall = version !== installedVersion;
76+
} catch (err) {
77+
shouldInstall = true;
7078
}
79+
}
7180

72-
this.$logger.out("Using inspector from cache.");
73-
return pathToPackageInCache;
81+
if (shouldInstall) {
82+
await this.$childProcess.exec(`npm install ${inspectorNpmPackageName}@${version} --prefix ${cachePath}`);
7483
}
7584

76-
return inspectorPath;
85+
this.$logger.out("Using inspector from cache.");
86+
return pathToPackageInCache;
7787
}
7888

7989
private prepareCacheDir(cacheDirName: string): void {

‎lib/services/ios-project-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
6464
const projectRoot = path.join(projectData.platformsDir, this.$devicePlatformsConstants.iOS.toLowerCase());
6565

6666
this._platformData = {
67-
frameworkPackageName: "tns-ios",
67+
frameworkPackageName: constants.TNS_IOS_RUNTIME_NAME,
6868
normalizedPlatformName: "iOS",
6969
appDestinationDirectoryPath: path.join(projectRoot, projectData.projectName),
7070
platformProjectService: this,

‎test/npm-installation-manager.ts

+121-103
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import * as StaticConfigLib from "../lib/config";
1010
import * as yok from "../lib/common/yok";
1111
import ChildProcessLib = require("../lib/common/child-process");
1212
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
13+
import { ProjectDataService } from "../lib/services/project-data-service";
1314

1415
function createTestInjector(): IInjector {
1516
const testInjector = new yok.Yok();
@@ -23,6 +24,7 @@ function createTestInjector(): IInjector {
2324
testInjector.register("staticConfig", StaticConfigLib.StaticConfig);
2425
testInjector.register("childProcess", ChildProcessLib.ChildProcess);
2526
testInjector.register("settingsService", SettingsService);
27+
testInjector.register("projectDataService", ProjectDataService);
2628

2729
testInjector.register("npmInstallationManager", NpmInstallationManagerLib.NpmInstallationManager);
2830

@@ -57,121 +59,137 @@ interface ITestData {
5759
*/
5860
cliVersion: string;
5961

62+
/**
63+
* Version, based on which the version of the package that will be installed is detected.
64+
* Used when semantically the correct reference version is different than the CLI version.
65+
* (e.g. inspector package version should be determined by the project's ios runtime version)
66+
*/
67+
referenceVersion?: string;
68+
6069
/**
6170
* Expected result
6271
*/
6372
expectedResult: string;
6473
}
6574

6675
describe("Npm installation manager tests", () => {
67-
const testData: IDictionary<ITestData> = {
68-
"when there's only one available version and it matches CLI's version": {
69-
versions: ["1.4.0"],
70-
packageLatestVersion: "1.4.0",
71-
cliVersion: "1.4.0",
72-
expectedResult: "1.4.0"
73-
},
74-
75-
"when there's only one available version and it is higher than match CLI's version": {
76-
versions: ["1.4.0"],
77-
packageLatestVersion: "1.4.0",
78-
cliVersion: "1.2.0",
79-
expectedResult: "1.4.0"
80-
},
81-
82-
"when there's only one available version and it is lower than CLI's version": {
83-
versions: ["1.4.0"],
84-
packageLatestVersion: "1.4.0",
85-
cliVersion: "1.6.0",
86-
expectedResult: "1.4.0"
87-
},
88-
89-
"when there are multiple package versions and the latest one matches ~<cli-version>": {
90-
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
91-
packageLatestVersion: "1.3.3",
92-
cliVersion: "1.3.0",
93-
expectedResult: "1.3.3"
94-
},
95-
96-
"when there are multiple package versions and the latest one matches ~<cli-version> when there are newer matching versions but they are not under latest tag": {
97-
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
98-
packageLatestVersion: "1.3.2",
99-
cliVersion: "1.3.0",
100-
expectedResult: "1.3.2"
101-
},
102-
103-
"when there are multiple package versions and the latest one is lower than ~<cli-version>": {
104-
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
105-
packageLatestVersion: "1.4.0",
106-
cliVersion: "1.5.0",
107-
expectedResult: "1.4.0"
108-
},
109-
110-
"when there are multiple package versions and there's beta version matching CLI's semver": {
111-
versions: ["1.2.0", "1.3.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182"],
112-
packageLatestVersion: "1.4.0",
113-
cliVersion: "1.5.0",
114-
expectedResult: "1.4.0"
115-
},
116-
117-
"when there are multiple package versions and package's latest version is greater than CLI's version": {
118-
versions: ["1.2.0", "1.3.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0", "1.6.0"],
119-
packageLatestVersion: "1.6.0",
120-
cliVersion: "1.5.0",
121-
expectedResult: "1.5.0"
122-
},
123-
124-
"when there are multiple versions latest one does not match CLI's semver and other versions are not matching either": {
125-
versions: ["1.0.0", "1.0.1", "1.2.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0"],
126-
packageLatestVersion: "1.0.0",
127-
cliVersion: "1.1.0",
128-
expectedResult: "1.0.0"
129-
},
130-
131-
"when CLI's version is beta (has dash) latest matching beta version is returned": {
132-
versions: ["1.0.0", "1.0.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0-2016-02-26-202"],
133-
packageLatestVersion: "1.4.0",
134-
cliVersion: "1.5.0-182",
135-
expectedResult: "1.5.0-2016-02-26-202"
136-
},
137-
138-
"when CLI's version is beta (has dash) latest matching official version is returned when beta versions do not match": {
139-
versions: ["1.0.0", "1.0.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0-2016-02-26-202"],
140-
packageLatestVersion: "1.4.0",
141-
cliVersion: "1.6.0-2016-03-01-182",
142-
expectedResult: "1.4.0"
143-
},
144-
145-
"when CLI's version is beta (has dash) latest matching official version is returned when beta versions do not match (when the prerelease of CLI is higher than prerelease version of runtime)": {
146-
versions: ["1.0.0", "1.0.1", "1.4.0", "1.6.0-2016-02-25-182", "1.6.0-2016-02-26-202"],
147-
packageLatestVersion: "1.4.0",
148-
cliVersion: "1.6.0-2016-10-01-182",
149-
expectedResult: "1.4.0"
150-
},
151-
"When CLI Version has patch version larger than an existing package, should return max compliant package from the same major.minor version": {
152-
versions: ["1.0.0", "1.0.1", "1.4.0", "2.5.0", "2.5.1", "2.5.2", "3.0.0"],
153-
packageLatestVersion: "3.0.0",
154-
cliVersion: "2.5.4",
155-
expectedResult: "2.5.2"
156-
}
157-
};
76+
describe("getLatestCompatibleVersion", () => {
77+
const testData: IDictionary<ITestData> = {
78+
"when there's only one available version and it matches CLI's version": {
79+
versions: ["1.4.0"],
80+
packageLatestVersion: "1.4.0",
81+
cliVersion: "1.4.0",
82+
expectedResult: "1.4.0"
83+
},
84+
85+
"when there's only one available version and it is higher than match CLI's version": {
86+
versions: ["1.4.0"],
87+
packageLatestVersion: "1.4.0",
88+
cliVersion: "1.2.0",
89+
expectedResult: "1.4.0"
90+
},
91+
92+
"when there's only one available version and it is lower than CLI's version": {
93+
versions: ["1.4.0"],
94+
packageLatestVersion: "1.4.0",
95+
cliVersion: "1.6.0",
96+
expectedResult: "1.4.0"
97+
},
98+
99+
"when there are multiple package versions and the latest one matches ~<cli-version>": {
100+
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
101+
packageLatestVersion: "1.3.3",
102+
cliVersion: "1.3.0",
103+
expectedResult: "1.3.3"
104+
},
105+
106+
"when there are multiple package versions and the latest one matches ~<cli-version> when there are newer matching versions but they are not under latest tag": {
107+
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
108+
packageLatestVersion: "1.3.2",
109+
cliVersion: "1.3.0",
110+
expectedResult: "1.3.2"
111+
},
112+
113+
"when there are multiple package versions and the latest one is lower than ~<cli-version>": {
114+
versions: ["1.2.0", "1.3.0", "1.3.1", "1.3.2", "1.3.3", "1.4.0"],
115+
packageLatestVersion: "1.4.0",
116+
cliVersion: "1.5.0",
117+
expectedResult: "1.4.0"
118+
},
119+
120+
"when there are multiple package versions and there's beta version matching CLI's semver": {
121+
versions: ["1.2.0", "1.3.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182"],
122+
packageLatestVersion: "1.4.0",
123+
cliVersion: "1.5.0",
124+
expectedResult: "1.4.0"
125+
},
126+
127+
"when there are multiple package versions and package's latest version is greater than CLI's version": {
128+
versions: ["1.2.0", "1.3.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0", "1.6.0"],
129+
packageLatestVersion: "1.6.0",
130+
cliVersion: "1.5.0",
131+
expectedResult: "1.5.0"
132+
},
133+
134+
"when there are multiple versions latest one does not match CLI's semver and other versions are not matching either": {
135+
versions: ["1.0.0", "1.0.1", "1.2.0", "1.3.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0"],
136+
packageLatestVersion: "1.0.0",
137+
cliVersion: "1.1.0",
138+
expectedResult: "1.0.0"
139+
},
140+
141+
"when CLI's version is beta (has dash) latest matching beta version is returned": {
142+
versions: ["1.0.0", "1.0.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0-2016-02-26-202"],
143+
packageLatestVersion: "1.4.0",
144+
cliVersion: "1.5.0-182",
145+
expectedResult: "1.5.0-2016-02-26-202"
146+
},
147+
148+
"when CLI's version is beta (has dash) latest matching official version is returned when beta versions do not match": {
149+
versions: ["1.0.0", "1.0.1", "1.4.0", "1.5.0-2016-02-25-182", "1.5.0-2016-02-26-202"],
150+
packageLatestVersion: "1.4.0",
151+
cliVersion: "1.6.0-2016-03-01-182",
152+
expectedResult: "1.4.0"
153+
},
154+
155+
"when CLI's version is beta (has dash) latest matching official version is returned when beta versions do not match (when the prerelease of CLI is higher than prerelease version of runtime)": {
156+
versions: ["1.0.0", "1.0.1", "1.4.0", "1.6.0-2016-02-25-182", "1.6.0-2016-02-26-202"],
157+
packageLatestVersion: "1.4.0",
158+
cliVersion: "1.6.0-2016-10-01-182",
159+
expectedResult: "1.4.0"
160+
},
161+
"When CLI Version has patch version larger than an existing package, should return max compliant package from the same major.minor version": {
162+
versions: ["1.0.0", "1.0.1", "1.4.0", "2.5.0", "2.5.1", "2.5.2", "3.0.0"],
163+
packageLatestVersion: "3.0.0",
164+
cliVersion: "2.5.4",
165+
expectedResult: "2.5.2"
166+
},
167+
"When reference version is specified as argument": {
168+
versions: ["122.0.4", "123.0.0", "123.0.1", "123.1.0", "124.0.0"],
169+
packageLatestVersion: "124.0.0",
170+
cliVersion: "0.0.0", // should not matter
171+
expectedResult: "123.0.1",
172+
referenceVersion: "123.0.5"
173+
}
174+
};
158175

159-
_.each(testData, (currentTestData: ITestData, testName: string) => {
160-
it(`returns correct latest compatible version, ${testName}`, async () => {
161-
const testInjector = createTestInjector();
176+
_.each(testData, (currentTestData: ITestData, testName: string) => {
177+
it(`returns correct latest compatible version, ${testName}`, async () => {
178+
const testInjector = createTestInjector();
162179

163-
mockNpm(testInjector, currentTestData.versions, currentTestData.packageLatestVersion);
180+
mockNpm(testInjector, currentTestData.versions, currentTestData.packageLatestVersion);
164181

165-
// Mock staticConfig.version
166-
const staticConfig = testInjector.resolve("staticConfig");
167-
staticConfig.version = currentTestData.cliVersion;
182+
// Mock staticConfig.version
183+
const staticConfig = testInjector.resolve("staticConfig");
184+
staticConfig.version = currentTestData.cliVersion;
168185

169-
// Mock npmInstallationManager.getLatestVersion
170-
const npmInstallationManager = testInjector.resolve("npmInstallationManager");
171-
npmInstallationManager.getLatestVersion = (packageName: string) => Promise.resolve(currentTestData.packageLatestVersion);
186+
// Mock npmInstallationManager.getLatestVersion
187+
const npmInstallationManager = testInjector.resolve("npmInstallationManager");
188+
npmInstallationManager.getLatestVersion = (packageName: string) => Promise.resolve(currentTestData.packageLatestVersion);
172189

173-
const actualLatestCompatibleVersion = await npmInstallationManager.getLatestCompatibleVersion("");
174-
assert.equal(actualLatestCompatibleVersion, currentTestData.expectedResult);
190+
const actualLatestCompatibleVersion = await npmInstallationManager.getLatestCompatibleVersion("", currentTestData.referenceVersion);
191+
assert.equal(actualLatestCompatibleVersion, currentTestData.expectedResult);
192+
});
175193
});
176194
});
177195
});

0 commit comments

Comments
 (0)