type-flash 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lebron_shi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,358 @@
1
+ <div align="center">
2
+
3
+ # type-gen
4
+
5
+ **JSON 智能生成 TypeScript 类型定义**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/type-gen.svg?style=flat-square)](https://www.npmjs.com/package/type-gen)
8
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
9
+
10
+ > **One line of code, types generated instantly.**
11
+ > 一行代码,类型秒出。告别手写 Interface 的繁琐时代。
12
+
13
+ [功能特性](#-功能特性) • [快速开始](#-快速开始) • [使用方式](#-使用方式) • [配置选项](#-配置选项) • [对比优势](#-对比优势)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## ✨ 功能特性
20
+
21
+ ### 🎯 核心能力
22
+
23
+ - **🔍 智能类型推断** - 自动识别 string / number / boolean / null / undefined 等基础类型
24
+ - **📦 嵌套对象支持** - 递归遍历深层结构,自动生成子接口定义
25
+ - **🔗 联合类型推断** - 数组元素类型不同?自动合并为 `(string | number)[]`
26
+ - **❓ 可选属性识别** - 数组中部分对象缺少某字段?自动标记为 `?` 可选
27
+ - **🔄 结构等价去重** - 相同结构的对象复用同一类型,避免重复定义
28
+ - **🔁 循环引用检测** - 智能检测并处理 JSON 中的循环引用
29
+
30
+ ### ⚡ 增强功能
31
+
32
+ - **📑 枚举自动提取** - 字符串字段取值有限时,自动提取为 `enum` 枚举类型
33
+ - **🧬 泛型模式识别** - 智能识别分页结构 `{ list: T[], total: number }`,提取为 `PageResult<T>`
34
+ - **📝 JSDoc 注释生成** - 根据字段名猜测含义,自动生成文档注释
35
+ - **🎨 多种输出风格** - 支持 `interface` 和 `type alias` 两种输出风格
36
+ - **📏 灵活命名控制** - 支持 PascalCase / camelCase、前缀后缀、自定义类型名映射
37
+
38
+ ### 🛠️ 工程化支持
39
+
40
+ - **💻 CLI 命令行工具** - 开箱即用的命令行工具,支持管道输入
41
+ - **📦 双模块输出** - 同时提供 CommonJS 和 ESM 两种模块格式
42
+ - **🔩 TypeScript 原生** - 纯 TypeScript 编写,类型定义开箱即用
43
+ - **🧪 完整测试覆盖** - Jest 单元测试,确保核心功能稳定可靠
44
+
45
+ ---
46
+
47
+ ## 🚀 快速开始
48
+
49
+ ### 安装
50
+
51
+ ```bash
52
+ # npm
53
+ npm install type-gen --save-dev
54
+
55
+ # yarn
56
+ yarn add type-gen -D
57
+
58
+ # pnpm
59
+ pnpm add type-gen -D
60
+ ```
61
+
62
+ ### 一行代码上手
63
+
64
+ ```typescript
65
+ import { generate } from 'type-gen';
66
+
67
+ const jsonData = {
68
+ id: 1,
69
+ name: 'Alice',
70
+ email: 'alice@example.com',
71
+ profile: {
72
+ avatar: 'https://example.com/avatar.jpg',
73
+ bio: 'Hello World',
74
+ },
75
+ tags: ['admin', 'user'],
76
+ };
77
+
78
+ const result = generate(jsonData, { rootName: 'User' });
79
+ console.log(result.code);
80
+ ```
81
+
82
+ **输出结果:**
83
+
84
+ ```typescript
85
+ /**
86
+ * Generated by type-gen
87
+ * Root type: User
88
+ */
89
+
90
+ export interface User {
91
+ email: string;
92
+ id: number;
93
+ name: string;
94
+ profile: UserProfile;
95
+ tags: string[];
96
+ }
97
+
98
+ export interface UserProfile {
99
+ avatar: string;
100
+ bio: string;
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 📖 使用方式
107
+
108
+ ### 1. 编程式 API
109
+
110
+ #### 基础用法
111
+
112
+ ```typescript
113
+ import { generate, generateFromString } from 'type-gen';
114
+
115
+ // 从 JS 对象生成
116
+ const result1 = generate({ name: 'foo', age: 25 }, { rootName: 'User' });
117
+
118
+ // 从 JSON 字符串生成
119
+ const result2 = generateFromString('{"name": "foo"}', { rootName: 'User' });
120
+
121
+ // 获取生成的代码
122
+ console.log(result1.code);
123
+
124
+ // 获取所有类型定义
125
+ console.log(result1.types);
126
+ ```
127
+
128
+ #### 分页接口示例
129
+
130
+ ```typescript
131
+ import { generate } from 'type-gen';
132
+
133
+ const apiResponse = {
134
+ code: 0,
135
+ message: 'success',
136
+ data: {
137
+ list: [
138
+ { id: 1, name: 'Alice', status: 'active' },
139
+ { id: 2, name: 'Bob', status: 'inactive' },
140
+ ],
141
+ total: 100,
142
+ page: 1,
143
+ pageSize: 10,
144
+ },
145
+ };
146
+
147
+ const result = generate(apiResponse, {
148
+ rootName: 'ApiResponse',
149
+ extractEnums: true,
150
+ extractGenerics: true,
151
+ });
152
+
153
+ console.log(result.code);
154
+ ```
155
+
156
+ **输出:**
157
+
158
+ ```typescript
159
+ export interface ApiResponse {
160
+ code: number;
161
+ data: ApiResponseData;
162
+ message: string;
163
+ }
164
+
165
+ export interface ApiResponseData {
166
+ list: PageResult<ListItem>;
167
+ page: number;
168
+ pageSize: number;
169
+ total: number;
170
+ }
171
+
172
+ export interface ListItem {
173
+ id: number;
174
+ name: string;
175
+ status: StatusEnum;
176
+ }
177
+
178
+ export enum StatusEnum {
179
+ ACTIVE = 'active',
180
+ INACTIVE = 'inactive',
181
+ }
182
+ ```
183
+
184
+ ### 2. CLI 命令行
185
+
186
+ #### 基础用法
187
+
188
+ ```bash
189
+ # 从文件生成,输出到控制台
190
+ type-gen user.json
191
+
192
+ # 指定输出文件
193
+ type-gen user.json -o user.types.ts
194
+
195
+ # 自定义根类型名
196
+ type-gen user.json -n User
197
+
198
+ # 使用 type 风格输出
199
+ type-gen data.json --style type
200
+ ```
201
+
202
+ #### 高级用法
203
+
204
+ ```bash
205
+ # 从标准输入读取(管道)
206
+ curl https://api.example.com/users | type-gen -n UserList
207
+
208
+ # 生成带注释的类型定义
209
+ type-gen api.json --comments -o api-types.ts
210
+
211
+ # 严格空值模式
212
+ type-gen data.json --strict-null
213
+
214
+ # 添加类型前缀
215
+ type-gen response.json --prefix I -o interfaces.ts
216
+
217
+ # 不生成 export
218
+ type-gen types.json --no-export
219
+ ```
220
+
221
+ #### 所有 CLI 选项
222
+
223
+ | 选项 | 说明 | 默认值 |
224
+ |------|------|--------|
225
+ | `-i, --input <file>` | 输入 JSON 文件路径 | - |
226
+ | `-o, --output <file>` | 输出 TS 文件路径 | stdout |
227
+ | `-n, --name <name>` | 根类型名称 | `Root` |
228
+ | `-s, --style <style>` | 输出风格: `interface` \| `type` | `interface` |
229
+ | `--naming-style <s>` | 命名风格: `PascalCase` \| `camelCase` | `PascalCase` |
230
+ | `--sort <order>` | 属性排序: `alpha` \| `definition` | `alpha` |
231
+ | `--no-export` | 不添加 export 关键字 | - |
232
+ | `--comments` | 生成 JSDoc 注释 | - |
233
+ | `--strict-null` | 严格空值模式 | - |
234
+ | `--no-optional` | 不标记可选属性 | - |
235
+ | `--no-enums` | 不提取枚举类型 | - |
236
+ | `--enum-threshold <n>` | 枚举提取阈值 | `5` |
237
+ | `--no-generics` | 不提取泛型类型 | - |
238
+ | `--indent <n>` | 缩进空格数 | `2` |
239
+ | `--prefix <prefix>` | 类型名前缀 | - |
240
+ | `--suffix <suffix>` | 类型名后缀 | - |
241
+ | `-h, --help` | 显示帮助 | - |
242
+ | `-v, --version` | 显示版本号 | - |
243
+
244
+ ---
245
+
246
+ ## ⚙️ 配置选项
247
+
248
+ ### GenerateOptions 完整配置
249
+
250
+ ```typescript
251
+ interface GenerateOptions {
252
+ /** 根类型名称,默认 'Root' */
253
+ rootName?: string;
254
+
255
+ /** 输出风格:interface 或 type,默认 'interface' */
256
+ outputStyle?: 'interface' | 'type';
257
+
258
+ /** 命名风格:PascalCase 或 camelCase,默认 'PascalCase' */
259
+ namingStyle?: 'PascalCase' | 'camelCase';
260
+
261
+ /** 属性排序方式,默认 'alpha' */
262
+ sortProperties?: 'alpha' | 'definition';
263
+
264
+ /** 是否添加 export 语句,默认 true */
265
+ addExport?: boolean;
266
+
267
+ /** 是否生成 JSDoc 注释,默认 false */
268
+ addComments?: boolean;
269
+
270
+ /** 是否严格空值,默认 false */
271
+ strictNullChecks?: boolean;
272
+
273
+ /** 是否标记可选属性,默认 true */
274
+ markOptional?: boolean;
275
+
276
+ /** 是否提取枚举类型,默认 true */
277
+ extractEnums?: boolean;
278
+
279
+ /** 枚举提取阈值,默认 5 */
280
+ enumThreshold?: number;
281
+
282
+ /** 是否提取泛型,默认 true */
283
+ extractGenerics?: boolean;
284
+
285
+ /** 缩进空格数,默认 2 */
286
+ indentSize?: number;
287
+
288
+ /** 自定义类型名映射 */
289
+ typeNameMap?: Record<string, string>;
290
+
291
+ /** 类型名前缀 */
292
+ typePrefix?: string;
293
+
294
+ /** 类型名后缀 */
295
+ typeSuffix?: string;
296
+ }
297
+ ```
298
+
299
+ ### 配置示例
300
+
301
+ #### 企业级 DTO 配置
302
+
303
+ ```typescript
304
+ import { generate } from 'type-gen';
305
+
306
+ const result = generate(jsonData, {
307
+ rootName: 'UserDTO',
308
+ outputStyle: 'interface',
309
+ namingStyle: 'PascalCase',
310
+ typePrefix: 'I',
311
+ typeSuffix: 'DTO',
312
+ addExport: true,
313
+ addComments: true,
314
+ sortProperties: 'alpha',
315
+ extractEnums: true,
316
+ enumThreshold: 8,
317
+ extractGenerics: true,
318
+ strictNullChecks: true,
319
+ indentSize: 2,
320
+ });
321
+ ```
322
+
323
+ #### 自定义类型名映射
324
+
325
+ ```typescript
326
+ const result = generate(jsonData, {
327
+ rootName: 'ApiResponse',
328
+ typeNameMap: {
329
+ 'ApiResponse.data': 'ResponseData',
330
+ 'ResponseData.list': 'UserItem',
331
+ },
332
+ });
333
+ ```
334
+
335
+ ---
336
+
337
+ ## 🆚 对比优势
338
+
339
+ ### 与其他方案对比
340
+
341
+ | 特性 | type-gen | json-schema-to-typescript | 在线转换工具 | quicktype |
342
+ |------|--------|---------------------------|--------------|-----------|
343
+ | **直接输入 JSON** | ✅ | ❌ 需要 JSON Schema | ✅ | ✅ |
344
+ | **嵌套对象自动命名** | ✅ 智能命名 | ✅ | ⚠️ 简单命名 | ✅ |
345
+ | **联合类型推断** | ✅ | ⚠️ 有限支持 | ❌ | ✅ |
346
+ | **可选属性识别** | ✅ | ✅ | ❌ | ✅ |
347
+ | **枚举自动提取** | ✅ | ⚠️ 需手动定义 | ❌ | ✅ |
348
+ | **泛型模式识别** | ✅ | ❌ | ❌ | ❌ |
349
+ | **结构等价去重** | ✅ | ⚠️ 有限 | ❌ | ✅ |
350
+ | **循环引用处理** | ✅ | ✅ | ❌ | ✅ |
351
+ | **JSDoc 注释生成** | ✅ | ✅ | ❌ | ✅ |
352
+ | **CLI 命令行** | ✅ | ✅ | ❌ | ✅ |
353
+ | **编程式 API** | ✅ | ✅ | ❌ | ✅ |
354
+ | **零依赖** | ✅ | ❌ 依赖多 | - | ❌ 包体大 |
355
+ | **体积大小** | ~10KB | ~100KB | - | ~500KB |
356
+
357
+ **如果觉得好用,别忘了给个 ⭐ Star 支持一下!**
358
+
@@ -0,0 +1,302 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * type-gen CLI - 命令行工具
4
+ *
5
+ * 用法:
6
+ * type-gen <input.json> [options]
7
+ * type-gen -i input.json -o output.ts
8
+ * cat data.json | type-gen
9
+ *
10
+ * 示例:
11
+ * type-gen user.json -n User
12
+ * type-gen api.json --style type --no-export
13
+ * curl https://api.example.com/users | type-gen -n UserList
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ // 解析命令行参数
22
+ function parseArgs(argv) {
23
+ const args = {
24
+ input: null,
25
+ output: null,
26
+ rootName: 'Root',
27
+ outputStyle: 'interface',
28
+ namingStyle: 'PascalCase',
29
+ sortProperties: 'alpha',
30
+ addExport: true,
31
+ addComments: false,
32
+ strictNullChecks: false,
33
+ markOptional: true,
34
+ extractEnums: true,
35
+ enumThreshold: 5,
36
+ extractGenerics: true,
37
+ indentSize: 2,
38
+ typePrefix: '',
39
+ typeSuffix: '',
40
+ help: false,
41
+ version: false,
42
+ };
43
+
44
+ let i = 2; // 跳过 node 和脚本路径
45
+ while (i < argv.length) {
46
+ const arg = argv[i];
47
+
48
+ switch (arg) {
49
+ case '-h':
50
+ case '--help':
51
+ args.help = true;
52
+ break;
53
+
54
+ case '-v':
55
+ case '--version':
56
+ args.version = true;
57
+ break;
58
+
59
+ case '-i':
60
+ case '--input':
61
+ args.input = argv[++i];
62
+ break;
63
+
64
+ case '-o':
65
+ case '--output':
66
+ args.output = argv[++i];
67
+ break;
68
+
69
+ case '-n':
70
+ case '--name':
71
+ case '--root-name':
72
+ args.rootName = argv[++i];
73
+ break;
74
+
75
+ case '-s':
76
+ case '--style':
77
+ args.outputStyle = argv[++i];
78
+ break;
79
+
80
+ case '--naming-style':
81
+ args.namingStyle = argv[++i];
82
+ break;
83
+
84
+ case '--sort':
85
+ args.sortProperties = argv[++i];
86
+ break;
87
+
88
+ case '--no-export':
89
+ args.addExport = false;
90
+ break;
91
+
92
+ case '--comments':
93
+ args.addComments = true;
94
+ break;
95
+
96
+ case '--strict-null':
97
+ args.strictNullChecks = true;
98
+ break;
99
+
100
+ case '--no-optional':
101
+ args.markOptional = false;
102
+ break;
103
+
104
+ case '--no-enums':
105
+ args.extractEnums = false;
106
+ break;
107
+
108
+ case '--enum-threshold':
109
+ args.enumThreshold = parseInt(argv[++i], 10);
110
+ break;
111
+
112
+ case '--no-generics':
113
+ args.extractGenerics = false;
114
+ break;
115
+
116
+ case '--indent':
117
+ args.indentSize = parseInt(argv[++i], 10);
118
+ break;
119
+
120
+ case '--prefix':
121
+ args.typePrefix = argv[++i];
122
+ break;
123
+
124
+ case '--suffix':
125
+ args.typeSuffix = argv[++i];
126
+ break;
127
+
128
+ default:
129
+ // 第一个非选项参数作为输入文件
130
+ if (!args.input && !arg.startsWith('-')) {
131
+ args.input = arg;
132
+ }
133
+ break;
134
+ }
135
+
136
+ i++;
137
+ }
138
+
139
+ return args;
140
+ }
141
+
142
+ // 显示帮助信息
143
+ function showHelp() {
144
+ console.log(`
145
+ type-gen - JSON 智能生成 TypeScript 类型定义
146
+
147
+ 用法:
148
+ type-gen <input.json> [options]
149
+ type-gen -i input.json -o output.ts
150
+ cat data.json | type-gen
151
+
152
+ 选项:
153
+ -i, --input <file> 输入 JSON 文件路径
154
+ -o, --output <file> 输出 TypeScript 文件路径(默认输出到 stdout)
155
+ -n, --name <name> 根类型名称(默认: Root)
156
+ -s, --style <style> 输出风格: interface | type(默认: interface)
157
+ --naming-style <s> 命名风格: PascalCase | camelCase(默认: PascalCase)
158
+ --sort <order> 属性排序: alpha | definition(默认: alpha)
159
+ --no-export 不添加 export 关键字
160
+ --comments 生成 JSDoc 注释
161
+ --strict-null 严格空值模式(保留 null 类型)
162
+ --no-optional 不标记可选属性
163
+ --no-enums 不提取枚举类型
164
+ --enum-threshold <n> 枚举提取阈值(默认: 5)
165
+ --no-generics 不提取泛型类型
166
+ --indent <n> 缩进空格数(默认: 2)
167
+ --prefix <prefix> 类型名前缀
168
+ --suffix <suffix> 类型名后缀
169
+ -h, --help 显示帮助信息
170
+ -v, --version 显示版本号
171
+
172
+ 示例:
173
+ # 从文件生成
174
+ type-gen user.json -n User -o user.ts
175
+
176
+ # 使用 type 风格输出
177
+ type-gen data.json --style type
178
+
179
+ # 从标准输入读取
180
+ curl https://api.example.com/data | type-gen -n ApiResponse
181
+
182
+ # 带前缀和注释
183
+ type-gen api.json --prefix Api --comments -o api-types.ts
184
+ `);
185
+ }
186
+
187
+ // 显示版本号
188
+ function showVersion() {
189
+ try {
190
+ const pkgPath = path.join(__dirname, '..', 'package.json');
191
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
192
+ console.log(`type-gen v${pkg.version}`);
193
+ } catch (e) {
194
+ console.log('type-gen (unknown version)');
195
+ }
196
+ }
197
+
198
+ // 读取输入
199
+ async function readInput(inputPath) {
200
+ if (inputPath) {
201
+ // 从文件读取
202
+ const fullPath = path.resolve(inputPath);
203
+ if (!fs.existsSync(fullPath)) {
204
+ console.error(`错误: 文件不存在: ${fullPath}`);
205
+ process.exit(1);
206
+ }
207
+ return fs.readFileSync(fullPath, 'utf-8');
208
+ }
209
+
210
+ // 从标准输入读取
211
+ return new Promise((resolve, reject) => {
212
+ let data = '';
213
+ process.stdin.setEncoding('utf-8');
214
+
215
+ process.stdin.on('data', chunk => {
216
+ data += chunk;
217
+ });
218
+
219
+ process.stdin.on('end', () => {
220
+ resolve(data);
221
+ });
222
+
223
+ process.stdin.on('error', reject);
224
+
225
+ // 检查是否有输入
226
+ setTimeout(() => {
227
+ if (!data) {
228
+ console.error('错误: 未提供输入数据。请指定输入文件或通过管道传入 JSON。');
229
+ console.error('使用 --help 查看帮助信息。');
230
+ process.exit(1);
231
+ }
232
+ }, 100);
233
+ });
234
+ }
235
+
236
+ // 主函数
237
+ async function main() {
238
+ const args = parseArgs(process.argv);
239
+
240
+ if (args.help) {
241
+ showHelp();
242
+ return;
243
+ }
244
+
245
+ if (args.version) {
246
+ showVersion();
247
+ return;
248
+ }
249
+
250
+ try {
251
+ // 读取输入
252
+ const jsonStr = await readInput(args.input);
253
+
254
+ // 解析 JSON
255
+ let jsonData;
256
+ try {
257
+ jsonData = JSON.parse(jsonStr);
258
+ } catch (e) {
259
+ console.error(`错误: JSON 解析失败 - ${e.message}`);
260
+ process.exit(1);
261
+ }
262
+
263
+ // 动态导入生成函数
264
+ const { generate } = require('../dist/index.js');
265
+
266
+ // 生成类型
267
+ const result = generate(jsonData, {
268
+ rootName: args.rootName,
269
+ outputStyle: args.outputStyle,
270
+ namingStyle: args.namingStyle,
271
+ sortProperties: args.sortProperties,
272
+ addExport: args.addExport,
273
+ addComments: args.addComments,
274
+ strictNullChecks: args.strictNullChecks,
275
+ markOptional: args.markOptional,
276
+ extractEnums: args.extractEnums,
277
+ enumThreshold: args.enumThreshold,
278
+ extractGenerics: args.extractGenerics,
279
+ indentSize: args.indentSize,
280
+ typePrefix: args.typePrefix,
281
+ typeSuffix: args.typeSuffix,
282
+ });
283
+
284
+ // 输出结果
285
+ if (args.output) {
286
+ const outputPath = path.resolve(args.output);
287
+ fs.writeFileSync(outputPath, result.code, 'utf-8');
288
+ console.log(`✓ 已生成: ${outputPath}`);
289
+ console.log(` 共生成 ${result.types.length} 个类型定义`);
290
+ } else {
291
+ console.log(result.code);
292
+ }
293
+ } catch (e) {
294
+ console.error(`错误: ${e.message}`);
295
+ if (process.env.DEBUG) {
296
+ console.error(e.stack);
297
+ }
298
+ process.exit(1);
299
+ }
300
+ }
301
+
302
+ main();