Skip to content

Commit

Permalink
add --strictTuples option: disallows additional elements in tuples (#29)
Browse files Browse the repository at this point in the history
With the `--strictTuples` option enabled, the generated schema does not allow for additional properties. 

See issue #28
  • Loading branch information
marcoqu authored and domoritz committed Jun 8, 2018
1 parent 2170b16 commit 7b8406e
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 5 deletions.
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,34 @@ npm install --save ts-json-schema-generator
--path 'my/project/**.*.ts' \
--type 'My.Type.Full.Name' \
--expose 'export' \
--jsDoc 'extended'
--jsDoc 'extended' \
--strictTuples
```

## Options

```
-e, --expose <all|none|export>
all: Create shared $ref definitions for all types.
none: Do not create shared $ref definitions.
export: Create shared $ref definitions only for exported types.
-r, --no-top-ref
Do not create a top-level $ref definition.
-j, --jsDoc <extended|none|basic>
basic: Read JsDoc annotations to provide schema properties.
extended: Also read @nullable, and @asType annotations.
none: Do not use JsDoc annotations.
-u, --unstable
Do not sort properties.
-s, --strictTuples
Do not allow additional items on tuples.
```


## Current state

* `interface` types
Expand Down
2 changes: 1 addition & 1 deletion factory/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function createFormatter(config: Config): TypeFormatter {
.addTypeFormatter(new LiteralUnionTypeFormatter())

.addTypeFormatter(new ArrayTypeFormatter(circularReferenceTypeFormatter))
.addTypeFormatter(new TupleTypeFormatter(circularReferenceTypeFormatter))
.addTypeFormatter(new TupleTypeFormatter(circularReferenceTypeFormatter, config))
.addTypeFormatter(new UnionTypeFormatter(circularReferenceTypeFormatter))
.addTypeFormatter(new IntersectionTypeFormatter(circularReferenceTypeFormatter));

Expand Down
2 changes: 2 additions & 0 deletions src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface PartialConfig {
topRef: boolean;
jsDoc: "none" | "extended" | "basic";
sortProps?: boolean;
strictTuples?: boolean;
}

export interface Config extends PartialConfig {
Expand All @@ -16,4 +17,5 @@ export const DEFAULT_CONFIG: PartialConfig = {
topRef: true,
jsDoc: "extended",
sortProps: true,
strictTuples: false,
};
1 change: 1 addition & 0 deletions src/Schema/Definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface Definition {
format?: string;
items?: Definition | Definition[];
minItems?: number;
maxItems?: number;
additionalItems?: {
anyOf: Definition[],
};
Expand Down
7 changes: 5 additions & 2 deletions src/TypeFormatter/TupleTypeFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Config } from "../Config";
import { Definition } from "../Schema/Definition";
import { SubTypeFormatter } from "../SubTypeFormatter";
import { BaseType } from "../Type/BaseType";
Expand All @@ -7,6 +8,7 @@ import { TypeFormatter } from "../TypeFormatter";
export class TupleTypeFormatter implements SubTypeFormatter {
public constructor(
private childTypeFormatter: TypeFormatter,
private config: Config,
) {
}

Expand All @@ -15,12 +17,13 @@ export class TupleTypeFormatter implements SubTypeFormatter {
}
public getDefinition(type: TupleType): Definition {
const tupleDefinitions = type.getTypes().map((item) => this.childTypeFormatter.getDefinition(item));

const addAdditionalItems = tupleDefinitions.length > 1 && !this.config.strictTuples;
const additionalItems = {additionalItems: {anyOf: tupleDefinitions}};
return {
type: "array",
items: tupleDefinitions,
minItems: tupleDefinitions.length,
...(tupleDefinitions.length > 1 ? {additionalItems: {anyOf: tupleDefinitions}} : {}),
...(addAdditionalItems ? additionalItems : {maxItems: tupleDefinitions.length}),
};
}
public getChildren(type: TupleType): BaseType[] {
Expand Down
17 changes: 16 additions & 1 deletion test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function assertSchema(name: string, partialConfig: PartialConfig & {type: string
const run: Run = only ? it.only : it;
run(name, () => {
const config: Config = {
... DEFAULT_CONFIG,
...DEFAULT_CONFIG,
...partialConfig,
path: resolve(`${basePath}/${name}/*.ts`),
};
Expand Down Expand Up @@ -61,4 +61,19 @@ describe("config", () => {

assertSchema("jsdoc-hide", {type: "MyObject", expose: "export", topRef: true, jsDoc: "extended"});
assertSchema("jsdoc-inheritance", {type: "MyObject", expose: "export", topRef: true, jsDoc: "extended"});

assertSchema("strict-tuples-true", {
type: "MyObject",
expose: "export",
topRef: true,
jsDoc: "none",
strictTuples: true,
});
assertSchema("strict-tuples-false", {
type: "MyObject",
expose: "export",
topRef: true,
jsDoc: "none",
strictTuples: false,
});
});
3 changes: 3 additions & 0 deletions test/config/strict-tuples-false/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface MyObject {
tuple: [number, string];
}
37 changes: 37 additions & 0 deletions test/config/strict-tuples-false/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$ref": "#/definitions/MyObject",
"$schema": "http://json-schema.org/draft-06/schema#",
"definitions": {
"MyObject": {
"additionalProperties": false,
"properties": {
"tuple": {
"additionalItems": {
"anyOf": [
{
"type": "number"
},
{
"type": "string"
}
]
},
"items": [
{
"type": "number"
},
{
"type": "string"
}
],
"minItems": 2,
"type": "array"
}
},
"required": [
"tuple"
],
"type": "object"
}
}
}
3 changes: 3 additions & 0 deletions test/config/strict-tuples-true/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface MyObject {
tuple: [number, string];
}
28 changes: 28 additions & 0 deletions test/config/strict-tuples-true/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$ref": "#/definitions/MyObject",
"$schema": "http://json-schema.org/draft-06/schema#",
"definitions": {
"MyObject": {
"additionalProperties": false,
"properties": {
"tuple": {
"items": [
{
"type": "number"
},
{
"type": "string"
}
],
"maxItems": 2,
"minItems": 2,
"type": "array"
}
},
"required": [
"tuple"
],
"type": "object"
}
}
}
5 changes: 5 additions & 0 deletions ts-json-schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const args = commander
"-u, --unstable",
"Do not sort properties",
)
.option(
"-s, --strictTuples",
"Do not allow additional items on tuples",
)
.parse(process.argv);

const config: Config = {
Expand All @@ -39,6 +43,7 @@ const config: Config = {
topRef: args.topRef,
jsDoc: args.jsDoc,
sortProps: !args.unstable,
strictTuples: args.strictTuples,
};

try {
Expand Down

0 comments on commit 7b8406e

Please sign in to comment.