@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 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
- const zod_1 = require("zod");
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 instanceof zod_1.z.ZodObject)) {
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 instanceof zod_1.z.ZodOptional) {
39
+ if (isZodType(schema, 'ZodOptional')) {
34
40
  const inner = schema.unwrap();
35
41
  // 对于简单类型直接包装
36
- if (inner instanceof zod_1.z.ZodObject || inner instanceof zod_1.z.ZodArray) {
42
+ if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodArray')) {
37
43
  collectFields(inner, prefix, fields, 'Optional');
38
44
  }
39
- else if (inner instanceof zod_1.z.ZodUnion || inner instanceof zod_1.z.ZodDiscriminatedUnion || inner instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodNullable) {
59
+ if (isZodType(schema, 'ZodNullable')) {
54
60
  const inner = schema.unwrap();
55
- if (inner instanceof zod_1.z.ZodObject || inner instanceof zod_1.z.ZodArray) {
61
+ if (isZodType(inner, 'ZodObject') || isZodType(inner, 'ZodArray')) {
56
62
  collectFields(inner, prefix, fields, 'Nullable');
57
63
  }
58
- else if (inner instanceof zod_1.z.ZodUnion || inner instanceof zod_1.z.ZodDiscriminatedUnion || inner instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodDefault) {
78
+ if (isZodType(schema, 'ZodDefault')) {
73
79
  collectFields(schema.removeDefault(), prefix, fields);
74
80
  return;
75
81
  }
76
82
  // 处理 Array - 收集元素类型
77
- if (schema instanceof zod_1.z.ZodArray) {
83
+ if (isZodType(schema, 'ZodArray')) {
78
84
  const element = schema.element;
79
85
  // 如果是对象数组,展开其字段
80
- if (element instanceof zod_1.z.ZodObject) {
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 instanceof zod_1.z.ZodUnion || element instanceof zod_1.z.ZodDiscriminatedUnion) {
98
+ else if (isZodType(element, 'ZodUnion') || isZodType(element, 'ZodDiscriminatedUnion')) {
93
99
  // 数组元素是 Union 类型时,展开每个选项
94
- element.options.forEach((opt, index) => {
100
+ const unionSchema = element;
101
+ unionSchema.options.forEach((opt, index) => {
95
102
  // 对于 ZodOptional/ZodNullable,保留包装类型信息
96
- if (opt instanceof zod_1.z.ZodOptional || opt instanceof zod_1.z.ZodNullable) {
103
+ if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
97
104
  const typeStr = getTypeString(opt);
98
- const inner = opt instanceof zod_1.z.ZodOptional ? opt.unwrap() : opt.unwrap();
99
- if (inner instanceof zod_1.z.ZodObject || inner instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodObject || opt instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodOptional) {
150
+ else if (isZodType(element, 'ZodOptional')) {
141
151
  // 数组元素是 Optional 类型时,展开内部类型
142
152
  const inner = element.unwrap();
143
- if (inner instanceof zod_1.z.ZodObject) {
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 instanceof zod_1.z.ZodObject) {
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 instanceof zod_1.z.ZodUnion) {
185
- schema.options.forEach((opt, index) => {
194
+ if (isZodType(schema, 'ZodUnion')) {
195
+ const unionSchema = schema;
196
+ unionSchema.options.forEach((opt, index) => {
186
197
  // 对于 ZodOptional/ZodNullable,保留包装类型信息
187
- if (opt instanceof zod_1.z.ZodOptional || opt instanceof zod_1.z.ZodNullable) {
198
+ if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
188
199
  const typeStr = getTypeString(opt);
189
- const innerWrapperType = opt instanceof zod_1.z.ZodOptional ? 'Optional' : 'Nullable';
190
- const inner = opt instanceof zod_1.z.ZodOptional ? opt.unwrap() : opt.unwrap();
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 instanceof zod_1.z.ZodObject || inner instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodObject || opt instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodDiscriminatedUnion) {
236
- schema.options.forEach((opt, index) => {
248
+ if (isZodType(schema, 'ZodDiscriminatedUnion')) {
249
+ const discUnionSchema = schema;
250
+ discUnionSchema.options.forEach((opt, index) => {
237
251
  // 对于 ZodOptional/ZodNullable,保留包装类型信息
238
- if (opt instanceof zod_1.z.ZodOptional || opt instanceof zod_1.z.ZodNullable) {
252
+ if (isZodType(opt, 'ZodOptional') || isZodType(opt, 'ZodNullable')) {
239
253
  const typeStr = getTypeString(opt);
240
- const innerWrapperType = opt instanceof zod_1.z.ZodOptional ? 'Optional' : 'Nullable';
241
- const inner = opt instanceof zod_1.z.ZodOptional ? opt.unwrap() : opt.unwrap();
242
- if (inner instanceof zod_1.z.ZodObject || inner instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodObject || opt instanceof zod_1.z.ZodIntersection) {
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 instanceof zod_1.z.ZodIntersection) {
299
+ if (isZodType(schema, 'ZodIntersection')) {
300
+ const intSchema = schema;
284
301
  const leftFields = [];
285
302
  const rightFields = [];
286
- collectFields(schema._def.left, '', leftFields);
287
- collectFields(schema._def.right, '', rightFields);
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 instanceof zod_1.z.ZodRecord) {
322
+ if (isZodType(schema, 'ZodRecord')) {
323
+ const recordSchema = schema;
306
324
  fields.push({
307
325
  path: prefix,
308
- type: `Record<${getTypeString(schema.keySchema)}, ${getTypeString(schema.valueSchema)}>`,
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 instanceof zod_1.z.ZodTuple) {
315
- const items = schema.items.map((item) => getTypeString(item)).join(', ');
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 instanceof zod_1.z.ZodOptional) {
383
+ if (isZodType(schema, 'ZodOptional')) {
342
384
  return `Optional<${getTypeString(schema.unwrap())}>`;
343
385
  }
344
- if (schema instanceof zod_1.z.ZodNullable) {
386
+ if (isZodType(schema, 'ZodNullable')) {
345
387
  return `Nullable<${getTypeString(schema.unwrap())}>`;
346
388
  }
347
- if (schema instanceof zod_1.z.ZodDefault) {
389
+ if (isZodType(schema, 'ZodDefault')) {
348
390
  return `Default<${getTypeString(schema.removeDefault())}>`;
349
391
  }
350
- if (schema instanceof zod_1.z.ZodArray) {
392
+ if (isZodType(schema, 'ZodArray')) {
351
393
  return `Array<${getTypeString(schema.element)}>`;
352
394
  }
353
- if (schema instanceof zod_1.z.ZodString) {
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 (schema.minLength !== null || schema.maxLength !== null) {
403
+ if (strSchema.minLength !== null || strSchema.maxLength !== null) {
356
404
  const constraints = [];
357
- if (schema.minLength !== null)
358
- constraints.push(`min: ${schema.minLength}`);
359
- if (schema.maxLength !== null)
360
- constraints.push(`max: ${schema.maxLength}`);
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 instanceof zod_1.z.ZodNumber) {
413
+ if (isZodType(schema, 'ZodNumber')) {
414
+ const numSchema = schema;
366
415
  let result = 'Number';
367
- if (schema.minValue !== null || schema.maxValue !== null) {
416
+ if (numSchema.minValue !== null || numSchema.maxValue !== null) {
368
417
  const constraints = [];
369
- if (schema.minValue !== null)
370
- constraints.push(`min: ${schema.minValue}`);
371
- if (schema.maxValue !== null)
372
- constraints.push(`max: ${schema.maxValue}`);
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 instanceof zod_1.z.ZodEnum) {
378
- return `Enum(${schema.options.join(' | ')})`;
426
+ if (isZodType(schema, 'ZodEnum')) {
427
+ return `Enum(${(schema.options).join(' | ')})`;
379
428
  }
380
- if (schema instanceof zod_1.z.ZodLiteral) {
429
+ if (isZodType(schema, 'ZodLiteral')) {
381
430
  return `Literal(${JSON.stringify(schema.value)})`;
382
431
  }
383
- if (schema instanceof zod_1.z.ZodBoolean)
432
+ if (isZodType(schema, 'ZodBoolean'))
384
433
  return 'Boolean';
385
- if (schema instanceof zod_1.z.ZodBigInt)
434
+ if (isZodType(schema, 'ZodBigInt'))
386
435
  return 'BigInt';
387
- if (schema instanceof zod_1.z.ZodDate)
436
+ if (isZodType(schema, 'ZodDate'))
388
437
  return 'Date';
389
- if (schema instanceof zod_1.z.ZodNaN)
438
+ if (isZodType(schema, 'ZodNaN'))
390
439
  return 'NaN';
391
- if (schema instanceof zod_1.z.ZodNever)
440
+ if (isZodType(schema, 'ZodNever'))
392
441
  return 'Never';
393
- if (schema instanceof zod_1.z.ZodUnknown)
442
+ if (isZodType(schema, 'ZodUnknown'))
394
443
  return 'Unknown';
395
- if (schema instanceof zod_1.z.ZodVoid)
444
+ if (isZodType(schema, 'ZodVoid'))
396
445
  return 'Void';
397
- if (schema instanceof zod_1.z.ZodRecord) {
398
- return `Record<${getTypeString(schema.keySchema)}, ${getTypeString(schema.valueSchema)}>`;
446
+ if (isZodType(schema, 'ZodRecord')) {
447
+ const recSchema = schema;
448
+ return `Record<${getTypeString(recSchema.keySchema)}, ${getTypeString(recSchema.valueSchema)}>`;
399
449
  }
400
- if (schema instanceof zod_1.z.ZodTuple) {
401
- const items = schema.items.map((item) => getTypeString(item)).join(', ');
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 instanceof zod_1.z.ZodUnion) {
405
- const options = schema.options.map((opt) => getTypeString(opt)).join(' | ');
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 instanceof zod_1.z.ZodDiscriminatedUnion) {
460
+ if (isZodType(schema, 'ZodDiscriminatedUnion')) {
409
461
  return `DiscriminatedUnion(${schema.discriminator})`;
410
462
  }
411
- if (schema instanceof zod_1.z.ZodIntersection) {
463
+ if (isZodType(schema, 'ZodIntersection')) {
412
464
  return 'Intersection';
413
465
  }
414
- if (schema instanceof zod_1.z.ZodEffects) {
466
+ if (isZodType(schema, 'ZodEffects')) {
415
467
  return `Effects(${schema._def.effect.type})`;
416
468
  }
417
- return schema.constructor.name;
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 instanceof zod_1.z.ZodObject) {
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 instanceof zod_1.z.ZodArray) {
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 instanceof zod_1.z.ZodString) {
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 instanceof zod_1.z.ZodNumber) {
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 instanceof zod_1.z.ZodEnum) {
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 instanceof zod_1.z.ZodUnion) {
532
+ else if (isZodType(schema, 'ZodUnion')) {
533
+ const unionSchema = schema;
460
534
  markdown += `${indent}- Union\n`;
461
- schema.options.forEach((option, index) => {
535
+ unionSchema.options.forEach((option, index) => {
462
536
  markdown += zodSchemaToMarkdown(option, indentLevel + 1);
463
- if (index < schema.options.length - 1) {
537
+ if (index < unionSchema.options.length - 1) {
464
538
  markdown += `${indent} |\n`;
465
539
  }
466
540
  });
467
541
  }
468
- else if (schema instanceof zod_1.z.ZodBoolean) {
542
+ else if (isZodType(schema, 'ZodBoolean')) {
469
543
  markdown += `${indent}- Boolean\n`;
470
544
  }
471
- else if (schema instanceof zod_1.z.ZodDefault) {
472
- markdown += `${indent}- Default: ${JSON.stringify(schema._def.defaultValue())}\n`;
473
- markdown += zodSchemaToMarkdown(schema.removeDefault(), indentLevel);
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 instanceof zod_1.z.ZodOptional) {
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 instanceof zod_1.z.ZodNullable) {
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 instanceof zod_1.z.ZodEffects) {
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 instanceof zod_1.z.ZodDiscriminatedUnion) {
489
- const discriminator = schema.discriminator;
563
+ else if (isZodType(schema, 'ZodDiscriminatedUnion')) {
564
+ const discUnionSchema = schema;
565
+ const discriminator = discUnionSchema.discriminator;
490
566
  markdown += `${indent}- DiscriminatedUnion (key: ${discriminator})\n`;
491
- schema.options.forEach((option, index) => {
567
+ discUnionSchema.options.forEach((option, index) => {
492
568
  markdown += zodSchemaToMarkdown(option, indentLevel + 1);
493
- if (index < schema.options.length - 1) {
569
+ if (index < discUnionSchema.options.length - 1) {
494
570
  markdown += `${indent} |\n`;
495
571
  }
496
572
  });
497
573
  }
498
- else if (schema instanceof zod_1.z.ZodIntersection) {
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(schema._def.left, indentLevel + 2);
578
+ markdown += zodSchemaToMarkdown(intSchema._def.left, indentLevel + 2);
502
579
  markdown += `${indent} Right:\n`;
503
- markdown += zodSchemaToMarkdown(schema._def.right, indentLevel + 2);
580
+ markdown += zodSchemaToMarkdown(intSchema._def.right, indentLevel + 2);
504
581
  }
505
- else if (schema instanceof zod_1.z.ZodRecord) {
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(schema.keySchema, indentLevel + 2);
586
+ markdown += zodSchemaToMarkdown(recSchema.keySchema, indentLevel + 2);
509
587
  markdown += `${indent} Value:\n`;
510
- markdown += zodSchemaToMarkdown(schema.valueSchema, indentLevel + 2);
588
+ markdown += zodSchemaToMarkdown(recSchema.valueSchema, indentLevel + 2);
511
589
  }
512
- else if (schema instanceof zod_1.z.ZodTuple) {
590
+ else if (isZodType(schema, 'ZodTuple')) {
591
+ const tupSchema = schema;
513
592
  markdown += `${indent}- Tuple\n`;
514
- schema.items.forEach((item, index) => {
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 instanceof zod_1.z.ZodLiteral) {
598
+ else if (isZodType(schema, 'ZodLiteral')) {
520
599
  markdown += `${indent}- Literal: ${JSON.stringify(schema.value)}\n`;
521
600
  }
522
- else if (schema instanceof zod_1.z.ZodBigInt) {
601
+ else if (isZodType(schema, 'ZodBigInt')) {
523
602
  markdown += `${indent}- BigInt\n`;
524
603
  }
525
- else if (schema instanceof zod_1.z.ZodDate) {
604
+ else if (isZodType(schema, 'ZodDate')) {
526
605
  markdown += `${indent}- Date\n`;
527
606
  }
528
- else if (schema instanceof zod_1.z.ZodNaN) {
607
+ else if (isZodType(schema, 'ZodNaN')) {
529
608
  markdown += `${indent}- NaN\n`;
530
609
  }
531
- else if (schema instanceof zod_1.z.ZodNever) {
610
+ else if (isZodType(schema, 'ZodNever')) {
532
611
  markdown += `${indent}- Never\n`;
533
612
  }
534
- else if (schema instanceof zod_1.z.ZodUnknown) {
613
+ else if (isZodType(schema, 'ZodUnknown')) {
535
614
  markdown += `${indent}- Unknown\n`;
536
615
  }
537
- else if (schema instanceof zod_1.z.ZodVoid) {
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chnak/zod-to-markdown",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "A utility function to convert Zod schemas to Markdown documentation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",