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

feature: new strictNot option, enabled by default #492

Closed
wants to merge 7 commits into from
47 changes: 28 additions & 19 deletions src/core/astBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import * as ts from 'typescript';
import config from './config';
import { NormalizedSchema } from './jsonSchema';
import {
NormalizedSchema,
NormalizedSchemaWithoutContentFalse,
} from './jsonSchema';
import SchemaId from './schemaId';
import { Schema } from './type';
import { toValidIdentifier, checkInvalidCharacter } from './validateIdentifier';
Expand Down Expand Up @@ -116,7 +119,7 @@ export function buildTypeAliasNode(
}

export function buildPropertySignature(
_schema: NormalizedSchema,
_schema: NormalizedSchemaWithoutContentFalse,
propertyName: string,
valueType: ts.TypeNode,
required: string[] | undefined,
Expand Down Expand Up @@ -294,7 +297,10 @@ export function addComment<T extends ts.Node>(
schema: NormalizedSchema,
terminate: boolean
): T {
const comments = getComment(schema);
const comments =
schema.content === false
? []
: getComment(schema as NormalizedSchemaWithoutContentFalse);
if (comments.length === 0) {
return node;
} else if (!terminate && comments.length === 1) {
Expand All @@ -319,7 +325,7 @@ export function addComment<T extends ts.Node>(
}
}

function getComment(schema: NormalizedSchema): string[] {
function getComment(schema: NormalizedSchemaWithoutContentFalse): string[] {
const content = schema.content;
let comments: string[] = [];
function protectComment(str: string): string {
Expand Down Expand Up @@ -361,27 +367,30 @@ export function addOptionalInformation<T extends ts.Node>(
schema: NormalizedSchema,
terminate: boolean
): T {
const format = schema.content.format;
const pattern = schema.content.pattern;
if (!format && !pattern) {
return node;
}
const comment = (function () {
if (schema.content === false) {
return 'false';
} else if (schema.content.format) {
return `${schema.content.format}`;
} else if (schema.content.pattern) {
return `${schema.content.pattern}`;
}
return undefined;
})();

let comment = '';
if (format) {
comment += ' ' + format;
}
if (pattern) {
comment += ' ' + pattern;
if (comment === undefined) {
return node;
}

if (!terminate) {
comment += ' ';
}
const kind = terminate
? ts.SyntaxKind.SingleLineCommentTrivia
: ts.SyntaxKind.MultiLineCommentTrivia;
return ts.addSyntheticTrailingComment(node, kind, comment, false);
return ts.addSyntheticTrailingComment(
node,
kind,
` ${comment}${terminate ? '' : ' '}`,
false
);
}

function getLastTypeName(id: SchemaId): string {
Expand Down
2 changes: 2 additions & 0 deletions src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface Config {
outputFile?: string;
target: ScriptTarget;
outputAST: boolean;
strictNot: boolean;

plugins: {
[pluginName: string]: boolean | Record<string, unknown>;
Expand All @@ -24,6 +25,7 @@ const defaultConfig: Config = {
stdin: false,
},
outputAST: false,
strictNot: true,
target: ScriptTarget.Latest,
plugins: {},
};
Expand Down
65 changes: 46 additions & 19 deletions src/core/dtsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as ts from 'typescript';
import { get, set, tilde } from '../jsonPointer';
import * as ast from './astBuilder';
import config from './config';
import { getSubSchema, NormalizedSchema } from './jsonSchema';
import { getSubSchema, NormalizedSchema, NormalizedSchemaWithoutContentFalse } from './jsonSchema';
import ReferenceResolver from './referenceResolver';
import {
Plugin,
Expand Down Expand Up @@ -200,15 +200,27 @@ export default class DtsGenerator {
this.currentSchema = normalized;

const getNode = () => {
if (normalized.content === false) {
return this.generateDeclareType(normalized, root);
}
const type = normalized.content.type;
switch (type) {
case 'any':
return this.generateAnyTypeModel(normalized, root);
return this.generateAnyTypeModel(
normalized as NormalizedSchemaWithoutContentFalse,
root
);
case 'array':
return this.generateTypeCollection(normalized, root);
return this.generateTypeCollection(
normalized as NormalizedSchemaWithoutContentFalse,
root
);
case 'object':
default:
return this.generateDeclareType(normalized, root);
return this.generateDeclareType(
normalized as NormalizedSchemaWithoutContentFalse,
root
);
}
};
return ast.addOptionalInformation(
Expand All @@ -230,9 +242,11 @@ export default class DtsGenerator {
});
}

private normalizeSchemaContent(content: JsonSchema): JsonSchemaObject {
private normalizeSchemaContent(
content: JsonSchema
): NormalizedSchema['content'] {
if (typeof content === 'boolean') {
content = content ? {} : { not: {} };
content = content ? {} : false;
} else {
if (content.allOf) {
const work = {};
Expand Down Expand Up @@ -284,6 +298,7 @@ export default class DtsGenerator {
): ts.DeclarationStatement {
const content = schema.content;
if (
content === false ||
content.$ref ||
content.oneOf ||
content.anyOf ||
Expand All @@ -294,7 +309,9 @@ export default class DtsGenerator {
const type = this.generateTypeProperty(schema);
return ast.buildTypeAliasNode(schema.id, type, root);
} else {
const members = this.generateProperties(schema);
const members = this.generateProperties(
schema as NormalizedSchemaWithoutContentFalse
);
return ast.buildInterfaceNode(schema.id, members, root);
}
}
Expand All @@ -312,14 +329,16 @@ export default class DtsGenerator {
}

private generateTypeCollection(
schema: NormalizedSchema,
schema: NormalizedSchemaWithoutContentFalse,
root: boolean
): ts.DeclarationStatement {
const type = this.generateArrayTypeProperty(schema);
return ast.buildTypeAliasNode(schema.id, type, root);
}

private generateProperties(baseSchema: NormalizedSchema): ts.TypeElement[] {
private generateProperties(
baseSchema: NormalizedSchemaWithoutContentFalse
): ts.TypeElement[] {
const result: ts.TypeElement[] = [];
const content = baseSchema.content;
if (content.additionalProperties) {
Expand All @@ -345,7 +364,7 @@ export default class DtsGenerator {
'/properties/' + tilde(propertyName)
);
const node = ast.buildPropertySignature(
schema,
schema as NormalizedSchemaWithoutContentFalse,
propertyName,
this.generateTypeProperty(schema),
baseSchema.content.required,
Expand All @@ -370,7 +389,9 @@ export default class DtsGenerator {
schemasTypes.push(this.generateTypeProperty(schema));
}
const node = ast.buildPropertySignature(
{ content: { readOnly: false } } as NormalizedSchema,
{
content: { readOnly: false },
} as NormalizedSchemaWithoutContentFalse,
'pattern',
ts.createUnionTypeNode(schemasTypes),
baseSchema.content.required,
Expand All @@ -393,6 +414,9 @@ export default class DtsGenerator {
terminate = true
): ts.TypeNode {
const content = schema.content;
if (content === false) {
return ast.buildVoidKeyword();
}
if (content.$ref) {
const ref = this.resolver.dereference(content.$ref);
if (ref.id == null) {
Expand All @@ -415,7 +439,7 @@ export default class DtsGenerator {
const mergeContent = Object.assign({}, content);
delete mergeContent.anyOf;
return this.generateArrayedType(
schema,
schema as NormalizedSchemaWithoutContentFalse,
content.anyOf,
mergeContent,
'/anyOf/',
Expand All @@ -426,7 +450,7 @@ export default class DtsGenerator {
const mergeContent = Object.assign({}, content);
delete mergeContent.oneOf;
return this.generateArrayedType(
schema,
schema as NormalizedSchemaWithoutContentFalse,
content.oneOf,
mergeContent,
'/oneOf/',
Expand All @@ -441,12 +465,15 @@ export default class DtsGenerator {
},
terminate
);
} else if (content.not) {
} else if (config.strictNot && content.not) {
return ast.buildVoidKeyword();
} else if ('const' in content) {
return this.generateLiteralTypeNode(content, content.const);
} else {
return this.generateType(schema, terminate);
return this.generateType(
schema as NormalizedSchemaWithoutContentFalse,
terminate
);
}
}
private generateLiteralTypeNode(
Expand Down Expand Up @@ -479,7 +506,7 @@ export default class DtsGenerator {
}

private generateArrayedType(
baseSchema: NormalizedSchema,
baseSchema: NormalizedSchemaWithoutContentFalse,
contents: JsonSchema[],
mergeContent: JsonSchema,
path: string,
Expand Down Expand Up @@ -523,7 +550,7 @@ export default class DtsGenerator {
}

private generateArrayTypeProperty(
schema: NormalizedSchema,
schema: NormalizedSchemaWithoutContentFalse,
terminate = true
): ts.TypeNode {
const items = schema.content.items;
Expand Down Expand Up @@ -621,7 +648,7 @@ export default class DtsGenerator {
}

private generateType(
schema: NormalizedSchema,
schema: NormalizedSchemaWithoutContentFalse,
terminate: boolean
): ts.TypeNode {
const type = schema.content.type;
Expand All @@ -646,7 +673,7 @@ export default class DtsGenerator {
}
}
private generateTypeName(
schema: NormalizedSchema,
schema: NormalizedSchemaWithoutContentFalse,
type: string,
terminate: boolean
): ts.TypeNode {
Expand Down
3 changes: 3 additions & 0 deletions src/core/jsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ interface ParameterObject {
type Parameter = ParameterObject | { $ref?: string };

export interface NormalizedSchema extends Schema {
content: JsonSchemaObject | false;
}
export interface NormalizedSchemaWithoutContentFalse extends Schema {
content: JsonSchemaObject;
}

Expand Down
Loading