Skip to content
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
24 changes: 24 additions & 0 deletions jest/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,27 @@ export namespace Param_1 {
name: string;
}
}

export namespace ParamsRule {
export interface Level {
a?: boolean;
b?: boolean;
c?: boolean;
d?: boolean;
}

export enum PEnum {
'enum0' = 'enum0'
}

export interface PObject {
a: Level;
b?: PEnum;
c?: PEnum[];
}

export interface PAll {
level?: Level;
pObject?: PObject;
}
}
6 changes: 5 additions & 1 deletion jest/namespace.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Param, Param_1 } from './common';
import { Param, Param_1, ParamsRule } from './common';
import * as Type from './common';

export interface Namespace_1 {
Expand All @@ -18,3 +18,7 @@ export interface Namespace_4 {
other2: Param_1.A;
other3: Param_1.Label;
}

export interface Namespace_5 {
other1: ParamsRule.PAll
}
74 changes: 74 additions & 0 deletions src/__tests__/__snapshots__/namespace.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,77 @@ Object {
"type": "object",
}
`;

exports[`namespace案例_5 1`] = `
Object {
"additionalProperties": false,
"definitions": Object {
"ParamsRule.Level": Object {
"additionalProperties": false,
"properties": Object {
"a": Object {
"type": "boolean",
},
"b": Object {
"type": "boolean",
},
"c": Object {
"type": "boolean",
},
"d": Object {
"type": "boolean",
},
},
"type": "object",
},
"ParamsRule.PAll": Object {
"additionalProperties": false,
"properties": Object {
"level": Object {
"$ref": "#/definitions/ParamsRule.Level",
},
"pObject": Object {
"$ref": "#/definitions/ParamsRule.PObject",
},
},
"type": "object",
},
"ParamsRule.PEnum": Object {
"enum": Array [
"enum0",
],
"type": "string",
},
"ParamsRule.PObject": Object {
"additionalProperties": false,
"properties": Object {
"a": Object {
"$ref": "#/definitions/ParamsRule.Level",
},
"b": Object {
"$ref": "#/definitions/ParamsRule.PEnum",
},
"c": Object {
"items": Object {
"$ref": "#/definitions/ParamsRule.PEnum",
},
"type": "array",
},
},
"required": Array [
"a",
],
"type": "object",
},
},
"properties": Object {
"other1": Object {
"$ref": "#/definitions/ParamsRule.PAll",
},
},
"required": Array [
"other1",
],
"type": "object",
}
`;
57 changes: 57 additions & 0 deletions src/__tests__/__snapshots__/other.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,63 @@ Object {
],
"type": "number",
},
"ParamsRule.Level": Object {
"additionalProperties": false,
"properties": Object {
"a": Object {
"type": "boolean",
},
"b": Object {
"type": "boolean",
},
"c": Object {
"type": "boolean",
},
"d": Object {
"type": "boolean",
},
},
"type": "object",
},
"ParamsRule.PAll": Object {
"additionalProperties": false,
"properties": Object {
"level": Object {
"$ref": "#ParamsRule.Level",
},
"pObject": Object {
"$ref": "#ParamsRule.PObject",
},
},
"type": "object",
},
"ParamsRule.PEnum": Object {
"enum": Array [
"enum0",
],
"type": "string",
},
"ParamsRule.PObject": Object {
"additionalProperties": false,
"properties": Object {
"a": Object {
"$ref": "#ParamsRule.Level",
},
"b": Object {
"$ref": "#ParamsRule.PEnum",
},
"c": Object {
"items": Object {
"$ref": "#ParamsRule.PEnum",
},
"type": "array",
},
},
"required": Array [
"a",
],
"type": "object",
},
},
"/jest/other.ts": Object {
"AAA": Object {
Expand Down
4 changes: 4 additions & 0 deletions src/__tests__/namespace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ test('namespace案例_3', () => {
test('namespace案例_4', () => {
expect(getSchema('Namespace_4')).toMatchSnapshot();
});

test('namespace案例_5', () => {
expect(getSchema('Namespace_5')).toMatchSnapshot();
});
11 changes: 9 additions & 2 deletions src/get-jsonschema-from-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,25 @@ export default class genTypeSchema extends typescriptToFileDatas {
// 兼容import外部引入与内部引用两种方式
let $refJson = fileJson[firstKey] || fileJson[$refKey] || {};
$refJson = _.cloneDeep($refJson)

if ((entry as any).keySet.has($refKey)) {
(entry as any).refKeyTime[$refKey] = ((entry as any).refKeyTime[$refKey] || 0) + 1;
// 处理namespace方式导入的types
if ($refJson.type === ImportType.ImportNamespaceSpecifier) {
$refKey = otherKeys.join('.');
}
item.$ref = `#/definitions/${$refKey}`;
return $refJson;
}

(entry as any).keySet.add($refKey);
(entry as any).refKeyTime[$refKey] = ((entry as any).refKeyTime[$refKey] || 0) + 1;
// 处理namespace方式导入的types
if ($refJson.type === ImportType.ImportNamespaceSpecifier) {
$refKey = otherKeys.join('.');
}

