Skip to content

Commit 456361d

Browse files
sumitaroraBrocco
authored andcommitted
fix(@angular/cli): only values in enum should be allowed to update
1 parent 0ecaa2d commit 456361d

File tree

6 files changed

+72
-11
lines changed

6 files changed

+72
-11
lines changed

packages/@angular/cli/commands/set.ts

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import {CliConfig} from '../models/config';
1+
import * as fs from 'fs';
2+
import { CliConfig } from '../models/config';
3+
import { oneLine } from 'common-tags';
24

35
const SilentError = require('silent-error');
6+
const chalk = require('chalk');
47
const Command = require('../ember-cli/lib/models/command');
58

69

@@ -67,13 +70,42 @@ const SetCommand = Command.extend({
6770
default: value = parseValue(rawValue, jsonPath);
6871
}
6972

70-
config.set(jsonPath, value);
71-
config.save();
73+
if (jsonPath.indexOf('prefix') > 0) {
74+
// update tslint if prefix is updated
75+
updateLintForPrefix(this.project.root + '/tslint.json', value);
76+
}
77+
78+
try {
79+
config.set(jsonPath, value);
80+
config.save();
81+
} catch (error) {
82+
throw new SilentError(error.message);
83+
}
7284
resolve();
7385
});
7486
}
7587
});
7688

89+
function updateLintForPrefix(filePath: string, prefix: string): void {
90+
const tsLint = JSON.parse(fs.readFileSync(filePath, 'utf8'));
91+
const componentLint = tsLint.rules['component-selector'][2];
92+
if (componentLint instanceof Array) {
93+
tsLint.rules['component-selector'][2].push(prefix);
94+
} else {
95+
tsLint.rules['component-selector'][2] = prefix;
96+
}
97+
98+
const directiveLint = tsLint.rules['directive-selector'][2];
99+
if (directiveLint instanceof Array) {
100+
tsLint.rules['directive-selector'][2].push(prefix);
101+
} else {
102+
tsLint.rules['directive-selector'][2] = prefix;
103+
}
104+
fs.writeFileSync(filePath, JSON.stringify(tsLint, null, 2));
105+
console.log(chalk.yellow(oneLine`we have updated tslint to match prefix,
106+
you may want to fix linting errors.`));
107+
}
108+
77109
function parseValue(rawValue: string, path: string) {
78110
try {
79111
return JSON.parse(rawValue);

packages/@ngtools/json-schema/src/schema-class-factory.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import {JsonSchemaErrorBase} from './error';
44

55
import './mimetypes';
66

7-
87
export class InvalidJsonPath extends JsonSchemaErrorBase {}
98

10-
119
// The schema tree node property of the SchemaClass.
1210
const kSchemaNode = Symbol('schema-node');
1311
// The value property of the SchemaClass.
@@ -132,6 +130,7 @@ class SchemaClassBase<T> implements SchemaClass<T> {
132130
/** Set a value from a JSON path. */
133131
$$set(path: string, value: any): void {
134132
const node = _getSchemaNodeForPath(this.$$schema(), path);
133+
135134
if (node) {
136135
node.set(value);
137136
} else {

packages/@ngtools/json-schema/src/schema-tree.spec.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,11 @@ describe('@ngtools/json-schema', () => {
5353
});
5454

5555
expect(proto.a instanceof Array).toBe(true);
56-
expect(proto.a).toEqual([undefined, 'v1', undefined, 'v3']);
56+
expect(proto.a).toEqual(['v1', 'v3']);
5757

5858
// Set it to a string, which is valid.
5959
proto.a[0] = 'v2';
60-
proto.a[1] = 'INVALID';
61-
expect(proto.a).toEqual(['v2', undefined, undefined, 'v3']);
60+
expect(proto.a).toEqual(['v2', 'v3']);
6261
});
6362

6463
it('supports default values', () => {
@@ -70,6 +69,23 @@ describe('@ngtools/json-schema', () => {
7069

7170
expect(schema.children['b'].get()).toEqual('default');
7271
});
72+
73+
74+
it('should throw error when setting invalid value', () => {
75+
const proto: any = Object.create(null);
76+
// tslint:disable-next-line
77+
new RootSchemaTreeNode(proto, {
78+
value: valueJson,
79+
schema: schemaJson
80+
});
81+
82+
try {
83+
proto.a[0] = 'INVALID';
84+
} catch (error) {
85+
expect(error.message).toBe('Invalid value can only be one of these: v1,v2,v3');
86+
}
87+
});
88+
7389
});
7490

7591
});

packages/@ngtools/json-schema/src/schema-tree.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export class InvalidSchema extends JsonSchemaErrorBase {}
77
export class InvalidValueError extends JsonSchemaErrorBase {}
88
export class MissingImplementationError extends JsonSchemaErrorBase {}
99
export class SettingReadOnlyPropertyError extends JsonSchemaErrorBase {}
10-
10+
export class InvalidUpdateValue extends JsonSchemaErrorBase {}
1111

1212
export interface Schema {
1313
[key: string]: any;
@@ -482,6 +482,13 @@ class EnumSchemaTreeNode extends LeafSchemaTreeNode<any> {
482482

483483
get items() { return this._schema['enum']; }
484484

485+
set(value: string, init = false, force = false) {
486+
if (!(value === undefined || this._isInEnum(value))) {
487+
throw new InvalidUpdateValue('Invalid value can only be one of these: ' + this.items);
488+
}
489+
super.set(value, init, force);
490+
}
491+
485492
isCompatible(v: any) {
486493
return this._isInEnum(v);
487494
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
{
22
"a": [
3-
"INVALID",
43
"v1",
5-
"INVALID",
64
"v3"
75
]
86
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
export default function() {
5+
return Promise.resolve()
6+
.then(() => expectToFail(() => ng('set', 'defaults.component.aaa', 'bbb')))
7+
.then(() => expectToFail(() => ng('set', 'defaults.component.viewEncapsulation', 'bbb')))
8+
.then(() => ng('set', 'defaults.component.viewEncapsulation', 'Emulated'));
9+
}

0 commit comments

Comments
 (0)