type-flash 1.1.2 → 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 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(argv) {
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 = 2; // 跳过 node 和脚本路径
42
- while (i < argv.length) {
43
- const arg = argv[i];
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
- args.input = argv[++i];
42
+ options.input = args[++i];
59
43
  break;
60
-
61
44
  case '-o':
62
45
  case '--output':
63
- args.output = argv[++i];
46
+ options.output = args[++i];
64
47
  break;
65
-
66
48
  case '-n':
67
49
  case '--name':
68
- case '--root-name':
69
- args.rootName = argv[++i];
50
+ options.rootName = args[++i];
70
51
  break;
71
-
72
52
  case '-s':
73
53
  case '--style':
74
- args.outputStyle = argv[++i];
54
+ options.outputStyle = args[++i];
75
55
  break;
76
-
77
56
  case '--naming-style':
78
- args.namingStyle = argv[++i];
57
+ options.namingStyle = args[++i];
79
58
  break;
80
-
81
59
  case '--sort':
82
- args.sortProperties = argv[++i];
60
+ options.sortProperties = args[++i];
83
61
  break;
84
-
85
62
  case '--no-export':
86
- args.addExport = false;
63
+ options.addExport = false;
87
64
  break;
88
-
89
65
  case '--strict-null':
90
- args.strictNullChecks = true;
66
+ options.strictNullChecks = true;
91
67
  break;
92
-
93
68
  case '--no-optional':
94
- args.markOptional = false;
69
+ options.markOptional = false;
95
70
  break;
96
-
97
71
  case '--no-generics':
98
- args.extractGenerics = false;
72
+ options.extractGenerics = false;
99
73
  break;
100
-
101
74
  case '--indent':
102
- args.indentSize = parseInt(argv[++i], 10);
75
+ options.indentSize = parseInt(args[++i], 10);
103
76
  break;
104
-
105
77
  case '--prefix':
106
- args.typePrefix = argv[++i];
78
+ options.typePrefix = args[++i];
107
79
  break;
108
-
109
80
  case '--suffix':
110
- args.typeSuffix = argv[++i];
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 args;
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 <input.json> [options]
134
- type-flash -i input.json -o output.ts
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> 输入 JSON 文件路径
139
- -o, --output <file> 输出 TypeScript 文件路径(默认输出到 stdout)
140
- -n, --name <name> 根类型名称(默认: Root
141
- -s, --style <style> 输出风格: interface | type(默认: interface
142
- --naming-style <s> 命名风格: PascalCase | camelCase(默认: PascalCase
143
- --sort <order> 属性排序: alpha | definition(默认: alpha
144
- --no-export 不添加 export 关键字
145
- --strict-null 严格空值模式(保留 null 类型)
146
- --no-optional 不标记可选属性
147
- --no-generics 不提取泛型类型
148
- --indent <n> 缩进空格数(默认: 2
149
- --prefix <prefix> 类型名前缀
150
- --suffix <suffix> 类型名后缀
151
- -h, --help 显示帮助信息
152
- -v, --version 显示版本号
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 user.json -n User -o user.ts
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(`type-flash v${pkg.version}`);
138
+ console.log(pkg.version);
175
139
  } catch (e) {
176
- console.log('type-flash (unknown version)');
140
+ console.log('unknown');
177
141
  }
178
142
  }
179
143
 
180
- // 读取输入
181
- async function readInput(inputPath) {
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
- console.error('错误: 未提供输入数据。请指定输入文件或通过管道传入 JSON。');
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 args = parseArgs(process.argv);
171
+ const options = parseArgs();
221
172
 
222
- if (args.help) {
173
+ // 显示帮助
174
+ if (options.help) {
223
175
  showHelp();
224
176
  return;
225
177
  }
226
178
 
227
- if (args.version) {
179
+ // 显示版本
180
+ if (options.version) {
228
181
  showVersion();
229
182
  return;
230
183
  }
231
184
 
232
185
  try {
233
- // 读取输入
234
- const jsonStr = await readInput(args.input);
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(jsonStr);
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
- const { generate } = require('../dist/index.js');
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: args.rootName,
251
- outputStyle: args.outputStyle,
252
- namingStyle: args.namingStyle,
253
- sortProperties: args.sortProperties,
254
- addExport: args.addExport,
255
- strictNullChecks: args.strictNullChecks,
256
- markOptional: args.markOptional,
257
- extractGenerics: args.extractGenerics,
258
- indentSize: args.indentSize,
259
- typePrefix: args.typePrefix,
260
- typeSuffix: args.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 (args.output) {
265
- const outputPath = path.resolve(args.output);
266
- fs.writeFileSync(outputPath, result.code, 'utf-8');
267
- console.log(`✓ 已生成: ${outputPath}`);
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.code);
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();
package/dist/index.d.mts CHANGED
@@ -142,6 +142,8 @@ interface NamingContext {
142
142
  fieldName?: string;
143
143
  /** 父级类型名 */
144
144
  parentName?: string;
145
+ /** 完整字段路径(用于 typeNameMap 匹配) */
146
+ path?: string;
145
147
  /** 深度 */
146
148
  depth: number;
147
149
  }
package/dist/index.d.ts CHANGED
@@ -142,6 +142,8 @@ interface NamingContext {
142
142
  fieldName?: string;
143
143
  /** 父级类型名 */
144
144
  parentName?: string;
145
+ /** 完整字段路径(用于 typeNameMap 匹配) */
146
+ path?: string;
145
147
  /** 深度 */
146
148
  depth: number;
147
149
  }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";var b=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var M=(n,e)=>{for(var t in e)b(n,t,{get:e[t],enumerable:!0})},K=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of U(e))!G.call(n,i)&&i!==t&&b(n,i,{get:()=>e[i],enumerable:!(r=R(e,i))||r.enumerable});return n};var E=n=>K(b({},"__esModule",{value:!0}),n);var z={};M(z,{CodeFormatter:()=>y,GenericExtractor:()=>T,NullHandler:()=>g,OptionalHandler:()=>h,TypeCollector:()=>f,TypeNamer:()=>l,applyEnhancements:()=>S,createUnion:()=>x,default:()=>q,generate:()=>$,generateFromString:()=>w,inferArrayType:()=>O,inferObjectType:()=>v,inferType:()=>c,isStructurallyEqual:()=>N,mergeObjects:()=>j,mergeTypes:()=>d});module.exports=E(z);var P={rootName:"Root",outputStyle:"interface",namingStyle:"PascalCase",sortProperties:"alpha",addExport:!0,strictNullChecks:!1,markOptional:!0,extractGenerics:!0,indentSize:2,lineEnding:`
2
- `,typeNameMap:{},typePrefix:"",typeSuffix:""};function m(n){return{kind:"primitive",type:n}}function F(){return{kind:"null"}}function L(){return{kind:"undefined"}}function _(n){return{kind:"array",elementType:n}}function A(n=[]){return{kind:"object",properties:n}}function x(n){let e=[],t=new Set;for(let r of n)if(r.kind==="union")for(let i of r.types){let o=a(i);t.has(o)||(t.add(o),e.push(i))}else{let i=a(r);t.has(i)||(t.add(i),e.push(r))}return e.length===1?e[0]:{kind:"union",types:e}}function a(n){switch(n.kind){case"primitive":return`primitive:${n.type}`;case"null":return"null";case"undefined":return"undefined";case"literal":return`literal:${typeof n.value}:${String(n.value)}`;case"array":return`array:${a(n.elementType)}`;case"object":return`object:${n.properties.map(e=>`${e.name}:${a(e.type)}:${e.optional}`).join(",")}`;case"union":return`union:${n.types.map(a).sort().join("|")}`;case"generic":return`generic:${n.name}:${n.typeArgs.map(a).join(",")}`;default:return"unknown"}}function d(n,e){return a(n)===a(e)?n:n.kind==="object"&&e.kind==="object"?j(n,e):n.kind==="array"&&e.kind==="array"?_(d(n.elementType,e.elementType)):x([n,e])}function j(n,e){let t=new Map;for(let r of n.properties)t.set(r.name,{...r});for(let r of e.properties){let i=t.get(r.name);i?(i.type=d(i.type,r.type),i.optional=i.optional||r.optional):t.set(r.name,{...r,optional:!0})}for(let[r,i]of t)e.properties.some(s=>s.name===r)||(i.optional=!0);return A(Array.from(t.values()))}function c(n){return n===null?F():n===void 0?L():typeof n=="function"?m("function"):typeof n=="string"?m("string"):typeof n=="number"?m("number"):typeof n=="boolean"?m("boolean"):Array.isArray(n)?O(n):typeof n=="object"?v(n):m("unknown")}function O(n){if(n.length===0)return{kind:"array",elementType:{kind:"primitive",type:"any"}};let e=n.map(r=>c(r)),t=e[0];for(let r=1;r<e.length;r++)t=d(t,e[r]);return{kind:"array",elementType:t}}function v(n){let e=[];for(let[t,r]of Object.entries(n)){let i=c(r);e.push({name:t,type:i,optional:!1})}return A(e)}function N(n,e){return a(n)===a(e)}function u(n){switch(n.kind){case"primitive":case"null":case"undefined":return{...n};case"literal":return{...n};case"array":return{...n,elementType:u(n.elementType)};case"object":return{...n,properties:n.properties.map(e=>({...e,type:u(e.type)}))};case"union":return{...n,types:n.types.map(e=>u(e))};case"generic":return{...n,typeArgs:n.typeArgs.map(e=>u(e))};default:return{...n}}}var l=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")return null;let r=this.buildPathKey(t);if(this.customNameMap[r])return this.applyAffixes(this.customNameMap[r]);let i=this.getTypeKey(e);if(this.namedTypes.has(i))return this.namedTypes.get(i);let o=this.generateName(e,t);return o=this.formatName(o),o=this.ensureUniqueName(o),o=this.applyAffixes(o),this.namedTypes.set(i,o),o}generateName(e,t){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}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"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()}},f=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 i=this.collected.find(s=>s.name===t),o=this.collected.filter(s=>s.name!==t);return i?[i,...o]:this.collected}collectRecursive(e,t){let r=this.getStructKey(e);if(e.kind==="object"){let i=this.namer.nameType(e,t);if(i&&!this.seenStructs.has(r)){this.seenStructs.add(r),this.collected.push({name:i,type:u(e)});for(let o of e.properties)this.collectRecursive(o.type,{fieldName:o.name,parentName:i,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 i of e.types)this.collectRecursive(i,t);return}if(e.kind==="generic"){for(let i of e.typeArgs)this.collectRecursive(i,{...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}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"generic":return`generic:${e.name}`;default:return"unknown"}}};var y=class{constructor(e,t){this.allNamedTypes=[];this.options=e,this.namer=t}findTypeName(e){if(e.kind!=="object")return null;for(let t of this.allNamedTypes)if(N(t.type,e))return t.name;return null}formatTypeDef(e){let{name:t,type:r}=e,i=this.options.addExport?"export ":"";return this.formatObjectType(t,r,i)}formatObjectType(e,t,r){let i=" ".repeat(this.options.indentSize),o=this.sortProperties(t.properties),s=[];this.options.outputStyle==="interface"?s.push(`${r}interface ${e} {`):s.push(`${r}type ${e} = {`);for(let p of o){let k=this.formatPropertyName(p.name),C=p.optional?"?":"",D=this.formatType(p.type);s.push(`${i}${k}${C}: ${D};`)}return this.options.outputStyle==="interface"?s.push("}"):s.push("};"),s.join(`
1
+ "use strict";var b=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var M=(n,e)=>{for(var t in e)b(n,t,{get:e[t],enumerable:!0})},K=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of U(e))!G.call(n,i)&&i!==t&&b(n,i,{get:()=>e[i],enumerable:!(r=R(e,i))||r.enumerable});return n};var E=n=>K(b({},"__esModule",{value:!0}),n);var z={};M(z,{CodeFormatter:()=>f,GenericExtractor:()=>T,NullHandler:()=>g,OptionalHandler:()=>h,TypeCollector:()=>y,TypeNamer:()=>l,applyEnhancements:()=>S,createUnion:()=>x,default:()=>q,generate:()=>$,generateFromString:()=>w,inferArrayType:()=>O,inferObjectType:()=>v,inferType:()=>u,isStructurallyEqual:()=>N,mergeObjects:()=>j,mergeTypes:()=>d});module.exports=E(z);var P={rootName:"Root",outputStyle:"interface",namingStyle:"PascalCase",sortProperties:"alpha",addExport:!0,strictNullChecks:!1,markOptional:!0,extractGenerics:!0,indentSize:2,lineEnding:`
2
+ `,typeNameMap:{},typePrefix:"",typeSuffix:""};function m(n){return{kind:"primitive",type:n}}function F(){return{kind:"null"}}function L(){return{kind:"undefined"}}function _(n){return{kind:"array",elementType:n}}function A(n=[]){return{kind:"object",properties:n}}function x(n){let e=[],t=new Set;for(let r of n)if(r.kind==="union")for(let i of r.types){let o=a(i);t.has(o)||(t.add(o),e.push(i))}else{let i=a(r);t.has(i)||(t.add(i),e.push(r))}return e.length===1?e[0]:{kind:"union",types:e}}function a(n){switch(n.kind){case"primitive":return`primitive:${n.type}`;case"null":return"null";case"undefined":return"undefined";case"literal":return`literal:${typeof n.value}:${String(n.value)}`;case"array":return`array:${a(n.elementType)}`;case"object":return`object:${n.properties.map(e=>`${e.name}:${a(e.type)}:${e.optional}`).join(",")}`;case"union":return`union:${n.types.map(a).sort().join("|")}`;case"generic":return`generic:${n.name}:${n.typeArgs.map(a).join(",")}`;default:return"unknown"}}function d(n,e){return a(n)===a(e)?n:n.kind==="object"&&e.kind==="object"?j(n,e):n.kind==="array"&&e.kind==="array"?_(d(n.elementType,e.elementType)):x([n,e])}function j(n,e){let t=new Map;for(let r of n.properties)t.set(r.name,{...r});for(let r of e.properties){let i=t.get(r.name);i?(i.type=d(i.type,r.type),i.optional=i.optional||r.optional):t.set(r.name,{...r,optional:!0})}for(let[r,i]of t)e.properties.some(s=>s.name===r)||(i.optional=!0);return A(Array.from(t.values()))}function u(n){return n===null?F():n===void 0?L():typeof n=="function"?m("function"):typeof n=="string"?m("string"):typeof n=="number"?m("number"):typeof n=="boolean"?m("boolean"):Array.isArray(n)?O(n):typeof n=="object"?v(n):m("unknown")}function O(n){if(n.length===0)return{kind:"array",elementType:{kind:"primitive",type:"any"}};let e=n.map(r=>u(r)),t=e[0];for(let r=1;r<e.length;r++)t=d(t,e[r]);return{kind:"array",elementType:t}}function v(n){let e=[];for(let[t,r]of Object.entries(n)){let i=u(r);e.push({name:t,type:i,optional:!1})}return A(e)}function N(n,e){return a(n)===a(e)}function c(n){switch(n.kind){case"primitive":case"null":case"undefined":return{...n};case"literal":return{...n};case"array":return{...n,elementType:c(n.elementType)};case"object":return{...n,properties:n.properties.map(e=>({...e,type:c(e.type)}))};case"union":return{...n,types:n.types.map(e=>c(e))};case"generic":return{...n,typeArgs:n.typeArgs.map(e=>c(e))};default:return{...n}}}var l=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")return null;let r=this.buildPathKey(t);if(this.customNameMap[r])return this.applyAffixes(this.customNameMap[r]);let i=this.getTypeKey(e);if(this.namedTypes.has(i))return this.namedTypes.get(i);let o=this.generateName(e,t);return o=this.formatName(o),o=this.ensureUniqueName(o),o=this.applyAffixes(o),this.namedTypes.set(i,o),o}generateName(e,t){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){return e.path||""}getTypeKey(e){return e.kind==="object"?`object:${e.properties.map(t=>`${t.name}:${this.getSimpleTypeKey(t.type)}:${t.optional}`).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"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,path:t,depth:0}),this.collectRecursive(e,{fieldName:t,parentName:void 0,path:t,depth:0});let i=this.collected.find(s=>s.name===t),o=this.collected.filter(s=>s.name!==t);return i?[i,...o]:this.collected}collectRecursive(e,t){let r=this.getStructKey(e);if(e.kind==="object"){let i=this.namer.nameType(e,t);if(i&&!this.seenStructs.has(r)){this.seenStructs.add(r),this.collected.push({name:i,type:c(e)});for(let o of e.properties)this.collectRecursive(o.type,{fieldName:o.name,parentName:i,path:t.path?`${t.path}.${o.name}`:o.name,depth:t.depth+1})}return}if(e.kind==="array"){this.collectRecursive(e.elementType,{fieldName:t.fieldName?t.fieldName+"Item":void 0,parentName:t.parentName,path:t.path,depth:t.depth+1});return}if(e.kind==="union"){for(let i of e.types)this.collectRecursive(i,t);return}if(e.kind==="generic"){for(let i of e.typeArgs)this.collectRecursive(i,{...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}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"generic":return`generic:${e.name}`;default:return"unknown"}}};var f=class{constructor(e,t){this.allNamedTypes=[];this.options=e,this.namer=t}findTypeName(e){if(e.kind!=="object")return null;for(let t of this.allNamedTypes)if(N(t.type,e))return t.name;return null}formatTypeDef(e){let{name:t,type:r}=e,i=this.options.addExport?"export ":"";return this.formatObjectType(t,r,i)}formatObjectType(e,t,r){let i=" ".repeat(this.options.indentSize),o=this.sortProperties(t.properties),s=[];this.options.outputStyle==="interface"?s.push(`${r}interface ${e} {`):s.push(`${r}type ${e} = {`);for(let p of o){let k=this.formatPropertyName(p.name),C=p.optional?"?":"",D=this.formatType(p.type);s.push(`${i}${k}${C}: ${D};`)}return this.options.outputStyle==="interface"?s.push("}"):s.push("};"),s.join(`
3
3
  `)}formatType(e){if(e.kind==="object"){let t=this.findTypeName(e);if(t)return t}switch(e.kind){case"primitive":return e.type;case"null":return"null";case"undefined":return"undefined";case"array":return this.formatArrayType(e);case"object":return this.formatInlineObject(e);case"union":return this.formatUnionType(e.types);case"literal":return this.formatLiteral(e.value);case"generic":return`${e.name}<${e.typeArgs.map(t=>this.formatType(t)).join(", ")}>`;default:return"unknown"}}formatLiteral(e){return typeof e=="string"?`'${e}'`:String(e)}formatArrayType(e){let t=this.formatType(e.elementType);return e.elementType.kind==="union"?`(${t})[]`:`${t}[]`}formatInlineObject(e){let t=" ".repeat(this.options.indentSize),r=this.sortProperties(e.properties);if(r.length===0)return"{}";let i=["{"];for(let o of r){let s=this.formatPropertyName(o.name),p=o.optional?"?":"",k=this.formatType(o.type);i.push(`${t}${s}${p}: ${k};`)}return i.push("}"),i.join(`
4
4
  `)}formatUnionType(e){return e.map(t=>this.formatType(t)).join(" | ")}formatPropertyName(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?e:`'${e}'`}sortProperties(e){return this.options.sortProperties==="definition"?[...e]:[...e].sort((t,r)=>t.name.localeCompare(r.name))}formatAll(e){return this.allNamedTypes=e,e.map(t=>this.formatTypeDef(t)).join(`
5
5
 
@@ -9,4 +9,4 @@
9
9
  */`,i=this.formatAll(e);return`${r}
10
10
 
11
11
  ${i}
12
- `}};var T=class{constructor(){this.patterns=[{name:"PageResult",arrayFields:["list","records","rows","items"],countFields:["total","count","totalCount"]},{name:"ListResult",arrayFields:["list","data","items"],countFields:[]},{name:"ApiResponse",arrayFields:["data"],countFields:[]}]}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 e}tryMatchPattern(e,t){let r=null,i=t.countFields.length===0;for(let o of e.properties)t.arrayFields.includes(o.name)&&o.type.kind==="array"&&(r={name:o.name,elementType:o.type.elementType}),t.countFields.includes(o.name)&&(i=!0);return r&&i?{kind:"generic",name:t.name,typeArgs:[r.elementType]}:null}},g=class{constructor(e=!1){this.strict=e}process(e){if(this.strict)return e;if(e.kind==="union"){let t=e.types.filter(r=>r.kind!=="null");return t.length===0?{kind:"null"}:t.length===1?t[0]:{...e,types:t}}return e.kind==="array"?{...e,elementType:this.process(e.elementType)}:e.kind==="object"?{...e,properties:e.properties.map(t=>({...t,type:this.process(t.type)}))}:e}},h=class{constructor(e=!0){this.markOptional=e}process(e,t){if(!this.markOptional)return t;if(t.kind==="array"&&Array.isArray(e)){let r=t.elementType;if(r.kind==="object"){let i=this.processArrayObjects(e,r);return{...t,elementType:i}}}return t}processArrayObjects(e,t){if(e.length<=1)return t;let r={},i=e.length;for(let o of e)if(o&&typeof o=="object")for(let s of Object.keys(o))r[s]=(r[s]||0)+1;return{...t,properties:t.properties.map(o=>{let p=(r[o.name]||0)<i;return{...o,optional:p}})}}};function S(n,e,t){let r=e;return t.markOptional&&(r=new h(t.markOptional).process(n,r)),t.extractGenerics&&(r=new T().extract(r)),r=new g(t.strictNullChecks).process(r),r}function $(n,e={}){let t={...P,...e},r=c(n);r=S(n,r,t);let i=new l({namingStyle:t.namingStyle,prefix:t.typePrefix,suffix:t.typeSuffix,customNameMap:t.typeNameMap}),s=new f(i).collect(r,t.rootName);return new y(t,i).generateOutput(s,t.rootName)}function w(n,e={}){let t=JSON.parse(n);return $(t,e)}var q={generate:$,generateFromString:w};0&&(module.exports={CodeFormatter,GenericExtractor,NullHandler,OptionalHandler,TypeCollector,TypeNamer,applyEnhancements,createUnion,generate,generateFromString,inferArrayType,inferObjectType,inferType,isStructurallyEqual,mergeObjects,mergeTypes});
12
+ `}};var T=class{constructor(){this.patterns=[{name:"PageResult",arrayFields:["list","records","rows","items"],countFields:["total","count","totalCount"]},{name:"ListResult",arrayFields:["list","data","items"],countFields:[]},{name:"ApiResponse",arrayFields:["data"],countFields:[]}]}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 e}tryMatchPattern(e,t){let r=null,i=t.countFields.length===0;for(let o of e.properties)t.arrayFields.includes(o.name)&&o.type.kind==="array"&&(r={name:o.name,elementType:o.type.elementType}),t.countFields.includes(o.name)&&(i=!0);return r&&i?{kind:"generic",name:t.name,typeArgs:[r.elementType]}:null}},g=class{constructor(e=!1){this.strict=e}process(e){if(this.strict)return e;if(e.kind==="union"){let t=e.types.filter(r=>r.kind!=="null");return t.length===0?{kind:"null"}:t.length===1?t[0]:{...e,types:t}}return e.kind==="array"?{...e,elementType:this.process(e.elementType)}:e.kind==="object"?{...e,properties:e.properties.map(t=>({...t,type:this.process(t.type)}))}:e}},h=class{constructor(e=!0){this.markOptional=e}process(e,t){if(!this.markOptional)return t;if(t.kind==="array"&&Array.isArray(e)){let r=t.elementType;if(r.kind==="object"){let i=this.processArrayObjects(e,r);return{...t,elementType:i}}}return t}processArrayObjects(e,t){if(e.length<=1)return t;let r={},i=e.length;for(let o of e)if(o&&typeof o=="object")for(let s of Object.keys(o))r[s]=(r[s]||0)+1;return{...t,properties:t.properties.map(o=>{let p=(r[o.name]||0)<i;return{...o,optional:p}})}}};function S(n,e,t){let r=e;return t.markOptional&&(r=new h(t.markOptional).process(n,r)),t.extractGenerics&&(r=new T().extract(r)),r=new g(t.strictNullChecks).process(r),r}function $(n,e={}){let t={...P,...e},r=u(n);r=S(n,r,t);let i=new l({namingStyle:t.namingStyle,prefix:t.typePrefix,suffix:t.typeSuffix,customNameMap:t.typeNameMap}),s=new y(i).collect(r,t.rootName);return new f(t,i).generateOutput(s,t.rootName)}function w(n,e={}){let t=JSON.parse(n);return $(t,e)}var q={generate:$,generateFromString:w};0&&(module.exports={CodeFormatter,GenericExtractor,NullHandler,OptionalHandler,TypeCollector,TypeNamer,applyEnhancements,createUnion,generate,generateFromString,inferArrayType,inferObjectType,inferType,isStructurallyEqual,mergeObjects,mergeTypes});
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  var b={rootName:"Root",outputStyle:"interface",namingStyle:"PascalCase",sortProperties:"alpha",addExport:!0,strictNullChecks:!1,markOptional:!0,extractGenerics:!0,indentSize:2,lineEnding:`
2
- `,typeNameMap:{},typePrefix:"",typeSuffix:""};function c(n){return{kind:"primitive",type:n}}function C(){return{kind:"null"}}function D(){return{kind:"undefined"}}function R(n){return{kind:"array",elementType:n}}function x(n=[]){return{kind:"object",properties:n}}function j(n){let e=[],t=new Set;for(let r of n)if(r.kind==="union")for(let i of r.types){let o=a(i);t.has(o)||(t.add(o),e.push(i))}else{let i=a(r);t.has(i)||(t.add(i),e.push(r))}return e.length===1?e[0]:{kind:"union",types:e}}function a(n){switch(n.kind){case"primitive":return`primitive:${n.type}`;case"null":return"null";case"undefined":return"undefined";case"literal":return`literal:${typeof n.value}:${String(n.value)}`;case"array":return`array:${a(n.elementType)}`;case"object":return`object:${n.properties.map(e=>`${e.name}:${a(e.type)}:${e.optional}`).join(",")}`;case"union":return`union:${n.types.map(a).sort().join("|")}`;case"generic":return`generic:${n.name}:${n.typeArgs.map(a).join(",")}`;default:return"unknown"}}function d(n,e){return a(n)===a(e)?n:n.kind==="object"&&e.kind==="object"?O(n,e):n.kind==="array"&&e.kind==="array"?R(d(n.elementType,e.elementType)):j([n,e])}function O(n,e){let t=new Map;for(let r of n.properties)t.set(r.name,{...r});for(let r of e.properties){let i=t.get(r.name);i?(i.type=d(i.type,r.type),i.optional=i.optional||r.optional):t.set(r.name,{...r,optional:!0})}for(let[r,i]of t)e.properties.some(s=>s.name===r)||(i.optional=!0);return x(Array.from(t.values()))}function l(n){return n===null?C():n===void 0?D():typeof n=="function"?c("function"):typeof n=="string"?c("string"):typeof n=="number"?c("number"):typeof n=="boolean"?c("boolean"):Array.isArray(n)?v(n):typeof n=="object"?$(n):c("unknown")}function v(n){if(n.length===0)return{kind:"array",elementType:{kind:"primitive",type:"any"}};let e=n.map(r=>l(r)),t=e[0];for(let r=1;r<e.length;r++)t=d(t,e[r]);return{kind:"array",elementType:t}}function $(n){let e=[];for(let[t,r]of Object.entries(n)){let i=l(r);e.push({name:t,type:i,optional:!1})}return x(e)}function S(n,e){return a(n)===a(e)}function u(n){switch(n.kind){case"primitive":case"null":case"undefined":return{...n};case"literal":return{...n};case"array":return{...n,elementType:u(n.elementType)};case"object":return{...n,properties:n.properties.map(e=>({...e,type:u(e.type)}))};case"union":return{...n,types:n.types.map(e=>u(e))};case"generic":return{...n,typeArgs:n.typeArgs.map(e=>u(e))};default:return{...n}}}var f=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")return null;let r=this.buildPathKey(t);if(this.customNameMap[r])return this.applyAffixes(this.customNameMap[r]);let i=this.getTypeKey(e);if(this.namedTypes.has(i))return this.namedTypes.get(i);let o=this.generateName(e,t);return o=this.formatName(o),o=this.ensureUniqueName(o),o=this.applyAffixes(o),this.namedTypes.set(i,o),o}generateName(e,t){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}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"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 i=this.collected.find(s=>s.name===t),o=this.collected.filter(s=>s.name!==t);return i?[i,...o]:this.collected}collectRecursive(e,t){let r=this.getStructKey(e);if(e.kind==="object"){let i=this.namer.nameType(e,t);if(i&&!this.seenStructs.has(r)){this.seenStructs.add(r),this.collected.push({name:i,type:u(e)});for(let o of e.properties)this.collectRecursive(o.type,{fieldName:o.name,parentName:i,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 i of e.types)this.collectRecursive(i,t);return}if(e.kind==="generic"){for(let i of e.typeArgs)this.collectRecursive(i,{...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}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"generic":return`generic:${e.name}`;default:return"unknown"}}};var m=class{constructor(e,t){this.allNamedTypes=[];this.options=e,this.namer=t}findTypeName(e){if(e.kind!=="object")return null;for(let t of this.allNamedTypes)if(S(t.type,e))return t.name;return null}formatTypeDef(e){let{name:t,type:r}=e,i=this.options.addExport?"export ":"";return this.formatObjectType(t,r,i)}formatObjectType(e,t,r){let i=" ".repeat(this.options.indentSize),o=this.sortProperties(t.properties),s=[];this.options.outputStyle==="interface"?s.push(`${r}interface ${e} {`):s.push(`${r}type ${e} = {`);for(let p of o){let N=this.formatPropertyName(p.name),A=p.optional?"?":"",w=this.formatType(p.type);s.push(`${i}${N}${A}: ${w};`)}return this.options.outputStyle==="interface"?s.push("}"):s.push("};"),s.join(`
2
+ `,typeNameMap:{},typePrefix:"",typeSuffix:""};function u(n){return{kind:"primitive",type:n}}function C(){return{kind:"null"}}function D(){return{kind:"undefined"}}function R(n){return{kind:"array",elementType:n}}function x(n=[]){return{kind:"object",properties:n}}function j(n){let e=[],t=new Set;for(let r of n)if(r.kind==="union")for(let i of r.types){let o=a(i);t.has(o)||(t.add(o),e.push(i))}else{let i=a(r);t.has(i)||(t.add(i),e.push(r))}return e.length===1?e[0]:{kind:"union",types:e}}function a(n){switch(n.kind){case"primitive":return`primitive:${n.type}`;case"null":return"null";case"undefined":return"undefined";case"literal":return`literal:${typeof n.value}:${String(n.value)}`;case"array":return`array:${a(n.elementType)}`;case"object":return`object:${n.properties.map(e=>`${e.name}:${a(e.type)}:${e.optional}`).join(",")}`;case"union":return`union:${n.types.map(a).sort().join("|")}`;case"generic":return`generic:${n.name}:${n.typeArgs.map(a).join(",")}`;default:return"unknown"}}function d(n,e){return a(n)===a(e)?n:n.kind==="object"&&e.kind==="object"?O(n,e):n.kind==="array"&&e.kind==="array"?R(d(n.elementType,e.elementType)):j([n,e])}function O(n,e){let t=new Map;for(let r of n.properties)t.set(r.name,{...r});for(let r of e.properties){let i=t.get(r.name);i?(i.type=d(i.type,r.type),i.optional=i.optional||r.optional):t.set(r.name,{...r,optional:!0})}for(let[r,i]of t)e.properties.some(s=>s.name===r)||(i.optional=!0);return x(Array.from(t.values()))}function l(n){return n===null?C():n===void 0?D():typeof n=="function"?u("function"):typeof n=="string"?u("string"):typeof n=="number"?u("number"):typeof n=="boolean"?u("boolean"):Array.isArray(n)?v(n):typeof n=="object"?$(n):u("unknown")}function v(n){if(n.length===0)return{kind:"array",elementType:{kind:"primitive",type:"any"}};let e=n.map(r=>l(r)),t=e[0];for(let r=1;r<e.length;r++)t=d(t,e[r]);return{kind:"array",elementType:t}}function $(n){let e=[];for(let[t,r]of Object.entries(n)){let i=l(r);e.push({name:t,type:i,optional:!1})}return x(e)}function S(n,e){return a(n)===a(e)}function c(n){switch(n.kind){case"primitive":case"null":case"undefined":return{...n};case"literal":return{...n};case"array":return{...n,elementType:c(n.elementType)};case"object":return{...n,properties:n.properties.map(e=>({...e,type:c(e.type)}))};case"union":return{...n,types:n.types.map(e=>c(e))};case"generic":return{...n,typeArgs:n.typeArgs.map(e=>c(e))};default:return{...n}}}var y=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")return null;let r=this.buildPathKey(t);if(this.customNameMap[r])return this.applyAffixes(this.customNameMap[r]);let i=this.getTypeKey(e);if(this.namedTypes.has(i))return this.namedTypes.get(i);let o=this.generateName(e,t);return o=this.formatName(o),o=this.ensureUniqueName(o),o=this.applyAffixes(o),this.namedTypes.set(i,o),o}generateName(e,t){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){return e.path||""}getTypeKey(e){return e.kind==="object"?`object:${e.properties.map(t=>`${t.name}:${this.getSimpleTypeKey(t.type)}:${t.optional}`).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"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()}},f=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,path:t,depth:0}),this.collectRecursive(e,{fieldName:t,parentName:void 0,path:t,depth:0});let i=this.collected.find(s=>s.name===t),o=this.collected.filter(s=>s.name!==t);return i?[i,...o]:this.collected}collectRecursive(e,t){let r=this.getStructKey(e);if(e.kind==="object"){let i=this.namer.nameType(e,t);if(i&&!this.seenStructs.has(r)){this.seenStructs.add(r),this.collected.push({name:i,type:c(e)});for(let o of e.properties)this.collectRecursive(o.type,{fieldName:o.name,parentName:i,path:t.path?`${t.path}.${o.name}`:o.name,depth:t.depth+1})}return}if(e.kind==="array"){this.collectRecursive(e.elementType,{fieldName:t.fieldName?t.fieldName+"Item":void 0,parentName:t.parentName,path:t.path,depth:t.depth+1});return}if(e.kind==="union"){for(let i of e.types)this.collectRecursive(i,t);return}if(e.kind==="generic"){for(let i of e.typeArgs)this.collectRecursive(i,{...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}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"generic":return`generic:${e.name}`;default:return"unknown"}}};var m=class{constructor(e,t){this.allNamedTypes=[];this.options=e,this.namer=t}findTypeName(e){if(e.kind!=="object")return null;for(let t of this.allNamedTypes)if(S(t.type,e))return t.name;return null}formatTypeDef(e){let{name:t,type:r}=e,i=this.options.addExport?"export ":"";return this.formatObjectType(t,r,i)}formatObjectType(e,t,r){let i=" ".repeat(this.options.indentSize),o=this.sortProperties(t.properties),s=[];this.options.outputStyle==="interface"?s.push(`${r}interface ${e} {`):s.push(`${r}type ${e} = {`);for(let p of o){let N=this.formatPropertyName(p.name),A=p.optional?"?":"",w=this.formatType(p.type);s.push(`${i}${N}${A}: ${w};`)}return this.options.outputStyle==="interface"?s.push("}"):s.push("};"),s.join(`
3
3
  `)}formatType(e){if(e.kind==="object"){let t=this.findTypeName(e);if(t)return t}switch(e.kind){case"primitive":return e.type;case"null":return"null";case"undefined":return"undefined";case"array":return this.formatArrayType(e);case"object":return this.formatInlineObject(e);case"union":return this.formatUnionType(e.types);case"literal":return this.formatLiteral(e.value);case"generic":return`${e.name}<${e.typeArgs.map(t=>this.formatType(t)).join(", ")}>`;default:return"unknown"}}formatLiteral(e){return typeof e=="string"?`'${e}'`:String(e)}formatArrayType(e){let t=this.formatType(e.elementType);return e.elementType.kind==="union"?`(${t})[]`:`${t}[]`}formatInlineObject(e){let t=" ".repeat(this.options.indentSize),r=this.sortProperties(e.properties);if(r.length===0)return"{}";let i=["{"];for(let o of r){let s=this.formatPropertyName(o.name),p=o.optional?"?":"",N=this.formatType(o.type);i.push(`${t}${s}${p}: ${N};`)}return i.push("}"),i.join(`
4
4
  `)}formatUnionType(e){return e.map(t=>this.formatType(t)).join(" | ")}formatPropertyName(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?e:`'${e}'`}sortProperties(e){return this.options.sortProperties==="definition"?[...e]:[...e].sort((t,r)=>t.name.localeCompare(r.name))}formatAll(e){return this.allNamedTypes=e,e.map(t=>this.formatTypeDef(t)).join(`
5
5
 
@@ -9,4 +9,4 @@ var b={rootName:"Root",outputStyle:"interface",namingStyle:"PascalCase",sortProp
9
9
  */`,i=this.formatAll(e);return`${r}
10
10
 
11
11
  ${i}
12
- `}};var T=class{constructor(){this.patterns=[{name:"PageResult",arrayFields:["list","records","rows","items"],countFields:["total","count","totalCount"]},{name:"ListResult",arrayFields:["list","data","items"],countFields:[]},{name:"ApiResponse",arrayFields:["data"],countFields:[]}]}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 e}tryMatchPattern(e,t){let r=null,i=t.countFields.length===0;for(let o of e.properties)t.arrayFields.includes(o.name)&&o.type.kind==="array"&&(r={name:o.name,elementType:o.type.elementType}),t.countFields.includes(o.name)&&(i=!0);return r&&i?{kind:"generic",name:t.name,typeArgs:[r.elementType]}:null}},g=class{constructor(e=!1){this.strict=e}process(e){if(this.strict)return e;if(e.kind==="union"){let t=e.types.filter(r=>r.kind!=="null");return t.length===0?{kind:"null"}:t.length===1?t[0]:{...e,types:t}}return e.kind==="array"?{...e,elementType:this.process(e.elementType)}:e.kind==="object"?{...e,properties:e.properties.map(t=>({...t,type:this.process(t.type)}))}:e}},h=class{constructor(e=!0){this.markOptional=e}process(e,t){if(!this.markOptional)return t;if(t.kind==="array"&&Array.isArray(e)){let r=t.elementType;if(r.kind==="object"){let i=this.processArrayObjects(e,r);return{...t,elementType:i}}}return t}processArrayObjects(e,t){if(e.length<=1)return t;let r={},i=e.length;for(let o of e)if(o&&typeof o=="object")for(let s of Object.keys(o))r[s]=(r[s]||0)+1;return{...t,properties:t.properties.map(o=>{let p=(r[o.name]||0)<i;return{...o,optional:p}})}}};function k(n,e,t){let r=e;return t.markOptional&&(r=new h(t.markOptional).process(n,r)),t.extractGenerics&&(r=new T().extract(r)),r=new g(t.strictNullChecks).process(r),r}function P(n,e={}){let t={...b,...e},r=l(n);r=k(n,r,t);let i=new f({namingStyle:t.namingStyle,prefix:t.typePrefix,suffix:t.typeSuffix,customNameMap:t.typeNameMap}),s=new y(i).collect(r,t.rootName);return new m(t,i).generateOutput(s,t.rootName)}function U(n,e={}){let t=JSON.parse(n);return P(t,e)}var B={generate:P,generateFromString:U};export{m as CodeFormatter,T as GenericExtractor,g as NullHandler,h as OptionalHandler,y as TypeCollector,f as TypeNamer,k as applyEnhancements,j as createUnion,B as default,P as generate,U as generateFromString,v as inferArrayType,$ as inferObjectType,l as inferType,S as isStructurallyEqual,O as mergeObjects,d as mergeTypes};
12
+ `}};var T=class{constructor(){this.patterns=[{name:"PageResult",arrayFields:["list","records","rows","items"],countFields:["total","count","totalCount"]},{name:"ListResult",arrayFields:["list","data","items"],countFields:[]},{name:"ApiResponse",arrayFields:["data"],countFields:[]}]}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 e}tryMatchPattern(e,t){let r=null,i=t.countFields.length===0;for(let o of e.properties)t.arrayFields.includes(o.name)&&o.type.kind==="array"&&(r={name:o.name,elementType:o.type.elementType}),t.countFields.includes(o.name)&&(i=!0);return r&&i?{kind:"generic",name:t.name,typeArgs:[r.elementType]}:null}},g=class{constructor(e=!1){this.strict=e}process(e){if(this.strict)return e;if(e.kind==="union"){let t=e.types.filter(r=>r.kind!=="null");return t.length===0?{kind:"null"}:t.length===1?t[0]:{...e,types:t}}return e.kind==="array"?{...e,elementType:this.process(e.elementType)}:e.kind==="object"?{...e,properties:e.properties.map(t=>({...t,type:this.process(t.type)}))}:e}},h=class{constructor(e=!0){this.markOptional=e}process(e,t){if(!this.markOptional)return t;if(t.kind==="array"&&Array.isArray(e)){let r=t.elementType;if(r.kind==="object"){let i=this.processArrayObjects(e,r);return{...t,elementType:i}}}return t}processArrayObjects(e,t){if(e.length<=1)return t;let r={},i=e.length;for(let o of e)if(o&&typeof o=="object")for(let s of Object.keys(o))r[s]=(r[s]||0)+1;return{...t,properties:t.properties.map(o=>{let p=(r[o.name]||0)<i;return{...o,optional:p}})}}};function k(n,e,t){let r=e;return t.markOptional&&(r=new h(t.markOptional).process(n,r)),t.extractGenerics&&(r=new T().extract(r)),r=new g(t.strictNullChecks).process(r),r}function P(n,e={}){let t={...b,...e},r=l(n);r=k(n,r,t);let i=new y({namingStyle:t.namingStyle,prefix:t.typePrefix,suffix:t.typeSuffix,customNameMap:t.typeNameMap}),s=new f(i).collect(r,t.rootName);return new m(t,i).generateOutput(s,t.rootName)}function U(n,e={}){let t=JSON.parse(n);return P(t,e)}var B={generate:P,generateFromString:U};export{m as CodeFormatter,T as GenericExtractor,g as NullHandler,h as OptionalHandler,f as TypeCollector,y as TypeNamer,k as applyEnhancements,j as createUnion,B as default,P as generate,U as generateFromString,v as inferArrayType,$ as inferObjectType,l as inferType,S as isStructurallyEqual,O as mergeObjects,d as mergeTypes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-flash",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "JSON 智能生成 TypeScript 类型定义 - 一键从 JSON 数据生成 Interface / Type 定义",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",