(entry as any).keySet.add($refKey);
(entry as any).refKeyTime[$refKey] = ((entry as any).refKeyTime[$refKey] || 0) + 1;

item.$ref = `#/definitions/${$refKey}`;

// fileJson[$refJson.$ref.replace(/#(\/definitions\/)?/, '')] 表示在本文件就能找到
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ export interface TypeAnnotationConfig {
file?: string;
attrKey?: string;
refKey?: string;
namespaces?: string[];
}

export interface TSTypeAnnotationConfig {
node: AnyOption;
parentKey?: string;
file?: string;
namespaces?: string[];
}

export type EntryType = { keySet: Set<string>; times: number };
31 changes: 21 additions & 10 deletions src/typescript-to-file-datas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default class typescriptToFileDatas {
parentJson: null | AnyOption,
option: TSTypeAnnotationConfig,
): void {
const { node, parentKey, file } = option || {};
const { node, parentKey, file, namespaces } = option || {};

const key = _.get(node, 'key.name') || _.get(node, 'key.value') || '';
const required = !node.optional;
Expand All @@ -92,6 +92,7 @@ export default class typescriptToFileDatas {
typeAnnotation: node.typeAnnotation,
file,
attrKey: key,
namespaces,
});

if (typeAnnotation && typeof typeAnnotation === 'object') {
Expand Down Expand Up @@ -338,7 +339,7 @@ export default class typescriptToFileDatas {
}
const key = _.get(path, 'node.key.name') || _.get(path, 'node.key.value');

_this.handleTSTypeAnnotation(json, null, { node: path.node, file });
_this.handleTSTypeAnnotation(json, null, { node: path.node, file, namespaces, });

path.traverse({
TSTypeLiteral(path: AnyOption) {
Expand All @@ -352,6 +353,7 @@ export default class typescriptToFileDatas {
node: path.node,
parentKey: key,
file,
namespaces,
});
},
});
Expand Down Expand Up @@ -576,10 +578,12 @@ export default class typescriptToFileDatas {
* @param {AnyOption} typeAnnotation
* @returns {any} {string}
*/
getTypeName(typeName: AnyOption): string {
getTypeName(typeName: AnyOption, namespaces?: string[]): string {
const name = _.get(typeName, 'name');

if (name) {
if (typeName.type === 'Identifier' && Array.isArray(namespaces) && namespaces.length) {
return `${namespaces.join('.')}.${name}`
}
return name;
}
const { left, right } = typeName || {};
Expand Down Expand Up @@ -624,7 +628,7 @@ export default class typescriptToFileDatas {
* @returns {any}
*/
transformTypeAnnotation(option: TypeAnnotationConfig): AnyOption | null {
const { typeAnnotation, file, attrKey, refKey } = option || {};
const { typeAnnotation, file, attrKey, refKey, namespaces } = option || {};
if (!typeAnnotation) return null;
const cType = _.get(typeAnnotation, 'type');
if (!cType) return null;
Expand All @@ -648,17 +652,16 @@ export default class typescriptToFileDatas {

// 处理 Number/自定义 等类型
if (cType === 'TSTypeReference') {
const name = this.getTypeName(typeAnnotation.typeName);

const name = this.getTypeName(typeAnnotation.typeName, namespaces);
const type = this.handleRelationTypes(name);

let items = null;
if (typeAnnotation.typeParameters) {
items = this.transformTypeAnnotation({
typeAnnotation: typeAnnotation.typeParameters,
file,
attrKey,
refKey: name,
namespaces,
});
}
// promise 特殊处理
Expand Down Expand Up @@ -698,7 +701,12 @@ export default class typescriptToFileDatas {
if (cType === 'TSTypeParameterInstantiation') {
const params: (AnyOption | null)[] = [];
typeAnnotation.params.forEach((item: AnyOption) => {
const res = this.transformTypeAnnotation({ typeAnnotation: item, file, attrKey });
const res = this.transformTypeAnnotation({
typeAnnotation: item,
file,
attrKey,
namespaces,
});
if (res) {
params.push(res);
}
Expand All @@ -718,6 +726,7 @@ export default class typescriptToFileDatas {
typeAnnotation: typeAnnotation.typeAnnotation,
file,
attrKey,
namespaces,
});
}

Expand All @@ -727,6 +736,7 @@ export default class typescriptToFileDatas {
typeAnnotation: typeAnnotation.elementType,
file,
attrKey,
namespaces,
});
return type ? { type: 'array', items: type } : null;
}
Expand All @@ -737,6 +747,7 @@ export default class typescriptToFileDatas {
typeAnnotation: typeAnnotation.typeAnnotation,
file,
attrKey,
namespaces,
});
return type;
}
Expand All @@ -745,7 +756,7 @@ export default class typescriptToFileDatas {
const members = typeAnnotation.members || [];
const json = { type: 'object', properties: {}, required: [] };
members.forEach((item: AnyOption) => {
this.handleTSTypeAnnotation(json, null, { node: item, file });
this.handleTSTypeAnnotation(json, null, { node: item, file, namespaces, });
});

this.formatJsonSchema(json);
Expand Down