Skip to content

Commit 96770e3

Browse files
author
wangw19
committed
feat: 1. 新增通过 code 生成 jsonschema
2. 修复解析泛型不成功问题
1 parent 1e9bbad commit 96770e3

File tree

8 files changed

+224
-24
lines changed

8 files changed

+224
-24
lines changed

README.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# fast-typescript-to-jsonschema
22

3-
[![npm version](https://img.shields.io/npm/v/fast-typescript-to-jsonschema.svg)](https://www.npmjs.com/package/fast-typescript-to-jsonschema)
3+
[![npm version](https://img.shields.io/npm/v/fast-typescript-to-jsonschema.svg)](https://www.npmjs.com/package/fast-typescript-to-jsonschema)
44
![Test](https://github.com/yunke-yunfly/fast-typescript-to-jsonschema/workflows/Test/badge.svg)
55
[![codecov](https://codecov.io/gh/yunke-yunfly/fast-typescript-to-jsonschema/branch/master/graph/badge.svg)](https://app.codecov.io/gh/yunke-yunfly/fast-typescript-to-jsonschema)
66

@@ -33,6 +33,8 @@ interface ITest {
3333

3434
3. create `test.js`
3535

36+
3.1. gen jsonschema from file.
37+
3638
```js
3739
const { default: genTypeSchema } = require('fast-typescript-to-jsonschema');
3840
const path = require('path');
@@ -53,6 +55,31 @@ const jsonSchema = genTypeSchema.getJsonSchema(file, 'ITest');
5355
console.log(jsonSchema);
5456
```
5557

58+
3.2. gen jsonschema from code.
59+
60+
```js
61+
const { default: genTypeSchema } = require('fast-typescript-to-jsonschema');
62+
63+
const code = `
64+
interface ITest {
65+
attr1: string;
66+
attr2: number;
67+
attr3?: boolean;
68+
}
69+
`
70+
// generate data
71+
genTypeSchema.genJsonDataFromCode(code);
72+
73+
// get all jsonschema data of current file
74+
const json = genTypeSchema.genJsonData();
75+
76+
// get jsonschema of specific type
77+
const jsonSchema = genTypeSchema.getJsonSchema('ITest');
78+
79+
// result
80+
console.log(jsonSchema);
81+
```
82+
5683
4. execute script
5784

5885
```js
@@ -161,7 +188,7 @@ result:
161188
- [1.2 Named Export Modules](docs/module.en-US.md#12-named-export-modules)
162189
- [Extending Types](docs/extends.en-US.md#extending-types)
163190
- [1.1 Basic Extending Types](docs/extends.en-US.md#11-basic-extending-types)
164-
- [1.2 Multiple Extending Types ](docs/extends.en-US.md#12-multiple-extending-types)
191+
- [1.2 Multiple Extending Types](docs/extends.en-US.md#12-multiple-extending-types)
165192
- [Enums](docs/enum.en-US.md#enums)
166193
- [1.1 Numeric Enums](docs/enum.en-US.md#11-numeric-enums)
167194
- [1.2 String Enums](docs/enum.en-US.md#12-string-enums)

README.zh-cn.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# fast-typescript-to-jsonschema
22

3-
[![npm version](https://img.shields.io/npm/v/fast-typescript-to-jsonschema.svg)](https://www.npmjs.com/package/fast-typescript-to-jsonschema)
3+
[![npm version](https://img.shields.io/npm/v/fast-typescript-to-jsonschema.svg)](https://www.npmjs.com/package/fast-typescript-to-jsonschema)
44
![Test](https://github.com/yunke-yunfly/fast-typescript-to-jsonschema/workflows/Test/badge.svg)
55
[![codecov](https://codecov.io/gh/yunke-yunfly/fast-typescript-to-jsonschema/branch/master/graph/badge.svg)](https://app.codecov.io/gh/yunke-yunfly/fast-typescript-to-jsonschema)
66

@@ -31,7 +31,9 @@ interface ITest {
3131
}
3232
```
3333

34-
3.创建`test.js`文件,内容如下:
34+
3. 创建`test.js`文件,内容如下:
35+
36+
3.1 通过文件生成 jsonschema
3537

3638
```js
3739
const { default: genTypeSchema } = require('fast-typescript-to-jsonschema');
@@ -53,6 +55,31 @@ const jsonSchema = genTypeSchema.getJsonSchema(file, 'ITest');
5355
console.log(jsonSchema);
5456
```
5557

58+
3.2 通过 code 生成 jsonschema
59+
60+
```js
61+
const { default: genTypeSchema } = require('fast-typescript-to-jsonschema');
62+
63+
const code = `
64+
interface ITest {
65+
attr1: string;
66+
attr2: number;
67+
attr3?: boolean;
68+
}
69+
`
70+
// generate data
71+
genTypeSchema.genJsonDataFromCode(code);
72+
73+
// get all jsonschema data of current file
74+
const json = genTypeSchema.genJsonData();
75+
76+
// get jsonschema of specific type
77+
const jsonSchema = genTypeSchema.getJsonSchema('ITest');
78+
79+
// result
80+
console.log(jsonSchema);
81+
```
82+
5683
4.执行脚本
5784

5885
```js
@@ -84,7 +111,7 @@ node ./test.js
84111
```
85112

86113
- example 案例地址:
87-
https://github.com/yunke-yunfly/fast-typescript-to-jsonschema/tree/master/example
114+
<https://github.com/yunke-yunfly/fast-typescript-to-jsonschema/tree/master/example>
88115

89116
## 注释
90117

@@ -141,7 +168,6 @@ interface Interface_4 {
141168
}
142169
```
143170

144-
145171
> 更多支持的类型解析[请看](docs/index.md),目录如下:
146172
147173
- [接口](docs/interface.md)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "fast-typescript-to-jsonschema",
3-
"version": "0.0.7",
3+
"version": "0.0.8",
44
"description": "fast-typescript-to-jsonschema generates JSON Schema files from your Typescript sources.",
55
"main": "./dist/index.js",
66
"typings": "dist/index.d.ts",

src/__tests__/__snapshots__/generic.test.ts.snap

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,76 @@ Object {
3434
}
3535
`;
3636

37+
exports[`Generic多层对象_类型_2 1`] = `
38+
Object {
39+
"additionalProperties": false,
40+
"definitions": Object {
41+
"Generic_8<string>": Object {
42+
"additionalProperties": false,
43+
"properties": Object {
44+
"value1": Object {
45+
"additionalProperties": false,
46+
"properties": Object {
47+
"value2": Object {
48+
"additionalProperties": false,
49+
"properties": Object {
50+
"value3": Object {
51+
"type": "string",
52+
},
53+
},
54+
"required": Array [
55+
"value3",
56+
],
57+
"type": "object",
58+
},
59+
},
60+
"required": Array [
61+
"value2",
62+
],
63+
"type": "object",
64+
},
65+
},
66+
"required": Array [
67+
"value1",
68+
],
69+
"type": "object",
70+
},
71+
},
72+
"properties": Object {
73+
"value": Object {
74+
"items": Object {
75+
"$realRef": "Generic_8",
76+
"$ref": "#/definitions/Generic_8<string>",
77+
},
78+
"type": "array",
79+
},
80+
},
81+
"required": Array [
82+
"value",
83+
],
84+
"type": "object",
85+
}
86+
`;
87+
88+
exports[`Generic多层对象_类型_3 1`] = `
89+
Object {
90+
"additionalProperties": false,
91+
"definitions": Object {},
92+
"properties": Object {
93+
"value": Object {
94+
"items": Object {
95+
"type": "string",
96+
},
97+
"type": "array",
98+
},
99+
},
100+
"required": Array [
101+
"value",
102+
],
103+
"type": "object",
104+
}
105+
`;
106+
37107
exports[`Generic引用别的文件_类型_1 1`] = `
38108
Object {
39109
"additionalProperties": false,

src/__tests__/generic.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ test('Generic多层对象_类型_1', () => {
3838
expect(getSchema('Generic_9')).toMatchSnapshot();
3939
});
4040

41+
test('Generic多层对象_类型_2', () => {
42+
expect(getSchema('Generic_11')).toMatchSnapshot();
43+
});
44+
45+
test('Generic多层对象_类型_3', () => {
46+
expect(getSchema('Generic_13')).toMatchSnapshot();
47+
});
48+
4149
test('Generic引用别的文件_类型_1', () => {
4250
expect(getSchema('Generic_10')).toMatchSnapshot();
43-
});
51+
});
52+

src/get-jsonschema-from-data.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,18 @@ export default class genTypeSchema extends typescriptToFileDatas {
3434
file: string,
3535
type: string,
3636
entry?: { keySet: Set<string>; refKeyTime: Record<string, number> },
37+
isLast?: boolean
3738
): AnyOption {
3839
if (!entry) {
3940
entry = { keySet: new Set(), refKeyTime: {} };
4041
}
42+
43+
// 支持输入的是 code 场景
44+
if (file && !type) {
45+
type = file;
46+
file = 'index.ts';
47+
}
48+
4149
if (!file || !type) return { type: 'object' };
4250

4351
// 处理 Param.C.D.E.F.GetBaseDetailResponse 这种外部导入路径
@@ -60,8 +68,13 @@ export default class genTypeSchema extends typescriptToFileDatas {
6068
refFile,
6169
typeJson.from ? type.replace(/.+?(?=\.)|.+/, typeJson.from) : type,
6270
entry,
71+
true,
6372
);
6473

74+
if (!isLast && typeJson.typeParams) {
75+
delete typeJson.typeParams
76+
}
77+
6578
return typeJson;
6679
}
6780
}
@@ -85,6 +98,11 @@ export default class genTypeSchema extends typescriptToFileDatas {
8598
}
8699
typeJson.definitions[type] = cloneTypeJson;
87100
}
101+
102+
if (!isLast && typeJson.typeParams) {
103+
delete typeJson.typeParams
104+
}
105+
88106
return typeJson;
89107
}
90108

@@ -200,7 +218,7 @@ export default class genTypeSchema extends typescriptToFileDatas {
200218
// 别的文件ref
201219
if (realRef.$ref && realRef.type !== ImportType.ImportNamespaceSpecifier) {
202220
const refFile = realRef.$ref.replace(/#\/definitions|#/, '');
203-
const realSchema = this.getJsonSchema(refFile, result.$realRef);
221+
const realSchema = this.getJsonSchema(refFile, result.$realRef, undefined, true);
204222
delete realRef.$ref;
205223
delete realRef.from;
206224
Object.assign(realRef, realSchema);
@@ -280,10 +298,10 @@ export default class genTypeSchema extends typescriptToFileDatas {
280298

281299
// 处理继承
282300
const handleExtends = (item: AnyOption) => {
283-
const newTypeJson = this.getJsonSchema(file as string, item.extends, entry);
301+
const newTypeJson = this.getJsonSchema(file as string, item.extends, entry, true);
284302
if (newTypeJson) {
285303
const result = newTypeJson.$ref
286-
? this.getJsonSchema(newTypeJson.$ref.replace(/#/g, ''), item.extends, entry)
304+
? this.getJsonSchema(newTypeJson.$ref.replace(/#/g, ''), item.extends, entry, true)
287305
: this.genJsonschema(fileJson, newTypeJson, entry);
288306
if (typeof result === 'object') {
289307
item = merge(result, item, {
@@ -358,6 +376,7 @@ export default class genTypeSchema extends typescriptToFileDatas {
358376
$dependRefKey,
359377
$refJson.from ? $refKey.replace(/.+?(?=\.)|.+/, $refJson.from) : $refKey,
360378
entry,
379+
true
361380
);
362381
handle && handleCommonRef(result, $refKey);
363382
return result;
@@ -650,6 +669,11 @@ export default class genTypeSchema extends typescriptToFileDatas {
650669
// anyOf|allOf
651670
allOfAnyOfHandle(typeJson);
652671

672+
// 处理泛型
673+
if (typeJson.typeParams && Object.keys(typeJson.typeParams).length) {
674+
handleGenericDefaultType(typeJson.properties, typeJson.typeParams);
675+
}
676+
653677
// 数组类型
654678
if (typeJson.type === 'array') {
655679
commonArrayHandle(typeJson);
@@ -660,7 +684,6 @@ export default class genTypeSchema extends typescriptToFileDatas {
660684
typeJson = handleExtends(typeJson);
661685
}
662686

663-
664687
// 对象类型
665688
if (typeJson.properties && Object.keys(typeJson.properties)) {
666689
// eslint-disable-next-line guard-for-in

src/typescript-to-file-datas.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as fs from 'fs';
77
// types
88
import type { AnyOption, TSTypeAnnotationConfig, TypeAnnotationConfig } from './types';
99
// utils
10-
import { genAst } from './utils';
10+
import { genAst, genAstFromCode } from './utils';
1111
// require
1212
const chalk = require('chalk');
1313
const doctrine = require('doctrine');
@@ -142,6 +142,13 @@ export default class typescriptToFileDatas {
142142
return { filePath: file, fileType: 'npm' };
143143
}
144144

145+
/**
146+
* 查找npm包types
147+
*
148+
* @param {{ sourceValue: string }} { sourceValue }
149+
* @return {*}
150+
* @memberof typescriptToFileDatas
151+
*/
145152
getTypeFileFromNpm({ sourceValue }: { sourceValue: string }) {
146153
// 1. 优先查找 index.d.ts 其次查找 ${sourceValue}.d.ts
147154
const sourceValueArr = sourceValue.split('/');
@@ -191,6 +198,13 @@ export default class typescriptToFileDatas {
191198
return source
192199
}
193200

201+
/**
202+
* 查找文件 import types
203+
*
204+
* @param {{ dir: string; sourceValue: string; ext: string }} { dir, sourceValue, ext }
205+
* @return {*}
206+
* @memberof typescriptToFileDatas
207+
*/
194208
getTypeFileFromImport({ dir, sourceValue, ext }: { dir: string; sourceValue: string; ext: string }) {
195209
let source = '';
196210
// 找依赖的文件,优先级 .ts >> .d.ts >> /index.ts >> /index.d.ts
@@ -502,6 +516,19 @@ export default class typescriptToFileDatas {
502516
return { data: result, file };
503517
}
504518

519+
/**
520+
* 通过代码获得解析数据
521+
*
522+
* @param {string} code
523+
* @return {*} {AnyOption}
524+
* @memberof typescriptToFileDatas
525+
*/
526+
genJsonDataFromCode(code: string): AnyOption {
527+
// ast
528+
const ast_ = genAstFromCode(code);
529+
return this.genJsonDataFormFile('index.ts', ast_);
530+
}
531+
505532
/**
506533
* 只获取代码前注释 支持行内注释与块注释
507534
*

0 commit comments

Comments
 (0)