@chnak/zod-to-markdown 1.0.4 → 1.0.6
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/lib/index.js +192 -113
- package/lib/index.test.js +60 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.zodSchemaToMarkdown = exports.zodSchemaToTable = void 0;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* 使用 typeName 检查 Zod 类型,解决跨模块实例化导致的 instanceof 失败问题
|
|
6
|
+
*/
|
|
7
|
+
function isZodType(schema, typeName) {
|
|
8
|
+
var _a;
|
|
9
|
+
return ((_a = schema._def) === null || _a === void 0 ? void 0 : _a.typeName) === typeName;
|
|
10
|
+
}
|
|
5
11
|
/**
|
|
6
12
|
* 将 Zod schema 转换为表格形式的 Markdown
|
|
7
13
|
* @param schema - 要转换的 Zod schema
|
|
8
14
|
* @returns 表格形式的 Markdown 字符串
|
|
9
15
|
*/
|
|
10
16
|
function zodSchemaToTable(schema) {
|
|
11
|
-
if (!(schema
|
|
17
|
+
if (!isZodType(schema, 'ZodObject')) {
|
|
12
18
|
return zodSchemaToMarkdown(schema);
|
|
13
19
|
}
|
|
14
20
|
// 收集所有嵌套字段
|
|
@@ -30,13 +36,13 @@ exports.zodSchemaToTable = zodSchemaToTable;
|
|
|
30
36
|
*/
|
|
31
37
|
function collectFields(schema, prefix, fields, wrapperType) {
|
|
32
38
|
// 处理 Optional - 包装类型
|
|
33
|
-
if (schema
|
|
39
|
+
if (isZodType(schema, 'ZodOptional')) {
|
|
34
40
|
const inner = schema.unwrap();
|
|
35
41
|
// 对于简单类型直接包装
|
|
36
|
-
if (inner
|
|
42
|
+
if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodArray')) {
|
|
37
43
|
collectFields(inner, prefix, fields, 'Optional');
|
|
38
44
|
}
|
|
39
|
-
else if (inner
|
|
45
|
+
else if (isZodType(inner, 'ZodUnion') || isZodType(inner, 'ZodDiscriminatedUnion') || isZodType(inner, 'ZodIntersection')) {
|
|
40
46
|
// 嵌套的复杂类型也需要展开
|
|
41
47
|
collectFields(inner, prefix, fields, 'Optional');
|
|
42
48
|
}
|
|
@@ -50,12 +56,12 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
50
56
|
return;
|
|
51
57
|
}
|
|
52
58
|
// 处理 Nullable - 包装类型
|
|
53
|
-
if (schema
|
|
59
|
+
if (isZodType(schema, 'ZodNullable')) {
|
|
54
60
|
const inner = schema.unwrap();
|
|
55
|
-
if (inner
|
|
61
|
+
if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodArray')) {
|
|
56
62
|
collectFields(inner, prefix, fields, 'Nullable');
|
|
57
63
|
}
|
|
58
|
-
else if (inner
|
|
64
|
+
else if (isZodType(inner, 'ZodUnion') || isZodType(inner, 'ZodDiscriminatedUnion') || isZodType(inner, 'ZodIntersection')) {
|
|
59
65
|
// 嵌套的复杂类型也需要展开
|
|
60
66
|
collectFields(inner, prefix, fields, 'Nullable');
|
|
61
67
|
}
|
|
@@ -69,15 +75,15 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
69
75
|
return;
|
|
70
76
|
}
|
|
71
77
|
// 处理 Default
|
|
72
|
-
if (schema
|
|
78
|
+
if (isZodType(schema, 'ZodDefault')) {
|
|
73
79
|
collectFields(schema.removeDefault(), prefix, fields);
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
82
|
// 处理 Array - 收集元素类型
|
|
77
|
-
if (schema
|
|
83
|
+
if (isZodType(schema, 'ZodArray')) {
|
|
78
84
|
const element = schema.element;
|
|
79
85
|
// 如果是对象数组,展开其字段
|
|
80
|
-
if (element
|
|
86
|
+
if (isZodType(element, 'ZodObject')) {
|
|
81
87
|
const innerFields = [];
|
|
82
88
|
collectFields(element, '', innerFields);
|
|
83
89
|
innerFields.forEach(field => {
|
|
@@ -89,16 +95,20 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
89
95
|
});
|
|
90
96
|
});
|
|
91
97
|
}
|
|
92
|
-
else if (element
|
|
98
|
+
else if (isZodType(element, 'ZodUnion') || isZodType(element, 'ZodDiscriminatedUnion')) {
|
|
93
99
|
// 数组元素是 Union 类型时,展开每个选项
|
|
94
|
-
|
|
100
|
+
const unionSchema = element;
|
|
101
|
+
unionSchema.options.forEach((opt, index) => {
|
|
95
102
|
// 对于 ZodOptional/ZodNullable,保留包装类型信息
|
|
96
|
-
if (opt
|
|
103
|
+
if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
|
|
97
104
|
const typeStr = getTypeString(opt);
|
|
98
|
-
const
|
|
99
|
-
|
|
105
|
+
const innerWrapperType = isZodType(opt, 'ZodOptional') ? 'Optional' : 'Nullable';
|
|
106
|
+
const inner = isZodType(opt, 'ZodOptional')
|
|
107
|
+
? opt.unwrap()
|
|
108
|
+
: opt.unwrap();
|
|
109
|
+
if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodIntersection')) {
|
|
100
110
|
const innerFields = [];
|
|
101
|
-
collectFields(inner, '', innerFields);
|
|
111
|
+
collectFields(inner, '', innerFields, innerWrapperType);
|
|
102
112
|
innerFields.forEach(field => {
|
|
103
113
|
fields.push({
|
|
104
114
|
path: `${prefix}[].${field.path} (option ${index + 1})`,
|
|
@@ -115,7 +125,7 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
115
125
|
});
|
|
116
126
|
}
|
|
117
127
|
}
|
|
118
|
-
else if (opt
|
|
128
|
+
else if (isZodType(opt, 'ZodObject') || isZodType(opt, 'ZodIntersection')) {
|
|
119
129
|
// 对象类型或交叉类型,递归展开
|
|
120
130
|
const innerFields = [];
|
|
121
131
|
collectFields(opt, '', innerFields);
|
|
@@ -137,10 +147,10 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
137
147
|
}
|
|
138
148
|
});
|
|
139
149
|
}
|
|
140
|
-
else if (element
|
|
150
|
+
else if (isZodType(element, 'ZodOptional')) {
|
|
141
151
|
// 数组元素是 Optional 类型时,展开内部类型
|
|
142
152
|
const inner = element.unwrap();
|
|
143
|
-
if (inner
|
|
153
|
+
if (isZodType(inner, 'ZodObject')) {
|
|
144
154
|
const innerFields = [];
|
|
145
155
|
collectFields(inner, '', innerFields);
|
|
146
156
|
innerFields.forEach(field => {
|
|
@@ -171,7 +181,7 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
171
181
|
return;
|
|
172
182
|
}
|
|
173
183
|
// 处理 ZodObject - 递归展开
|
|
174
|
-
if (schema
|
|
184
|
+
if (isZodType(schema, 'ZodObject')) {
|
|
175
185
|
const shape = schema.shape;
|
|
176
186
|
Object.keys(shape).forEach(key => {
|
|
177
187
|
const subSchema = shape[key];
|
|
@@ -181,15 +191,18 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
181
191
|
return;
|
|
182
192
|
}
|
|
183
193
|
// 处理 ZodUnion - 展开每个选项
|
|
184
|
-
if (schema
|
|
185
|
-
|
|
194
|
+
if (isZodType(schema, 'ZodUnion')) {
|
|
195
|
+
const unionSchema = schema;
|
|
196
|
+
unionSchema.options.forEach((opt, index) => {
|
|
186
197
|
// 对于 ZodOptional/ZodNullable,保留包装类型信息
|
|
187
|
-
if (opt
|
|
198
|
+
if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
|
|
188
199
|
const typeStr = getTypeString(opt);
|
|
189
|
-
const innerWrapperType = opt
|
|
190
|
-
const inner = opt
|
|
200
|
+
const innerWrapperType = isZodType(opt, 'ZodOptional') ? 'Optional' : 'Nullable';
|
|
201
|
+
const inner = isZodType(opt, 'ZodOptional')
|
|
202
|
+
? opt.unwrap()
|
|
203
|
+
: opt.unwrap();
|
|
191
204
|
// 只有内部是对象或交叉类型才展开,否则直接使用类型字符串
|
|
192
|
-
if (inner
|
|
205
|
+
if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodIntersection')) {
|
|
193
206
|
const innerFields = [];
|
|
194
207
|
collectFields(inner, '', innerFields, innerWrapperType);
|
|
195
208
|
innerFields.forEach(field => {
|
|
@@ -208,7 +221,7 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
208
221
|
});
|
|
209
222
|
}
|
|
210
223
|
}
|
|
211
|
-
else if (opt
|
|
224
|
+
else if (isZodType(opt, 'ZodObject') || isZodType(opt, 'ZodIntersection')) {
|
|
212
225
|
// 对象类型或交叉类型,递归展开
|
|
213
226
|
const innerFields = [];
|
|
214
227
|
collectFields(opt, '', innerFields);
|
|
@@ -232,14 +245,17 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
232
245
|
return;
|
|
233
246
|
}
|
|
234
247
|
// 处理 ZodDiscriminatedUnion - 类似 Union 但有关联键
|
|
235
|
-
if (schema
|
|
236
|
-
|
|
248
|
+
if (isZodType(schema, 'ZodDiscriminatedUnion')) {
|
|
249
|
+
const discUnionSchema = schema;
|
|
250
|
+
discUnionSchema.options.forEach((opt, index) => {
|
|
237
251
|
// 对于 ZodOptional/ZodNullable,保留包装类型信息
|
|
238
|
-
if (opt
|
|
252
|
+
if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
|
|
239
253
|
const typeStr = getTypeString(opt);
|
|
240
|
-
const innerWrapperType = opt
|
|
241
|
-
const inner = opt
|
|
242
|
-
|
|
254
|
+
const innerWrapperType = isZodType(opt, 'ZodOptional') ? 'Optional' : 'Nullable';
|
|
255
|
+
const inner = isZodType(opt, 'ZodOptional')
|
|
256
|
+
? opt.unwrap()
|
|
257
|
+
: opt.unwrap();
|
|
258
|
+
if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodIntersection')) {
|
|
243
259
|
const innerFields = [];
|
|
244
260
|
collectFields(inner, '', innerFields, innerWrapperType);
|
|
245
261
|
innerFields.forEach(field => {
|
|
@@ -258,7 +274,7 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
258
274
|
});
|
|
259
275
|
}
|
|
260
276
|
}
|
|
261
|
-
else if (opt
|
|
277
|
+
else if (isZodType(opt, 'ZodObject') || isZodType(opt, 'ZodIntersection')) {
|
|
262
278
|
const innerFields = [];
|
|
263
279
|
collectFields(opt, '', innerFields);
|
|
264
280
|
innerFields.forEach(field => {
|
|
@@ -280,11 +296,12 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
280
296
|
return;
|
|
281
297
|
}
|
|
282
298
|
// 处理 ZodIntersection - 展开左右两部分
|
|
283
|
-
if (schema
|
|
299
|
+
if (isZodType(schema, 'ZodIntersection')) {
|
|
300
|
+
const intSchema = schema;
|
|
284
301
|
const leftFields = [];
|
|
285
302
|
const rightFields = [];
|
|
286
|
-
collectFields(
|
|
287
|
-
collectFields(
|
|
303
|
+
collectFields(intSchema._def.left, '', leftFields);
|
|
304
|
+
collectFields(intSchema._def.right, '', rightFields);
|
|
288
305
|
leftFields.forEach(field => {
|
|
289
306
|
fields.push({
|
|
290
307
|
path: `${prefix}: ${field.path} (Left)`,
|
|
@@ -302,17 +319,19 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
302
319
|
return;
|
|
303
320
|
}
|
|
304
321
|
// 处理 Record
|
|
305
|
-
if (schema
|
|
322
|
+
if (isZodType(schema, 'ZodRecord')) {
|
|
323
|
+
const recordSchema = schema;
|
|
306
324
|
fields.push({
|
|
307
325
|
path: prefix,
|
|
308
|
-
type: `Record<${getTypeString(
|
|
326
|
+
type: `Record<${getTypeString(recordSchema.keySchema)}, ${getTypeString(recordSchema.valueSchema)}>`,
|
|
309
327
|
description: schema.description || '-',
|
|
310
328
|
});
|
|
311
329
|
return;
|
|
312
330
|
}
|
|
313
331
|
// 处理 Tuple
|
|
314
|
-
if (schema
|
|
315
|
-
const
|
|
332
|
+
if (isZodType(schema, 'ZodTuple')) {
|
|
333
|
+
const tupleSchema = schema;
|
|
334
|
+
const items = tupleSchema.items.map((item) => getTypeString(item)).join(', ');
|
|
316
335
|
fields.push({
|
|
317
336
|
path: prefix,
|
|
318
337
|
type: `Tuple(${items})`,
|
|
@@ -320,6 +339,29 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
320
339
|
});
|
|
321
340
|
return;
|
|
322
341
|
}
|
|
342
|
+
// 处理 ZodEffects (transform)
|
|
343
|
+
if (isZodType(schema, 'ZodEffects')) {
|
|
344
|
+
const effectsSchema = schema;
|
|
345
|
+
const innerFields = [];
|
|
346
|
+
collectFields(effectsSchema.innerType(), prefix, innerFields);
|
|
347
|
+
if (innerFields.length > 0) {
|
|
348
|
+
innerFields.forEach(field => {
|
|
349
|
+
fields.push({
|
|
350
|
+
path: field.path,
|
|
351
|
+
type: `Effects(${effectsSchema._def.effect.type})<${field.type}>`,
|
|
352
|
+
description: field.description,
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
fields.push({
|
|
358
|
+
path: prefix,
|
|
359
|
+
type: `Effects(${effectsSchema._def.effect.type})<${getTypeString(effectsSchema.innerType())}>`,
|
|
360
|
+
description: schema.description || '-',
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
323
365
|
// 其他类型直接添加
|
|
324
366
|
let typeStr = getTypeString(schema);
|
|
325
367
|
if (wrapperType === 'Optional' && !typeStr.startsWith('Optional<') && !typeStr.startsWith('Nullable<')) {
|
|
@@ -338,88 +380,119 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
338
380
|
* 获取类型的字符串描述
|
|
339
381
|
*/
|
|
340
382
|
function getTypeString(schema) {
|
|
341
|
-
if (schema
|
|
383
|
+
if (isZodType(schema, 'ZodOptional')) {
|
|
342
384
|
return `Optional<${getTypeString(schema.unwrap())}>`;
|
|
343
385
|
}
|
|
344
|
-
if (schema
|
|
386
|
+
if (isZodType(schema, 'ZodNullable')) {
|
|
345
387
|
return `Nullable<${getTypeString(schema.unwrap())}>`;
|
|
346
388
|
}
|
|
347
|
-
if (schema
|
|
389
|
+
if (isZodType(schema, 'ZodDefault')) {
|
|
348
390
|
return `Default<${getTypeString(schema.removeDefault())}>`;
|
|
349
391
|
}
|
|
350
|
-
if (schema
|
|
392
|
+
if (isZodType(schema, 'ZodArray')) {
|
|
351
393
|
return `Array<${getTypeString(schema.element)}>`;
|
|
352
394
|
}
|
|
353
|
-
if (schema
|
|
395
|
+
if (isZodType(schema, 'ZodObject')) {
|
|
396
|
+
// ZodObject 应该被 collectFields 展开,这里仅作为兜底
|
|
397
|
+
const keys = Object.keys(schema.shape);
|
|
398
|
+
return `Object{${keys.join(', ')}}`;
|
|
399
|
+
}
|
|
400
|
+
if (isZodType(schema, 'ZodString')) {
|
|
401
|
+
const strSchema = schema;
|
|
354
402
|
let result = 'String';
|
|
355
|
-
if (
|
|
403
|
+
if (strSchema.minLength !== null || strSchema.maxLength !== null) {
|
|
356
404
|
const constraints = [];
|
|
357
|
-
if (
|
|
358
|
-
constraints.push(`min: ${
|
|
359
|
-
if (
|
|
360
|
-
constraints.push(`max: ${
|
|
405
|
+
if (strSchema.minLength !== null)
|
|
406
|
+
constraints.push(`min: ${strSchema.minLength}`);
|
|
407
|
+
if (strSchema.maxLength !== null)
|
|
408
|
+
constraints.push(`max: ${strSchema.maxLength}`);
|
|
361
409
|
result += ` (${constraints.join(', ')})`;
|
|
362
410
|
}
|
|
363
411
|
return result;
|
|
364
412
|
}
|
|
365
|
-
if (schema
|
|
413
|
+
if (isZodType(schema, 'ZodNumber')) {
|
|
414
|
+
const numSchema = schema;
|
|
366
415
|
let result = 'Number';
|
|
367
|
-
if (
|
|
416
|
+
if (numSchema.minValue !== null || numSchema.maxValue !== null) {
|
|
368
417
|
const constraints = [];
|
|
369
|
-
if (
|
|
370
|
-
constraints.push(`min: ${
|
|
371
|
-
if (
|
|
372
|
-
constraints.push(`max: ${
|
|
418
|
+
if (numSchema.minValue !== null)
|
|
419
|
+
constraints.push(`min: ${numSchema.minValue}`);
|
|
420
|
+
if (numSchema.maxValue !== null)
|
|
421
|
+
constraints.push(`max: ${numSchema.maxValue}`);
|
|
373
422
|
result += ` (${constraints.join(', ')})`;
|
|
374
423
|
}
|
|
375
424
|
return result;
|
|
376
425
|
}
|
|
377
|
-
if (schema
|
|
378
|
-
return `Enum(${schema.options.join(' | ')})`;
|
|
426
|
+
if (isZodType(schema, 'ZodEnum')) {
|
|
427
|
+
return `Enum(${(schema.options).join(' | ')})`;
|
|
379
428
|
}
|
|
380
|
-
if (schema
|
|
429
|
+
if (isZodType(schema, 'ZodLiteral')) {
|
|
381
430
|
return `Literal(${JSON.stringify(schema.value)})`;
|
|
382
431
|
}
|
|
383
|
-
if (schema
|
|
432
|
+
if (isZodType(schema, 'ZodBoolean'))
|
|
384
433
|
return 'Boolean';
|
|
385
|
-
if (schema
|
|
434
|
+
if (isZodType(schema, 'ZodBigInt'))
|
|
386
435
|
return 'BigInt';
|
|
387
|
-
if (schema
|
|
436
|
+
if (isZodType(schema, 'ZodDate'))
|
|
388
437
|
return 'Date';
|
|
389
|
-
if (schema
|
|
438
|
+
if (isZodType(schema, 'ZodNaN'))
|
|
390
439
|
return 'NaN';
|
|
391
|
-
if (schema
|
|
440
|
+
if (isZodType(schema, 'ZodNever'))
|
|
392
441
|
return 'Never';
|
|
393
|
-
if (schema
|
|
442
|
+
if (isZodType(schema, 'ZodUnknown'))
|
|
394
443
|
return 'Unknown';
|
|
395
|
-
if (schema
|
|
444
|
+
if (isZodType(schema, 'ZodVoid'))
|
|
396
445
|
return 'Void';
|
|
397
|
-
if (schema
|
|
398
|
-
|
|
446
|
+
if (isZodType(schema, 'ZodRecord')) {
|
|
447
|
+
const recSchema = schema;
|
|
448
|
+
return `Record<${getTypeString(recSchema.keySchema)}, ${getTypeString(recSchema.valueSchema)}>`;
|
|
399
449
|
}
|
|
400
|
-
if (schema
|
|
401
|
-
const
|
|
450
|
+
if (isZodType(schema, 'ZodTuple')) {
|
|
451
|
+
const tupSchema = schema;
|
|
452
|
+
const items = tupSchema.items.map((item) => getTypeString(item)).join(', ');
|
|
402
453
|
return `Tuple(${items})`;
|
|
403
454
|
}
|
|
404
|
-
if (schema
|
|
405
|
-
const
|
|
455
|
+
if (isZodType(schema, 'ZodUnion')) {
|
|
456
|
+
const unionSchema = schema;
|
|
457
|
+
const options = unionSchema.options.map((opt) => getTypeString(opt)).join(' | ');
|
|
406
458
|
return `Union(${options})`;
|
|
407
459
|
}
|
|
408
|
-
if (schema
|
|
460
|
+
if (isZodType(schema, 'ZodDiscriminatedUnion')) {
|
|
409
461
|
return `DiscriminatedUnion(${schema.discriminator})`;
|
|
410
462
|
}
|
|
411
|
-
if (schema
|
|
463
|
+
if (isZodType(schema, 'ZodIntersection')) {
|
|
412
464
|
return 'Intersection';
|
|
413
465
|
}
|
|
414
|
-
if (schema
|
|
466
|
+
if (isZodType(schema, 'ZodEffects')) {
|
|
415
467
|
return `Effects(${schema._def.effect.type})`;
|
|
416
468
|
}
|
|
417
|
-
|
|
469
|
+
if (isZodType(schema, 'ZodMap')) {
|
|
470
|
+
const mapSchema = schema;
|
|
471
|
+
return `Map<${getTypeString(mapSchema.keySchema)}, ${getTypeString(mapSchema.valueSchema)}>`;
|
|
472
|
+
}
|
|
473
|
+
if (isZodType(schema, 'ZodSet')) {
|
|
474
|
+
return `Set<${getTypeString(schema._def.valueType)}>`;
|
|
475
|
+
}
|
|
476
|
+
if (isZodType(schema, 'ZodAny'))
|
|
477
|
+
return 'Any';
|
|
478
|
+
if (isZodType(schema, 'ZodLazy')) {
|
|
479
|
+
return `Lazy(${schema._def.getter().constructor.name || 'unknown'})`;
|
|
480
|
+
}
|
|
481
|
+
if (isZodType(schema, 'ZodFunction')) {
|
|
482
|
+
const fnSchema = schema;
|
|
483
|
+
const args = fnSchema._def.args ? getTypeString(fnSchema._def.args) : 'args';
|
|
484
|
+
const returns = fnSchema._def.returns ? getTypeString(fnSchema._def.returns) : 'returns';
|
|
485
|
+
return `Function(${args} => ${returns})`;
|
|
486
|
+
}
|
|
487
|
+
if (isZodType(schema, 'ZodPromise')) {
|
|
488
|
+
return `Promise<${getTypeString(schema._def.type)}>`;
|
|
489
|
+
}
|
|
490
|
+
return schema._def.typeName || schema.constructor.name;
|
|
418
491
|
}
|
|
419
492
|
function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
420
493
|
let markdown = "";
|
|
421
494
|
const indent = " ".repeat(indentLevel);
|
|
422
|
-
if (schema
|
|
495
|
+
if (isZodType(schema, 'ZodObject')) {
|
|
423
496
|
const shape = schema.shape;
|
|
424
497
|
Object.keys(shape).forEach((key) => {
|
|
425
498
|
const subSchema = shape[key];
|
|
@@ -428,11 +501,11 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
428
501
|
markdown += zodSchemaToMarkdown(subSchema, indentLevel + 1);
|
|
429
502
|
});
|
|
430
503
|
}
|
|
431
|
-
else if (schema
|
|
504
|
+
else if (isZodType(schema, 'ZodArray')) {
|
|
432
505
|
markdown += `${indent}- Array\n`;
|
|
433
506
|
markdown += zodSchemaToMarkdown(schema.element, indentLevel + 1);
|
|
434
507
|
}
|
|
435
|
-
else if (schema
|
|
508
|
+
else if (isZodType(schema, 'ZodString')) {
|
|
436
509
|
markdown += `${indent}- String`;
|
|
437
510
|
if (schema.minLength !== null) {
|
|
438
511
|
markdown += ` (minLength: ${schema.minLength})`;
|
|
@@ -442,7 +515,7 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
442
515
|
}
|
|
443
516
|
markdown += "\n";
|
|
444
517
|
}
|
|
445
|
-
else if (schema
|
|
518
|
+
else if (isZodType(schema, 'ZodNumber')) {
|
|
446
519
|
markdown += `${indent}- Number`;
|
|
447
520
|
if (schema.minValue !== null) {
|
|
448
521
|
markdown += ` (minValue: ${schema.minValue})`;
|
|
@@ -452,93 +525,99 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
452
525
|
}
|
|
453
526
|
markdown += "\n";
|
|
454
527
|
}
|
|
455
|
-
else if (schema
|
|
528
|
+
else if (isZodType(schema, 'ZodEnum')) {
|
|
456
529
|
const values = schema.options.join(", ");
|
|
457
530
|
markdown += `${indent}- Enum: ${values}\n`;
|
|
458
531
|
}
|
|
459
|
-
else if (schema
|
|
532
|
+
else if (isZodType(schema, 'ZodUnion')) {
|
|
533
|
+
const unionSchema = schema;
|
|
460
534
|
markdown += `${indent}- Union\n`;
|
|
461
|
-
|
|
535
|
+
unionSchema.options.forEach((option, index) => {
|
|
462
536
|
markdown += zodSchemaToMarkdown(option, indentLevel + 1);
|
|
463
|
-
if (index <
|
|
537
|
+
if (index < unionSchema.options.length - 1) {
|
|
464
538
|
markdown += `${indent} |\n`;
|
|
465
539
|
}
|
|
466
540
|
});
|
|
467
541
|
}
|
|
468
|
-
else if (schema
|
|
542
|
+
else if (isZodType(schema, 'ZodBoolean')) {
|
|
469
543
|
markdown += `${indent}- Boolean\n`;
|
|
470
544
|
}
|
|
471
|
-
else if (schema
|
|
472
|
-
|
|
473
|
-
markdown +=
|
|
545
|
+
else if (isZodType(schema, 'ZodDefault')) {
|
|
546
|
+
const defSchema = schema;
|
|
547
|
+
markdown += `${indent}- Default: ${JSON.stringify(defSchema._def.defaultValue())}\n`;
|
|
548
|
+
markdown += zodSchemaToMarkdown(defSchema.removeDefault(), indentLevel);
|
|
474
549
|
}
|
|
475
|
-
else if (schema
|
|
550
|
+
else if (isZodType(schema, 'ZodOptional')) {
|
|
476
551
|
markdown += `${indent}- Optional\n`;
|
|
477
552
|
markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
|
|
478
553
|
}
|
|
479
|
-
else if (schema
|
|
554
|
+
else if (isZodType(schema, 'ZodNullable')) {
|
|
480
555
|
markdown += `${indent}- Nullable\n`;
|
|
481
556
|
markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
|
|
482
557
|
}
|
|
483
|
-
else if (schema
|
|
558
|
+
else if (isZodType(schema, 'ZodEffects')) {
|
|
484
559
|
const effectType = schema._def.effect.type;
|
|
485
560
|
markdown += `${indent}- Effects (${effectType})\n`;
|
|
486
561
|
markdown += zodSchemaToMarkdown(schema.innerType(), indentLevel + 1);
|
|
487
562
|
}
|
|
488
|
-
else if (schema
|
|
489
|
-
const
|
|
563
|
+
else if (isZodType(schema, 'ZodDiscriminatedUnion')) {
|
|
564
|
+
const discUnionSchema = schema;
|
|
565
|
+
const discriminator = discUnionSchema.discriminator;
|
|
490
566
|
markdown += `${indent}- DiscriminatedUnion (key: ${discriminator})\n`;
|
|
491
|
-
|
|
567
|
+
discUnionSchema.options.forEach((option, index) => {
|
|
492
568
|
markdown += zodSchemaToMarkdown(option, indentLevel + 1);
|
|
493
|
-
if (index <
|
|
569
|
+
if (index < discUnionSchema.options.length - 1) {
|
|
494
570
|
markdown += `${indent} |\n`;
|
|
495
571
|
}
|
|
496
572
|
});
|
|
497
573
|
}
|
|
498
|
-
else if (schema
|
|
574
|
+
else if (isZodType(schema, 'ZodIntersection')) {
|
|
575
|
+
const intSchema = schema;
|
|
499
576
|
markdown += `${indent}- Intersection\n`;
|
|
500
577
|
markdown += `${indent} Left:\n`;
|
|
501
|
-
markdown += zodSchemaToMarkdown(
|
|
578
|
+
markdown += zodSchemaToMarkdown(intSchema._def.left, indentLevel + 2);
|
|
502
579
|
markdown += `${indent} Right:\n`;
|
|
503
|
-
markdown += zodSchemaToMarkdown(
|
|
580
|
+
markdown += zodSchemaToMarkdown(intSchema._def.right, indentLevel + 2);
|
|
504
581
|
}
|
|
505
|
-
else if (schema
|
|
582
|
+
else if (isZodType(schema, 'ZodRecord')) {
|
|
583
|
+
const recSchema = schema;
|
|
506
584
|
markdown += `${indent}- Record\n`;
|
|
507
585
|
markdown += `${indent} Key:\n`;
|
|
508
|
-
markdown += zodSchemaToMarkdown(
|
|
586
|
+
markdown += zodSchemaToMarkdown(recSchema.keySchema, indentLevel + 2);
|
|
509
587
|
markdown += `${indent} Value:\n`;
|
|
510
|
-
markdown += zodSchemaToMarkdown(
|
|
588
|
+
markdown += zodSchemaToMarkdown(recSchema.valueSchema, indentLevel + 2);
|
|
511
589
|
}
|
|
512
|
-
else if (schema
|
|
590
|
+
else if (isZodType(schema, 'ZodTuple')) {
|
|
591
|
+
const tupSchema = schema;
|
|
513
592
|
markdown += `${indent}- Tuple\n`;
|
|
514
|
-
|
|
593
|
+
tupSchema.items.forEach((item, index) => {
|
|
515
594
|
markdown += `${indent} [${index}]:\n`;
|
|
516
595
|
markdown += zodSchemaToMarkdown(item, indentLevel + 2);
|
|
517
596
|
});
|
|
518
597
|
}
|
|
519
|
-
else if (schema
|
|
598
|
+
else if (isZodType(schema, 'ZodLiteral')) {
|
|
520
599
|
markdown += `${indent}- Literal: ${JSON.stringify(schema.value)}\n`;
|
|
521
600
|
}
|
|
522
|
-
else if (schema
|
|
601
|
+
else if (isZodType(schema, 'ZodBigInt')) {
|
|
523
602
|
markdown += `${indent}- BigInt\n`;
|
|
524
603
|
}
|
|
525
|
-
else if (schema
|
|
604
|
+
else if (isZodType(schema, 'ZodDate')) {
|
|
526
605
|
markdown += `${indent}- Date\n`;
|
|
527
606
|
}
|
|
528
|
-
else if (schema
|
|
607
|
+
else if (isZodType(schema, 'ZodNaN')) {
|
|
529
608
|
markdown += `${indent}- NaN\n`;
|
|
530
609
|
}
|
|
531
|
-
else if (schema
|
|
610
|
+
else if (isZodType(schema, 'ZodNever')) {
|
|
532
611
|
markdown += `${indent}- Never\n`;
|
|
533
612
|
}
|
|
534
|
-
else if (schema
|
|
613
|
+
else if (isZodType(schema, 'ZodUnknown')) {
|
|
535
614
|
markdown += `${indent}- Unknown\n`;
|
|
536
615
|
}
|
|
537
|
-
else if (schema
|
|
616
|
+
else if (isZodType(schema, 'ZodVoid')) {
|
|
538
617
|
markdown += `${indent}- Void\n`;
|
|
539
618
|
}
|
|
540
619
|
else {
|
|
541
|
-
markdown += `${indent}- Type: ${schema.constructor.name}\n`;
|
|
620
|
+
markdown += `${indent}- Type: ${schema._def.typeName || schema.constructor.name}\n`;
|
|
542
621
|
}
|
|
543
622
|
return markdown;
|
|
544
623
|
}
|
package/lib/index.test.js
CHANGED
|
@@ -309,6 +309,66 @@ describe('zodSchemaToTable', () => {
|
|
|
309
309
|
|------|------|------|
|
|
310
310
|
| items[].a (option 1) | String | - |
|
|
311
311
|
| items[].b (option 2) | Number | - |
|
|
312
|
+
`;
|
|
313
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
314
|
+
});
|
|
315
|
+
it('should convert object schema with ZodMap to table', () => {
|
|
316
|
+
const schema = zod_1.z.object({
|
|
317
|
+
map: zod_1.z.map(zod_1.z.string(), zod_1.z.number()),
|
|
318
|
+
});
|
|
319
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
320
|
+
|------|------|------|
|
|
321
|
+
| map | Map<String, Number> | - |
|
|
322
|
+
`;
|
|
323
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
324
|
+
});
|
|
325
|
+
it('should convert object schema with ZodSet to table', () => {
|
|
326
|
+
const schema = zod_1.z.object({
|
|
327
|
+
set: zod_1.z.set(zod_1.z.string()),
|
|
328
|
+
});
|
|
329
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
330
|
+
|------|------|------|
|
|
331
|
+
| set | Set<String> | - |
|
|
332
|
+
`;
|
|
333
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
334
|
+
});
|
|
335
|
+
it('should convert object schema with ZodAny to table', () => {
|
|
336
|
+
const schema = zod_1.z.object({
|
|
337
|
+
any: zod_1.z.any(),
|
|
338
|
+
});
|
|
339
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
340
|
+
|------|------|------|
|
|
341
|
+
| any | Any | - |
|
|
342
|
+
`;
|
|
343
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
344
|
+
});
|
|
345
|
+
it('should convert object schema with ZodLazy to table', () => {
|
|
346
|
+
const schema = zod_1.z.object({
|
|
347
|
+
lazy: zod_1.z.lazy(() => zod_1.z.string()),
|
|
348
|
+
});
|
|
349
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
350
|
+
|------|------|------|
|
|
351
|
+
| lazy | Lazy(ZodString) | - |
|
|
352
|
+
`;
|
|
353
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
354
|
+
});
|
|
355
|
+
it('should convert object schema with ZodFunction to table', () => {
|
|
356
|
+
const schema = zod_1.z.object({
|
|
357
|
+
fn: zod_1.z.function().args(zod_1.z.string()).returns(zod_1.z.number()),
|
|
358
|
+
});
|
|
359
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
360
|
+
|------|------|------|
|
|
361
|
+
| fn | Function(Tuple(String) => Number) | - |
|
|
362
|
+
`;
|
|
363
|
+
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
364
|
+
});
|
|
365
|
+
it('should convert object schema with ZodPromise to table', () => {
|
|
366
|
+
const schema = zod_1.z.object({
|
|
367
|
+
promise: zod_1.z.promise(zod_1.z.string()),
|
|
368
|
+
});
|
|
369
|
+
const expected = `| 字段 | 类型 | 描述 |
|
|
370
|
+
|------|------|------|
|
|
371
|
+
| promise | Promise<String> | - |
|
|
312
372
|
`;
|
|
313
373
|
expect((0, index_1.zodSchemaToTable)(schema)).toBe(expected);
|
|
314
374
|
});
|