Skip to content

Commit 4732694

Browse files
author
Dimitar Tachev
authored
feat: introduce migrate command
2 parents 314e745 + 990b6f1 commit 4732694

26 files changed

+800
-394
lines changed

docs/man_pages/project/configuration/update.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<% if (isJekyll) { %>---
2-
title: tns platform update
2+
title: tns update
33
position: 8
44
---<% } %>
55

6-
# tns platform update
6+
# tns update
77

88
### Description
99

10-
Updates a NativeScript project to the latest (or specified) version.
10+
Updates a NativeScript to the latest compatible combination of NativeScript dependencies. The combination of dependencies is taken from the latest(or specified) version of the template for the type of the target project (Angular, Vue.js and etc.).
1111

1212
### Commands
1313

lib/bootstrap.ts

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ $injector.requirePublicClass("buildController", "./controllers/build-controller"
5050
$injector.requirePublicClass("runController", "./controllers/run-controller");
5151
$injector.requirePublicClass("debugController", "./controllers/debug-controller");
5252
$injector.requirePublicClass("previewAppController", "./controllers/preview-app-controller");
53+
$injector.requirePublicClass("updateController", "./controllers/update-controller");
54+
$injector.requirePublicClass("migrateController", "./controllers/migrate-controller");
5355

5456
$injector.require("prepareDataService", "./services/prepare-data-service");
5557
$injector.require("buildDataService", "./services/build-data-service");
@@ -172,6 +174,7 @@ $injector.require("messages", "./common/messages/messages");
172174
$injector.require("xmlValidator", "./xml-validator");
173175

174176
$injector.requireCommand("post-install-cli", "./commands/post-install");
177+
$injector.requireCommand("migrate", "./commands/migrate");
175178
$injector.requireCommand("update", "./commands/update");
176179

177180
$injector.require("iOSLogFilter", "./services/ios-log-filter");

lib/commands/migrate.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export class MigrateCommand implements ICommand {
2+
public allowedParameters: ICommandParameter[] = [];
3+
4+
constructor(
5+
private $migrateController: IMigrateController,
6+
private $projectData: IProjectData,
7+
private $errors: IErrors) {
8+
this.$projectData.initializeProjectData();
9+
}
10+
11+
public async execute(args: string[]): Promise<void> {
12+
await this.$migrateController.migrate({projectDir: this.$projectData.projectDir});
13+
}
14+
15+
public async canExecute(args: string[]): Promise<boolean> {
16+
if (!await this.$migrateController.shouldMigrate({ projectDir: this.$projectData.projectDir })) {
17+
this.$errors.failWithoutHelp('Project is compatible with NativeScript "v6.0.0". To get the latest NativesScript packages execute "tns update".');
18+
}
19+
20+
return true;
21+
}
22+
}
23+
24+
$injector.registerCommand("migrate", MigrateCommand);

lib/commands/update.ts

+15-139
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,31 @@
1-
import * as path from "path";
2-
import * as constants from "../constants";
3-
import { ValidatePlatformCommandBase } from "./command-base";
4-
5-
export class UpdateCommand extends ValidatePlatformCommandBase implements ICommand {
1+
export class UpdateCommand implements ICommand {
62
public allowedParameters: ICommandParameter[] = [];
3+
public static readonly SHOULD_MIGRATE_PROJECT_MESSAGE = 'This project is not compatible with the current NativeScript version and cannot be updated. Use "tns migrate" to make your project compatible.';
4+
public static readonly PROJECT_UP_TO_DATE_MESSAGE = 'This project is up to date.';
75

86
constructor(
9-
private $fs: IFileSystem,
10-
private $logger: ILogger,
11-
$options: IOptions,
12-
private $platformCommandHelper: IPlatformCommandHelper,
13-
$platformsDataService: IPlatformsDataService,
14-
$platformValidationService: IPlatformValidationService,
15-
private $pluginsService: IPluginsService,
16-
$projectData: IProjectData,
17-
private $projectDataService: IProjectDataService) {
18-
super($options, $platformsDataService, $platformValidationService, $projectData);
7+
private $updateController: IUpdateController,
8+
private $migrateController: IMigrateController,
9+
private $options: IOptions,
10+
private $errors: IErrors,
11+
private $projectData: IProjectData) {
1912
this.$projectData.initializeProjectData();
2013
}
2114

22-
static readonly folders: string[] = [
23-
constants.LIB_DIR_NAME,
24-
constants.HOOKS_DIR_NAME,
25-
constants.PLATFORMS_DIR_NAME,
26-
constants.NODE_MODULES_FOLDER_NAME
27-
];
28-
static readonly tempFolder: string = ".tmp_backup";
29-
static readonly updateFailMessage: string = "Could not update the project!";
30-
static readonly backupFailMessage: string = "Could not backup project folders!";
31-
3215
public async execute(args: string[]): Promise<void> {
33-
const tmpDir = path.join(this.$projectData.projectDir, UpdateCommand.tempFolder);
34-
35-
try {
36-
this.backup(tmpDir);
37-
} catch (error) {
38-
this.$logger.error(UpdateCommand.backupFailMessage);
39-
this.$fs.deleteDirectory(tmpDir);
40-
return;
41-
}
42-
43-
try {
44-
await this.executeCore(args);
45-
} catch (error) {
46-
this.restoreBackup(tmpDir);
47-
this.$logger.error(UpdateCommand.updateFailMessage);
48-
} finally {
49-
this.$fs.deleteDirectory(tmpDir);
50-
}
16+
await this.$updateController.update({projectDir: this.$projectData.projectDir, version: args[0], frameworkPath: this.$options.frameworkPath});
5117
}
5218

53-
public async canExecute(args: string[]): Promise<ICanExecuteCommandOutput> {
54-
const platforms = this.getPlatforms();
55-
56-
let canExecute = true;
57-
for (const platform of platforms.packagePlatforms) {
58-
const output = await super.canExecuteCommandBase(platform);
59-
canExecute = canExecute && output.canExecute;
60-
}
61-
62-
let result = null;
63-
64-
if (canExecute) {
65-
result = {
66-
canExecute: args.length < 2 && this.$projectData.projectDir !== "",
67-
suppressCommandHelp: false
68-
};
69-
} else {
70-
result = {
71-
canExecute: false,
72-
suppressCommandHelp: true
73-
};
74-
}
75-
76-
return result;
77-
}
78-
79-
private async executeCore(args: string[]): Promise<void> {
80-
const platforms = this.getPlatforms();
81-
82-
for (const platform of _.xor(platforms.installed, platforms.packagePlatforms)) {
83-
const platformData = this.$platformsDataService.getPlatformData(platform, this.$projectData);
84-
this.$projectDataService.removeNSProperty(this.$projectData.projectDir, platformData.frameworkPackageName);
85-
}
86-
87-
await this.$platformCommandHelper.removePlatforms(platforms.installed, this.$projectData);
88-
await this.$pluginsService.remove(constants.TNS_CORE_MODULES_NAME, this.$projectData);
89-
if (!!this.$projectData.dependencies[constants.TNS_CORE_MODULES_WIDGETS_NAME]) {
90-
await this.$pluginsService.remove(constants.TNS_CORE_MODULES_WIDGETS_NAME, this.$projectData);
19+
public async canExecute(args: string[]): Promise<boolean> {
20+
if (await this.$migrateController.shouldMigrate({projectDir: this.$projectData.projectDir})) {
21+
this.$errors.failWithoutHelp(UpdateCommand.SHOULD_MIGRATE_PROJECT_MESSAGE);
9122
}
9223

93-
for (const folder of UpdateCommand.folders) {
94-
this.$fs.deleteDirectory(path.join(this.$projectData.projectDir, folder));
24+
if (!await this.$updateController.shouldUpdate({projectDir:this.$projectData.projectDir, version: args[0]})) {
25+
this.$errors.failWithoutHelp(UpdateCommand.PROJECT_UP_TO_DATE_MESSAGE);
9526
}
9627

97-
if (args.length === 1) {
98-
for (const platform of platforms.packagePlatforms) {
99-
await this.$platformCommandHelper.addPlatforms([platform + "@" + args[0]], this.$projectData, this.$options.frameworkPath);
100-
}
101-
102-
await this.$pluginsService.add(`${constants.TNS_CORE_MODULES_NAME}@${args[0]}`, this.$projectData);
103-
} else {
104-
await this.$platformCommandHelper.addPlatforms(platforms.packagePlatforms, this.$projectData, this.$options.frameworkPath);
105-
await this.$pluginsService.add(constants.TNS_CORE_MODULES_NAME, this.$projectData);
106-
}
107-
108-
await this.$pluginsService.ensureAllDependenciesAreInstalled(this.$projectData);
109-
}
110-
111-
private getPlatforms(): { installed: string[], packagePlatforms: string[] } {
112-
const installedPlatforms = this.$platformCommandHelper.getInstalledPlatforms(this.$projectData);
113-
const availablePlatforms = this.$platformCommandHelper.getAvailablePlatforms(this.$projectData);
114-
const packagePlatforms: string[] = [];
115-
116-
for (const platform of availablePlatforms) {
117-
const platformData = this.$platformsDataService.getPlatformData(platform, this.$projectData);
118-
const platformVersion = this.$projectDataService.getNSValue(this.$projectData.projectDir, platformData.frameworkPackageName);
119-
if (platformVersion) {
120-
packagePlatforms.push(platform);
121-
}
122-
}
123-
124-
return {
125-
installed: installedPlatforms,
126-
packagePlatforms: installedPlatforms.concat(packagePlatforms)
127-
};
128-
}
129-
130-
private restoreBackup(tmpDir: string): void {
131-
this.$fs.copyFile(path.join(tmpDir, constants.PACKAGE_JSON_FILE_NAME), this.$projectData.projectDir);
132-
for (const folder of UpdateCommand.folders) {
133-
this.$fs.deleteDirectory(path.join(this.$projectData.projectDir, folder));
134-
135-
const folderToCopy = path.join(tmpDir, folder);
136-
137-
if (this.$fs.exists(folderToCopy)) {
138-
this.$fs.copyFile(folderToCopy, this.$projectData.projectDir);
139-
}
140-
}
141-
}
142-
143-
private backup(tmpDir: string): void {
144-
this.$fs.deleteDirectory(tmpDir);
145-
this.$fs.createDirectory(tmpDir);
146-
this.$fs.copyFile(path.join(this.$projectData.projectDir, constants.PACKAGE_JSON_FILE_NAME), tmpDir);
147-
for (const folder of UpdateCommand.folders) {
148-
const folderToCopy = path.join(this.$projectData.projectDir, folder);
149-
if (this.$fs.exists(folderToCopy)) {
150-
this.$fs.copyFile(folderToCopy, tmpDir);
151-
}
152-
}
28+
return args.length < 2 && this.$projectData.projectDir !== "";
15329
}
15430
}
15531

lib/common/definitions/mobile.d.ts

-2
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,6 @@ declare module Mobile {
993993
platformNames: string[];
994994
isAndroidPlatform(platform: string): boolean;
995995
isiOSPlatform(platform: string): boolean;
996-
isWP8Platform(platform: string): boolean;
997996
normalizePlatformName(platform: string): string;
998997
validatePlatformName(platform: string): string;
999998
buildDevicePath(...args: string[]): string;
@@ -1016,7 +1015,6 @@ declare module Mobile {
10161015
interface IDevicePlatformsConstants {
10171016
iOS: string;
10181017
Android: string;
1019-
WP8: string;
10201018
}
10211019

10221020
interface IDeviceApplication {
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export class DevicePlatformsConstants implements Mobile.IDevicePlatformsConstants {
22
public iOS = "iOS";
33
public Android = "Android";
4-
public WP8 = "WP8";
54
}
65
$injector.register("devicePlatformsConstants", DevicePlatformsConstants);

lib/common/mobile/mobile-helper.ts

-6
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,11 @@ export class MobileHelper implements Mobile.IMobileHelper {
2121
return !!(platform && (this.$devicePlatformsConstants.iOS.toLowerCase() === platform.toLowerCase()));
2222
}
2323

24-
public isWP8Platform(platform: string): boolean {
25-
return !!(platform && (this.$devicePlatformsConstants.WP8.toLowerCase() === platform.toLowerCase()));
26-
}
27-
2824
public normalizePlatformName(platform: string): string {
2925
if (this.isAndroidPlatform(platform)) {
3026
return "Android";
3127
} else if (this.isiOSPlatform(platform)) {
3228
return "iOS";
33-
} else if (this.isWP8Platform(platform)) {
34-
return "WP8";
3529
}
3630

3731
return undefined;

lib/constants.ts

+4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ export const NATIVESCRIPT_KEY_NAME = "nativescript";
1010
export const NODE_MODULES_FOLDER_NAME = "node_modules";
1111
export const TNS_MODULES_FOLDER_NAME = "tns_modules";
1212
export const TNS_CORE_MODULES_NAME = "tns-core-modules";
13+
export const WEBPACK_PLUGIN_NAME = "nativescript-dev-webpack";
1314
export const TNS_CORE_MODULES_WIDGETS_NAME = "tns-core-modules-widgets";
1415
export const TNS_ANDROID_RUNTIME_NAME = "tns-android";
1516
export const TNS_IOS_RUNTIME_NAME = "tns-ios";
1617
export const PACKAGE_JSON_FILE_NAME = "package.json";
18+
export const PACKAGE_LOCK_JSON_FILE_NAME = "package-lock.json";
1719
export const ANDROID_DEVICE_APP_ROOT_TEMPLATE = `/data/data/%s/files`;
1820
export const NODE_MODULE_CACHE_PATH_KEY_NAME = "node-modules-cache-path";
1921
export const DEFAULT_APP_IDENTIFIER_PREFIX = "org.nativescript";
@@ -24,6 +26,8 @@ export const LIVESYNC_EXCLUDED_FILE_PATTERNS = ["**/*.js.map", "**/*.ts"];
2426
export const XML_FILE_EXTENSION = ".xml";
2527
export const PLATFORMS_DIR_NAME = "platforms";
2628
export const HOOKS_DIR_NAME = "hooks";
29+
export const WEBPACK_CONFIG_NAME = "webpack.config.js";
30+
export const TSCCONFIG_TNS_JSON_NAME = "tsconfig.tns.json";
2731
export const LIB_DIR_NAME = "lib";
2832
export const CODE_SIGN_ENTITLEMENTS = "CODE_SIGN_ENTITLEMENTS";
2933
export const AWAIT_NOTIFICATION_TIMEOUT_SECONDS = 9;

0 commit comments

Comments
 (0)