type-flash 1.1.3 → 1.1.4
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/bin/type-flash.js +130 -146
- package/package.json +1 -1
package/bin/type-flash.js
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
|
-
* type-flash CLI
|
|
4
|
+
* type-flash - CLI 命令行工具
|
|
4
5
|
*
|
|
5
6
|
* 用法:
|
|
6
|
-
* type-flash <input.json> [options]
|
|
7
7
|
* type-flash -i input.json -o output.ts
|
|
8
|
-
* cat data.json | type-flash
|
|
9
|
-
*
|
|
10
|
-
* 示例:
|
|
11
|
-
* type-flash user.json -n User
|
|
12
|
-
* type-flash api.json --style type --no-export
|
|
13
|
-
* curl https://api.example.com/users | type-flash -n UserList
|
|
8
|
+
* cat data.json | type-flash -n User
|
|
14
9
|
*/
|
|
15
10
|
|
|
16
|
-
'use strict';
|
|
17
|
-
|
|
18
11
|
const fs = require('fs');
|
|
19
12
|
const path = require('path');
|
|
20
13
|
|
|
21
14
|
// 解析命令行参数
|
|
22
|
-
function parseArgs(
|
|
23
|
-
const args =
|
|
15
|
+
function parseArgs() {
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const options = {
|
|
24
18
|
input: null,
|
|
25
19
|
output: null,
|
|
26
20
|
rootName: 'Root',
|
|
@@ -34,182 +28,139 @@ function parseArgs(argv) {
|
|
|
34
28
|
indentSize: 2,
|
|
35
29
|
typePrefix: '',
|
|
36
30
|
typeSuffix: '',
|
|
31
|
+
typeNameMap: {},
|
|
37
32
|
help: false,
|
|
38
33
|
version: false,
|
|
39
34
|
};
|
|
40
35
|
|
|
41
|
-
let i =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
const arg = args[i];
|
|
38
|
+
|
|
45
39
|
switch (arg) {
|
|
46
|
-
case '-h':
|
|
47
|
-
case '--help':
|
|
48
|
-
args.help = true;
|
|
49
|
-
break;
|
|
50
|
-
|
|
51
|
-
case '-v':
|
|
52
|
-
case '--version':
|
|
53
|
-
args.version = true;
|
|
54
|
-
break;
|
|
55
|
-
|
|
56
40
|
case '-i':
|
|
57
41
|
case '--input':
|
|
58
|
-
|
|
42
|
+
options.input = args[++i];
|
|
59
43
|
break;
|
|
60
|
-
|
|
61
44
|
case '-o':
|
|
62
45
|
case '--output':
|
|
63
|
-
|
|
46
|
+
options.output = args[++i];
|
|
64
47
|
break;
|
|
65
|
-
|
|
66
48
|
case '-n':
|
|
67
49
|
case '--name':
|
|
68
|
-
|
|
69
|
-
args.rootName = argv[++i];
|
|
50
|
+
options.rootName = args[++i];
|
|
70
51
|
break;
|
|
71
|
-
|
|
72
52
|
case '-s':
|
|
73
53
|
case '--style':
|
|
74
|
-
|
|
54
|
+
options.outputStyle = args[++i];
|
|
75
55
|
break;
|
|
76
|
-
|
|
77
56
|
case '--naming-style':
|
|
78
|
-
|
|
57
|
+
options.namingStyle = args[++i];
|
|
79
58
|
break;
|
|
80
|
-
|
|
81
59
|
case '--sort':
|
|
82
|
-
|
|
60
|
+
options.sortProperties = args[++i];
|
|
83
61
|
break;
|
|
84
|
-
|
|
85
62
|
case '--no-export':
|
|
86
|
-
|
|
63
|
+
options.addExport = false;
|
|
87
64
|
break;
|
|
88
|
-
|
|
89
65
|
case '--strict-null':
|
|
90
|
-
|
|
66
|
+
options.strictNullChecks = true;
|
|
91
67
|
break;
|
|
92
|
-
|
|
93
68
|
case '--no-optional':
|
|
94
|
-
|
|
69
|
+
options.markOptional = false;
|
|
95
70
|
break;
|
|
96
|
-
|
|
97
71
|
case '--no-generics':
|
|
98
|
-
|
|
72
|
+
options.extractGenerics = false;
|
|
99
73
|
break;
|
|
100
|
-
|
|
101
74
|
case '--indent':
|
|
102
|
-
|
|
75
|
+
options.indentSize = parseInt(args[++i], 10);
|
|
103
76
|
break;
|
|
104
|
-
|
|
105
77
|
case '--prefix':
|
|
106
|
-
|
|
78
|
+
options.typePrefix = args[++i];
|
|
107
79
|
break;
|
|
108
|
-
|
|
109
80
|
case '--suffix':
|
|
110
|
-
|
|
81
|
+
options.typeSuffix = args[++i];
|
|
82
|
+
break;
|
|
83
|
+
case '-h':
|
|
84
|
+
case '--help':
|
|
85
|
+
options.help = true;
|
|
86
|
+
break;
|
|
87
|
+
case '-v':
|
|
88
|
+
case '--version':
|
|
89
|
+
options.version = true;
|
|
111
90
|
break;
|
|
112
|
-
|
|
113
91
|
default:
|
|
114
|
-
//
|
|
115
|
-
if (!args.input && !arg.startsWith('-')) {
|
|
116
|
-
args.input = arg;
|
|
117
|
-
}
|
|
92
|
+
// 未知参数,忽略
|
|
118
93
|
break;
|
|
119
94
|
}
|
|
120
|
-
|
|
121
|
-
i++;
|
|
122
95
|
}
|
|
123
96
|
|
|
124
|
-
return
|
|
97
|
+
return options;
|
|
125
98
|
}
|
|
126
99
|
|
|
127
|
-
//
|
|
100
|
+
// 显示帮助
|
|
128
101
|
function showHelp() {
|
|
129
102
|
console.log(`
|
|
130
103
|
type-flash - JSON 智能生成 TypeScript 类型定义
|
|
131
104
|
|
|
132
105
|
用法:
|
|
133
|
-
type-flash <
|
|
134
|
-
|
|
135
|
-
cat data.json | type-flash
|
|
106
|
+
type-flash -i <file> [选项]
|
|
107
|
+
cat data.json | type-flash [选项]
|
|
136
108
|
|
|
137
109
|
选项:
|
|
138
|
-
-i, --input <file>
|
|
139
|
-
-o, --output <file>
|
|
140
|
-
-n, --name <name>
|
|
141
|
-
-s, --style <style>
|
|
142
|
-
--naming-style <s>
|
|
143
|
-
--sort <order>
|
|
144
|
-
--no-export
|
|
145
|
-
--strict-null
|
|
146
|
-
--no-optional
|
|
147
|
-
--no-generics
|
|
148
|
-
--indent <n>
|
|
149
|
-
--prefix <prefix>
|
|
150
|
-
--suffix <suffix>
|
|
151
|
-
-
|
|
152
|
-
-
|
|
110
|
+
-i, --input <file> 输入 JSON 文件路径
|
|
111
|
+
-o, --output <file> 输出 TS 文件路径
|
|
112
|
+
-n, --name <name> 根类型名称 (默认: Root)
|
|
113
|
+
-s, --style <style> 输出风格: interface | type (默认: interface)
|
|
114
|
+
--naming-style <s> 命名风格: PascalCase | camelCase (默认: PascalCase)
|
|
115
|
+
--sort <order> 属性排序: alpha | definition (默认: alpha)
|
|
116
|
+
--no-export 不添加 export 语句
|
|
117
|
+
--strict-null 严格空值模式
|
|
118
|
+
--no-optional 不标记可选属性
|
|
119
|
+
--no-generics 不提取泛型
|
|
120
|
+
--indent <n> 缩进空格数 (默认: 2)
|
|
121
|
+
--prefix <prefix> 类型名前缀
|
|
122
|
+
--suffix <suffix> 类型名后缀
|
|
123
|
+
-v, --version 显示版本号
|
|
124
|
+
-h, --help 显示帮助
|
|
153
125
|
|
|
154
126
|
示例:
|
|
155
|
-
|
|
156
|
-
type-flash
|
|
157
|
-
|
|
158
|
-
# 使用 type 风格输出
|
|
159
|
-
type-flash data.json --style type
|
|
160
|
-
|
|
161
|
-
# 从标准输入读取
|
|
162
|
-
curl https://api.example.com/data | type-flash -n ApiResponse
|
|
163
|
-
|
|
164
|
-
# 带前缀
|
|
165
|
-
type-flash api.json --prefix Api -o api-types.ts
|
|
127
|
+
type-flash -i data.json -o types.ts
|
|
128
|
+
type-flash -i data.json -n User
|
|
129
|
+
cat data.json | type-flash -s type
|
|
166
130
|
`);
|
|
167
131
|
}
|
|
168
132
|
|
|
169
|
-
//
|
|
133
|
+
// 显示版本
|
|
170
134
|
function showVersion() {
|
|
171
135
|
try {
|
|
172
136
|
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
173
137
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
174
|
-
console.log(
|
|
138
|
+
console.log(pkg.version);
|
|
175
139
|
} catch (e) {
|
|
176
|
-
console.log('
|
|
140
|
+
console.log('unknown');
|
|
177
141
|
}
|
|
178
142
|
}
|
|
179
143
|
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
if (inputPath) {
|
|
183
|
-
// 从文件读取
|
|
184
|
-
const fullPath = path.resolve(inputPath);
|
|
185
|
-
if (!fs.existsSync(fullPath)) {
|
|
186
|
-
console.error(`错误: 文件不存在: ${fullPath}`);
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
return fs.readFileSync(fullPath, 'utf-8');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// 从标准输入读取
|
|
144
|
+
// 读取标准输入
|
|
145
|
+
function readStdin() {
|
|
193
146
|
return new Promise((resolve, reject) => {
|
|
194
147
|
let data = '';
|
|
195
148
|
process.stdin.setEncoding('utf-8');
|
|
196
|
-
|
|
149
|
+
|
|
197
150
|
process.stdin.on('data', chunk => {
|
|
198
151
|
data += chunk;
|
|
199
152
|
});
|
|
200
|
-
|
|
153
|
+
|
|
201
154
|
process.stdin.on('end', () => {
|
|
202
155
|
resolve(data);
|
|
203
156
|
});
|
|
204
|
-
|
|
157
|
+
|
|
205
158
|
process.stdin.on('error', reject);
|
|
206
|
-
|
|
207
|
-
//
|
|
159
|
+
|
|
160
|
+
// 如果没有输入,超时返回空
|
|
208
161
|
setTimeout(() => {
|
|
209
162
|
if (!data) {
|
|
210
|
-
|
|
211
|
-
console.error('使用 --help 查看帮助信息。');
|
|
212
|
-
process.exit(1);
|
|
163
|
+
resolve('');
|
|
213
164
|
}
|
|
214
165
|
}, 100);
|
|
215
166
|
});
|
|
@@ -217,65 +168,98 @@ async function readInput(inputPath) {
|
|
|
217
168
|
|
|
218
169
|
// 主函数
|
|
219
170
|
async function main() {
|
|
220
|
-
const
|
|
171
|
+
const options = parseArgs();
|
|
221
172
|
|
|
222
|
-
|
|
173
|
+
// 显示帮助
|
|
174
|
+
if (options.help) {
|
|
223
175
|
showHelp();
|
|
224
176
|
return;
|
|
225
177
|
}
|
|
226
178
|
|
|
227
|
-
|
|
179
|
+
// 显示版本
|
|
180
|
+
if (options.version) {
|
|
228
181
|
showVersion();
|
|
229
182
|
return;
|
|
230
183
|
}
|
|
231
184
|
|
|
232
185
|
try {
|
|
233
|
-
//
|
|
234
|
-
|
|
186
|
+
// 1. 获取 JSON 数据
|
|
187
|
+
let jsonString;
|
|
188
|
+
|
|
189
|
+
if (options.input) {
|
|
190
|
+
// 从文件读取
|
|
191
|
+
const inputPath = path.resolve(options.input);
|
|
192
|
+
if (!fs.existsSync(inputPath)) {
|
|
193
|
+
console.error(`错误: 文件不存在 - ${options.input}`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
jsonString = fs.readFileSync(inputPath, 'utf-8');
|
|
197
|
+
} else {
|
|
198
|
+
// 从标准输入读取
|
|
199
|
+
jsonString = await readStdin();
|
|
200
|
+
if (!jsonString.trim()) {
|
|
201
|
+
console.error('错误: 未提供输入数据。使用 -i 指定文件或通过管道输入');
|
|
202
|
+
console.error('使用 type-flash --help 查看帮助');
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
235
206
|
|
|
236
|
-
// 解析 JSON
|
|
207
|
+
// 2. 解析 JSON
|
|
237
208
|
let jsonData;
|
|
238
209
|
try {
|
|
239
|
-
jsonData = JSON.parse(
|
|
210
|
+
jsonData = JSON.parse(jsonString);
|
|
240
211
|
} catch (e) {
|
|
241
212
|
console.error(`错误: JSON 解析失败 - ${e.message}`);
|
|
242
213
|
process.exit(1);
|
|
243
214
|
}
|
|
244
215
|
|
|
245
|
-
//
|
|
246
|
-
|
|
216
|
+
// 3. 生成类型
|
|
217
|
+
// 动态导入生成的模块
|
|
218
|
+
const distPath = path.join(__dirname, '..', 'dist', 'index.js');
|
|
219
|
+
let generate;
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
const mod = require(distPath);
|
|
223
|
+
generate = mod.generate || mod.default?.generate;
|
|
224
|
+
} catch (e) {
|
|
225
|
+
console.error(`错误: 加载模块失败 - ${e.message}`);
|
|
226
|
+
console.error('请先运行 npm run build 构建项目');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (!generate) {
|
|
231
|
+
console.error('错误: 未找到 generate 函数');
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
247
234
|
|
|
248
|
-
//
|
|
235
|
+
// 生成类型(generate 直接返回字符串)
|
|
249
236
|
const result = generate(jsonData, {
|
|
250
|
-
rootName:
|
|
251
|
-
outputStyle:
|
|
252
|
-
namingStyle:
|
|
253
|
-
sortProperties:
|
|
254
|
-
addExport:
|
|
255
|
-
strictNullChecks:
|
|
256
|
-
markOptional:
|
|
257
|
-
extractGenerics:
|
|
258
|
-
indentSize:
|
|
259
|
-
typePrefix:
|
|
260
|
-
typeSuffix:
|
|
237
|
+
rootName: options.rootName,
|
|
238
|
+
outputStyle: options.outputStyle,
|
|
239
|
+
namingStyle: options.namingStyle,
|
|
240
|
+
sortProperties: options.sortProperties,
|
|
241
|
+
addExport: options.addExport,
|
|
242
|
+
strictNullChecks: options.strictNullChecks,
|
|
243
|
+
markOptional: options.markOptional,
|
|
244
|
+
extractGenerics: options.extractGenerics,
|
|
245
|
+
indentSize: options.indentSize,
|
|
246
|
+
typePrefix: options.typePrefix,
|
|
247
|
+
typeSuffix: options.typeSuffix,
|
|
261
248
|
});
|
|
262
249
|
|
|
263
|
-
// 输出结果
|
|
264
|
-
if (
|
|
265
|
-
const outputPath = path.resolve(
|
|
266
|
-
fs.writeFileSync(outputPath, result
|
|
267
|
-
console.log(
|
|
268
|
-
console.log(` 共生成 ${result.types.length} 个类型定义`);
|
|
250
|
+
// 4. 输出结果
|
|
251
|
+
if (options.output) {
|
|
252
|
+
const outputPath = path.resolve(options.output);
|
|
253
|
+
fs.writeFileSync(outputPath, result, 'utf-8');
|
|
254
|
+
console.log(`✅ 已生成: ${options.output}`);
|
|
269
255
|
} else {
|
|
270
|
-
console.log(result
|
|
256
|
+
console.log(result);
|
|
271
257
|
}
|
|
258
|
+
|
|
272
259
|
} catch (e) {
|
|
273
260
|
console.error(`错误: ${e.message}`);
|
|
274
|
-
if (process.env.DEBUG) {
|
|
275
|
-
console.error(e.stack);
|
|
276
|
-
}
|
|
277
261
|
process.exit(1);
|
|
278
262
|
}
|
|
279
263
|
}
|
|
280
264
|
|
|
281
|
-
main();
|
|
265
|
+
main();
|