Skip to content

Commit ea9f334

Browse files
authored
fix(@ngtools/json-schema): enum values properly handle defaults and null. (#4387)
NULL are not valid values, and now the default will be respected.
1 parent 2048459 commit ea9f334

File tree

4 files changed

+34
-18
lines changed

4 files changed

+34
-18
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ describe('@ngtools/json-schema', () => {
6060
proto.a[1] = 'INVALID';
6161
expect(proto.a).toEqual(['v2', null, null, 'v3']);
6262
});
63+
64+
it('supports default values', () => {
65+
const proto: any = Object.create(null);
66+
const schema = new RootSchemaTreeNode(proto, {
67+
value: valueJson,
68+
schema: schemaJson
69+
});
70+
71+
expect(schema.children['b'].get()).toEqual('default');
72+
});
6373
});
6474

6575
});

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

+18-16
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export abstract class SchemaTreeNode<T> implements SchemaNode {
9797
get itemPrototype(): SchemaTreeNode<any> | null { return null; }
9898

9999
abstract get(): T;
100-
set(v: T, force = false) {
100+
set(v: T, init = false, force = false) {
101101
if (!this.readOnly) {
102102
throw new MissingImplementationError();
103103
}
@@ -220,10 +220,10 @@ export class OneOfSchemaTreeNode extends NonLeafSchemaTreeNode<any> {
220220
}
221221

222222
this._currentTypeHolder = proto;
223-
this._currentTypeHolder.set(v, true);
223+
this._currentTypeHolder.set(v, false, true);
224224
}
225225

226-
set(v: any, force = false) {
226+
set(v: any, init = false, force = false) {
227227
return this._set(v, false, force);
228228
}
229229

@@ -338,7 +338,6 @@ export class ArraySchemaTreeNode extends NonLeafSchemaTreeNode<Array<any>> {
338338
const schema = this._schema;
339339
const forward = this._forward;
340340

341-
this._defined = !!value;
342341
this._value = Object.create(null);
343342
this._dirty = this._dirty || !init;
344343

@@ -361,8 +360,8 @@ export class ArraySchemaTreeNode extends NonLeafSchemaTreeNode<Array<any>> {
361360
}
362361
}
363362

364-
set(v: any, force = false) {
365-
return this._set(v, false, force);
363+
set(v: any, init = false, force = false) {
364+
return this._set(v, init, force);
366365
}
367366

368367
isCompatible(v: any) { return Array.isArray(v); }
@@ -395,7 +394,7 @@ export class RootSchemaTreeNode extends ObjectSchemaTreeNode {
395394

396395
/** A leaf in the schema tree. Must contain a single primitive value. */
397396
export abstract class LeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
398-
private _default: T;
397+
protected _default: T;
399398

400399
constructor(metaData: TreeNodeConstructorArgument<T>) {
401400
super(metaData);
@@ -410,13 +409,13 @@ export abstract class LeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
410409
return this._forward.get();
411410
}
412411
if (!this.defined) {
413-
return this._default !== undefined ? this._default : undefined;
412+
return 'default' in this._schema ? this._default : undefined;
414413
}
415414
return this._value === undefined
416415
? undefined
417416
: (this._value === null ? null : this.convert(this._value));
418417
}
419-
set(v: T, force = false) {
418+
set(v: T, init = false, force = false) {
420419
if (this.readOnly && !force) {
421420
throw new SettingReadOnlyPropertyError();
422421
}
@@ -428,7 +427,7 @@ export abstract class LeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
428427
}
429428
}
430429

431-
this.dirty = true;
430+
this.dirty = !init;
432431
this._value = convertedValue;
433432
}
434433

@@ -438,7 +437,10 @@ export abstract class LeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
438437
}
439438

440439
get defaultValue(): T {
441-
return 'default' in this._schema ? this._default : null;
440+
return this.hasDefault ? this._default : null;
441+
}
442+
get hasDefault() {
443+
return 'default' in this._schema;
442444
}
443445

444446
abstract convert(v: any): T;
@@ -462,20 +464,20 @@ class StringSchemaTreeNode extends LeafSchemaTreeNode<string> {
462464

463465

464466
class EnumSchemaTreeNode extends StringSchemaTreeNode {
465-
private _enumValues: string[];
466-
467467
constructor(metaData: TreeNodeConstructorArgument<string>) {
468468
super(metaData);
469469

470470
if (!Array.isArray(metaData.schema['enum'])) {
471471
throw new InvalidSchema();
472472
}
473-
this._enumValues = [].concat(metaData.schema['enum']);
474-
this.set(metaData.value, true);
473+
if (this.hasDefault && !this._isInEnum(this._default)) {
474+
throw new InvalidSchema();
475+
}
476+
this.set(metaData.value, true, true);
475477
}
476478

477479
protected _isInEnum(value: string) {
478-
return this._enumValues.some(v => v === value);
480+
return this._schema['enum'].some((v: string) => v === value);
479481
}
480482

481483
isCompatible(v: any) {

packages/@ngtools/json-schema/tests/schema2.json

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
"items": {
99
"enum": [ "v1", "v2", "v3" ]
1010
}
11+
},
12+
"b": {
13+
"enum": [ "default", "v1", "v2" ],
14+
"default": "default"
1115
}
1216
}
1317
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"a": [
3-
null,
3+
"v2",
44
"v1",
5-
null,
5+
"v2",
66
"v3"
77
]
88
}

0 commit comments

Comments
 (0)