Skip to content

feat(json-schema): Introduce a separate package for JSON schema. #3927

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

Merged
merged 1 commit into from
Jan 11, 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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"test:deps": "node scripts/publish/validate_dependencies.js",
"test:inspect": "node --inspect --debug-brk tests/runner",
"test:packages": "node scripts/run-packages-spec.js",
"build-config-interface": "dtsgen packages/angular-cli/lib/config/schema.json --out packages/angular-cli/lib/config/schema.d.ts",
"eslint": "eslint .",
"tslint": "tslint \"**/*.ts\" -c tslint.json -e \"**/blueprints/*/files/**/*.ts\" -e \"node_modules/**\" -e \"tmp/**\" -e \"dist/**\"",
"lint": "npm-run-all -c eslint tslint"
Expand Down
32 changes: 32 additions & 0 deletions packages/@ngtools/json-schema/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@ngtools/json-schema",
"version": "1.2.1",
"description": "Schema validating and reading for configurations, similar to Angular CLI config.",
"main": "./src/index.js",
"typings": "src/index.d.ts",
"license": "MIT",
"keywords": [
"angular",
"json",
"json-schema",
"schema",
"config"
],
"repository": {
"type": "git",
"url": "https://github.com/angular/angular-cli.git"
},
"author": "angular",
"bugs": {
"url": "https://github.com/angular/angular-cli/issues"
},
"homepage": "https://github.com/angular/angular-cli/tree/master/packages/@ngtools/json-schema",
"engines": {
"node": ">= 4.1.0",
"npm": ">= 3.0.0"
},
"dependencies": {
},
"peerDependencies": {
}
}
12 changes: 12 additions & 0 deletions packages/@ngtools/json-schema/src/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

export class JsonSchemaErrorBase extends Error {
constructor(message?: string) {
super();

if (message) {
this.message = message;
} else {
this.message = (<any>this.constructor).name;
}
}
}
1 change: 1 addition & 0 deletions packages/@ngtools/json-schema/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {SchemaClass, SchemaClassFactory} from './schema-class-factory';
34 changes: 34 additions & 0 deletions packages/@ngtools/json-schema/src/mimetypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {JsonSchemaErrorBase} from './error';
import {Serializer, WriterFn} from './serializer';
import {JsonSerializer} from './serializers/json';
import {DTsSerializer} from './serializers/dts';


export class UnknownMimetype extends JsonSchemaErrorBase {}


export function createSerializerFromMimetype(mimetype: string,
writer: WriterFn,
...opts: any[]): Serializer {
let Klass: { new (writer: WriterFn, ...args: any[]): Serializer } = null;
switch (mimetype) {
case 'application/json': Klass = JsonSerializer; break;
case 'text/json': Klass = JsonSerializer; break;
case 'text/x.typescript': Klass = DTsSerializer; break;
case 'text/x.dts': Klass = DTsSerializer; break;

default: throw new UnknownMimetype();
}

return new Klass(writer, ...opts);

}


declare module './serializer' {
namespace Serializer {
export let fromMimetype: typeof createSerializerFromMimetype;
}
}

Serializer.fromMimetype = createSerializerFromMimetype;
42 changes: 42 additions & 0 deletions packages/@ngtools/json-schema/src/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {Serializer} from './serializer';


// A TypeScript Type. This can be used to do `new tsType(value)`.
// `null` implies any type; be careful.
export type TypeScriptType = typeof Number
| typeof Boolean
| typeof String
| typeof Object
| typeof Array
| null;


// The most generic interface for a schema node. This is used by the serializers.
export interface SchemaNode {
readonly name: string;
readonly type: string;
readonly tsType: TypeScriptType;
readonly defined: boolean;
readonly dirty: boolean;
readonly frozen: boolean;
readonly readOnly: boolean;
readonly defaultValue: any | null;
readonly required: boolean;
readonly parent: SchemaNode | null;

// Schema related properties.
readonly description: string | null;

// Object-only properties. `null` for everything else.
readonly children: { [key: string]: SchemaNode } | null;

// Array-only properties. `null` for everything else.
readonly items: SchemaNode[] | null;
readonly itemPrototype: SchemaNode | null;

// Mutable properties.
value: any;

// Serialization.
serialize(serializer: Serializer): void;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {NgToolkitError} from '../error';
import {Serializer} from './serializer';
import {RootSchemaTreeNode, SchemaTreeNode} from './schema-tree';
import {JsonSchemaErrorBase} from './error';

export class InvalidJsonPath extends NgToolkitError {}
import './mimetypes';


export class InvalidJsonPath extends JsonSchemaErrorBase {}


// The schema tree node property of the SchemaClass.
Expand Down Expand Up @@ -66,6 +69,9 @@ export interface SchemaClass<JsonType> extends Object {
$$defined(path: string): boolean;
$$delete(path: string): void;

// Direct access to the schema.
$$schema(): RootSchemaTreeNode;

$$serialize(mimetype?: string): string;
}

Expand Down
34 changes: 34 additions & 0 deletions packages/@ngtools/json-schema/src/schema-tree.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {readFileSync} from 'fs';
import {join} from 'path';

import {RootSchemaTreeNode} from './schema-tree';


describe('SchemaTreeNode', () => {

});


describe('OneOfSchemaTreeNode', () => {
const schemaJsonFilePath = join(__dirname, '../tests/schema1.json');
const schemaJson = JSON.parse(readFileSync(schemaJsonFilePath, 'utf-8'));
const valueJsonFilePath = join(__dirname, '../tests/value1-1.json');
const valueJson = JSON.parse(readFileSync(valueJsonFilePath, 'utf-8'));


it('works', () => {
const proto: any = Object.create(null);
new RootSchemaTreeNode(proto, {
value: valueJson,
schema: schemaJson
});

expect(proto.oneOfKey2 instanceof Array).toBe(true);
expect(proto.oneOfKey2.length).toBe(2);

// Set it to a string, which is valid.
proto.oneOfKey2 = 'hello';
expect(proto.oneOfKey2 instanceof Array).toBe(false);
});
});

Loading