Skip to content

Commit 9e52987

Browse files
fix: Plugin remove command fails in case plugin name has dot
In case plugin name has dot (`.`) in its name, the `plugin remove` command fails. The reason is the way we are trying to remove plugin related data from the `nativescript` key of application's package.json. We are using `.` to concatenate the keys inside nativescript key and later we are trying to split by `.` in order to find which key should be deleted. This works in most of the cases, but when the plugin name has `.` in it, our logic fails as the split operation finds the dot. Fix this by using some symbols that are not allowed in npm for plugins names. Use symbols that will rarely be used in the same sequence.
1 parent 2d96010 commit 9e52987

File tree

3 files changed

+46
-34
lines changed

3 files changed

+46
-34
lines changed

lib/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,8 @@ export const enum BuildStates {
139139
}
140140

141141
export const NATIVESCRIPT_CLOUD_EXTENSION_NAME = "nativescript-cloud";
142+
143+
/**
144+
* Used in ProjectDataService to concatenate the names of the properties inside nativescript key of package.json.
145+
*/
146+
export const NATIVESCRIPT_PROPS_INTERNAL_DELIMITER = "**|__**";

lib/services/project-data-service.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as path from "path";
22
import { ProjectData } from "../project-data";
33
import { exported } from "../common/decorators";
4+
import { NATIVESCRIPT_PROPS_INTERNAL_DELIMITER } from "../constants";
45

