Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(@ngtools/json-schema): support enums in d.ts #4426

Merged
merged 1 commit into from
Feb 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:inspect": "node --inspect --debug-brk tests/runner",
"test:packages": "node scripts/run-packages-spec.js",
"eslint": "eslint .",
"tslint": "tslint \"**/*.ts\" -c tslint.json -e \"**/blueprints/*/files/**/*.ts\" -e \"node_modules/**\" -e \"tmp/**\" -e \"dist/**\"",
"tslint": "tslint \"**/*.ts\" -c tslint.json -e \"**/tests/**\" -e \"**/blueprints/*/files/**/*.ts\" -e \"node_modules/**\" -e \"tmp/**\" -e \"dist/**\"",
"lint": "npm-run-all -c eslint tslint"
},
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions packages/@angular/cli/lib/config/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "CliConfig",
"$schema": "http://json-schema.org/schema",
"id": "https://github.com/angular/angular-cli/blob/master/packages/@angular/cli/lib/config/schema.json#CliConfig",
"title": "Angular CLI Config Schema",
"type": "object",
"properties": {
Expand Down
4 changes: 2 additions & 2 deletions packages/@ngtools/json-schema/src/schema-tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ describe('@ngtools/json-schema', () => {
});

expect(proto.a instanceof Array).toBe(true);
expect(proto.a).toEqual([null, 'v1', null, 'v3']);
expect(proto.a).toEqual([undefined, 'v1', undefined, 'v3']);

// Set it to a string, which is valid.
proto.a[0] = 'v2';
proto.a[1] = 'INVALID';
expect(proto.a).toEqual(['v2', null, null, 'v3']);
expect(proto.a).toEqual(['v2', undefined, undefined, 'v3']);
});

