Skip to content

Commit 254ac9f

Browse files
Use profileDir from settingsService (#3203)
Currently CLI's configuration directory is used from `$options.profileDir`. When user passes `--profileDir <path>`, the `$options.profileDir` value is populated. In case user does not pass anything, a default value is set. All services that require configuration directory use the `$options.profileDir`. However, this causes several issues: - `$options` is intended for use only when CLI is used as a standalone command line. In case you are using it as a library, the `$options` object will not be populated. - Unable to test local installations of extensions when CLI is used as library - there's no way to set the custom profileDir when using CLI as a library. So the extensions are always loaded from the default location. In order to resolve these issues, move the logic for profileDir in `settingsService` and introduce a new method to get the profileDir. In order to ensure code is backwards compatible (i.e. extensions that use `$options.profileDir` should still work), modify `$options` to set the value of `profileDir` in `settingsService`. Whenever you want to test local extensions you can use: ```JavaScript const tns = require("nativescript"); tns.settingsService.setSettings({ profileDir: "my custom dir" }); Promise.all(tns.extensibilityService.loadExtensions()) .then((result) => { console.log("Loaded extensions:", result); // write your code here }); ``` Replace all places where `$options.profileDir` is used with `$settingsService.getProfileDir()`.
1 parent cd214db commit 254ac9f

19 files changed

+52
-40
lines changed

PublicAPI.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ interface ISettingsService {
273273
274274
* Usage:
275275
```JavaScript
276-
tns.settingsService.setSettings({ userAgentName: "myUserAgent" });
276+
tns.settingsService.setSettings({ userAgentName: "myUserAgent", profileDir: "customProfileDir" });
277277
```
278278
279279
## npm

lib/commands/post-install.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ export class PostInstallCliCommand extends PostInstallCommand {
66
$staticConfig: Config.IStaticConfig,
77
$commandsService: ICommandsService,
88
$helpService: IHelpService,
9-
$options: ICommonOptions,
9+
$settingsService: ISettingsService,
1010
$doctorService: IDoctorService,
1111
$analyticsService: IAnalyticsService,
1212
$logger: ILogger) {
13-
super($fs, $staticConfig, $commandsService, $helpService, $options, $doctorService, $analyticsService, $logger);
13+
super($fs, $staticConfig, $commandsService, $helpService, $settingsService, $doctorService, $analyticsService, $logger);
1414
}
1515

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

lib/config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export class StaticConfig extends StaticConfigBase implements IStaticConfig {
2828
public ERROR_REPORT_SETTING_NAME = "TrackExceptions";
2929
public ANALYTICS_INSTALLATION_ID_SETTING_NAME = "AnalyticsInstallationID";
3030
public INSTALLATION_SUCCESS_MESSAGE = "Installation successful. You are good to go. Connect with us on `http://twitter.com/NativeScript`.";
31+
public get PROFILE_DIR_NAME(): string {
32+
return ".nativescript-cli";
33+
}
3134

3235
constructor($injector: IInjector) {
3336
super($injector);

lib/npm-installation-manager.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export class NpmInstallationManager implements INpmInstallationManager {
77
private $childProcess: IChildProcess,
88
private $logger: ILogger,
99
private $options: IOptions,
10+
private $settingsService: ISettingsService,
1011
private $fs: IFileSystem,
1112
private $staticConfig: IStaticConfig) {
1213
}
@@ -59,7 +60,7 @@ export class NpmInstallationManager implements INpmInstallationManager {
5960

6061
// local installation takes precedence over cache
6162
if (!this.inspectorAlreadyInstalled(inspectorPath)) {
62-
const cachePath = path.join(this.$options.profileDir, constants.INSPECTOR_CACHE_DIRNAME);
63+
const cachePath = path.join(this.$settingsService.getProfileDir(), constants.INSPECTOR_CACHE_DIRNAME);
6364
this.prepareCacheDir(cachePath);
6465
const pathToPackageInCache = path.join(cachePath, constants.NODE_MODULES_FOLDER_NAME, inspectorNpmPackageName);
6566

lib/options.ts

+3-21
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import * as commonOptionsLibPath from "./common/options";
2-
import * as osenv from "osenv";
3-
import * as path from "path";
42

53
export class Options extends commonOptionsLibPath.OptionsBase {
64
constructor($errors: IErrors,
75
$staticConfig: IStaticConfig,
8-
$hostInfo: IHostInfo) {
6+
$hostInfo: IHostInfo,
7+
$settingsService: ISettingsService) {
98
super({
109
ipa: { type: OptionType.String },
1110
frameworkPath: { type: OptionType.String },
@@ -39,24 +38,7 @@ export class Options extends commonOptionsLibPath.OptionsBase {
3938
clean: { type: OptionType.Boolean },
4039
watch: { type: OptionType.Boolean, default: true }
4140
},
42-
path.join($hostInfo.isWindows ? process.env.AppData : path.join(osenv.home(), ".local/share"), ".nativescript-cli"),
43-
$errors, $staticConfig);
44-
45-
// On Windows we moved settings from LocalAppData to AppData. Move the existing file to keep the existing settings
46-
// I guess we can remove this code after some grace period, say after 1.7 is out
47-
if ($hostInfo.isWindows) {
48-
try {
49-
const shelljs = require("shelljs"),
50-
oldSettings = path.join(process.env.LocalAppData, ".nativescript-cli", "user-settings.json"),
51-
newSettings = path.join(process.env.AppData, ".nativescript-cli", "user-settings.json");
52-
if (shelljs.test("-e", oldSettings) && !shelljs.test("-e", newSettings)) {
53-
shelljs.mkdir(path.join(process.env.AppData, ".nativescript-cli"));
54-
shelljs.mv(oldSettings, newSettings);
55-
}
56-
} catch (err) {
57-
// ignore the error - it is too early to use $logger here
58-
}
59-
}
41+
$errors, $staticConfig, $settingsService);
6042

6143
const that = (<any>this);
6244
// if justlaunch is set, it takes precedence over the --watch flag and the default true value

lib/services/extensibility-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as constants from "../constants";
44

55
export class ExtensibilityService implements IExtensibilityService {
66
private get pathToExtensions(): string {
7-
return path.join(path.resolve(this.$options.profileDir), "extensions");
7+
return path.join(this.$settingsService.getProfileDir(), "extensions");
88
}
99

1010
private get pathToPackageJson(): string {
@@ -14,7 +14,7 @@ export class ExtensibilityService implements IExtensibilityService {
1414
constructor(private $fs: IFileSystem,
1515
private $logger: ILogger,
1616
private $npm: INodePackageManager,
17-
private $options: IOptions,
17+
private $settingsService: ISettingsService,
1818
private $requireService: IRequireService) {
1919
}
2020

lib/services/user-settings-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import * as userSettingsServiceBaseLib from "../common/services/user-settings-se
33

44
class UserSettingsService extends userSettingsServiceBaseLib.UserSettingsServiceBase {
55
constructor($fs: IFileSystem,
6-
$options: IOptions,
6+
$settingsService: ISettingsService,
77
$lockfile: ILockFile) {
8-
const userSettingsFilePath = path.join($options.profileDir, "user-settings.json");
8+
const userSettingsFilePath = path.join($settingsService.getProfileDir(), "user-settings.json");
99
super(userSettingsFilePath, $fs, $lockfile);
1010
}
1111

test/android-project-properties-manager.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as LoggerLib from "../lib/common/logger";
88
import * as ConfigLib from "../lib/config";
99
import * as OptionsLib from "../lib/options";
1010
import * as yok from "../lib/common/yok";
11+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
1112
import * as path from "path";
1213
import temp = require("temp");
1314
temp.track();
@@ -23,6 +24,7 @@ function createTestInjector(): IInjector {
2324
testInjector.register("logger", LoggerLib.Logger);
2425
testInjector.register("config", ConfigLib.Configuration);
2526
testInjector.register("options", OptionsLib.Options);
27+
testInjector.register("settingsService", SettingsService);
2628

2729
return testInjector;
2830
}

test/commands/post-install.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Yok } from "../../lib/common/yok";
22
import { assert } from "chai";
33
import { PostInstallCliCommand } from "../../lib/commands/post-install";
4+
import { SettingsService } from "../../lib/common/test/unit-tests/stubs";
45

56
const createTestInjector = (): IInjector => {
67
const testInjector = new Yok();
@@ -38,6 +39,8 @@ const createTestInjector = (): IInjector => {
3839
printMarkdown: (...args: any[]): void => undefined
3940
});
4041

42+
testInjector.register("settingsService", SettingsService);
43+
4144
testInjector.registerCommand("post-install-cli", PostInstallCliCommand);
4245

4346
return testInjector;

test/debug.ts

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { AndroidDebugBridge } from "../lib/common/mobile/android/android-debug-b
1111
import { AndroidDebugBridgeResultHandler } from "../lib/common/mobile/android/android-debug-bridge-result-handler";
1212
import { DebugCommandErrors } from "../lib/constants";
1313
import { CONNECTED_STATUS, UNREACHABLE_STATUS } from "../lib/common/constants";
14+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
15+
1416
const helpers = require("../lib/common/helpers");
1517
const originalIsInteracive = helpers.isInteractive;
1618

@@ -73,6 +75,7 @@ function createTestInjector(): IInjector {
7375
return null;
7476
}
7577
});
78+
testInjector.register("settingsService", SettingsService);
7679

7780
return testInjector;
7881
}

test/ios-project-service.ts

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import * as constants from "../lib/constants";
3333

3434
import { assert } from "chai";
3535
import { IOSProvisionService } from "../lib/services/ios-provision-service";
36+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
3637
import temp = require("temp");
3738

3839
temp.track();
@@ -114,6 +115,8 @@ function createTestInjector(projectPath: string, projectName: string): IInjector
114115
testInjector.register("npmInstallationManager", NpmInstallationManager);
115116
testInjector.register("npm", NodePackageManager);
116117
testInjector.register("xCConfigService", XCConfigService);
118+
testInjector.register("settingsService", SettingsService);
119+
117120
return testInjector;
118121
}
119122

test/npm-installation-manager.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as OptionsLib from "../lib/options";
99
import * as StaticConfigLib from "../lib/config";
1010
import * as yok from "../lib/common/yok";
1111
import ChildProcessLib = require("../lib/common/child-process");
12+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
1213

1314
function createTestInjector(): IInjector {
1415
const testInjector = new yok.Yok();
@@ -21,6 +22,7 @@ function createTestInjector(): IInjector {
2122
testInjector.register("hostInfo", HostInfoLib.HostInfo);
2223
testInjector.register("staticConfig", StaticConfigLib.StaticConfig);
2324
testInjector.register("childProcess", ChildProcessLib.ChildProcess);
25+
testInjector.register("settingsService", SettingsService);
2426

2527
testInjector.register("npmInstallationManager", NpmInstallationManagerLib.NpmInstallationManager);
2628

test/npm-support.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { XmlValidator } from "../lib/xml-validator";
2626
import ProjectChangesLib = require("../lib/services/project-changes-service");
2727
import { Messages } from "../lib/common/messages/messages";
2828
import { NodeModulesDependenciesBuilder } from "../lib/tools/node-modules/node-modules-dependencies-builder";
29+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
2930

3031
import path = require("path");
3132
import temp = require("temp");
@@ -82,7 +83,7 @@ function createTestInjector(): IInjector {
8283
});
8384
testInjector.register("messages", Messages);
8485
testInjector.register("nodeModulesDependenciesBuilder", NodeModulesDependenciesBuilder);
85-
86+
testInjector.register("settingsService", SettingsService);
8687
testInjector.register("devicePathProvider", {});
8788

8889
return testInjector;

test/platform-commands.ts

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { XmlValidator } from "../lib/xml-validator";
2121
import * as ChildProcessLib from "../lib/common/child-process";
2222
import ProjectChangesLib = require("../lib/services/project-changes-service");
2323
import { Messages } from "../lib/common/messages/messages";
24+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
2425

2526
let isCommandExecuted = true;
2627

@@ -149,6 +150,7 @@ function createTestInjector() {
149150
testInjector.register("helpService", {
150151
showCommandLineHelp: async (): Promise<void> => (undefined)
151152
});
153+
testInjector.register("settingsService", SettingsService);
152154

153155
return testInjector;
154156
}

test/platform-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { XmlValidator } from "../lib/xml-validator";
1919
import * as ChildProcessLib from "../lib/common/child-process";
2020
import ProjectChangesLib = require("../lib/services/project-changes-service");
2121
import { Messages } from "../lib/common/messages/messages";
22+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
2223

2324
require("should");
2425
const temp = require("temp");
@@ -90,6 +91,7 @@ function createTestInjector() {
9091
testInjector.register("helpService", {
9192
showCommandLineHelp: async (): Promise<void> => (undefined)
9293
});
94+
testInjector.register("settingsService", SettingsService);
9395

9496
return testInjector;
9597
}

test/plugin-variables-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ProjectHelper } from "../lib/common/project-helper";
1111
import { StaticConfig } from "../lib/config";
1212
import { MessagesService } from "../lib/common/services/messages-service";
1313
import { Yok } from '../lib/common/yok';
14+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
1415
import * as stubs from './stubs';
1516
import * as path from "path";
1617
import * as temp from "temp";
@@ -37,6 +38,7 @@ function createTestInjector(): IInjector {
3738
}
3839
});
3940
testInjector.register("staticConfig", StaticConfig);
41+
testInjector.register("settingsService", SettingsService);
4042

4143
return testInjector;
4244
}

test/plugins-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { ProjectFilesProvider } from "../lib/providers/project-files-provider";
3030
import { MobilePlatformsCapabilities } from "../lib/mobile-platforms-capabilities";
3131
import { DevicePlatformsConstants } from "../lib/common/mobile/device-platforms-constants";
3232
import { XmlValidator } from "../lib/xml-validator";
33+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
3334
import StaticConfigLib = require("../lib/config");
3435
import * as path from "path";
3536
import * as temp from "temp";
@@ -101,6 +102,7 @@ function createTestInjector() {
101102
testInjector.register("helpService", {
102103
showCommandLineHelp: async (): Promise<void> => (undefined)
103104
});
105+
testInjector.register("settingsService", SettingsService);
104106

105107
return testInjector;
106108
}

test/project-service.ts

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { assert } from "chai";
1818
import { Options } from "../lib/options";
1919
import { HostInfo } from "../lib/common/host-info";
2020
import { ProjectTemplatesService } from "../lib/services/project-templates-service";
21+
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
2122

2223
const mockProjectNameValidator = {
2324
validate: () => true
@@ -156,6 +157,7 @@ class ProjectIntegrationTest {
156157
}
157158
});
158159
this.testInjector.register("npmInstallationManager", NpmInstallationManager);
160+
this.testInjector.register("settingsService", SettingsService);
159161
}
160162
}
161163

@@ -429,6 +431,7 @@ describe("Project Service Tests", () => {
429431
testInjector.register("staticConfig", {});
430432
testInjector.register("projectHelper", {});
431433
testInjector.register("npmInstallationManager", {});
434+
testInjector.register("settingsService", SettingsService);
432435

433436
return testInjector;
434437
};

test/services/extensibility-service.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Yok } from "../../lib/common/yok";
33
import * as stubs from "../stubs";
44
import { assert } from "chai";
55
import * as constants from "../../lib/constants";
6+
import { SettingsService } from "../../lib/common/test/unit-tests/stubs";
67
const path = require("path");
78
const originalResolve = path.resolve;
89

@@ -20,9 +21,7 @@ describe("extensibilityService", () => {
2021
testInjector.register("fs", {});
2122
testInjector.register("logger", stubs.LoggerStub);
2223
testInjector.register("npm", {});
23-
testInjector.register("options", {
24-
profileDir: "profileDir"
25-
});
24+
testInjector.register("settingsService", SettingsService);
2625
testInjector.register("requireService", {
2726
require: (pathToRequire: string): any => undefined
2827
});
@@ -121,10 +120,11 @@ describe("extensibilityService", () => {
121120
it("passes full path to extensions dir for installation", async () => {
122121
const extensionName = "extension1";
123122
const testInjector = getTestInjector();
124-
const options: IOptions = testInjector.resolve("options");
125-
options.profileDir = "my-profile-dir";
123+
const settingsService: ISettingsService = testInjector.resolve("settingsService");
124+
const profileDir = "my-profile-dir";
125+
settingsService.getProfileDir = () => profileDir;
126126

127-
const expectedDirForInstallation = path.join(options.profileDir, "extensions");
127+
const expectedDirForInstallation = path.join(profileDir, "extensions");
128128
const argsPassedToNpmInstall = await getArgsPassedToNpmInstallDuringInstallExtensionCall(extensionName, testInjector);
129129
assert.deepEqual(argsPassedToNpmInstall.pathToSave, expectedDirForInstallation);
130130
});
@@ -514,12 +514,13 @@ describe("extensibilityService", () => {
514514
it("passes full path to extensions dir for uninstallation", async () => {
515515
const extensionName = "extension1";
516516
const testInjector = getTestInjector();
517-
const options: IOptions = testInjector.resolve("options");
518-
options.profileDir = "my-profile-dir";
517+
const settingsService: ISettingsService = testInjector.resolve("settingsService");
518+
const profileDir = "my-profile-dir";
519+
settingsService.getProfileDir = () => profileDir;
519520

520-
const expectedDirForInstallation = path.join(options.profileDir, "extensions");
521+
const expectedDirForUninstall = path.join(profileDir, "extensions");
521522
const argsPassedToNpmUninstall = await getArgsPassedToNpmUninstallDuringUninstallExtensionCall(extensionName, testInjector);
522-
assert.deepEqual(argsPassedToNpmUninstall.pathToSave, expectedDirForInstallation);
523+
assert.deepEqual(argsPassedToNpmUninstall.pathToSave, expectedDirForUninstall);
523524
});
524525
});
525526

0 commit comments

Comments
 (0)