@chnak/zod-to-markdown 1.0.1

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/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # zod-to-markdown
2
+
3
+ 将 Zod schema 转换为 Markdown 文档的工具函数。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install @chnak/zod-to-markdown
9
+ ```
10
+
11
+ ## 使用方法
12
+
13
+ ### ESM / TypeScript
14
+
15
+ ```typescript
16
+ import { zodSchemaToMarkdown } from '@chnak/zod-to-markdown';
17
+ import { z } from 'zod';
18
+
19
+ const schema = z.object({
20
+ name: z.string(),
21
+ age: z.number(),
22
+ });
23
+
24
+ const markdown = zodSchemaToMarkdown(schema);
25
+ console.log(markdown);
26
+ ```
27
+
28
+ ### CommonJS / Node.js
29
+
30
+ ```javascript
31
+ const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
32
+ const { z } = require('zod');
33
+
34
+ const schema = z.object({
35
+ name: z.string(),
36
+ age: z.number(),
37
+ });
38
+
39
+ const markdown = zodSchemaToMarkdown(schema);
40
+ console.log(markdown);
41
+ ```
42
+
43
+ ### 输出结果
44
+
45
+ ```markdown
46
+ - name
47
+ - String
48
+ - age
49
+ - Number
50
+ ```
51
+
52
+ ## 支持的 Zod 类型
53
+
54
+ ### 基础类型
55
+ - `ZodObject` - 对象 schema,包含嵌套属性
56
+ - `ZodArray` - 数组 schema,包含元素类型
57
+ - `ZodString` - 字符串,可选 minLength/maxLength
58
+ - `ZodNumber` - 数字,可选 minValue/maxValue
59
+ - `ZodBoolean` - 布尔类型
60
+ - `ZodEnum` - 枚举值
61
+ - `ZodBigInt` - BigInt 类型
62
+ - `ZodDate` - Date 类型
63
+
64
+ ### 工具类型
65
+ - `ZodOptional` - 可选属性
66
+ - `ZodNullable` - 可为空属性
67
+ - `ZodDefault` - 默认值
68
+ - `ZodEffects` - transform/coerce 效果
69
+
70
+ ### 高级类型
71
+ - `ZodUnion` - 联合类型
72
+ - `ZodDiscriminatedUnion` - 带鉴别键的联合类型
73
+ - `ZodIntersection` - 交叉类型
74
+ - `ZodRecord` - Record(字典)类型
75
+ - `ZodTuple` - 元组类型
76
+
77
+ ### 特殊类型
78
+ - `ZodLiteral` - 字面量值(如 `"hello"`, `1`, `true`)
79
+ - `ZodNaN` - NaN 类型
80
+ - `ZodNever` - Never 类型
81
+ - `ZodUnknown` - Unknown 类型
82
+ - `ZodVoid` - Void 类型
83
+
84
+ ## 示例
85
+
86
+ ### 复杂 Schema
87
+
88
+ ```typescript
89
+ import { z } from 'zod';
90
+
91
+ const userSchema = z.object({
92
+ id: z.string().uuid(),
93
+ name: z.string(),
94
+ email: z.string().email(),
95
+ age: z.number().optional(),
96
+ role: z.enum(['admin', 'user', 'guest']),
97
+ metadata: z.record(z.string(), z.unknown()).optional(),
98
+ });
99
+
100
+ console.log(zodSchemaToMarkdown(userSchema));
101
+ ```
102
+
103
+ 输出:
104
+ ```markdown
105
+ - id
106
+ - String
107
+ - name
108
+ - String
109
+ - email
110
+ - String
111
+ - age
112
+ - Optional
113
+ - Number
114
+ - role
115
+ - Enum: admin, user, guest
116
+ - metadata
117
+ - Optional
118
+ - Record
119
+ Key:
120
+ - String
121
+ Value:
122
+ - Unknown
123
+ ```
124
+
125
+ ### 鉴别联合类型 (Discriminated Union)
126
+
127
+ ```typescript
128
+ const messageSchema = z.discriminatedUnion('role', [
129
+ z.object({ role: z.literal('user'), content: z.string() }),
130
+ z.object({ role: z.literal('assistant'), content: z.string() }),
131
+ ]);
132
+
133
+ console.log(zodSchemaToMarkdown(messageSchema));
134
+ ```
135
+
136
+ 输出:
137
+ ```markdown
138
+ - DiscriminatedUnion (key: role)
139
+ - role
140
+ - Literal: "user"
141
+ - content
142
+ - String
143
+ |
144
+ - role
145
+ - Literal: "assistant"
146
+ - content
147
+ - String
148
+ ```
149
+
150
+ ### Transform 效果
151
+
152
+ ```typescript
153
+ const transformedSchema = z.string().transform(val => val.length);
154
+
155
+ console.log(zodSchemaToMarkdown(transformedSchema));
156
+ ```
157
+
158
+ 输出:
159
+ ```markdown
160
+ - Effects (transform)
161
+ - String
162
+ ```
163
+
164
+ ## API
165
+
166
+ ### `zodSchemaToMarkdown(schema, indentLevel?)`
167
+
168
+ | 参数 | 类型 | 说明 |
169
+ |------|------|------|
170
+ | `schema` | `z.ZodTypeAny` | 要转换的 Zod schema |
171
+ | `indentLevel` | `number` | 初始缩进级别(默认: `0`) |
172
+
173
+ 返回转换后的 Markdown 字符串。
174
+
175
+ ## License
176
+
177
+ MIT License
@@ -0,0 +1,152 @@
1
+ # Zod to Markdown - Complex Types Examples
2
+
3
+ This document demonstrates the `zodSchemaToMarkdown` function's support for complex Zod types used in OpenAI API schemas.
4
+
5
+ ## ZodEffects (Transform)
6
+
7
+ ```typescript
8
+ const schema = z.string().transform(val => val.length);
9
+ ```
10
+
11
+ Output:
12
+ ```markdown
13
+ - Effects (transform)
14
+ - String
15
+ ```
16
+
17
+ ## ZodDiscriminatedUnion
18
+
19
+ ```typescript
20
+ const schema = z.discriminatedUnion('type', [
21
+ z.object({ type: z.literal('a'), a: z.string() }),
22
+ z.object({ type: z.literal('b'), b: z.number() })
23
+ ]);
24
+ ```
25
+
26
+ Output:
27
+ ```markdown
28
+ - DiscriminatedUnion (key: type)
29
+ - type
30
+ - Literal: "a"
31
+ - a
32
+ - String
33
+ |
34
+ - type
35
+ - Literal: "b"
36
+ - b
37
+ - Number
38
+ ```
39
+
40
+ ## ZodIntersection
41
+
42
+ ```typescript
43
+ const schema = z.object({ a: z.string() }).and(z.object({ b: z.number() }));
44
+ ```
45
+
46
+ Output:
47
+ ```markdown
48
+ - Intersection
49
+ Left:
50
+ - a
51
+ - String
52
+ Right:
53
+ - b
54
+ - Number
55
+ ```
56
+
57
+ ## ZodRecord
58
+
59
+ ```typescript
60
+ const schema = z.record(z.string(), z.number());
61
+ ```
62
+
63
+ Output:
64
+ ```markdown
65
+ - Record
66
+ Key:
67
+ - String
68
+ Value:
69
+ - Number
70
+ ```
71
+
72
+ ## ZodTuple
73
+
74
+ ```typescript
75
+ const schema = z.tuple([z.string(), z.number()]);
76
+ ```
77
+
78
+ Output:
79
+ ```markdown
80
+ - Tuple
81
+ [0]:
82
+ - String
83
+ [1]:
84
+ - Number
85
+ ```
86
+
87
+ ## ZodLiteral
88
+
89
+ ```typescript
90
+ const schema = z.literal('hello');
91
+ ```
92
+
93
+ Output:
94
+ ```markdown
95
+ - Literal: "hello"
96
+ ```
97
+
98
+ ## Primitive Types
99
+
100
+ ### ZodBigInt
101
+ ```typescript
102
+ z.bigint()
103
+ ```
104
+ Output:
105
+ ```markdown
106
+ - BigInt
107
+ ```
108
+
109
+ ### ZodDate
110
+ ```typescript
111
+ z.date()
112
+ ```
113
+ Output:
114
+ ```markdown
115
+ - Date
116
+ ```
117
+
118
+ ### ZodNaN
119
+ ```typescript
120
+ z.nan()
121
+ ```
122
+ Output:
123
+ ```markdown
124
+ - NaN
125
+ ```
126
+
127
+ ### ZodNever
128
+ ```typescript
129
+ z.never()
130
+ ```
131
+ Output:
132
+ ```markdown
133
+ - Never
134
+ ```
135
+
136
+ ### ZodUnknown
137
+ ```typescript
138
+ z.unknown()
139
+ ```
140
+ Output:
141
+ ```markdown
142
+ - Unknown
143
+ ```
144
+
145
+ ### ZodVoid
146
+ ```typescript
147
+ z.void()
148
+ ```
149
+ Output:
150
+ ```markdown
151
+ - Void
152
+ ```
@@ -0,0 +1,191 @@
1
+ # OpenAI Chat Completion Schema
2
+
3
+ 完整的 OpenAI API Schema 转换为 Markdown 文档的示例。
4
+
5
+ ## TypeScript 定义
6
+
7
+ ```typescript
8
+ const messageSchema = z.discriminatedUnion('role', [
9
+ z.object({
10
+ role: z.literal('system'),
11
+ content: z.string(),
12
+ name: z.string().optional(),
13
+ }),
14
+ z.object({
15
+ role: z.literal('user'),
16
+ content: z.union([z.string(), z.array(z.object({
17
+ type: z.literal('text'),
18
+ text: z.string(),
19
+ }))]),
20
+ name: z.string().optional(),
21
+ }),
22
+ z.object({
23
+ role: z.literal('assistant'),
24
+ content: z.string().nullable(),
25
+ tool_calls: z.array(z.object({
26
+ id: z.string(),
27
+ type: z.literal('function'),
28
+ function: z.object({
29
+ name: z.string(),
30
+ arguments: z.string(),
31
+ }),
32
+ })).optional(),
33
+ name: z.string().optional(),
34
+ }),
35
+ z.object({
36
+ role: z.literal('tool'),
37
+ content: z.union([z.string(), z.object({
38
+ type: z.literal('image_url'),
39
+ image_url: z.object({
40
+ url: z.string(),
41
+ detail: z.enum(['low', 'high', 'auto']).optional(),
42
+ }),
43
+ })]),
44
+ tool_call_id: z.string(),
45
+ name: z.string().optional(),
46
+ }),
47
+ ]);
48
+
49
+ const chatCompletionRequestSchema = z.object({
50
+ model: z.string(),
51
+ messages: z.array(messageSchema),
52
+ temperature: z.number().min(0).max(2).optional(),
53
+ top_p: z.number().min(0).max(1).optional(),
54
+ n: z.number().int().min(1).optional(),
55
+ stream: z.boolean().optional(),
56
+ stop: z.union([z.string(), z.array(z.string())]).optional(),
57
+ max_tokens: z.number().int().optional(),
58
+ presence_penalty: z.number().min(-2).max(2).optional(),
59
+ frequency_penalty: z.number().min(-2).max(2).optional(),
60
+ logit_bias: z.record(z.string(), z.number()).optional(),
61
+ user: z.string().optional(),
62
+ });
63
+ ```
64
+
65
+ ## 生成的 Markdown 文档
66
+
67
+ ```markdown
68
+ - model
69
+ - String
70
+ - messages
71
+ - Array
72
+ - DiscriminatedUnion (key: role)
73
+ - role
74
+ - Literal: "system"
75
+ - content
76
+ - String
77
+ - name
78
+ - Optional
79
+ - String
80
+ |
81
+ - role
82
+ - Literal: "user"
83
+ - content
84
+ - Union
85
+ - String
86
+ |
87
+ - Array
88
+ - type
89
+ - Literal: "text"
90
+ - text
91
+ - String
92
+ - name
93
+ - Optional
94
+ - String
95
+ |
96
+ - role
97
+ - Literal: "assistant"
98
+ - content
99
+ - Nullable
100
+ - String
101
+ - tool_calls
102
+ - Optional
103
+ - Array
104
+ - id
105
+ - String
106
+ - type
107
+ - Literal: "function"
108
+ - function
109
+ - name
110
+ - String
111
+ - arguments
112
+ - String
113
+ - name
114
+ - Optional
115
+ - String
116
+ |
117
+ - role
118
+ - Literal: "tool"
119
+ - content
120
+ - Union
121
+ - String
122
+ |
123
+ - type
124
+ - Literal: "image_url"
125
+ - image_url
126
+ - url
127
+ - String
128
+ - detail
129
+ - Optional
130
+ - Enum: low, high, auto
131
+ - tool_call_id
132
+ - String
133
+ - name
134
+ - Optional
135
+ - String
136
+ - temperature
137
+ - Optional
138
+ - Number (minValue: 0) (maxValue: 2)
139
+ - top_p
140
+ - Optional
141
+ - Number (minValue: 0) (maxValue: 1)
142
+ - n
143
+ - Optional
144
+ - Number (minValue: 1)
145
+ - stream
146
+ - Optional
147
+ - Boolean
148
+ - stop
149
+ - Optional
150
+ - Union
151
+ - String
152
+ |
153
+ - Array
154
+ - String
155
+ - max_tokens
156
+ - Optional
157
+ - Number
158
+ - presence_penalty
159
+ - Optional
160
+ - Number (minValue: -2) (maxValue: 2)
161
+ - frequency_penalty
162
+ - Optional
163
+ - Number (minValue: -2) (maxValue: 2)
164
+ - logit_bias
165
+ - Optional
166
+ - Record
167
+ Key:
168
+ - String
169
+ Value:
170
+ - Number
171
+ - user
172
+ - Optional
173
+ - String
174
+ ```
175
+
176
+ ## 使用的类型覆盖
177
+
178
+ | 类型 | 出现位置 |
179
+ |------|----------|
180
+ | `ZodDiscriminatedUnion` | `messages` 数组元素,role 鉴别键 |
181
+ | `ZodObject` | 顶层 schema 和各 message 类型 |
182
+ | `ZodArray` | `messages`, `tool_calls`, `stop` |
183
+ | `ZodOptional` | `name`, `tool_calls`, `detail` 等 |
184
+ | `ZodNullable` | `content` (assistant) |
185
+ | `ZodUnion` | `content`, `stop` |
186
+ | `ZodLiteral` | `role` 值,`type` 值 |
187
+ | `ZodEnum` | `detail` 枚举 |
188
+ | `ZodRecord` | `logit_bias` |
189
+ | `ZodString` | 各种字符串字段 |
190
+ | `ZodNumber` | 各种数字字段,带 min/max 约束 |
191
+ | `ZodBoolean` | `stream` |
@@ -0,0 +1,64 @@
1
+ import { z } from 'zod';
2
+ import { zodSchemaToMarkdown } from '../src/index';
3
+
4
+ // OpenAI Chat Message Schema Example
5
+ const messageSchema = z.discriminatedUnion('role', [
6
+ z.object({
7
+ role: z.literal('system'),
8
+ content: z.string(),
9
+ name: z.string().optional(),
10
+ }),
11
+ z.object({
12
+ role: z.literal('user'),
13
+ content: z.union([z.string(), z.array(z.object({
14
+ type: z.literal('text'),
15
+ text: z.string(),
16
+ }))]),
17
+ name: z.string().optional(),
18
+ }),
19
+ z.object({
20
+ role: z.literal('assistant'),
21
+ content: z.string().nullable(),
22
+ tool_calls: z.array(z.object({
23
+ id: z.string(),
24
+ type: z.literal('function'),
25
+ function: z.object({
26
+ name: z.string(),
27
+ arguments: z.string(),
28
+ }),
29
+ })).optional(),
30
+ name: z.string().optional(),
31
+ }),
32
+ z.object({
33
+ role: z.literal('tool'),
34
+ content: z.union([z.string(), z.object({
35
+ type: z.literal('image_url'),
36
+ image_url: z.object({
37
+ url: z.string(),
38
+ detail: z.enum(['low', 'high', 'auto']).optional(),
39
+ }),
40
+ })]),
41
+ tool_call_id: z.string(),
42
+ name: z.string().optional(),
43
+ }),
44
+ ]);
45
+
46
+ const chatCompletionRequestSchema = z.object({
47
+ model: z.string(),
48
+ messages: z.array(messageSchema),
49
+ temperature: z.number().min(0).max(2).optional(),
50
+ top_p: z.number().min(0).max(1).optional(),
51
+ n: z.number().int().min(1).optional(),
52
+ stream: z.boolean().optional(),
53
+ stop: z.union([z.string(), z.array(z.string())]).optional(),
54
+ max_tokens: z.number().int().optional(),
55
+ presence_penalty: z.number().min(-2).max(2).optional(),
56
+ frequency_penalty: z.number().min(-2).max(2).optional(),
57
+ logit_bias: z.record(z.string(), z.number()).optional(),
58
+ user: z.string().optional(),
59
+ });
60
+
61
+ const schema = chatCompletionRequestSchema;
62
+ const markdown = zodSchemaToMarkdown(schema);
63
+
64
+ console.log(markdown);
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ testPathIgnorePatterns: ['/node_modules/', '/lib/'],
5
+ };
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { z } from "zod";
2
+ export declare function zodSchemaToMarkdown(schema: z.ZodTypeAny, indentLevel?: number): string;
package/lib/index.js ADDED
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.zodSchemaToMarkdown = void 0;
4
+ const zod_1 = require("zod");
5
+ function zodSchemaToMarkdown(schema, indentLevel = 0) {
6
+ let markdown = "";
7
+ const indent = " ".repeat(indentLevel);
8
+ if (schema instanceof zod_1.z.ZodObject) {
9
+ const shape = schema.shape;
10
+ Object.keys(shape).forEach((key) => {
11
+ const subSchema = shape[key];
12
+ const description = subSchema.description ? `: ${subSchema.description}` : "";
13
+ markdown += `${indent}- ${key}${description}\n`;
14
+ markdown += zodSchemaToMarkdown(subSchema, indentLevel + 1);
15
+ });
16
+ }
17
+ else if (schema instanceof zod_1.z.ZodArray) {
18
+ markdown += `${indent}- Array\n`;
19
+ markdown += zodSchemaToMarkdown(schema.element, indentLevel + 1);
20
+ }
21
+ else if (schema instanceof zod_1.z.ZodString) {
22
+ markdown += `${indent}- String`;
23
+ if (schema.minLength !== null) {
24
+ markdown += ` (minLength: ${schema.minLength})`;
25
+ }
26
+ if (schema.maxLength !== null) {
27
+ markdown += ` (maxLength: ${schema.maxLength})`;
28
+ }
29
+ markdown += "\n";
30
+ }
31
+ else if (schema instanceof zod_1.z.ZodNumber) {
32
+ markdown += `${indent}- Number`;
33
+ if (schema.minValue !== null) {
34
+ markdown += ` (minValue: ${schema.minValue})`;
35
+ }
36
+ if (schema.maxValue !== null) {
37
+ markdown += ` (maxValue: ${schema.maxValue})`;
38
+ }
39
+ markdown += "\n";
40
+ }
41
+ else if (schema instanceof zod_1.z.ZodEnum) {
42
+ const values = schema.options.join(", ");
43
+ markdown += `${indent}- Enum: ${values}\n`;
44
+ }
45
+ else if (schema instanceof zod_1.z.ZodUnion) {
46
+ markdown += `${indent}- Union\n`;
47
+ schema.options.forEach((option, index) => {
48
+ markdown += zodSchemaToMarkdown(option, indentLevel + 1);
49
+ if (index < schema.options.length - 1) {
50
+ markdown += `${indent} |\n`;
51
+ }
52
+ });
53
+ }
54
+ else if (schema instanceof zod_1.z.ZodBoolean) {
55
+ markdown += `${indent}- Boolean\n`;
56
+ }
57
+ else if (schema instanceof zod_1.z.ZodDefault) {
58
+ markdown += `${indent}- Default: ${JSON.stringify(schema._def.defaultValue())}\n`;
59
+ markdown += zodSchemaToMarkdown(schema.removeDefault(), indentLevel);
60
+ }
61
+ else if (schema instanceof zod_1.z.ZodOptional) {
62
+ markdown += `${indent}- Optional\n`;
63
+ markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
64
+ }
65
+ else if (schema instanceof zod_1.z.ZodNullable) {
66
+ markdown += `${indent}- Nullable\n`;
67
+ markdown += zodSchemaToMarkdown(schema.unwrap(), indentLevel + 1);
68
+ }
69
+ else if (schema instanceof zod_1.z.ZodEffects) {
70
+ const effectType = schema._def.effect.type;
71
+ markdown += `${indent}- Effects (${effectType})\n`;
72
+ markdown += zodSchemaToMarkdown(schema.innerType(), indentLevel + 1);
73
+ }
74
+ else if (schema instanceof zod_1.z.ZodDiscriminatedUnion) {
75
+ const discriminator = schema.discriminator;
76
+ markdown += `${indent}- DiscriminatedUnion (key: ${discriminator})\n`;
77
+ schema.options.forEach((option, index) => {
78
+ markdown += zodSchemaToMarkdown(option, indentLevel + 1);
79
+ if (index < schema.options.length - 1) {
80
+ markdown += `${indent} |\n`;
81
+ }
82
+ });
83
+ }
84
+ else if (schema instanceof zod_1.z.ZodIntersection) {
85
+ markdown += `${indent}- Intersection\n`;
86
+ markdown += `${indent} Left:\n`;
87
+ markdown += zodSchemaToMarkdown(schema._def.left, indentLevel + 2);
88
+ markdown += `${indent} Right:\n`;
89
+ markdown += zodSchemaToMarkdown(schema._def.right, indentLevel + 2);
90
+ }
91
+ else if (schema instanceof zod_1.z.ZodRecord) {
92
+ markdown += `${indent}- Record\n`;
93
+ markdown += `${indent} Key:\n`;
94
+ markdown += zodSchemaToMarkdown(schema.keySchema, indentLevel + 2);
95
+ markdown += `${indent} Value:\n`;
96
+ markdown += zodSchemaToMarkdown(schema.valueSchema, indentLevel + 2);
97
+ }
98
+ else if (schema instanceof zod_1.z.ZodTuple) {
99
+ markdown += `${indent}- Tuple\n`;
100
+ schema.items.forEach((item, index) => {
101
+ markdown += `${indent} [${index}]:\n`;
102
+ markdown += zodSchemaToMarkdown(item, indentLevel + 2);
103
+ });
104
+ }
105
+ else if (schema instanceof zod_1.z.ZodLiteral) {
106
+ markdown += `${indent}- Literal: ${JSON.stringify(schema.value)}\n`;
107
+ }
108
+ else if (schema instanceof zod_1.z.ZodBigInt) {
109
+ markdown += `${indent}- BigInt\n`;
110
+ }
111
+ else if (schema instanceof zod_1.z.ZodDate) {
112
+ markdown += `${indent}- Date\n`;
113
+ }
114
+ else if (schema instanceof zod_1.z.ZodNaN) {
115
+ markdown += `${indent}- NaN\n`;
116
+ }
117
+ else if (schema instanceof zod_1.z.ZodNever) {
118
+ markdown += `${indent}- Never\n`;
119
+ }
120
+ else if (schema instanceof zod_1.z.ZodUnknown) {
121
+ markdown += `${indent}- Unknown\n`;
122
+ }
123
+ else if (schema instanceof zod_1.z.ZodVoid) {
124
+ markdown += `${indent}- Void\n`;
125
+ }
126
+ else {
127
+ markdown += `${indent}- Type: ${schema.constructor.name}\n`;
128
+ }
129
+ return markdown;
130
+ }
131
+ exports.zodSchemaToMarkdown = zodSchemaToMarkdown;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const zod_1 = require("zod");
4
+ const index_1 = require("./index");
5
+ describe('zodSchemaToMarkdown', () => {
6
+ it('should convert a simple object schema to markdown', () => {
7
+ const schema = zod_1.z.object({
8
+ name: zod_1.z.string(),
9
+ age: zod_1.z.number(),
10
+ });
11
+ const expected = `- name
12
+ - String
13
+ - age
14
+ - Number
15
+ `;
16
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
17
+ });
18
+ it('should convert an array schema to markdown', () => {
19
+ const schema = zod_1.z.array(zod_1.z.string());
20
+ const expected = `- Array
21
+ - String
22
+ `;
23
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
24
+ });
25
+ it('should convert a union schema to markdown', () => {
26
+ const schema = zod_1.z.union([zod_1.z.string(), zod_1.z.number()]);
27
+ const expected = `- Union
28
+ - String
29
+ |
30
+ - Number
31
+ `;
32
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
33
+ });
34
+ it('should convert ZodEffects (transform) to markdown', () => {
35
+ const schema = zod_1.z.string().transform(val => val.length);
36
+ const expected = `- Effects (transform)
37
+ - String
38
+ `;
39
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
40
+ });
41
+ it('should convert ZodDiscriminatedUnion to markdown', () => {
42
+ const schema = zod_1.z.discriminatedUnion('type', [
43
+ zod_1.z.object({ type: zod_1.z.literal('a'), a: zod_1.z.string() }),
44
+ zod_1.z.object({ type: zod_1.z.literal('b'), b: zod_1.z.number() })
45
+ ]);
46
+ const expected = `- DiscriminatedUnion (key: type)
47
+ - type
48
+ - Literal: "a"
49
+ - a
50
+ - String
51
+ |
52
+ - type
53
+ - Literal: "b"
54
+ - b
55
+ - Number
56
+ `;
57
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
58
+ });
59
+ it('should convert ZodIntersection to markdown', () => {
60
+ const schema = zod_1.z.object({ a: zod_1.z.string() }).and(zod_1.z.object({ b: zod_1.z.number() }));
61
+ const expected = `- Intersection
62
+ Left:
63
+ - a
64
+ - String
65
+ Right:
66
+ - b
67
+ - Number
68
+ `;
69
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
70
+ });
71
+ it('should convert ZodRecord to markdown', () => {
72
+ const schema = zod_1.z.record(zod_1.z.string(), zod_1.z.number());
73
+ const expected = `- Record
74
+ Key:
75
+ - String
76
+ Value:
77
+ - Number
78
+ `;
79
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
80
+ });
81
+ it('should convert ZodTuple to markdown', () => {
82
+ const schema = zod_1.z.tuple([zod_1.z.string(), zod_1.z.number()]);
83
+ const expected = `- Tuple
84
+ [0]:
85
+ - String
86
+ [1]:
87
+ - Number
88
+ `;
89
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
90
+ });
91
+ it('should convert ZodLiteral to markdown', () => {
92
+ const schema = zod_1.z.literal('hello');
93
+ const expected = `- Literal: "hello"
94
+ `;
95
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
96
+ });
97
+ it('should convert ZodBigInt to markdown', () => {
98
+ const schema = zod_1.z.bigint();
99
+ const expected = `- BigInt
100
+ `;
101
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
102
+ });
103
+ it('should convert ZodDate to markdown', () => {
104
+ const schema = zod_1.z.date();
105
+ const expected = `- Date
106
+ `;
107
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
108
+ });
109
+ it('should convert ZodNaN to markdown', () => {
110
+ const schema = zod_1.z.nan();
111
+ const expected = `- NaN
112
+ `;
113
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
114
+ });
115
+ it('should convert ZodNever to markdown', () => {
116
+ const schema = zod_1.z.never();
117
+ const expected = `- Never
118
+ `;
119
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
120
+ });
121
+ it('should convert ZodUnknown to markdown', () => {
122
+ const schema = zod_1.z.unknown();
123
+ const expected = `- Unknown
124
+ `;
125
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
126
+ });
127
+ it('should convert ZodVoid to markdown', () => {
128
+ const schema = zod_1.z.void();
129
+ const expected = `- Void
130
+ `;
131
+ expect((0, index_1.zodSchemaToMarkdown)(schema)).toBe(expected);
132
+ });
133
+ });
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@chnak/zod-to-markdown",
3
+ "version": "1.0.1",
4
+ "description": "A utility function to convert Zod schemas to Markdown documentation",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "jest",
13
+ "prepublish": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "zod",
17
+ "markdown",
18
+ "documentation",
19
+ "schema",
20
+ "typescript"
21
+ ],
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/chnak/zod-to-markdown.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/chnak/zod-to-markdown/issues"
29
+ },
30
+ "homepage": "https://github.com/chnak/zod-to-markdown#readme",
31
+ "dependencies": {
32
+ "zod": "^3.24.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/jest": "^29.5.12",
36
+ "@types/node": "^14.0.0",
37
+ "jest": "^29.7.0",
38
+ "ts-jest": "^29.1.2",
39
+ "typescript": "^4.0.0"
40
+ }
41
+ }