it('supports default values', () => {
Expand Down
24 changes: 15 additions & 9 deletions packages/@ngtools/json-schema/src/schema-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class ObjectSchemaTreeNode extends NonLeafSchemaTreeNode<{[key: string]:
const propertySchema = schema['properties'][name];
this._children[name] = this._createChildProperty(
name,
value ? value[name] : null,
value ? value[name] : undefined,
forward ? (forward as ObjectSchemaTreeNode).children[name] : null,
propertySchema);
}
Expand Down Expand Up @@ -331,7 +331,7 @@ export class ArraySchemaTreeNode extends NonLeafSchemaTreeNode<Array<any>> {

// Keep the item's schema as a schema node. This is important to keep type information.
this._itemPrototype = this._createChildProperty(
'', null, null, metaData.schema['items'], false);
'', undefined, null, metaData.schema['items'], false);
}

_set(value: any, init: boolean, force: boolean) {
Expand Down Expand Up @@ -398,7 +398,7 @@ export abstract class LeafSchemaTreeNode<T> extends SchemaTreeNode<T> {

constructor(metaData: TreeNodeConstructorArgument<T>) {
super(metaData);
this._defined = !(metaData.value === undefined || metaData.value === null);
this._defined = metaData.value !== undefined;
if ('default' in metaData.schema) {
this._default = this.convert(metaData.schema['default']);
}
Expand Down Expand Up @@ -463,8 +463,8 @@ class StringSchemaTreeNode extends LeafSchemaTreeNode<string> {
}


class EnumSchemaTreeNode extends StringSchemaTreeNode {
constructor(metaData: TreeNodeConstructorArgument<string>) {
class EnumSchemaTreeNode extends LeafSchemaTreeNode<any> {
constructor(metaData: TreeNodeConstructorArgument<any>) {
super(metaData);

if (!Array.isArray(metaData.schema['enum'])) {
Expand All @@ -480,18 +480,24 @@ class EnumSchemaTreeNode extends StringSchemaTreeNode {
return this._schema['enum'].some((v: string) => v === value);
}

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

isCompatible(v: any) {
return (typeof v == 'string' || v instanceof String) && this._isInEnum('' + v);
return this._isInEnum(v);
}
convert(v: any) {
if (v === undefined) {
return undefined;
}
if (v === null || !this._isInEnum('' + v)) {
return null;
if (!this._isInEnum(v)) {
return undefined;
}
return '' + v;
return v;
}

get type() { return 'any'; }
get tsType(): null { return null; }
serialize(serializer: Serializer) { serializer.outputEnum(this); }
}


Expand Down
1 change: 1 addition & 0 deletions packages/@ngtools/json-schema/src/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export abstract class Serializer {
abstract array(node: SchemaNode): void;

abstract outputOneOf(node: SchemaNode): void;
abstract outputEnum(node: SchemaNode): void;

abstract outputString(node: SchemaNode): void;
abstract outputNumber(node: SchemaNode): void;
Expand Down
49 changes: 28 additions & 21 deletions packages/@ngtools/json-schema/src/serializers/dts.spec.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import * as path from 'path';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';

import {DTsSerializer} from './dts';
import {SchemaClassFactory} from '../schema-class-factory';
import {RootSchemaTreeNode} from '../schema-tree';


describe('DtsSerializer', () => {
const schemaJsonFilePath = path.join(__dirname, '../../tests/schema1.json');
const schemaJson = JSON.parse(fs.readFileSync(schemaJsonFilePath, 'utf-8'));
const schemaClass = new (SchemaClassFactory(schemaJson))({});
const schema: RootSchemaTreeNode = schemaClass.$$schema();

it('works', () => {
let str = '';
function writer(s: string) {
str += s;
}

const serializer = new DTsSerializer(writer, 'HelloWorld');

serializer.start();
schema.serialize(serializer);
serializer.end();

// Expect optional properties to be followed by `?`
expect(str).toMatch(/stringKey\?/);
});
for (const nb of [1, 2, 3]) {
it(`works (${nb})`, () => {
const schemaJsonFilePath = path.join(__dirname, `../../tests/serializer/schema${nb}.json`);
const schemaJson = JSON.parse(fs.readFileSync(schemaJsonFilePath, 'utf-8'));
const valueDTsFilePath = path.join(__dirname, `../../tests/serializer/value${nb}.d.ts`);
const valueDTs = fs.readFileSync(valueDTsFilePath, 'utf-8');
const valueSourceFile = ts.createSourceFile('test.d.ts', valueDTs, ts.ScriptTarget.Latest);

const schemaClass = new (SchemaClassFactory(schemaJson))({});
const schema: RootSchemaTreeNode = schemaClass.$$schema();

let str = '';
function writer(s: string) {
str += s;
}

const serializer = new DTsSerializer(writer);

serializer.start();
schema.serialize(serializer);
serializer.end();

const sourceFile = ts.createSourceFile('test.d.ts', str, ts.ScriptTarget.Latest);
expect(sourceFile).toEqual(valueSourceFile);
});
}
});
17 changes: 16 additions & 1 deletion packages/@ngtools/json-schema/src/serializers/dts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class DTsSerializer implements Serializer {
if (interfaceName) {
_writer(`export interface ${interfaceName} `);
} else {
_writer('export default interface ');
_writer('interface _ ');
}
}

Expand Down Expand Up @@ -52,6 +52,9 @@ export class DTsSerializer implements Serializer {
if (this._indentDelta) {
this._writer('\n');
}
if (!this.interfaceName) {
this._writer('export default _;\n');
}
}

object(node: SchemaNode) {
Expand Down Expand Up @@ -126,6 +129,18 @@ export class DTsSerializer implements Serializer {
this._writer(')');
}

outputEnum(node: SchemaNode) {
this._willOutputValue();
this._writer('(');
for (let i = 0; i < node.items.length; i++) {
this._writer(JSON.stringify(node.items[i]));
if (i != node.items.length - 1) {
this._writer(' | ');
}
}
this._writer(')');
}

outputValue(node: SchemaNode) {
this._willOutputValue();
this._writer('any');
Expand Down
3 changes: 3 additions & 0 deletions packages/@ngtools/json-schema/src/serializers/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ export class JsonSerializer implements Serializer {
outputOneOf(node: SchemaNode) {
this.outputValue(node);
}
outputEnum(node: SchemaNode) {
this.outputValue(node);
}

outputValue(node: SchemaNode) {
this._willOutputValue();
Expand Down
6 changes: 6 additions & 0 deletions packages/@ngtools/json-schema/tests/serializer/schema2.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
"items": {
"enum": [ "v1", "v2", "v3" ]
}
},
"b": {
"type": "array",
"items": {
"enum": [ 0, 1, "string", true, null ]
}
}
}
}
26 changes: 26 additions & 0 deletions packages/@ngtools/json-schema/tests/serializer/value1.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
interface _ {
requiredKey: number;
stringKeyDefault?: string;
stringKey?: string;
booleanKey?: boolean;
numberKey?: number;
oneOfKey1?: (string | number);
oneOfKey2?: (string | string[]);
objectKey1?: {
stringKey?: string;
objectKey?: {
stringKey?: string;
};
};
objectKey2?: {
stringKey?: string;
[name: string]: any;
};
arrayKey1?: {
stringKey?: string;
}[];
arrayKey2?: {
stringKey?: string;
}[];
}
export default _;
5 changes: 5 additions & 0 deletions packages/@ngtools/json-schema/tests/serializer/value2.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface _ {
a?: ("v1" | "v2" | "v3")[];
b?: (0 | 1 | "string" | true | null)[];
}
export default _;
6 changes: 6 additions & 0 deletions packages/@ngtools/json-schema/tests/serializer/value2.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@
"v1",
"v2",
"v3"
],
"b": [
1,
null,
"string",
true
]
}
85 changes: 85 additions & 0 deletions packages/@ngtools/json-schema/tests/serializer/value3.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
interface _ {
/**
* The global configuration of the project.
*/
project?: {
version?: string;
name?: string;
};
/**
* Properties of the different applications in this project.
*/
apps?: {
root?: string;
outDir?: string;
assets?: (string | string[]);
deployUrl?: string;
index?: string;
main?: string;
test?: string;
tsconfig?: string;
prefix?: string;
/**
* Global styles to be included in the build.
*/
styles?: (string | {
input?: string;
[name: string]: any;
})[];
/**
* Global scripts to be included in the build.
*/
scripts?: (string | {
input: string;
[name: string]: any;
})[];
/**
* Name and corresponding file for environment config.
*/
environments?: {
[name: string]: any;
};
}[];
/**
* Configuration reserved for installed third party addons.
*/
addons?: {
[name: string]: any;
}[];
/**
* Configuration reserved for installed third party packages.
*/
packages?: {
[name: string]: any;
}[];
e2e?: {
protractor?: {
config?: string;
};
};
test?: {
karma?: {
config?: string;
};
};
defaults?: {
styleExt?: string;
prefixInterfaces?: boolean;
poll?: number;
viewEncapsulation?: string;
changeDetection?: string;
inline?: {
style?: boolean;
template?: boolean;
};
spec?: {
class?: boolean;
component?: boolean;
directive?: boolean;
module?: boolean;
pipe?: boolean;
service?: boolean;
};
};
}
export default _;