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 +21 -0
- package/README.md +358 -0
- package/bin/type-gen.js +302 -0
- package/dist/index.d.mts +626 -0
- package/dist/index.d.ts +626 -0
- package/dist/index.js +6 -0
- package/dist/index.mjs +6 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 类型定义
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 原始类型
|
|
6
|
+
*/
|
|
7
|
+
interface PrimitiveType {
|
|
8
|
+
kind: 'primitive';
|
|
9
|
+
type: 'string' | 'number' | 'boolean' | 'any' | 'unknown' | 'never';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 数组类型
|
|
13
|
+
*/
|
|
14
|
+
interface ArrayType {
|
|
15
|
+
kind: 'array';
|
|
16
|
+
elementType: TSTypeNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 对象类型(接口)
|
|
20
|
+
*/
|
|
21
|
+
interface ObjectType {
|
|
22
|
+
kind: 'object';
|
|
23
|
+
properties: PropertyDef[];
|
|
24
|
+
/** 是否为字典类型(索引签名) */
|
|
25
|
+
isRecord?: boolean;
|
|
26
|
+
/** 字典值类型 */
|
|
27
|
+
valueType?: TSTypeNode;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 属性定义
|
|
31
|
+
*/
|
|
32
|
+
interface PropertyDef {
|
|
33
|
+
name: string;
|
|
34
|
+
type: TSTypeNode;
|
|
35
|
+
/** 是否可选 */
|
|
36
|
+
optional: boolean;
|
|
37
|
+
/** JSDoc 注释 */
|
|
38
|
+
comment?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 联合类型
|
|
42
|
+
*/
|
|
43
|
+
interface UnionType {
|
|
44
|
+
kind: 'union';
|
|
45
|
+
types: TSTypeNode[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 字面量类型
|
|
49
|
+
*/
|
|
50
|
+
interface LiteralType {
|
|
51
|
+
kind: 'literal';
|
|
52
|
+
value: string | number | boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 枚举类型
|
|
56
|
+
*/
|
|
57
|
+
interface EnumType {
|
|
58
|
+
kind: 'enum';
|
|
59
|
+
name: string;
|
|
60
|
+
values: (string | number)[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* null 类型
|
|
64
|
+
*/
|
|
65
|
+
interface NullType {
|
|
66
|
+
kind: 'null';
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* undefined 类型
|
|
70
|
+
*/
|
|
71
|
+
interface UndefinedType {
|
|
72
|
+
kind: 'undefined';
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 泛型类型
|
|
76
|
+
*/
|
|
77
|
+
interface GenericType {
|
|
78
|
+
kind: 'generic';
|
|
79
|
+
name: string;
|
|
80
|
+
typeArgs: TSTypeNode[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* TS 类型节点(联合类型,支持 discriminated union 类型收窄)
|
|
84
|
+
*/
|
|
85
|
+
type TSTypeNode = PrimitiveType | ArrayType | ObjectType | UnionType | LiteralType | EnumType | NullType | UndefinedType | GenericType;
|
|
86
|
+
/**
|
|
87
|
+
* 命名风格
|
|
88
|
+
*/
|
|
89
|
+
type NamingStyle = 'PascalCase' | 'camelCase';
|
|
90
|
+
/**
|
|
91
|
+
* 输出风格
|
|
92
|
+
*/
|
|
93
|
+
type OutputStyle = 'interface' | 'type';
|
|
94
|
+
/**
|
|
95
|
+
* 排序方式
|
|
96
|
+
*/
|
|
97
|
+
type SortOrder = 'alpha' | 'definition';
|
|
98
|
+
/**
|
|
99
|
+
* 生成配置选项
|
|
100
|
+
*/
|
|
101
|
+
interface GenerateOptions {
|
|
102
|
+
/** 根类型名称,默认 'Root' */
|
|
103
|
+
rootName?: string;
|
|
104
|
+
/** 输出风格:interface 或 type,默认 'interface' */
|
|
105
|
+
outputStyle?: OutputStyle;
|
|
106
|
+
/** 命名风格:PascalCase 或 camelCase,默认 'PascalCase' */
|
|
107
|
+
namingStyle?: NamingStyle;
|
|
108
|
+
/** 属性排序方式,默认 'alpha' */
|
|
109
|
+
sortProperties?: SortOrder;
|
|
110
|
+
/** 是否添加 export 语句,默认 true */
|
|
111
|
+
addExport?: boolean;
|
|
112
|
+
/** 是否生成 JSDoc 注释,默认 false */
|
|
113
|
+
addComments?: boolean;
|
|
114
|
+
/** 是否严格空值(null 单独类型),默认 false */
|
|
115
|
+
strictNullChecks?: boolean;
|
|
116
|
+
/** 是否将可选属性标记为 ?,默认 true */
|
|
117
|
+
markOptional?: boolean;
|
|
118
|
+
/** 是否提取枚举类型,默认 true */
|
|
119
|
+
extractEnums?: boolean;
|
|
120
|
+
/** 枚举提取阈值(字段不同值数量 ≤ 此值时提取为枚举),默认 5 */
|
|
121
|
+
enumThreshold?: number;
|
|
122
|
+
/** 是否提取泛型(如 PageResult<T>),默认 true */
|
|
123
|
+
extractGenerics?: boolean;
|
|
124
|
+
/** 缩进空格数,默认 2 */
|
|
125
|
+
indentSize?: number;
|
|
126
|
+
/** 行尾换行符,默认 '\n' */
|
|
127
|
+
lineEnding?: string;
|
|
128
|
+
/** 自定义类型名映射 { 字段路径: 类型名 } */
|
|
129
|
+
typeNameMap?: Record<string, string>;
|
|
130
|
+
/** 前缀,所有生成的类型名添加此前缀 */
|
|
131
|
+
typePrefix?: string;
|
|
132
|
+
/** 后缀,所有生成的类型名添加此后缀 */
|
|
133
|
+
typeSuffix?: string;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 已命名的类型定义
|
|
137
|
+
*/
|
|
138
|
+
interface NamedTypeDef {
|
|
139
|
+
name: string;
|
|
140
|
+
type: TSTypeNode;
|
|
141
|
+
comment?: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* 生成结果
|
|
145
|
+
*/
|
|
146
|
+
interface GenerateResult {
|
|
147
|
+
/** 生成的 TypeScript 代码字符串 */
|
|
148
|
+
code: string;
|
|
149
|
+
/** 生成的类型定义列表 */
|
|
150
|
+
types: NamedTypeDef[];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* ts-gen - 命名与去重模块
|
|
155
|
+
*
|
|
156
|
+
* 核心功能:
|
|
157
|
+
* - 根据字段名 + 上下文自动生成有意义的类型名
|
|
158
|
+
* - 结构等价性判断与类型去重
|
|
159
|
+
* - 循环引用检测与处理
|
|
160
|
+
* - 命名风格转换(PascalCase / camelCase)
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 命名上下文
|
|
165
|
+
*/
|
|
166
|
+
interface NamingContext {
|
|
167
|
+
/** 当前字段名 */
|
|
168
|
+
fieldName?: string;
|
|
169
|
+
/** 父级类型名 */
|
|
170
|
+
parentName?: string;
|
|
171
|
+
/** 深度 */
|
|
172
|
+
depth: number;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 类型命名器
|
|
176
|
+
*/
|
|
177
|
+
declare class TypeNamer {
|
|
178
|
+
/** 已命名的类型映射(结构 key -> 类型名) */
|
|
179
|
+
private namedTypes;
|
|
180
|
+
/** 类型名计数器(用于重名时加序号) */
|
|
181
|
+
private nameCounter;
|
|
182
|
+
/** 命名风格 */
|
|
183
|
+
private namingStyle;
|
|
184
|
+
/** 类型名前缀 */
|
|
185
|
+
private prefix;
|
|
186
|
+
/** 类型名后缀 */
|
|
187
|
+
private suffix;
|
|
188
|
+
/** 自定义类型名映射 */
|
|
189
|
+
private customNameMap;
|
|
190
|
+
/** 正在处理的对象(用于循环引用检测) */
|
|
191
|
+
private processing;
|
|
192
|
+
/** 循环引用类型名映射 */
|
|
193
|
+
private circularRefs;
|
|
194
|
+
constructor(options?: {
|
|
195
|
+
namingStyle?: NamingStyle;
|
|
196
|
+
prefix?: string;
|
|
197
|
+
suffix?: string;
|
|
198
|
+
customNameMap?: Record<string, string>;
|
|
199
|
+
});
|
|
200
|
+
/**
|
|
201
|
+
* 为类型生成名称
|
|
202
|
+
* @param type 类型节点
|
|
203
|
+
* @param context 命名上下文
|
|
204
|
+
* @returns 类型名,如果是内联类型则返回 null
|
|
205
|
+
*/
|
|
206
|
+
nameType(type: TSTypeNode, context?: NamingContext): string | null;
|
|
207
|
+
/**
|
|
208
|
+
* 生成类型名
|
|
209
|
+
*/
|
|
210
|
+
private generateName;
|
|
211
|
+
/**
|
|
212
|
+
* 确保名称唯一
|
|
213
|
+
*/
|
|
214
|
+
private ensureUniqueName;
|
|
215
|
+
/**
|
|
216
|
+
* 应用前后缀
|
|
217
|
+
*/
|
|
218
|
+
private applyAffixes;
|
|
219
|
+
/**
|
|
220
|
+
* 构建路径 key(用于自定义名称映射)
|
|
221
|
+
*/
|
|
222
|
+
private buildPathKey;
|
|
223
|
+
/**
|
|
224
|
+
* 获取类型的结构 key
|
|
225
|
+
*/
|
|
226
|
+
private getTypeKey;
|
|
227
|
+
/**
|
|
228
|
+
* 获取简单类型 key(用于属性比较)
|
|
229
|
+
*/
|
|
230
|
+
private getSimpleTypeKey;
|
|
231
|
+
/**
|
|
232
|
+
* 转换为 PascalCase
|
|
233
|
+
*/
|
|
234
|
+
toPascalCase(str: string): string;
|
|
235
|
+
/**
|
|
236
|
+
* 转换为 camelCase
|
|
237
|
+
*/
|
|
238
|
+
toCamelCase(str: string): string;
|
|
239
|
+
/**
|
|
240
|
+
* 根据命名风格转换
|
|
241
|
+
*/
|
|
242
|
+
formatName(name: string): string;
|
|
243
|
+
/**
|
|
244
|
+
* 检查是否为循环引用
|
|
245
|
+
*/
|
|
246
|
+
isCircular(obj: object): boolean;
|
|
247
|
+
/**
|
|
248
|
+
* 标记对象为正在处理
|
|
249
|
+
*/
|
|
250
|
+
markProcessing(obj: object): void;
|
|
251
|
+
/**
|
|
252
|
+
* 取消标记
|
|
253
|
+
*/
|
|
254
|
+
unmarkProcessing(obj: object): void;
|
|
255
|
+
/**
|
|
256
|
+
* 获取所有已命名的类型
|
|
257
|
+
*/
|
|
258
|
+
getAllNamedTypes(): Map<string, string>;
|
|
259
|
+
/**
|
|
260
|
+
* 重置命名器
|
|
261
|
+
*/
|
|
262
|
+
reset(): void;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 类型去重与收集器
|
|
266
|
+
* 遍历类型树,收集所有需要单独定义的命名类型
|
|
267
|
+
*/
|
|
268
|
+
declare class TypeCollector {
|
|
269
|
+
private namer;
|
|
270
|
+
private collected;
|
|
271
|
+
private seenStructs;
|
|
272
|
+
constructor(namer: TypeNamer);
|
|
273
|
+
/**
|
|
274
|
+
* 收集类型树中的所有命名类型
|
|
275
|
+
* @param rootType 根类型
|
|
276
|
+
* @param rootName 根类型名
|
|
277
|
+
* @returns 类型定义列表(根类型在最前)
|
|
278
|
+
*/
|
|
279
|
+
collect(rootType: TSTypeNode, rootName: string): NamedTypeDef[];
|
|
280
|
+
/**
|
|
281
|
+
* 递归收集
|
|
282
|
+
*/
|
|
283
|
+
private collectRecursive;
|
|
284
|
+
/**
|
|
285
|
+
* 获取结构 key(用于去重)
|
|
286
|
+
*/
|
|
287
|
+
private getStructKey;
|
|
288
|
+
/**
|
|
289
|
+
* 获取属性类型的简化 key
|
|
290
|
+
*/
|
|
291
|
+
private getPropTypeKey;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* ts-gen - 格式化输出模块
|
|
296
|
+
*
|
|
297
|
+
* 核心功能:
|
|
298
|
+
* - 将类型节点转换为 TypeScript 代码字符串
|
|
299
|
+
* - 支持 interface 和 type alias 两种输出风格
|
|
300
|
+
* - 自动缩进、排序
|
|
301
|
+
* - 支持导出语句
|
|
302
|
+
* - 支持 JSDoc 注释生成
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 代码格式化器
|
|
307
|
+
*/
|
|
308
|
+
declare class CodeFormatter {
|
|
309
|
+
private options;
|
|
310
|
+
private namer;
|
|
311
|
+
constructor(options: Required<GenerateOptions>, namer: TypeNamer);
|
|
312
|
+
/**
|
|
313
|
+
* 格式化单个类型定义为代码
|
|
314
|
+
*/
|
|
315
|
+
formatTypeDef(typeDef: NamedTypeDef): string;
|
|
316
|
+
/**
|
|
317
|
+
* 格式化对象类型
|
|
318
|
+
*/
|
|
319
|
+
private formatObjectType;
|
|
320
|
+
/**
|
|
321
|
+
* 格式化枚举类型
|
|
322
|
+
*/
|
|
323
|
+
private formatEnumType;
|
|
324
|
+
/**
|
|
325
|
+
* 格式化类型节点为字符串
|
|
326
|
+
*/
|
|
327
|
+
formatType(type: TSTypeNode): string;
|
|
328
|
+
/**
|
|
329
|
+
* 格式化字面量
|
|
330
|
+
*/
|
|
331
|
+
private formatLiteral;
|
|
332
|
+
/**
|
|
333
|
+
* 格式化数组类型
|
|
334
|
+
*/
|
|
335
|
+
private formatArrayType;
|
|
336
|
+
/**
|
|
337
|
+
* 格式化内联对象类型
|
|
338
|
+
*/
|
|
339
|
+
private formatInlineObject;
|
|
340
|
+
/**
|
|
341
|
+
* 格式化联合类型
|
|
342
|
+
*/
|
|
343
|
+
private formatUnionType;
|
|
344
|
+
/**
|
|
345
|
+
* 格式化属性名
|
|
346
|
+
* 处理非法标识符的情况(用引号包裹)
|
|
347
|
+
*/
|
|
348
|
+
private formatPropertyName;
|
|
349
|
+
/**
|
|
350
|
+
* 排序属性
|
|
351
|
+
*/
|
|
352
|
+
private sortProperties;
|
|
353
|
+
/**
|
|
354
|
+
* 格式化 JSDoc 注释(多行)
|
|
355
|
+
*/
|
|
356
|
+
private formatJSDoc;
|
|
357
|
+
/**
|
|
358
|
+
* 格式化内联 JSDoc 注释(单行)
|
|
359
|
+
*/
|
|
360
|
+
private formatInlineJSDoc;
|
|
361
|
+
/**
|
|
362
|
+
* 转换为枚举键名
|
|
363
|
+
*/
|
|
364
|
+
private toEnumKey;
|
|
365
|
+
/**
|
|
366
|
+
* 格式化所有类型定义
|
|
367
|
+
*/
|
|
368
|
+
formatAll(typeDefs: NamedTypeDef[]): string;
|
|
369
|
+
/**
|
|
370
|
+
* 生成完整的输出代码
|
|
371
|
+
*/
|
|
372
|
+
generateOutput(typeDefs: NamedTypeDef[], rootTypeName: string): string;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* ts-gen - 类型推断引擎
|
|
377
|
+
*
|
|
378
|
+
* 核心功能:
|
|
379
|
+
* - 基础类型识别(string、number、boolean、null、undefined)
|
|
380
|
+
* - 数组类型识别与元素类型统一
|
|
381
|
+
* - 对象类型递归遍历
|
|
382
|
+
* - 联合类型推断与合并
|
|
383
|
+
* - 可选属性识别
|
|
384
|
+
* - 空值处理
|
|
385
|
+
* - 循环引用检测
|
|
386
|
+
* - 结构等价性判断
|
|
387
|
+
*/
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* 创建联合类型节点
|
|
391
|
+
*/
|
|
392
|
+
declare function createUnion(types: TSTypeNode[]): UnionType;
|
|
393
|
+
/**
|
|
394
|
+
* 合并两个类型为联合类型
|
|
395
|
+
*/
|
|
396
|
+
declare function mergeTypes(a: TSTypeNode, b: TSTypeNode): TSTypeNode;
|
|
397
|
+
/**
|
|
398
|
+
* 合并两个对象类型
|
|
399
|
+
* - 相同字段合并类型
|
|
400
|
+
* - 仅在一个对象中存在的字段标记为可选
|
|
401
|
+
*/
|
|
402
|
+
declare function mergeObjects(a: ObjectType, b: ObjectType): ObjectType;
|
|
403
|
+
/**
|
|
404
|
+
* 推断单个值的类型
|
|
405
|
+
*/
|
|
406
|
+
declare function inferType(value: unknown): TSTypeNode;
|
|
407
|
+
/**
|
|
408
|
+
* 推断数组类型
|
|
409
|
+
* - 统一提取元素类型
|
|
410
|
+
* - 元素类型不一致时生成联合类型
|
|
411
|
+
*/
|
|
412
|
+
declare function inferArrayType(arr: unknown[]): TSTypeNode;
|
|
413
|
+
/**
|
|
414
|
+
* 推断对象类型
|
|
415
|
+
*/
|
|
416
|
+
declare function inferObjectType(obj: Record<string, unknown>): ObjectType;
|
|
417
|
+
/**
|
|
418
|
+
* 判断两个类型是否结构等价
|
|
419
|
+
* 用于类型去重与复用
|
|
420
|
+
*/
|
|
421
|
+
declare function isStructurallyEqual(a: TSTypeNode, b: TSTypeNode): boolean;
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* ts-gen - 增强功能模块
|
|
425
|
+
*
|
|
426
|
+
* 核心功能:
|
|
427
|
+
* - 泛型提取(识别列表结构,提取为 PageResult<T>)
|
|
428
|
+
* - 枚举提取(字符串字段取值有限时自动提取为枚举)
|
|
429
|
+
* - 空值处理(严格/非严格模式)
|
|
430
|
+
* - 可选属性处理
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* 泛型模式定义
|
|
435
|
+
*/
|
|
436
|
+
interface GenericPattern {
|
|
437
|
+
/** 模式名称,如 'PageResult' */
|
|
438
|
+
name: string;
|
|
439
|
+
/** 匹配的属性列表 */
|
|
440
|
+
match: {
|
|
441
|
+
/** 列表字段名(可变的部分) */
|
|
442
|
+
listField?: string[];
|
|
443
|
+
/** 总数字段名 */
|
|
444
|
+
totalField?: string[];
|
|
445
|
+
/** 页码字段名 */
|
|
446
|
+
pageField?: string[];
|
|
447
|
+
/** 每页大小字段名 */
|
|
448
|
+
pageSizeField?: string[];
|
|
449
|
+
};
|
|
450
|
+
/** 泛型参数索引(哪个字段作为 T) */
|
|
451
|
+
typeParamIndex: number;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* 泛型提取器
|
|
455
|
+
*/
|
|
456
|
+
declare class GenericExtractor {
|
|
457
|
+
private patterns;
|
|
458
|
+
constructor(customPatterns?: GenericPattern[]);
|
|
459
|
+
/**
|
|
460
|
+
* 尝试提取泛型类型
|
|
461
|
+
* @param type 对象类型
|
|
462
|
+
* @returns 如果匹配成功返回泛型类型,否则返回原类型
|
|
463
|
+
*/
|
|
464
|
+
extract(type: TSTypeNode): TSTypeNode;
|
|
465
|
+
/**
|
|
466
|
+
* 尝试匹配泛型模式
|
|
467
|
+
*/
|
|
468
|
+
private tryMatchPattern;
|
|
469
|
+
/**
|
|
470
|
+
* 递归处理子属性
|
|
471
|
+
*/
|
|
472
|
+
private extractRecursive;
|
|
473
|
+
/**
|
|
474
|
+
* 提取属性类型中的泛型
|
|
475
|
+
*/
|
|
476
|
+
private extractPropertyType;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* 枚举提取器
|
|
480
|
+
*/
|
|
481
|
+
declare class EnumExtractor {
|
|
482
|
+
private threshold;
|
|
483
|
+
constructor(threshold?: number);
|
|
484
|
+
/**
|
|
485
|
+
* 从 JSON 数据中提取枚举
|
|
486
|
+
* @param jsonData JSON 数据
|
|
487
|
+
* @param type 已推断的类型
|
|
488
|
+
* @returns 处理后的类型(可能包含枚举)
|
|
489
|
+
*/
|
|
490
|
+
extract(jsonData: unknown, type: TSTypeNode): TSTypeNode;
|
|
491
|
+
/**
|
|
492
|
+
* 递归提取
|
|
493
|
+
*/
|
|
494
|
+
private extractRecursive;
|
|
495
|
+
/**
|
|
496
|
+
* 收集数组中某个字段的所有取值
|
|
497
|
+
*/
|
|
498
|
+
private collectFieldValues;
|
|
499
|
+
/**
|
|
500
|
+
* 尝试提取枚举
|
|
501
|
+
*/
|
|
502
|
+
private tryExtractEnum;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* 空值处理器
|
|
506
|
+
*/
|
|
507
|
+
declare class NullHandler {
|
|
508
|
+
private strictNullChecks;
|
|
509
|
+
constructor(strictNullChecks?: boolean);
|
|
510
|
+
/**
|
|
511
|
+
* 处理类型中的 null
|
|
512
|
+
*/
|
|
513
|
+
process(type: TSTypeNode): TSTypeNode;
|
|
514
|
+
/**
|
|
515
|
+
* 递归处理(严格模式)
|
|
516
|
+
*/
|
|
517
|
+
private processRecursive;
|
|
518
|
+
/**
|
|
519
|
+
* 递归移除 null
|
|
520
|
+
*/
|
|
521
|
+
private removeNullRecursive;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* 可选属性处理器
|
|
525
|
+
* 基于数组中对象的字段出现频率判断是否可选
|
|
526
|
+
*/
|
|
527
|
+
declare class OptionalHandler {
|
|
528
|
+
private markOptional;
|
|
529
|
+
constructor(markOptional?: boolean);
|
|
530
|
+
/**
|
|
531
|
+
* 处理可选属性
|
|
532
|
+
* @param jsonData 原始 JSON 数据
|
|
533
|
+
* @param type 已推断的类型
|
|
534
|
+
*/
|
|
535
|
+
process(jsonData: unknown, type: TSTypeNode): TSTypeNode;
|
|
536
|
+
/**
|
|
537
|
+
* 递归处理
|
|
538
|
+
*/
|
|
539
|
+
private processRecursive;
|
|
540
|
+
/**
|
|
541
|
+
* 在数组对象中标记可选属性
|
|
542
|
+
*/
|
|
543
|
+
private markOptionalInArrayObjects;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* 应用所有增强功能
|
|
547
|
+
*/
|
|
548
|
+
declare function applyEnhancements(jsonData: unknown, type: TSTypeNode, options: Required<GenerateOptions>): TSTypeNode;
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* ts-gen - JSON 智能生成 TypeScript 类型定义
|
|
552
|
+
*
|
|
553
|
+
* 主入口文件
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```ts
|
|
557
|
+
* import { generate } from 'ts-gen';
|
|
558
|
+
*
|
|
559
|
+
* const json = { name: 'foo', age: 25 };
|
|
560
|
+
* const result = generate(json, { rootName: 'User' });
|
|
561
|
+
* console.log(result.code);
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* 从 JSON 数据生成 TypeScript 类型定义
|
|
567
|
+
*
|
|
568
|
+
* @param jsonData JSON 数据(对象或数组)
|
|
569
|
+
* @param options 生成选项
|
|
570
|
+
* @returns 生成结果,包含代码字符串和类型定义列表
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* import { generate } from 'ts-gen';
|
|
575
|
+
*
|
|
576
|
+
* const data = {
|
|
577
|
+
* id: 1,
|
|
578
|
+
* name: 'Alice',
|
|
579
|
+
* email: 'alice@example.com',
|
|
580
|
+
* profile: {
|
|
581
|
+
* avatar: 'https://...',
|
|
582
|
+
* bio: null
|
|
583
|
+
* }
|
|
584
|
+
* };
|
|
585
|
+
*
|
|
586
|
+
* const result = generate(data, {
|
|
587
|
+
* rootName: 'User',
|
|
588
|
+
* outputStyle: 'interface'
|
|
589
|
+
* });
|
|
590
|
+
*
|
|
591
|
+
* console.log(result.code);
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
declare function generate(jsonData: unknown, options?: GenerateOptions): GenerateResult;
|
|
595
|
+
/**
|
|
596
|
+
* 从 JSON 字符串生成 TypeScript 类型定义
|
|
597
|
+
*
|
|
598
|
+
* @param jsonString JSON 字符串
|
|
599
|
+
* @param options 生成选项
|
|
600
|
+
* @returns 生成结果
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```ts
|
|
604
|
+
* import { generateFromString } from 'ts-gen';
|
|
605
|
+
*
|
|
606
|
+
* const jsonStr = '{"name": "foo", "age": 25}';
|
|
607
|
+
* const result = generateFromString(jsonStr, { rootName: 'User' });
|
|
608
|
+
* ```
|
|
609
|
+
*/
|
|
610
|
+
declare function generateFromString(jsonString: string, options?: GenerateOptions): GenerateResult;
|
|
611
|
+
/**
|
|
612
|
+
* 生成单个类型的字符串表示(不生成完整文件)
|
|
613
|
+
*
|
|
614
|
+
* @param jsonData JSON 数据
|
|
615
|
+
* @param options 生成选项
|
|
616
|
+
* @returns 类型定义字符串
|
|
617
|
+
*/
|
|
618
|
+
declare function generateType(jsonData: unknown, options?: GenerateOptions): string;
|
|
619
|
+
|
|
620
|
+
declare const _default: {
|
|
621
|
+
generate: typeof generate;
|
|
622
|
+
generateFromString: typeof generateFromString;
|
|
623
|
+
generateType: typeof generateType;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
export { type ArrayType, CodeFormatter, EnumExtractor, type EnumType, type GenerateOptions, type GenerateResult, GenericExtractor, type GenericType, type NamedTypeDef, type NamingStyle, NullHandler, type ObjectType, OptionalHandler, type OutputStyle, type PrimitiveType, type PropertyDef, type SortOrder, type TSTypeNode, TypeCollector, TypeNamer, type UnionType, applyEnhancements, createUnion, _default as default, generate, generateFromString, generateType, inferArrayType, inferObjectType, inferType, isStructurallyEqual, mergeObjects, mergeTypes };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";var P=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var _=(i,e)=>{for(var t in e)P(i,t,{get:e[t],enumerable:!0})},q=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of V(e))!z.call(i,n)&&n!==t&&P(i,n,{get:()=>e[n],enumerable:!(r=L(e,n))||r.enumerable});return i};var J=i=>q(P({},"__esModule",{value:!0}),i);var X={};_(X,{CodeFormatter:()=>T,EnumExtractor:()=>S,GenericExtractor:()=>k,NullHandler:()=>v,OptionalHandler:()=>b,TypeCollector:()=>y,TypeNamer:()=>d,applyEnhancements:()=>x,createUnion:()=>h,default:()=>Q,generate:()=>$,generateFromString:()=>M,generateType:()=>F,inferArrayType:()=>A,inferObjectType:()=>E,inferType:()=>f,isStructurallyEqual:()=>U,mergeObjects:()=>R,mergeTypes:()=>N});module.exports=J(X);var D={rootName:"Root",outputStyle:"interface",namingStyle:"PascalCase",sortProperties:"alpha",addExport:!0,addComments:!1,strictNullChecks:!1,markOptional:!0,extractEnums:!0,enumThreshold:5,extractGenerics:!0,indentSize:2,lineEnding:`
|
|
2
|
+
`,typeNameMap:{},typePrefix:"",typeSuffix:""};function m(i){return{kind:"primitive",type:i}}function Z(){return{kind:"null"}}function B(){return{kind:"undefined"}}function w(i){return{kind:"array",elementType:i}}function G(i=[]){return{kind:"object",properties:i}}function h(i){let e=[],t=new Set;for(let r of i)if(r.kind==="union")for(let n of r.types){let o=c(n);t.has(o)||(t.add(o),e.push(n))}else{let n=c(r);t.has(n)||(t.add(n),e.push(r))}return e.length===1?e[0]:{kind:"union",types:e}}function c(i){switch(i.kind){case"primitive":return`primitive:${i.type}`;case"null":return"null";case"undefined":return"undefined";case"literal":return`literal:${typeof i.value}:${String(i.value)}`;case"array":return`array:${c(i.elementType)}`;case"object":return`object:${i.properties.map(e=>`${e.name}:${c(e.type)}:${e.optional}`).join(",")}`;case"union":return`union:${i.types.map(c).sort().join("|")}`;case"enum":return`enum:${i.name}:${i.values.join(",")}`;case"generic":return`generic:${i.name}:${i.typeArgs.map(c).join(",")}`;default:return"unknown"}}function N(i,e){return c(i)===c(e)?i:i.kind==="object"&&e.kind==="object"?R(i,e):i.kind==="array"&&e.kind==="array"?w(N(i.elementType,e.elementType)):h([i,e])}function R(i,e){let t=new Map;for(let r of i.properties)t.set(r.name,{...r});for(let r of e.properties){let n=t.get(r.name);n?(n.type=N(n.type,r.type),n.optional=n.optional||r.optional,r.comment&&!n.comment&&(n.comment=r.comment)):t.set(r.name,{...r,optional:!0})}for(let[r,n]of t)e.properties.some(s=>s.name===r)||(n.optional=!0);return G(Array.from(t.values()))}function f(i){return i===null?Z():i===void 0?B():typeof i=="string"?m("string"):typeof i=="number"?m("number"):typeof i=="boolean"?m("boolean"):Array.isArray(i)?A(i):typeof i=="object"?E(i):m("unknown")}function A(i){if(i.length===0)return w(m("never"));let e=f(i[0]);for(let t=1;t<i.length;t++){let r=f(i[t]);e=N(e,r)}return w(e)}function E(i){let e=[];for(let[t,r]of Object.entries(i)){let n=f(r);e.push({name:t,type:n,optional:!1})}return G(e)}function U(i,e){return c(i)===c(e)}function l(i){switch(i.kind){case"primitive":case"null":case"undefined":return{...i};case"literal":return{...i};case"array":return{...i,elementType:l(i.elementType)};case"object":return{...i,properties:i.properties.map(e=>({...e,type:l(e.type)}))};case"union":return{...i,types:i.types.map(e=>l(e))};case"enum":return{...i,values:[...i.values]};case"generic":return{...i,typeArgs:i.typeArgs.map(e=>l(e))};default:return{...i}}}var d=class{constructor(e={}){this.namedTypes=new Map;this.nameCounter=new Map;this.processing=new WeakSet;this.circularRefs=new Map;this.namingStyle=e.namingStyle||"PascalCase",this.prefix=e.prefix||"",this.suffix=e.suffix||"",this.customNameMap=e.customNameMap||{}}nameType(e,t={depth:0}){if(e.kind!=="object"&&e.kind!=="enum")return null;let r=this.buildPathKey(t);if(this.customNameMap[r])return this.applyAffixes(this.customNameMap[r]);let n=this.getTypeKey(e);if(this.namedTypes.has(n))return this.namedTypes.get(n);let o=this.generateName(e,t);return o=this.ensureUniqueName(o),o=this.applyAffixes(o),this.namedTypes.set(n,o),o}generateName(e,t){if(e.kind==="enum")return t.fieldName?this.toPascalCase(t.fieldName)+"Enum":"AnonymousEnum";if(e.kind==="object"){if(t.fieldName){let r=this.toPascalCase(t.fieldName);return t.parentName?`${t.parentName}${r}`:r}return t.parentName?`${t.parentName}Item`:"AnonymousObject"}return"UnknownType"}ensureUniqueName(e){let t=this.nameCounter.get(e)||0;if(t===0)return this.nameCounter.set(e,1),e;let r=`${e}${t+1}`;return this.nameCounter.set(e,t+1),r}applyAffixes(e){let t=e;return this.prefix&&(t=this.toPascalCase(this.prefix)+t),this.suffix&&(t=t+this.toPascalCase(this.suffix)),t}buildPathKey(e){let t=[];return e.parentName&&t.push(e.parentName),e.fieldName&&t.push(e.fieldName),t.join(".")}getTypeKey(e){return e.kind==="object"?`object:${e.properties.map(t=>`${t.name}:${this.getSimpleTypeKey(t.type)}:${t.optional}`).sort().join(",")}`:e.kind==="enum"?`enum:${e.values.sort().join(",")}`:e.kind}getSimpleTypeKey(e){switch(e.kind){case"primitive":return e.type;case"null":return"null";case"undefined":return"undefined";case"array":return`array<${this.getSimpleTypeKey(e.elementType)}>`;case"object":return"object";case"union":return e.types.map(t=>this.getSimpleTypeKey(t)).sort().join("|");case"enum":return`enum:${e.name}`;case"generic":return`generic:${e.name}`;default:return"unknown"}}toPascalCase(e){return e?e.replace(/[-_\s]+/g," ").replace(/([a-z])([A-Z])/g,"$1 $2").trim().split(" ").filter(Boolean).map(r=>r.charAt(0).toUpperCase()+r.slice(1).toLowerCase()).join(""):""}toCamelCase(e){let t=this.toPascalCase(e);return t.charAt(0).toLowerCase()+t.slice(1)}formatName(e){return this.namingStyle==="camelCase"?this.toCamelCase(e):this.toPascalCase(e)}isCircular(e){return this.processing.has(e)}markProcessing(e){this.processing.add(e)}unmarkProcessing(e){this.processing.delete(e)}getAllNamedTypes(){return new Map(this.namedTypes)}reset(){this.namedTypes.clear(),this.nameCounter.clear(),this.processing=new WeakSet,this.circularRefs.clear()}},y=class{constructor(e){this.collected=[];this.seenStructs=new Set;this.namer=e}collect(e,t){this.collected=[],this.seenStructs.clear(),this.namer.reset();let r=this.getStructKey(e);this.namer.nameType(e,{fieldName:t,depth:0}),this.collectRecursive(e,{fieldName:t,parentName:void 0,depth:0});let n=this.collected.find(s=>s.name===t),o=this.collected.filter(s=>s.name!==t);return n?[n,...o]:this.collected}collectRecursive(e,t){let r=this.getStructKey(e);if(e.kind==="object"){let n=this.namer.nameType(e,t);if(n&&!this.seenStructs.has(r)){this.seenStructs.add(r),this.collected.push({name:n,type:l(e)});for(let o of e.properties)this.collectRecursive(o.type,{fieldName:o.name,parentName:n,depth:t.depth+1})}return}if(e.kind==="array"){this.collectRecursive(e.elementType,{fieldName:t.fieldName?t.fieldName+"Item":void 0,parentName:t.parentName,depth:t.depth+1});return}if(e.kind==="union"){for(let n of e.types)this.collectRecursive(n,t);return}if(e.kind==="enum"){let n=this.namer.nameType(e,t);n&&!this.seenStructs.has(r)&&(this.seenStructs.add(r),this.collected.push({name:n,type:l(e)}));return}if(e.kind==="generic"){for(let n of e.typeArgs)this.collectRecursive(n,{...t,depth:t.depth+1});return}}getStructKey(e){return e.kind==="object"?`object:${e.properties.map(t=>`${t.name}:${this.getPropTypeKey(t.type)}:${t.optional}`).sort().join("|")}`:e.kind==="enum"?`enum:${[...e.values].sort().join(",")}`:e.kind}getPropTypeKey(e){switch(e.kind){case"primitive":return e.type;case"null":return"null";case"undefined":return"undefined";case"array":return`array:${this.getPropTypeKey(e.elementType)}`;case"object":return"object";case"union":return e.types.map(t=>this.getPropTypeKey(t)).sort().join("|");case"enum":return`enum:${e.name}`;case"generic":return`generic:${e.name}`;default:return"unknown"}}};function I(i){let e=i.replace(/[^a-zA-Z0-9_$]/g,"_");return/^\d/.test(e)&&(e="_"+e),e}function C(i){return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(i)}var T=class{constructor(e,t){this.options=e,this.namer=t}formatTypeDef(e){let{name:t,type:r,comment:n}=e,o="";this.options.addComments&&n&&(o+=this.formatJSDoc(n)+this.options.lineEnding);let s=this.options.addExport?"export ":"";return r.kind==="object"?o+=this.formatObjectType(t,r,s):r.kind==="enum"?o+=this.formatEnumType(t,r,s):o+=`${s}type ${t} = ${this.formatType(r)};`,o}formatObjectType(e,t,r){let n=this.options.outputStyle,o=" ".repeat(this.options.indentSize),s=this.options.lineEnding,u=this.sortProperties(t.properties);if(n==="interface"){let a=`${r}interface ${e} {${s}`;for(let p of u){this.options.addComments&&p.comment&&(a+=o+this.formatInlineJSDoc(p.comment)+s);let g=this.formatPropertyName(p.name),j=p.optional&&this.options.markOptional?"?":"",O=this.formatType(p.type);a+=`${o}${g}${j}: ${O};${s}`}return a+=`}${s}`,a}else{let a=`${r}type ${e} = {${s}`;for(let p of u){this.options.addComments&&p.comment&&(a+=o+this.formatInlineJSDoc(p.comment)+s);let g=this.formatPropertyName(p.name),j=p.optional&&this.options.markOptional?"?":"",O=this.formatType(p.type);a+=`${o}${g}${j}: ${O};${s}`}return a+=`};${s}`,a}}formatEnumType(e,t,r){let n=" ".repeat(this.options.indentSize),o=this.options.lineEnding,s=t.values.every(a=>typeof a=="string"),u=`${r}enum ${e} {${o}`;for(let a of t.values)if(s){let p=this.toEnumKey(String(a));u+=`${n}${p} = '${a}',${o}`}else{let p=`Value${a}`;u+=`${n}${p} = ${a},${o}`}return u+=`}${o}`,u}formatType(e){switch(e.kind){case"primitive":return e.type;case"null":return"null";case"undefined":return"undefined";case"literal":return this.formatLiteral(e.value);case"array":return this.formatArrayType(e.elementType);case"object":return this.formatInlineObject(e);case"union":return this.formatUnionType(e.types);case"enum":return e.name;case"generic":return`${e.name}<${e.typeArgs.map(t=>this.formatType(t)).join(", ")}>`;default:return"unknown"}}formatLiteral(e){return typeof e=="string"?`'${e.replace(/'/g,"\\'")}'`:String(e)}formatArrayType(e){let t=this.formatType(e);return e.kind==="union"?`(${t})[]`:`${t}[]`}formatInlineObject(e){let t=" ".repeat(this.options.indentSize),r=this.options.lineEnding,n=this.sortProperties(e.properties);if(n.length===0)return"{}";let o=`{${r}`;for(let s of n){let u=this.formatPropertyName(s.name),a=s.optional&&this.options.markOptional?"?":"",p=this.formatType(s.type);o+=`${t}${u}${a}: ${p};${r}`}return o+="}",o}formatUnionType(e){return e.map(t=>this.formatType(t)).join(" | ")}formatPropertyName(e){return C(e)?e:`'${e.replace(/'/g,"\\'")}'`}sortProperties(e){return this.options.sortProperties==="alpha"?[...e].sort((r,n)=>r.name.localeCompare(n.name)):[...e]}formatJSDoc(e){let t=e.split(`
|
|
3
|
+
`);return t.length===1?`/** ${e} */`:`/**
|
|
4
|
+
* ${t.join(`
|
|
5
|
+
* `)}
|
|
6
|
+
*/`}formatInlineJSDoc(e){return`/** ${e} */`}toEnumKey(e){let r=e.replace(/[-_\s]+/g," ").replace(/([a-z])([A-Z])/g,"$1 $2").trim().split(" ").filter(Boolean).map(n=>n.toUpperCase()).join("_");return/^\d/.test(r)&&(r="VALUE_"+r),C(r)||(r=I(r)),r}formatAll(e){let t=this.options.lineEnding,r=[];for(let n of e)r.push(this.formatTypeDef(n));return r.join(t)}generateOutput(e,t){let r=this.options.lineEnding,n="";return n+=`/**${r}`,n+=` * Generated by ts-gen${r}`,n+=` * Root type: ${t}${r}`,n+=` */${r}`,n+=r,n+=this.formatAll(e),n}};function H(i){let e=i.toLowerCase();return{id:"\u552F\u4E00\u6807\u8BC6\u7B26",name:"\u540D\u79F0",title:"\u6807\u9898",desc:"\u63CF\u8FF0",description:"\u63CF\u8FF0",type:"\u7C7B\u578B",status:"\u72B6\u6001",code:"\u7F16\u7801/\u72B6\u6001\u7801",msg:"\u6D88\u606F",message:"\u6D88\u606F",data:"\u6570\u636E",list:"\u5217\u8868\u6570\u636E",total:"\u603B\u6570",page:"\u9875\u7801",pageSize:"\u6BCF\u9875\u6570\u91CF",pageNum:"\u9875\u7801",pageIndex:"\u9875\u7801",size:"\u6570\u91CF/\u5927\u5C0F",count:"\u6570\u91CF",createTime:"\u521B\u5EFA\u65F6\u95F4",updateTime:"\u66F4\u65B0\u65F6\u95F4",createdAt:"\u521B\u5EFA\u65F6\u95F4",updatedAt:"\u66F4\u65B0\u65F6\u95F4",deleted:"\u662F\u5426\u5DF2\u5220\u9664",enabled:"\u662F\u5426\u542F\u7528",active:"\u662F\u5426\u6FC0\u6D3B",url:"\u94FE\u63A5\u5730\u5740",avatar:"\u5934\u50CF",email:"\u90AE\u7BB1",phone:"\u624B\u673A\u53F7",mobile:"\u624B\u673A\u53F7",username:"\u7528\u6237\u540D",password:"\u5BC6\u7801",token:"\u4EE4\u724C",userId:"\u7528\u6237ID",userName:"\u7528\u6237\u540D"}[e]}function K(i){return{...i,properties:i.properties.map(e=>({...e,comment:e.comment||H(e.name)}))}}var W=[{name:"PageResult",match:{listField:["list","records","rows","items","dataList"],totalField:["total","totalCount","count"]},typeParamIndex:0},{name:"ListResult",match:{listField:["list","records","rows","items"]},typeParamIndex:0},{name:"ApiResponse",match:{listField:["data"],totalField:["code","status"]},typeParamIndex:0}],k=class{constructor(e){this.patterns=e||W}extract(e){if(e.kind!=="object")return e;for(let t of this.patterns){let r=this.tryMatchPattern(e,t);if(r)return r}return this.extractRecursive(e)}tryMatchPattern(e,t){let r=e.properties,n=r.map(a=>a.name),o;if(t.match.listField)for(let a of t.match.listField){let p=r.find(g=>g.name===a);if(p&&p.type.kind==="array"){o=p;break}}if(!o||t.match.totalField&&!t.match.totalField.some(p=>n.includes(p)))return null;let s=o.type.elementType,u=this.extract(s);return{kind:"generic",name:t.name,typeArgs:[u]}}extractRecursive(e){return{...e,properties:e.properties.map(t=>({...t,type:this.extractPropertyType(t.type)}))}}extractPropertyType(e){return e.kind==="object"?this.extract(e):e.kind==="array"?{...e,elementType:this.extractPropertyType(e.elementType)}:e.kind==="union"?{...e,types:e.types.map(t=>this.extractPropertyType(t))}:e}},S=class{constructor(e=5){this.threshold=e}extract(e,t){return this.extractRecursive(e,t,"")}extractRecursive(e,t,r){if(t.kind==="object"&&e&&typeof e=="object"){let n=e;return{...t,properties:t.properties.map(o=>{let s=r?`${r}.${o.name}`:o.name,u=n[o.name];return{...o,type:this.extractRecursive(u,o.type,s)}})}}if(t.kind==="array"&&Array.isArray(e)){let n=t.elementType;if(n.kind==="object"){let o=n.properties.map(s=>{let u=this.collectFieldValues(e,s.name),a=this.tryExtractEnum(u,s.type,s.name);return{...s,type:a}});return{...t,elementType:{...n,properties:o}}}if(n.kind==="primitive"&&n.type==="string"){let o=e.filter(u=>typeof u=="string"),s=[...new Set(o)];if(s.length>0&&s.length<=this.threshold)return{...t,elementType:{kind:"enum",name:"",values:s}}}return t}return t}collectFieldValues(e,t){let r=[];for(let n of e)if(n&&typeof n=="object"){let o=n[t];o!==void 0&&r.push(o)}return r}tryExtractEnum(e,t,r){if(t.kind!=="primitive"||t.type!=="string")return t;let n=e.filter(a=>typeof a=="string"),o=[...new Set(n)];return o.length===0||o.length>this.threshold||!o.every(a=>a.length<=50&&/^[a-zA-Z0-9_\-]+$/.test(a))?t:{kind:"enum",name:"",values:o}}},v=class{constructor(e=!1){this.strictNullChecks=e}process(e){return this.strictNullChecks?this.processRecursive(e):this.removeNullRecursive(e)}processRecursive(e){return e.kind==="object"?{...e,properties:e.properties.map(t=>({...t,type:this.processRecursive(t.type)}))}:e.kind==="array"?{...e,elementType:this.processRecursive(e.elementType)}:e.kind==="union"?{...e,types:e.types.map(t=>this.processRecursive(t))}:e}removeNullRecursive(e){if(e.kind==="object")return{...e,properties:e.properties.map(t=>({...t,type:this.removeNullRecursive(t.type)}))};if(e.kind==="array")return{...e,elementType:this.removeNullRecursive(e.elementType)};if(e.kind==="union"){let t=e.types.map(r=>this.removeNullRecursive(r)).filter(r=>r.kind!=="null");return t.length===0?m("unknown"):t.length===1?t[0]:h(t)}return e}},b=class{constructor(e=!0){this.markOptional=e}process(e,t){return this.markOptional?this.processRecursive(e,t):t}processRecursive(e,t){if(t.kind==="array"&&Array.isArray(e)&&e.length>1){let r=t.elementType;if(r.kind==="object"){let n=e.filter(o=>o!==null&&typeof o=="object"&&!Array.isArray(o));if(n.length>0){let o=this.markOptionalInArrayObjects(n,r);return{...t,elementType:o}}}return{...t,elementType:this.processRecursive(e[0],t.elementType)}}if(t.kind==="object"&&e&&typeof e=="object"){let r=e;return{...t,properties:t.properties.map(n=>{let o=r[n.name];return{...n,type:this.processRecursive(o,n.type)}})}}return t.kind==="union"?{...t,types:t.types.map(r=>this.processRecursive(e,r))}:t}markOptionalInArrayObjects(e,t){let r=e.length;return{...t,properties:t.properties.map(n=>{let o=0;for(let p of e)n.name in p&&o++;let s=o<r,u=e.map(p=>p[n.name]).filter(p=>p!==void 0),a=u.length>0?this.processRecursive(u[0],n.type):n.type;return{...n,optional:n.optional||s,type:a}})}}};function x(i,e,t){let r=l(e);return t.markOptional&&(r=new b(t.markOptional).process(i,r)),t.extractEnums&&(r=new S(t.enumThreshold).extract(i,r)),t.extractGenerics&&(r=new k().extract(r)),r=new v(t.strictNullChecks).process(r),r}function $(i,e={}){let t={...D,...e},r=f(i);r=x(i,r,t),t.addComments&&r.kind==="object"&&(r=K(r));let n=new d({namingStyle:t.namingStyle,prefix:t.typePrefix,suffix:t.typeSuffix,customNameMap:t.typeNameMap}),o=new y(n),s=t.rootName||"Root",u=o.collect(r,s);return{code:new T(t,n).generateOutput(u,s),types:u}}function M(i,e={}){let t=JSON.parse(i);return $(t,e)}function F(i,e={}){return $(i,e).code}var Q={generate:$,generateFromString:M,generateType:F};0&&(module.exports={CodeFormatter,EnumExtractor,GenericExtractor,NullHandler,OptionalHandler,TypeCollector,TypeNamer,applyEnhancements,createUnion,generate,generateFromString,generateType,inferArrayType,inferObjectType,inferType,isStructurallyEqual,mergeObjects,mergeTypes});
|