56
interface IProjectFileData {
67
projectData: any;
@@ -65,11 +66,11 @@ export class ProjectDataService implements IProjectDataService {
6566
}
6667

6768
private getNativeScriptPropertyName(propertyName: string) {
68-
return `${this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE}.${propertyName}`;
69+
return `${this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE}${NATIVESCRIPT_PROPS_INTERNAL_DELIMITER}${propertyName}`;
6970
}
7071

7172
private getPropertyValueFromJson(jsonData: any, dottedPropertyName: string): any {
72-
const props = dottedPropertyName.split(".");
73+
const props = dottedPropertyName.split(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
7374
let result = jsonData[props.shift()];
7475

7576
for (const prop of props) {
@@ -82,7 +83,7 @@ export class ProjectDataService implements IProjectDataService {
8283
private setValue(projectDir: string, key: string, value: any): void {
8384
const projectFileInfo = this.getProjectFileData(projectDir);
8485

85-
const props = key.split(".");
86+
const props = key.split(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
8687
const data: any = projectFileInfo.projectData;
8788
let currentData = data;
8889

@@ -103,7 +104,7 @@ export class ProjectDataService implements IProjectDataService {
103104
const projectFileInfo = this.getProjectFileData(projectDir);
104105
const data: any = projectFileInfo.projectData;
105106
let currentData = data;
106-
const props = propertyName.split(".");
107+
const props = propertyName.split(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
107108
const propertyToDelete = props.splice(props.length - 1, 1)[0];
108109

109110
_.each(props, (prop) => {

test/services/project-data-service.ts

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,40 @@ import { Yok } from "../../lib/common/yok";
22
import { assert } from "chai";
33
import { ProjectDataService } from "../../lib/services/project-data-service";
44
import { LoggerStub } from "../stubs";
5+
import { NATIVESCRIPT_PROPS_INTERNAL_DELIMITER } from '../../lib/constants';
56

67
const CLIENT_NAME_KEY_IN_PROJECT_FILE = "nativescript";
78

8-
const testData: any = [{
9-
"propertyValue": 1,
10-
"propertyName": "root",
11-
"description": "returns correct result when a single propertyName is passed and the value of it is number"
12-
},
13-
{
14-
"propertyValue": "expectedData",
15-
"propertyName": "root",
16-
"description": "returns correct result when a single propertyName is passed and the value of it is string"
17-
},
18-
{
19-
"propertyValue": "expectedData",
20-
"propertyName": "root.prop1",
21-
"description": "returns correct result when inner propertyName is passed and the value of it is string"
22-
},
23-
{
24-
"propertyValue": 1234,
25-
"propertyName": "root.prop1",
26-
"description": "returns correct result when inner propertyName is passed and the value of it is number"
27-
},
28-
{
29-
"propertyValue": "expectedData",
30-
"propertyName": "root.prop1.prop2.prop3.prop4",
31-
"description": "returns correct result when really inner propertyName is passed and the value of it is string"
32-
}
9+
const getPropertyName = (props: string[]): string => {
10+
return props.join(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
11+
};
12+
13+
const testData: any = [
14+
{
15+
"propertyValue": 1,
16+
"propertyName": "root",
17+
"description": "returns correct result when a single propertyName is passed and the value of it is number"
18+
},
19+
{
20+
"propertyValue": "expectedData",
21+
"propertyName": "root",
22+
"description": "returns correct result when a single propertyName is passed and the value of it is string"
23+
},
24+
{
25+
"propertyValue": "expectedData",
26+
"propertyName": getPropertyName(["root", "prop1"]),
27+
"description": "returns correct result when inner propertyName is passed and the value of it is string"
28+
},
29+
{
30+
"propertyValue": 1234,
31+
"propertyName": getPropertyName(["root", "prop1"]),
32+
"description": "returns correct result when inner propertyName is passed and the value of it is number"
33+
},
34+
{
35+
"propertyValue": "expectedData",
36+
"propertyName": getPropertyName(["root", "prop1", "prop2", "prop3", "prop4"]),
37+
"description": "returns correct result when really inner propertyName is passed and the value of it is string"
38+
}
3339
];
3440

3541
const createTestInjector = (readTextData?: string): IInjector => {
@@ -60,7 +66,7 @@ const createTestInjector = (readTextData?: string): IInjector => {
6066

6167
describe("projectDataService", () => {
6268
const generateJsonDataFromTestData = (currentTestData: any, skipNativeScriptKey?: boolean) => {
63-
const props = currentTestData.propertyName.split(".");
69+
const props = currentTestData.propertyName.split(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
6470
const data: any = {};
6571
let currentData: any = skipNativeScriptKey ? data : (data[CLIENT_NAME_KEY_IN_PROJECT_FILE] = {});
6672

@@ -140,7 +146,7 @@ describe("projectDataService", () => {
140146
};
141147

142148
const projectDataService: IProjectDataService = testInjector.resolve("projectDataService");
143-
projectDataService.setNSValue("projectDir", "root.id", "2");
149+
projectDataService.setNSValue("projectDir", getPropertyName(["root", "id"]), "2");
144150
const expectedData = _.cloneDeep(initialData);
145151
expectedData[CLIENT_NAME_KEY_IN_PROJECT_FILE].root.id = "2";
146152
assert.isTrue(!!dataPassedToWriteJson[CLIENT_NAME_KEY_IN_PROJECT_FILE], "Data passed to write JSON must contain nativescript key.");
@@ -154,7 +160,7 @@ describe("projectDataService", () => {
154160
describe("removeNSProperty", () => {
155161

156162
const generateExpectedDataFromTestData = (currentTestData: any) => {
157-
const props = currentTestData.propertyName.split(".");
163+
const props = currentTestData.propertyName.split(NATIVESCRIPT_PROPS_INTERNAL_DELIMITER);
158164
props.splice(props.length - 1, 1);
159165

160166
const data: any = {};
@@ -207,15 +213,15 @@ describe("projectDataService", () => {
207213
};
208214

209215
const projectDataService: IProjectDataService = testInjector.resolve("projectDataService");
210-
projectDataService.removeNSProperty("projectDir", "root.id");
216+
projectDataService.removeNSProperty("projectDir", getPropertyName(["root", "id"]));
211217
assert.deepEqual(dataPassedToWriteJson, { nativescript: { root: { constantItem: "myValue" } } });
212218
});
213219
});
214220

215221
describe("removeDependency", () => {
216222
it("removes specified dependency from project file", () => {
217223
const currentTestData = {
218-
propertyName: "dependencies.myDeps",
224+
propertyName: getPropertyName(["dependencies", "myDeps"]),
219225
propertyValue: "1.0.0"
220226
};
221227

0 commit comments

Comments
 (0)