@chnak/zod-to-markdown 1.0.5 → 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 +170 -118
- 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})`,
|
|
@@ -321,14 +340,15 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
321
340
|
return;
|
|
322
341
|
}
|
|
323
342
|
// 处理 ZodEffects (transform)
|
|
324
|
-
if (schema
|
|
343
|
+
if (isZodType(schema, 'ZodEffects')) {
|
|
344
|
+
const effectsSchema = schema;
|
|
325
345
|
const innerFields = [];
|
|
326
|
-
collectFields(
|
|
346
|
+
collectFields(effectsSchema.innerType(), prefix, innerFields);
|
|
327
347
|
if (innerFields.length > 0) {
|
|
328
348
|
innerFields.forEach(field => {
|
|
329
349
|
fields.push({
|
|
330
350
|
path: field.path,
|
|
331
|
-
type: `Effects(${
|
|
351
|
+
type: `Effects(${effectsSchema._def.effect.type})<${field.type}>`,
|
|
332
352
|
description: field.description,
|
|
333
353
|
});
|
|
334
354
|
});
|
|
@@ -336,7 +356,7 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
336
356
|
else {
|
|
337
357
|
fields.push({
|
|
338
358
|
path: prefix,
|
|
339
|
-
type: `Effects(${
|
|
359
|
+
type: `Effects(${effectsSchema._def.effect.type})<${getTypeString(effectsSchema.innerType())}>`,
|
|
340
360
|
description: schema.description || '-',
|
|
341
361
|
});
|
|
342
362
|
}
|
|
@@ -360,93 +380,119 @@ function collectFields(schema, prefix, fields, wrapperType) {
|
|
|
360
380
|
* 获取类型的字符串描述
|
|
361
381
|
*/
|
|
362
382
|
function getTypeString(schema) {
|
|
363
|
-
if (schema
|
|
383
|
+
if (isZodType(schema, 'ZodOptional')) {
|
|
364
384
|
return `Optional<${getTypeString(schema.unwrap())}>`;
|
|
365
385
|
}
|
|
366
|
-
if (schema
|
|
386
|
+
if (isZodType(schema, 'ZodNullable')) {
|
|
367
387
|
return `Nullable<${getTypeString(schema.unwrap())}>`;
|
|
368
388
|
}
|
|
369
|
-
if (schema
|
|
389
|
+
if (isZodType(schema, 'ZodDefault')) {
|
|
370
390
|
return `Default<${getTypeString(schema.removeDefault())}>`;
|
|
371
391
|
}
|
|
372
|
-
if (schema
|
|
392
|
+
if (isZodType(schema, 'ZodArray')) {
|
|
373
393
|
return `Array<${getTypeString(schema.element)}>`;
|
|
374
394
|
}
|
|
375
|
-
if (schema
|
|
395
|
+
if (isZodType(schema, 'ZodObject')) {
|
|
376
396
|
// ZodObject 应该被 collectFields 展开,这里仅作为兜底
|
|
377
397
|
const keys = Object.keys(schema.shape);
|
|
378
398
|
return `Object{${keys.join(', ')}}`;
|
|
379
399
|
}
|
|
380
|
-
if (schema
|
|
400
|
+
if (isZodType(schema, 'ZodString')) {
|
|
401
|
+
const strSchema = schema;
|
|
381
402
|
let result = 'String';
|
|
382
|
-
if (
|
|
403
|
+
if (strSchema.minLength !== null || strSchema.maxLength !== null) {
|
|
383
404
|
const constraints = [];
|
|
384
|
-
if (
|
|
385
|
-
constraints.push(`min: ${
|
|
386
|
-
if (
|
|
387
|
-
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}`);
|
|
388
409
|
result += ` (${constraints.join(', ')})`;
|
|
389
410
|
}
|
|
390
411
|
return result;
|
|
391
412
|
}
|
|
392
|
-
if (schema
|
|
413
|
+
if (isZodType(schema, 'ZodNumber')) {
|
|
414
|
+
const numSchema = schema;
|
|
393
415
|
let result = 'Number';
|
|
394
|
-
if (
|
|
416
|
+
if (numSchema.minValue !== null || numSchema.maxValue !== null) {
|
|
395
417
|
const constraints = [];
|
|
396
|
-
if (
|
|
397
|
-
constraints.push(`min: ${
|
|
398
|
-
if (
|
|
399
|
-
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}`);
|
|
400
422
|
result += ` (${constraints.join(', ')})`;
|
|
401
423
|
}
|
|
402
424
|
return result;
|
|
403
425
|
}
|
|
404
|
-
if (schema
|
|
405
|
-
return `Enum(${schema.options.join(' | ')})`;
|
|
426
|
+
if (isZodType(schema, 'ZodEnum')) {
|
|
427
|
+
return `Enum(${(schema.options).join(' | ')})`;
|
|
406
428
|
}
|
|
407
|
-
if (schema
|
|
429
|
+
if (isZodType(schema, 'ZodLiteral')) {
|
|
408
430
|
return `Literal(${JSON.stringify(schema.value)})`;
|
|
409
431
|
}
|
|
410
|
-
if (schema
|
|
432
|
+
if (isZodType(schema, 'ZodBoolean'))
|
|
411
433
|
return 'Boolean';
|
|
412
|
-
if (schema
|
|
434
|
+
if (isZodType(schema, 'ZodBigInt'))
|
|
413
435
|
return 'BigInt';
|
|
414
|
-
if (schema
|
|
436
|
+
if (isZodType(schema, 'ZodDate'))
|
|
415
437
|
return 'Date';
|
|
416
|
-
if (schema
|
|
438
|
+
if (isZodType(schema, 'ZodNaN'))
|
|
417
439
|
return 'NaN';
|
|
418
|
-
if (schema
|
|
440
|
+
if (isZodType(schema, 'ZodNever'))
|
|
419
441
|
return 'Never';
|
|
420
|
-
if (schema
|
|
442
|
+
if (isZodType(schema, 'ZodUnknown'))
|
|
421
443
|
return 'Unknown';
|
|
422
|
-
if (schema
|
|
444
|
+
if (isZodType(schema, 'ZodVoid'))
|
|
423
445
|
return 'Void';
|
|
424
|
-
if (schema
|
|
425
|
-
|
|
446
|
+
if (isZodType(schema, 'ZodRecord')) {
|
|
447
|
+
const recSchema = schema;
|
|
448
|
+
return `Record<${getTypeString(recSchema.keySchema)}, ${getTypeString(recSchema.valueSchema)}>`;
|
|
426
449
|
}
|
|
427
|
-
if (schema
|
|
428
|
-
const
|
|
450
|
+
if (isZodType(schema, 'ZodTuple')) {
|
|
451
|
+
const tupSchema = schema;
|
|
452
|
+
const items = tupSchema.items.map((item) => getTypeString(item)).join(', ');
|
|
429
453
|
return `Tuple(${items})`;
|
|
430
454
|
}
|
|
431
|
-
if (schema
|
|
432
|
-
const
|
|
455
|
+
if (isZodType(schema, 'ZodUnion')) {
|
|
456
|
+
const unionSchema = schema;
|
|
457
|
+
const options = unionSchema.options.map((opt) => getTypeString(opt)).join(' | ');
|
|
433
458
|
return `Union(${options})`;
|
|
434
459
|
}
|
|
435
|
-
if (schema
|
|
460
|
+
if (isZodType(schema, 'ZodDiscriminatedUnion')) {
|
|
436
461
|
return `DiscriminatedUnion(${schema.discriminator})`;
|
|
437
462
|
}
|
|
438
|
-
if (schema
|
|
463
|
+
if (isZodType(schema, 'ZodIntersection')) {
|
|
439
464
|
return 'Intersection';
|
|
440
465
|
}
|
|
441
|
-
if (schema
|
|
466
|
+
if (isZodType(schema, 'ZodEffects')) {
|
|
442
467
|
return `Effects(${schema._def.effect.type})`;
|
|
443
468
|
}
|
|
444
|
-
|
|
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;
|
|
445
491
|
}
|
|
446
492
|
function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
447
493
|
let markdown = "";
|
|
448
494
|
const indent = " ".repeat(indentLevel);
|
|
449
|
-
if (schema
|
|
495
|
+
if (isZodType(schema, 'ZodObject')) {
|
|
450
496
|
const shape = schema.shape;
|
|
451
497
|
Object.keys(shape).forEach((key) => {
|
|
452
498
|
const subSchema = shape[key];
|
|
@@ -455,11 +501,11 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
455
501
|
markdown += zodSchemaToMarkdown(subSchema, indentLevel + 1);
|
|
456
502
|
});
|
|
457
503
|
}
|
|
458
|
-
else if (schema
|
|
504
|
+
else if (isZodType(schema, 'ZodArray')) {
|
|
459
505
|
markdown += `${indent}- Array\n`;
|
|
460
506
|
markdown += zodSchemaToMarkdown(schema.element, indentLevel + 1);
|
|
461
507
|
}
|
|
462
|
-
else if (schema
|
|
508
|
+
else if (isZodType(schema, 'ZodString')) {
|
|
463
509
|
markdown += `${indent}- String`;
|
|
464
510
|
if (schema.minLength !== null) {
|
|
465
511
|
markdown += ` (minLength: ${schema.minLength})`;
|
|
@@ -469,7 +515,7 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
469
515
|
}
|
|
470
516
|
markdown += "\n";
|
|
471
517
|
}
|
|
472
|
-
else if (schema
|
|
518
|
+
else if (isZodType(schema, 'ZodNumber')) {
|
|
473
519
|
markdown += `${indent}- Number`;
|
|
474
520
|
if (schema.minValue !== null) {
|
|
475
521
|
markdown += ` (minValue: ${schema.minValue})`;
|
|
@@ -479,93 +525,99 @@ function zodSchemaToMarkdown(schema, indentLevel = 0) {
|
|
|
479
525
|
}
|
|
480
526
|
markdown += "\n";
|
|
481
527
|
}
|
|
482
|
-
else if (schema
|
|
528
|
+
else if (isZodType(schema, 'ZodEnum')) {
|
|
483
529
|
const values = schema.options.join(", ");
|
|
484
530
|
markdown += `${indent}- Enum: ${values}\n`;
|
|
485
531
|
}
|
|
486
|
-
else if (schema
|
|
532
|
+
else if (isZodType(schema, 'ZodUnion')) {
|
|
533
|
+
const unionSchema = schema;
|
|
487
534
|
markdown += `${indent}- Union\n`;
|
|
488
|
-
|
|
535
|
+
unionSchema.options.forEach((option, index) => {
|
|
489
536
|
markdown += zodSchemaToMarkdown(option, indentLevel + 1);
|
|
490
|
-
if (index <
|
|
537
|
+
if (index < unionSchema.options.length - 1) {
|
|
491
538
|
markdown += `${indent} |\n`;
|
|
492
539
|
}
|
|
493
540
|
});
|
|
494
541
|
}
|
|
495
|
-
else if (schema
|
|
542
|
+
else if (isZodType(schema, 'ZodBoolean')) {
|
|
496
543
|
markdown += `${indent}- Boolean\n`;
|
|
497
544
|
}
|
|
498
|
-
else if (schema
|
|
499
|
-
|
|
500
|
-
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);
|
|
501
549
|
}
|
|
502
|
-
else if (schema
|
|
550
|
+
else if (isZodType(schema, 'ZodOptional')) {
|
|
503
551
|
markdown += `${indent}- Optional\n`;
|
|
504
552
|
markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
|
|
505
553
|
}
|
|
506
|
-
else if (schema
|
|
554
|
+
else if (isZodType(schema, 'ZodNullable')) {
|
|
507
555
|
markdown += `${indent}- Nullable\n`;
|
|
508
556
|
markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
|
|
509
557
|
}
|
|
510
|
-
else if (schema
|
|
558
|
+
else if (isZodType(schema, 'ZodEffects')) {
|
|
511
559
|
const effectType = schema._def.effect.type;
|
|
512
560
|
markdown += `${indent}- Effects (${effectType})\n`;
|
|
513
561
|
markdown += zodSchemaToMarkdown(schema.innerType(), indentLevel + 1);
|
|
514
562
|
}
|
|
515
|
-
else if (schema
|
|
516
|
-
const
|
|
563
|
+
else if (isZodType(schema, 'ZodDiscriminatedUnion')) {
|
|
564
|
+
const discUnionSchema = schema;
|
|
565
|
+
const discriminator = discUnionSchema.discriminator;
|
|
517
566
|
markdown += `${indent}- DiscriminatedUnion (key: ${discriminator})\n`;
|
|
518
|
-
|
|
567
|
+
discUnionSchema.options.forEach((option, index) => {
|
|
519
568
|
markdown += zodSchemaToMarkdown(option, indentLevel + 1);
|
|
520
|
-
if (index <
|
|
569
|
+
if (index < discUnionSchema.options.length - 1) {
|
|
521
570
|
markdown += `${indent} |\n`;
|
|
522
571
|
}
|
|
523
572
|
});
|
|
524
573
|
}
|
|
525
|
-
else if (schema
|
|
574
|
+
else if (isZodType(schema, 'ZodIntersection')) {
|
|
575
|
+
const intSchema = schema;
|
|
526
576
|
markdown += `${indent}- Intersection\n`;
|
|
527
577
|
markdown += `${indent} Left:\n`;
|
|
528
|
-
markdown += zodSchemaToMarkdown(
|
|
578
|
+
markdown += zodSchemaToMarkdown(intSchema._def.left, indentLevel + 2);
|
|
529
579
|
markdown += `${indent} Right:\n`;
|
|
530
|
-
markdown += zodSchemaToMarkdown(
|
|
580
|
+
markdown += zodSchemaToMarkdown(intSchema._def.right, indentLevel + 2);
|
|
531
581
|
}
|
|
532
|
-
else if (schema
|
|
582
|
+
else if (isZodType(schema, 'ZodRecord')) {
|
|
583
|
+
const recSchema = schema;
|
|
533
584
|
markdown += `${indent}- Record\n`;
|
|
534
585
|
markdown += `${indent} Key:\n`;
|
|
535
|
-
markdown += zodSchemaToMarkdown(
|
|
586
|
+
markdown += zodSchemaToMarkdown(recSchema.keySchema, indentLevel + 2);
|
|
536
587
|
markdown += `${indent} Value:\n`;
|
|
537
|
-
markdown += zodSchemaToMarkdown(
|
|
588
|
+
markdown += zodSchemaToMarkdown(recSchema.valueSchema, indentLevel + 2);
|
|
538
589
|
}
|
|
539
|
-
else if (schema
|
|
590
|
+
else if (isZodType(schema, 'ZodTuple')) {
|
|
591
|
+
const tupSchema = schema;
|
|
540
592
|
markdown += `${indent}- Tuple\n`;
|
|
541
|
-
|
|
593
|
+
tupSchema.items.forEach((item, index) => {
|
|
542
594
|
markdown += `${indent} [${index}]:\n`;
|
|
543
595
|
markdown += zodSchemaToMarkdown(item, indentLevel + 2);
|
|
544
596
|
});
|
|
545
597
|
}
|
|
546
|
-
else if (schema
|
|
598
|
+
else if (isZodType(schema, 'ZodLiteral')) {
|
|
547
599
|
markdown += `${indent}- Literal: ${JSON.stringify(schema.value)}\n`;
|
|
548
600
|
}
|
|
549
|
-
else if (schema
|
|
601
|
+
else if (isZodType(schema, 'ZodBigInt')) {
|
|
550
602
|
markdown += `${indent}- BigInt\n`;
|
|
551
603
|
}
|
|
552
|
-
else if (schema
|
|
604
|
+
else if (isZodType(schema, 'ZodDate')) {
|
|
553
605
|
markdown += `${indent}- Date\n`;
|
|
554
606
|
}
|
|
555
|
-
else if (schema
|
|
607
|
+
else if (isZodType(schema, 'ZodNaN')) {
|
|
556
608
|
markdown += `${indent}- NaN\n`;
|
|
557
609
|
}
|
|
558
|
-
else if (schema
|
|
610
|
+
else if (isZodType(schema, 'ZodNever')) {
|
|
559
611
|
markdown += `${indent}- Never\n`;
|
|
560
612
|
}
|
|
561
|
-
else if (schema
|
|
613
|
+
else if (isZodType(schema, 'ZodUnknown')) {
|
|
562
614
|
markdown += `${indent}- Unknown\n`;
|
|
563
615
|
}
|
|
564
|
-
else if (schema
|
|
616
|
+
else if (isZodType(schema, 'ZodVoid')) {
|
|
565
617
|
markdown += `${indent}- Void\n`;
|
|
566
618
|
}
|
|
567
619
|
else {
|
|
568
|
-
markdown += `${indent}- Type: ${schema.constructor.name}\n`;
|
|
620
|
+
markdown += `${indent}- Type: ${schema._def.typeName || schema.constructor.name}\n`;
|
|
569
621
|
}
|
|
570
622
|
return markdown;
|
|
571
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
|
});
|