@schemashift/zod-arktype 0.10.0
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 +136 -0
- package/dist/index.cjs +392 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +362 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# @schemashift/zod-arktype
|
|
2
|
+
|
|
3
|
+
Zod ↔ ArkType transformer for SchemaShift. Supports both forward (Zod → ArkType) and backward (ArkType → Zod) migrations.
|
|
4
|
+
|
|
5
|
+
**Tier:** Pro+
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @schemashift/zod-arktype
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createZodToArktypeHandler, createArktypeToZodHandler } from '@schemashift/zod-arktype';
|
|
17
|
+
import { TransformEngine } from '@schemashift/core';
|
|
18
|
+
|
|
19
|
+
const engine = new TransformEngine();
|
|
20
|
+
engine.registerHandler('zod', 'arktype', createZodToArktypeHandler());
|
|
21
|
+
engine.registerHandler('arktype', 'zod', createArktypeToZodHandler()); // Backward migration (Pro+)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API Paradigm Difference
|
|
25
|
+
|
|
26
|
+
Zod uses a **method chain** API:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
z.object({ name: z.string().email(), age: z.number().int() })
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
ArkType uses a **TypeScript-like string** API:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
type({ name: "string.email", age: "number.integer" })
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Transformation Mappings
|
|
39
|
+
|
|
40
|
+
### Imports
|
|
41
|
+
|
|
42
|
+
| Zod | ArkType |
|
|
43
|
+
|-----|---------|
|
|
44
|
+
| `import { z } from 'zod'` | `import { type } from 'arktype'` |
|
|
45
|
+
|
|
46
|
+
### Factory Methods
|
|
47
|
+
|
|
48
|
+
| Zod | ArkType |
|
|
49
|
+
|-----|---------|
|
|
50
|
+
| `z.string()` | `"string"` |
|
|
51
|
+
| `z.number()` | `"number"` |
|
|
52
|
+
| `z.boolean()` | `"boolean"` |
|
|
53
|
+
| `z.bigint()` | `"bigint"` |
|
|
54
|
+
| `z.date()` | `"Date"` |
|
|
55
|
+
| `z.unknown()` | `"unknown"` |
|
|
56
|
+
| `z.never()` | `"never"` |
|
|
57
|
+
| `z.null()` | `"null"` |
|
|
58
|
+
| `z.void()` | `"void"` |
|
|
59
|
+
| `z.any()` | `"unknown"` |
|
|
60
|
+
| `z.object({...})` | `type({...})` |
|
|
61
|
+
| `z.array(s)` | `"s[]"` |
|
|
62
|
+
| `z.enum(["a", "b"])` | `type("'a' \| 'b'")` |
|
|
63
|
+
| `z.literal(42)` | `type("=== 42")` |
|
|
64
|
+
| `z.union([a, b])` | `type("a \| b")` |
|
|
65
|
+
| `z.record(k, v)` | `type("Record<k, v>")` |
|
|
66
|
+
|
|
67
|
+
### Validations
|
|
68
|
+
|
|
69
|
+
| Zod | ArkType |
|
|
70
|
+
|-----|---------|
|
|
71
|
+
| `z.string().email()` | `"string.email"` |
|
|
72
|
+
| `z.string().url()` | `"string.url"` |
|
|
73
|
+
| `z.string().uuid()` | `"string.uuid"` |
|
|
74
|
+
| `z.string().ip()` | `"string.ip"` |
|
|
75
|
+
| `z.number().int()` | `"number.integer"` |
|
|
76
|
+
|
|
77
|
+
### Modifiers
|
|
78
|
+
|
|
79
|
+
| Zod | ArkType |
|
|
80
|
+
|-----|---------|
|
|
81
|
+
| `.optional()` | `"type?"` |
|
|
82
|
+
| `.nullable()` | `"type \| null"` |
|
|
83
|
+
|
|
84
|
+
### Type Helpers
|
|
85
|
+
|
|
86
|
+
| Zod | ArkType |
|
|
87
|
+
|-----|---------|
|
|
88
|
+
| `z.infer<typeof s>` | `typeof s.infer` |
|
|
89
|
+
| `z.input<typeof s>` | `typeof s.in` |
|
|
90
|
+
| `z.output<typeof s>` | `typeof s.infer` |
|
|
91
|
+
|
|
92
|
+
## Patterns Requiring Manual Review
|
|
93
|
+
|
|
94
|
+
### `.superRefine()` / `.refine()`
|
|
95
|
+
|
|
96
|
+
ArkType uses `.narrow()` for refinements:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// Zod
|
|
100
|
+
z.string().refine((s) => s.length > 0, "Required");
|
|
101
|
+
|
|
102
|
+
// ArkType
|
|
103
|
+
type("string").narrow((s) => s.length > 0);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `.transform()`
|
|
107
|
+
|
|
108
|
+
ArkType uses morphs via `.pipe()`:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Zod
|
|
112
|
+
z.string().transform((s) => s.toUpperCase());
|
|
113
|
+
|
|
114
|
+
// ArkType
|
|
115
|
+
type("string").pipe((s) => s.toUpperCase());
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Recursive Types
|
|
119
|
+
|
|
120
|
+
ArkType uses `scope()` for recursive definitions:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Zod
|
|
124
|
+
const node: z.ZodType<Node> = z.lazy(() => z.object({ children: z.array(node) }));
|
|
125
|
+
|
|
126
|
+
// ArkType
|
|
127
|
+
const types = scope({ node: { children: "node[]" } }).export();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `.brand()`
|
|
131
|
+
|
|
132
|
+
ArkType has no `.brand()` equivalent. Use nominal types or tagged unions instead.
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ARKTYPE_TO_ZOD_MAPPINGS: () => ARKTYPE_TO_ZOD_MAPPINGS,
|
|
24
|
+
ZOD_TO_ARKTYPE_MAPPINGS: () => ZOD_TO_ARKTYPE_MAPPINGS,
|
|
25
|
+
createArktypeToZodHandler: () => createArktypeToZodHandler,
|
|
26
|
+
createZodToArktypeHandler: () => createZodToArktypeHandler
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/mappings.ts
|
|
31
|
+
var ZOD_TO_ARKTYPE_MAPPINGS = {
|
|
32
|
+
"z.string()": '"string"',
|
|
33
|
+
"z.number()": '"number"',
|
|
34
|
+
"z.boolean()": '"boolean"',
|
|
35
|
+
"z.bigint()": '"bigint"',
|
|
36
|
+
"z.symbol()": '"symbol"',
|
|
37
|
+
"z.undefined()": '"undefined"',
|
|
38
|
+
"z.null()": '"null"',
|
|
39
|
+
"z.void()": '"void"',
|
|
40
|
+
"z.any()": '"unknown"',
|
|
41
|
+
"z.unknown()": '"unknown"',
|
|
42
|
+
"z.never()": '"never"',
|
|
43
|
+
"z.date()": '"Date"'
|
|
44
|
+
};
|
|
45
|
+
var ZOD_VALIDATION_TO_ARKTYPE = {
|
|
46
|
+
email: "string.email",
|
|
47
|
+
url: "string.url",
|
|
48
|
+
uuid: "string.uuid",
|
|
49
|
+
ip: "string.ip",
|
|
50
|
+
integer: "number.integer"
|
|
51
|
+
};
|
|
52
|
+
var ARKTYPE_TO_ZOD_MAPPINGS = {
|
|
53
|
+
string: "z.string()",
|
|
54
|
+
number: "z.number()",
|
|
55
|
+
boolean: "z.boolean()",
|
|
56
|
+
bigint: "z.bigint()",
|
|
57
|
+
symbol: "z.symbol()",
|
|
58
|
+
undefined: "z.undefined()",
|
|
59
|
+
null: "z.null()",
|
|
60
|
+
void: "z.void()",
|
|
61
|
+
unknown: "z.unknown()",
|
|
62
|
+
never: "z.never()",
|
|
63
|
+
Date: "z.date()",
|
|
64
|
+
"string.email": "z.string().email()",
|
|
65
|
+
"string.url": "z.string().url()",
|
|
66
|
+
"string.uuid": "z.string().uuid()",
|
|
67
|
+
"string.ip": "z.string().ip()",
|
|
68
|
+
"number.integer": "z.number().int()"
|
|
69
|
+
};
|
|
70
|
+
var MANUAL_REVIEW_PATTERNS = /* @__PURE__ */ new Set([
|
|
71
|
+
"discriminatedUnion",
|
|
72
|
+
// ArkType uses native TS union syntax
|
|
73
|
+
"superRefine",
|
|
74
|
+
// ArkType uses .narrow()
|
|
75
|
+
"transform",
|
|
76
|
+
// ArkType uses .pipe() or morphs
|
|
77
|
+
"preprocess",
|
|
78
|
+
// ArkType uses .from()
|
|
79
|
+
"lazy",
|
|
80
|
+
// ArkType handles recursion differently
|
|
81
|
+
"brand",
|
|
82
|
+
// ArkType has no equivalent
|
|
83
|
+
"coerce",
|
|
84
|
+
// ArkType uses .from() morphs
|
|
85
|
+
"pipe",
|
|
86
|
+
// Different semantics
|
|
87
|
+
"catch"
|
|
88
|
+
// ArkType has no .catch() equivalent
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
// src/arktype-to-zod-transformer.ts
|
|
92
|
+
var ArktypeToZodTransformer = class {
|
|
93
|
+
errors = [];
|
|
94
|
+
warnings = [];
|
|
95
|
+
transform(sourceFile) {
|
|
96
|
+
this.errors = [];
|
|
97
|
+
this.warnings = [];
|
|
98
|
+
const filePath = sourceFile.getFilePath();
|
|
99
|
+
const originalCode = sourceFile.getFullText();
|
|
100
|
+
try {
|
|
101
|
+
let text = originalCode;
|
|
102
|
+
text = this.rewriteImports(text, filePath);
|
|
103
|
+
text = this.transformTypeDefinitions(text, filePath);
|
|
104
|
+
text = this.transformTypeHelpers(text);
|
|
105
|
+
text = this.transformStringTypes(text);
|
|
106
|
+
sourceFile.replaceWithText(text);
|
|
107
|
+
return {
|
|
108
|
+
success: this.errors.length === 0,
|
|
109
|
+
filePath,
|
|
110
|
+
originalCode,
|
|
111
|
+
transformedCode: sourceFile.getFullText(),
|
|
112
|
+
errors: this.errors,
|
|
113
|
+
warnings: this.warnings
|
|
114
|
+
};
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.errors.push({
|
|
117
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
filePath,
|
|
122
|
+
originalCode,
|
|
123
|
+
errors: this.errors,
|
|
124
|
+
warnings: this.warnings
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
rewriteImports(text, filePath) {
|
|
129
|
+
text = text.replace(
|
|
130
|
+
/import\s*\{\s*type\s*\}\s*from\s*['"]arktype['"]/g,
|
|
131
|
+
"import { z } from 'zod'"
|
|
132
|
+
);
|
|
133
|
+
text = text.replace(
|
|
134
|
+
/import\s*\{[^}]*\btype\b[^}]*\}\s*from\s*['"]arktype['"]/g,
|
|
135
|
+
"import { z } from 'zod'"
|
|
136
|
+
);
|
|
137
|
+
text = text.replace(
|
|
138
|
+
/import\s+type\s*\{[^}]*\}\s*from\s*['"]arktype['"]/g,
|
|
139
|
+
"import type { z } from 'zod'"
|
|
140
|
+
);
|
|
141
|
+
if (text.includes("scope(")) {
|
|
142
|
+
this.warnings.push(
|
|
143
|
+
`${filePath}: ArkType scope() has no direct Zod equivalent. Convert to individual z.object() schemas with z.lazy() for recursive types.`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return text;
|
|
147
|
+
}
|
|
148
|
+
transformTypeDefinitions(text, filePath) {
|
|
149
|
+
text = text.replace(/\btype\(\{/g, "z.object({");
|
|
150
|
+
text = text.replace(/\btype\("string"\)/g, "z.string()");
|
|
151
|
+
text = text.replace(/\btype\("number"\)/g, "z.number()");
|
|
152
|
+
text = text.replace(/\btype\("boolean"\)/g, "z.boolean()");
|
|
153
|
+
text = text.replace(/\btype\("bigint"\)/g, "z.bigint()");
|
|
154
|
+
text = text.replace(/\btype\("unknown"\)/g, "z.unknown()");
|
|
155
|
+
text = text.replace(/\btype\("never"\)/g, "z.never()");
|
|
156
|
+
text = text.replace(/\btype\("Date"\)/g, "z.date()");
|
|
157
|
+
text = text.replace(/\btype\("string\.email"\)/g, "z.string().email()");
|
|
158
|
+
text = text.replace(/\btype\("string\.url"\)/g, "z.string().url()");
|
|
159
|
+
text = text.replace(/\btype\("string\.uuid"\)/g, "z.string().uuid()");
|
|
160
|
+
text = text.replace(/\btype\("string\.ip"\)/g, "z.string().ip()");
|
|
161
|
+
text = text.replace(/\btype\("number\.integer"\)/g, "z.number().int()");
|
|
162
|
+
text = text.replace(/\btype\("(\w+)\[\]"\)/g, (_match, typeName) => {
|
|
163
|
+
const zodType = ARKTYPE_TO_ZOD_MAPPINGS[typeName];
|
|
164
|
+
return zodType ? `z.array(${zodType})` : `z.array(z.${typeName}())`;
|
|
165
|
+
});
|
|
166
|
+
text = text.replace(/\btype\("([^"]+\|[^"]+)"\)/g, (_match, unionStr) => {
|
|
167
|
+
const types = unionStr.split("|").map((t) => {
|
|
168
|
+
const trimmed = t.trim();
|
|
169
|
+
const zodType = ARKTYPE_TO_ZOD_MAPPINGS[trimmed];
|
|
170
|
+
if (zodType) return zodType;
|
|
171
|
+
if (trimmed === "null") return "z.null()";
|
|
172
|
+
return `z.${trimmed}()`;
|
|
173
|
+
});
|
|
174
|
+
return `z.union([${types.join(", ")}])`;
|
|
175
|
+
});
|
|
176
|
+
if (text.includes(".narrow(")) {
|
|
177
|
+
this.warnings.push(
|
|
178
|
+
`${filePath}: ArkType .narrow() should be converted to z.refine() or z.superRefine().`
|
|
179
|
+
);
|
|
180
|
+
text = text.replace(/\.narrow\(/g, ".refine(");
|
|
181
|
+
}
|
|
182
|
+
if (text.includes(".pipe(")) {
|
|
183
|
+
this.warnings.push(
|
|
184
|
+
`${filePath}: ArkType .pipe() morphs should be reviewed \u2014 Zod .transform() or .pipe() may apply.`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return text;
|
|
188
|
+
}
|
|
189
|
+
transformTypeHelpers(text) {
|
|
190
|
+
text = text.replace(/typeof\s+(\w+)\.infer\b/g, "z.infer<typeof $1>");
|
|
191
|
+
text = text.replace(/typeof\s+(\w+)\.in\b/g, "z.input<typeof $1>");
|
|
192
|
+
text = text.replace(/Type<typeof\s+(\w+)>/g, "z.infer<typeof $1>");
|
|
193
|
+
return text;
|
|
194
|
+
}
|
|
195
|
+
transformStringTypes(text) {
|
|
196
|
+
text = text.replace(/"string\?"/g, "z.string().optional()");
|
|
197
|
+
text = text.replace(/"number\?"/g, "z.number().optional()");
|
|
198
|
+
text = text.replace(/"boolean\?"/g, "z.boolean().optional()");
|
|
199
|
+
text = text.replace(/"string \| null"/g, "z.string().nullable()");
|
|
200
|
+
text = text.replace(/"number \| null"/g, "z.number().nullable()");
|
|
201
|
+
text = text.replace(/"boolean \| null"/g, "z.boolean().nullable()");
|
|
202
|
+
text = text.replace(/:\s*"string"/g, ": z.string()");
|
|
203
|
+
text = text.replace(/:\s*"number"/g, ": z.number()");
|
|
204
|
+
text = text.replace(/:\s*"boolean"/g, ": z.boolean()");
|
|
205
|
+
text = text.replace(/:\s*"Date"/g, ": z.date()");
|
|
206
|
+
text = text.replace(/:\s*"bigint"/g, ": z.bigint()");
|
|
207
|
+
text = text.replace(/:\s*"unknown"/g, ": z.unknown()");
|
|
208
|
+
text = text.replace(/:\s*"string\.email"/g, ": z.string().email()");
|
|
209
|
+
text = text.replace(/:\s*"string\.url"/g, ": z.string().url()");
|
|
210
|
+
text = text.replace(/:\s*"string\.uuid"/g, ": z.string().uuid()");
|
|
211
|
+
return text;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/arktype-to-zod-handler.ts
|
|
216
|
+
function createArktypeToZodHandler() {
|
|
217
|
+
return {
|
|
218
|
+
transform(sourceFile, _options) {
|
|
219
|
+
const transformer = new ArktypeToZodTransformer();
|
|
220
|
+
return transformer.transform(sourceFile);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/zod-to-arktype-transformer.ts
|
|
226
|
+
var ZodToArktypeTransformer = class {
|
|
227
|
+
errors = [];
|
|
228
|
+
warnings = [];
|
|
229
|
+
transform(sourceFile) {
|
|
230
|
+
this.errors = [];
|
|
231
|
+
this.warnings = [];
|
|
232
|
+
const filePath = sourceFile.getFilePath();
|
|
233
|
+
const originalCode = sourceFile.getFullText();
|
|
234
|
+
try {
|
|
235
|
+
this.rewriteImports(sourceFile);
|
|
236
|
+
this.transformSchemas(sourceFile);
|
|
237
|
+
this.transformTypeHelpers(sourceFile);
|
|
238
|
+
this.checkManualReviewPatterns(sourceFile);
|
|
239
|
+
return {
|
|
240
|
+
success: this.errors.length === 0,
|
|
241
|
+
filePath,
|
|
242
|
+
originalCode,
|
|
243
|
+
transformedCode: sourceFile.getFullText(),
|
|
244
|
+
errors: this.errors,
|
|
245
|
+
warnings: this.warnings
|
|
246
|
+
};
|
|
247
|
+
} catch (error) {
|
|
248
|
+
this.errors.push({
|
|
249
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
250
|
+
});
|
|
251
|
+
return {
|
|
252
|
+
success: false,
|
|
253
|
+
filePath,
|
|
254
|
+
originalCode,
|
|
255
|
+
errors: this.errors,
|
|
256
|
+
warnings: this.warnings
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
rewriteImports(sourceFile) {
|
|
261
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
262
|
+
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
263
|
+
if (moduleSpecifier === "zod") {
|
|
264
|
+
importDecl.setModuleSpecifier("arktype");
|
|
265
|
+
const namedImports = importDecl.getNamedImports();
|
|
266
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
267
|
+
const namespaceImport = importDecl.getNamespaceImport();
|
|
268
|
+
if (namespaceImport) {
|
|
269
|
+
importDecl.removeNamespaceImport();
|
|
270
|
+
importDecl.addNamedImport("type");
|
|
271
|
+
} else if (namedImports.length > 0) {
|
|
272
|
+
for (const namedImport of namedImports) {
|
|
273
|
+
const name = namedImport.getName();
|
|
274
|
+
if (name === "z") {
|
|
275
|
+
namedImport.remove();
|
|
276
|
+
} else {
|
|
277
|
+
this.warnings.push(
|
|
278
|
+
`${sourceFile.getFilePath()}: '${name}' import requires manual conversion to ArkType equivalent.`
|
|
279
|
+
);
|
|
280
|
+
namedImport.remove();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
importDecl.addNamedImport("type");
|
|
284
|
+
} else if (defaultImport) {
|
|
285
|
+
importDecl.removeDefaultImport();
|
|
286
|
+
importDecl.addNamedImport("type");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
transformSchemas(sourceFile) {
|
|
292
|
+
let text = sourceFile.getFullText();
|
|
293
|
+
const filePath = sourceFile.getFilePath();
|
|
294
|
+
const simpleReplacements = [
|
|
295
|
+
// z.object({...}) → type({...}) — handled separately for nested content
|
|
296
|
+
[/\bz\.string\(\)/g, '"string"'],
|
|
297
|
+
[/\bz\.number\(\)/g, '"number"'],
|
|
298
|
+
[/\bz\.boolean\(\)/g, '"boolean"'],
|
|
299
|
+
[/\bz\.bigint\(\)/g, '"bigint"'],
|
|
300
|
+
[/\bz\.symbol\(\)/g, '"symbol"'],
|
|
301
|
+
[/\bz\.undefined\(\)/g, '"undefined"'],
|
|
302
|
+
[/\bz\.null\(\)/g, '"null"'],
|
|
303
|
+
[/\bz\.void\(\)/g, '"void"'],
|
|
304
|
+
[/\bz\.any\(\)/g, '"unknown"'],
|
|
305
|
+
[/\bz\.unknown\(\)/g, '"unknown"'],
|
|
306
|
+
[/\bz\.never\(\)/g, '"never"'],
|
|
307
|
+
[/\bz\.date\(\)/g, '"Date"'],
|
|
308
|
+
[/\bz\.nan\(\)/g, '"number"']
|
|
309
|
+
];
|
|
310
|
+
for (const [pattern, replacement] of simpleReplacements) {
|
|
311
|
+
text = text.replace(pattern, replacement);
|
|
312
|
+
}
|
|
313
|
+
text = text.replace(/\bz\.object\(/g, "type(");
|
|
314
|
+
text = text.replace(/\bz\.array\(("[\w.]+")\)/g, 'type("$1[]")');
|
|
315
|
+
text = text.replace(/\bz\.enum\(\[([^\]]+)\]\)/g, (_match, values) => {
|
|
316
|
+
const items = values.split(",").map((v) => v.trim());
|
|
317
|
+
return `type("${items.join(" | ")}")`;
|
|
318
|
+
});
|
|
319
|
+
text = text.replace(/"([\w.]+)"\.optional\(\)/g, '"$1?"');
|
|
320
|
+
text = text.replace(/"([\w.?]+)"\.nullable\(\)/g, '"$1 | null"');
|
|
321
|
+
for (const [zodMethod, arktypeType] of Object.entries(ZOD_VALIDATION_TO_ARKTYPE)) {
|
|
322
|
+
const pattern = new RegExp(`"string"\\.${zodMethod}\\(\\)`, "g");
|
|
323
|
+
text = text.replace(pattern, `"${arktypeType}"`);
|
|
324
|
+
}
|
|
325
|
+
text = text.replace(/\bz\.union\(\[([^\]]+)\]\)/g, (_match, items) => {
|
|
326
|
+
const types = items.split(",").map((t) => t.trim().replace(/^"|"$/g, ""));
|
|
327
|
+
return `type("${types.join(" | ")}")`;
|
|
328
|
+
});
|
|
329
|
+
text = text.replace(/\bz\.literal\((\d+)\)/g, 'type("=== $1")');
|
|
330
|
+
text = text.replace(/\bz\.literal\((['"][^'"]+['"])\)/g, "type($1)");
|
|
331
|
+
text = text.replace(/\bz\.literal\((true|false)\)/g, 'type("=== $1")');
|
|
332
|
+
text = text.replace(/\bz\.record\("string", "(\w+)"\)/g, 'type("Record<string, $1>")');
|
|
333
|
+
sourceFile.replaceWithText(text);
|
|
334
|
+
const currentText = sourceFile.getFullText();
|
|
335
|
+
if (currentText.includes("z.")) {
|
|
336
|
+
this.warnings.push(
|
|
337
|
+
`${filePath}: Some Zod patterns could not be auto-transformed to ArkType. Look for remaining z.* references and convert manually.`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
transformTypeHelpers(sourceFile) {
|
|
342
|
+
let text = sourceFile.getFullText();
|
|
343
|
+
text = text.replace(/z\.infer<typeof\s+(\w+)>/g, "typeof $1.infer");
|
|
344
|
+
text = text.replace(/z\.input<typeof\s+(\w+)>/g, "typeof $1.in");
|
|
345
|
+
text = text.replace(/z\.output<typeof\s+(\w+)>/g, "typeof $1.infer");
|
|
346
|
+
sourceFile.replaceWithText(text);
|
|
347
|
+
}
|
|
348
|
+
checkManualReviewPatterns(sourceFile) {
|
|
349
|
+
const filePath = sourceFile.getFilePath();
|
|
350
|
+
const text = sourceFile.getFullText();
|
|
351
|
+
for (const pattern of MANUAL_REVIEW_PATTERNS) {
|
|
352
|
+
if (text.includes(`.${pattern}(`)) {
|
|
353
|
+
const guidance = this.getManualGuidance(pattern);
|
|
354
|
+
this.warnings.push(
|
|
355
|
+
`${filePath}: .${pattern}() requires manual conversion to ArkType. ${guidance}`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
getManualGuidance(pattern) {
|
|
361
|
+
const guidance = {
|
|
362
|
+
discriminatedUnion: `ArkType uses native TypeScript union syntax: type("{ kind: 'a', ... } | { kind: 'b', ... }").`,
|
|
363
|
+
superRefine: 'ArkType uses .narrow() for refinements: type("string").narrow((s) => s.length > 0).',
|
|
364
|
+
transform: 'ArkType uses morphs: type("string").pipe((s) => s.toUpperCase()).',
|
|
365
|
+
preprocess: "ArkType uses .from() for input transforms.",
|
|
366
|
+
lazy: 'ArkType handles recursion with scope(): const types = scope({ node: { left: "node | null", right: "node | null" } }).export().',
|
|
367
|
+
brand: "ArkType has no .brand() equivalent. Use nominal types or tagged unions instead.",
|
|
368
|
+
coerce: 'ArkType uses .from() morphs for coercion: type("string").from("number").',
|
|
369
|
+
pipe: "ArkType uses .pipe() with different semantics for morphs.",
|
|
370
|
+
catch: "ArkType has no .catch() equivalent. Handle fallback values at the application level."
|
|
371
|
+
};
|
|
372
|
+
return guidance[pattern] || "See ArkType documentation for equivalent pattern.";
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// src/zod-to-arktype-handler.ts
|
|
377
|
+
function createZodToArktypeHandler() {
|
|
378
|
+
return {
|
|
379
|
+
transform(sourceFile, _options) {
|
|
380
|
+
const transformer = new ZodToArktypeTransformer();
|
|
381
|
+
return transformer.transform(sourceFile);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
386
|
+
0 && (module.exports = {
|
|
387
|
+
ARKTYPE_TO_ZOD_MAPPINGS,
|
|
388
|
+
ZOD_TO_ARKTYPE_MAPPINGS,
|
|
389
|
+
createArktypeToZodHandler,
|
|
390
|
+
createZodToArktypeHandler
|
|
391
|
+
});
|
|
392
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/mappings.ts","../src/arktype-to-zod-transformer.ts","../src/arktype-to-zod-handler.ts","../src/zod-to-arktype-transformer.ts","../src/zod-to-arktype-handler.ts"],"sourcesContent":["export { createArktypeToZodHandler } from './arktype-to-zod-handler.js';\nexport { ARKTYPE_TO_ZOD_MAPPINGS, ZOD_TO_ARKTYPE_MAPPINGS } from './mappings.js';\nexport { createZodToArktypeHandler } from './zod-to-arktype-handler.js';\n","/**\n * Zod ↔ ArkType Mapping Tables\n *\n * ArkType uses a TypeScript-like string syntax for type definitions,\n * while Zod uses method chains. This makes the transformation quite different\n * from other library pairs.\n *\n * ArkType: type({ name: \"string\", age: \"number\" })\n * Zod: z.object({ name: z.string(), age: z.number() })\n */\n\n// Zod factory → ArkType string type\nexport const ZOD_TO_ARKTYPE_MAPPINGS: Record<string, string> = {\n 'z.string()': '\"string\"',\n 'z.number()': '\"number\"',\n 'z.boolean()': '\"boolean\"',\n 'z.bigint()': '\"bigint\"',\n 'z.symbol()': '\"symbol\"',\n 'z.undefined()': '\"undefined\"',\n 'z.null()': '\"null\"',\n 'z.void()': '\"void\"',\n 'z.any()': '\"unknown\"',\n 'z.unknown()': '\"unknown\"',\n 'z.never()': '\"never\"',\n 'z.date()': '\"Date\"',\n};\n\n// Zod validation methods → ArkType constraints\nexport const ZOD_VALIDATION_TO_ARKTYPE: Record<string, string> = {\n email: 'string.email',\n url: 'string.url',\n uuid: 'string.uuid',\n ip: 'string.ip',\n integer: 'number.integer',\n};\n\n// ArkType string type → Zod factory\nexport const ARKTYPE_TO_ZOD_MAPPINGS: Record<string, string> = {\n string: 'z.string()',\n number: 'z.number()',\n boolean: 'z.boolean()',\n bigint: 'z.bigint()',\n symbol: 'z.symbol()',\n undefined: 'z.undefined()',\n null: 'z.null()',\n void: 'z.void()',\n unknown: 'z.unknown()',\n never: 'z.never()',\n Date: 'z.date()',\n 'string.email': 'z.string().email()',\n 'string.url': 'z.string().url()',\n 'string.uuid': 'z.string().uuid()',\n 'string.ip': 'z.string().ip()',\n 'number.integer': 'z.number().int()',\n};\n\n// Import mappings\nexport const IMPORT_MAPPINGS = {\n zod: {\n from: \"import { z } from 'zod'\",\n to: \"import { type } from 'arktype'\",\n },\n arktype: {\n from: \"import { type } from 'arktype'\",\n to: \"import { z } from 'zod'\",\n },\n};\n\n// Type helper mappings\nexport const TYPE_HELPER_MAPPINGS = {\n zodToArktype: {\n 'z.infer': 'typeof',\n 'z.input': 'typeof',\n 'z.output': 'typeof',\n },\n arktypeToZod: {\n 'Type<typeof': 'z.infer<typeof',\n },\n};\n\n// Patterns requiring manual review\nexport const MANUAL_REVIEW_PATTERNS = new Set([\n 'discriminatedUnion', // ArkType uses native TS union syntax\n 'superRefine', // ArkType uses .narrow()\n 'transform', // ArkType uses .pipe() or morphs\n 'preprocess', // ArkType uses .from()\n 'lazy', // ArkType handles recursion differently\n 'brand', // ArkType has no equivalent\n 'coerce', // ArkType uses .from() morphs\n 'pipe', // Different semantics\n 'catch', // ArkType has no .catch() equivalent\n]);\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ARKTYPE_TO_ZOD_MAPPINGS } from './mappings.js';\n\n/**\n * ArkType → Zod Transformer (Backward Migration)\n *\n * Converts ArkType type definitions to Zod schemas.\n * ArkType uses string-based type syntax which makes AST-based\n * transformation challenging, so this uses text-based approach.\n *\n * ArkType: type({ name: \"string.email\", age: \"number\" })\n * Zod: z.object({ name: z.string().email(), age: z.number() })\n */\nexport class ArktypeToZodTransformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n let text = originalCode;\n\n // Step 1: Rewrite imports\n text = this.rewriteImports(text, filePath);\n\n // Step 2: Transform type() calls to z.object() etc.\n text = this.transformTypeDefinitions(text, filePath);\n\n // Step 3: Transform type helpers\n text = this.transformTypeHelpers(text);\n\n // Step 4: Transform string type references to Zod factories\n text = this.transformStringTypes(text);\n\n sourceFile.replaceWithText(text);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n private rewriteImports(text: string, filePath: string): string {\n // import { type } from 'arktype' → import { z } from 'zod'\n text = text.replace(\n /import\\s*\\{\\s*type\\s*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import { z } from 'zod'\",\n );\n\n // import { type, scope } from 'arktype' → import { z } from 'zod'\n text = text.replace(\n /import\\s*\\{[^}]*\\btype\\b[^}]*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import { z } from 'zod'\",\n );\n\n // import type { Type } from 'arktype' → import type { z } from 'zod'\n text = text.replace(\n /import\\s+type\\s*\\{[^}]*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import type { z } from 'zod'\",\n );\n\n // Check for scope() usage\n if (text.includes('scope(')) {\n this.warnings.push(\n `${filePath}: ArkType scope() has no direct Zod equivalent. ` +\n 'Convert to individual z.object() schemas with z.lazy() for recursive types.',\n );\n }\n\n return text;\n }\n\n private transformTypeDefinitions(text: string, filePath: string): string {\n // type({ ... }) → z.object({ ... })\n text = text.replace(/\\btype\\(\\{/g, 'z.object({');\n\n // type(\"string\") → z.string()\n text = text.replace(/\\btype\\(\"string\"\\)/g, 'z.string()');\n text = text.replace(/\\btype\\(\"number\"\\)/g, 'z.number()');\n text = text.replace(/\\btype\\(\"boolean\"\\)/g, 'z.boolean()');\n text = text.replace(/\\btype\\(\"bigint\"\\)/g, 'z.bigint()');\n text = text.replace(/\\btype\\(\"unknown\"\\)/g, 'z.unknown()');\n text = text.replace(/\\btype\\(\"never\"\\)/g, 'z.never()');\n text = text.replace(/\\btype\\(\"Date\"\\)/g, 'z.date()');\n\n // type(\"string.email\") → z.string().email()\n text = text.replace(/\\btype\\(\"string\\.email\"\\)/g, 'z.string().email()');\n text = text.replace(/\\btype\\(\"string\\.url\"\\)/g, 'z.string().url()');\n text = text.replace(/\\btype\\(\"string\\.uuid\"\\)/g, 'z.string().uuid()');\n text = text.replace(/\\btype\\(\"string\\.ip\"\\)/g, 'z.string().ip()');\n text = text.replace(/\\btype\\(\"number\\.integer\"\\)/g, 'z.number().int()');\n\n // type(\"X[]\") → z.array(z.X())\n text = text.replace(/\\btype\\(\"(\\w+)\\[\\]\"\\)/g, (_match, typeName: string) => {\n const zodType = ARKTYPE_TO_ZOD_MAPPINGS[typeName];\n return zodType ? `z.array(${zodType})` : `z.array(z.${typeName}())`;\n });\n\n // type(\"X | Y\") → z.union([z.X(), z.Y()])\n text = text.replace(/\\btype\\(\"([^\"]+\\|[^\"]+)\"\\)/g, (_match, unionStr: string) => {\n const types = unionStr.split('|').map((t: string) => {\n const trimmed = t.trim();\n const zodType = ARKTYPE_TO_ZOD_MAPPINGS[trimmed];\n if (zodType) return zodType;\n if (trimmed === 'null') return 'z.null()';\n return `z.${trimmed}()`;\n });\n return `z.union([${types.join(', ')}])`;\n });\n\n // Check for .narrow() — ArkType refinement\n if (text.includes('.narrow(')) {\n this.warnings.push(\n `${filePath}: ArkType .narrow() should be converted to z.refine() or z.superRefine().`,\n );\n text = text.replace(/\\.narrow\\(/g, '.refine(');\n }\n\n // Check for .pipe() morphs — ArkType transforms\n if (text.includes('.pipe(')) {\n this.warnings.push(\n `${filePath}: ArkType .pipe() morphs should be reviewed — Zod .transform() or .pipe() may apply.`,\n );\n }\n\n return text;\n }\n\n private transformTypeHelpers(text: string): string {\n // typeof schema.infer → z.infer<typeof schema>\n text = text.replace(/typeof\\s+(\\w+)\\.infer\\b/g, 'z.infer<typeof $1>');\n text = text.replace(/typeof\\s+(\\w+)\\.in\\b/g, 'z.input<typeof $1>');\n\n // Type<typeof schema> → z.infer<typeof schema>\n text = text.replace(/Type<typeof\\s+(\\w+)>/g, 'z.infer<typeof $1>');\n\n return text;\n }\n\n private transformStringTypes(text: string): string {\n // Inside object definitions, transform string type references\n // \"string\" → z.string()\n // \"number\" → z.number()\n // \"string?\" → z.string().optional()\n // \"string | null\" → z.string().nullable()\n\n // Optional types\n text = text.replace(/\"string\\?\"/g, 'z.string().optional()');\n text = text.replace(/\"number\\?\"/g, 'z.number().optional()');\n text = text.replace(/\"boolean\\?\"/g, 'z.boolean().optional()');\n\n // Nullable types\n text = text.replace(/\"string \\| null\"/g, 'z.string().nullable()');\n text = text.replace(/\"number \\| null\"/g, 'z.number().nullable()');\n text = text.replace(/\"boolean \\| null\"/g, 'z.boolean().nullable()');\n\n // Simple types in property positions\n text = text.replace(/:\\s*\"string\"/g, ': z.string()');\n text = text.replace(/:\\s*\"number\"/g, ': z.number()');\n text = text.replace(/:\\s*\"boolean\"/g, ': z.boolean()');\n text = text.replace(/:\\s*\"Date\"/g, ': z.date()');\n text = text.replace(/:\\s*\"bigint\"/g, ': z.bigint()');\n text = text.replace(/:\\s*\"unknown\"/g, ': z.unknown()');\n\n // Validated string types in property positions\n text = text.replace(/:\\s*\"string\\.email\"/g, ': z.string().email()');\n text = text.replace(/:\\s*\"string\\.url\"/g, ': z.string().url()');\n text = text.replace(/:\\s*\"string\\.uuid\"/g, ': z.string().uuid()');\n\n return text;\n }\n}\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ArktypeToZodTransformer } from './arktype-to-zod-transformer.js';\n\nexport function createArktypeToZodHandler(): TransformHandler {\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n const transformer = new ArktypeToZodTransformer();\n return transformer.transform(sourceFile);\n },\n };\n}\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { MANUAL_REVIEW_PATTERNS, ZOD_VALIDATION_TO_ARKTYPE } from './mappings.js';\n\n/**\n * Zod → ArkType Transformer\n *\n * Converts Zod schemas to ArkType type definitions.\n * ArkType uses a fundamentally different paradigm:\n * Zod: z.object({ name: z.string().email() })\n * ArkType: type({ name: \"string.email\" })\n *\n * This transformer uses text-based transformation with AST-guided\n * import rewriting for the initial implementation.\n */\nexport class ZodToArktypeTransformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n // Step 1: Rewrite imports\n this.rewriteImports(sourceFile);\n\n // Step 2: Transform schema definitions\n this.transformSchemas(sourceFile);\n\n // Step 3: Transform type helpers\n this.transformTypeHelpers(sourceFile);\n\n // Step 4: Check for patterns requiring manual review\n this.checkManualReviewPatterns(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n private rewriteImports(sourceFile: SourceFile): void {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (moduleSpecifier === 'zod') {\n importDecl.setModuleSpecifier('arktype');\n\n // Replace `import { z } from 'zod'` with `import { type } from 'arktype'`\n const namedImports = importDecl.getNamedImports();\n const defaultImport = importDecl.getDefaultImport();\n const namespaceImport = importDecl.getNamespaceImport();\n\n if (namespaceImport) {\n // import * as z from 'zod' → import { type } from 'arktype'\n importDecl.removeNamespaceImport();\n importDecl.addNamedImport('type');\n } else if (namedImports.length > 0) {\n // Remove z, keep other type imports with warnings\n for (const namedImport of namedImports) {\n const name = namedImport.getName();\n if (name === 'z') {\n namedImport.remove();\n } else {\n // Type imports like ZodType need manual conversion\n this.warnings.push(\n `${sourceFile.getFilePath()}: '${name}' import requires manual conversion to ArkType equivalent.`,\n );\n namedImport.remove();\n }\n }\n importDecl.addNamedImport('type');\n } else if (defaultImport) {\n importDecl.removeDefaultImport();\n importDecl.addNamedImport('type');\n }\n }\n }\n }\n\n private transformSchemas(sourceFile: SourceFile): void {\n let text = sourceFile.getFullText();\n const filePath = sourceFile.getFilePath();\n\n // Transform z.object({...}) → type({...})\n // First pass: simple factory replacements\n const simpleReplacements: Array<[RegExp, string]> = [\n // z.object({...}) → type({...}) — handled separately for nested content\n [/\\bz\\.string\\(\\)/g, '\"string\"'],\n [/\\bz\\.number\\(\\)/g, '\"number\"'],\n [/\\bz\\.boolean\\(\\)/g, '\"boolean\"'],\n [/\\bz\\.bigint\\(\\)/g, '\"bigint\"'],\n [/\\bz\\.symbol\\(\\)/g, '\"symbol\"'],\n [/\\bz\\.undefined\\(\\)/g, '\"undefined\"'],\n [/\\bz\\.null\\(\\)/g, '\"null\"'],\n [/\\bz\\.void\\(\\)/g, '\"void\"'],\n [/\\bz\\.any\\(\\)/g, '\"unknown\"'],\n [/\\bz\\.unknown\\(\\)/g, '\"unknown\"'],\n [/\\bz\\.never\\(\\)/g, '\"never\"'],\n [/\\bz\\.date\\(\\)/g, '\"Date\"'],\n [/\\bz\\.nan\\(\\)/g, '\"number\"'],\n ];\n\n for (const [pattern, replacement] of simpleReplacements) {\n text = text.replace(pattern, replacement);\n }\n\n // Transform z.object() → type()\n text = text.replace(/\\bz\\.object\\(/g, 'type(');\n\n // Transform z.array(X) → type(\"X[]\") for simple types\n text = text.replace(/\\bz\\.array\\((\"[\\w.]+\")\\)/g, 'type(\"$1[]\")');\n\n // Transform z.enum([\"a\", \"b\"]) → type(\"'a' | 'b'\")\n text = text.replace(/\\bz\\.enum\\(\\[([^\\]]+)\\]\\)/g, (_match, values: string) => {\n const items = values.split(',').map((v: string) => v.trim());\n return `type(\"${items.join(' | ')}\")`;\n });\n\n // Transform .optional() → add \"?\" suffix or wrap\n text = text.replace(/\"([\\w.]+)\"\\.optional\\(\\)/g, '\"$1?\"');\n\n // Transform .nullable() → add \" | null\"\n text = text.replace(/\"([\\w.?]+)\"\\.nullable\\(\\)/g, '\"$1 | null\"');\n\n // Transform validation chains on strings\n for (const [zodMethod, arktypeType] of Object.entries(ZOD_VALIDATION_TO_ARKTYPE)) {\n const pattern = new RegExp(`\"string\"\\\\.${zodMethod}\\\\(\\\\)`, 'g');\n text = text.replace(pattern, `\"${arktypeType}\"`);\n }\n\n // Transform z.union([...]) → type(\"X | Y\")\n text = text.replace(/\\bz\\.union\\(\\[([^\\]]+)\\]\\)/g, (_match, items: string) => {\n const types = items.split(',').map((t: string) => t.trim().replace(/^\"|\"$/g, ''));\n return `type(\"${types.join(' | ')}\")`;\n });\n\n // Transform z.literal(value) → type(\"=== value\") for simple literals\n text = text.replace(/\\bz\\.literal\\((\\d+)\\)/g, 'type(\"=== $1\")');\n text = text.replace(/\\bz\\.literal\\((['\"][^'\"]+['\"])\\)/g, 'type($1)');\n text = text.replace(/\\bz\\.literal\\((true|false)\\)/g, 'type(\"=== $1\")');\n\n // Transform z.record(keySchema, valueSchema) → type(\"Record<string, X>\")\n text = text.replace(/\\bz\\.record\\(\"string\", \"(\\w+)\"\\)/g, 'type(\"Record<string, $1>\")');\n\n // Transform z.tuple([...]) → type([\"X\", \"Y\"])\n // Leave as-is since ArkType has similar tuple syntax\n\n // Transform z.intersection(a, b) → type(\"A & B\")\n // Complex - add TODO for now\n\n sourceFile.replaceWithText(text);\n\n // Add warnings for complex patterns\n const currentText = sourceFile.getFullText();\n if (currentText.includes('z.')) {\n this.warnings.push(\n `${filePath}: Some Zod patterns could not be auto-transformed to ArkType. ` +\n 'Look for remaining z.* references and convert manually.',\n );\n }\n }\n\n private transformTypeHelpers(sourceFile: SourceFile): void {\n let text = sourceFile.getFullText();\n\n // z.infer<typeof schema> → typeof schema.infer (ArkType)\n // Actually in ArkType: type().infer is the type, used as typeof schema.infer\n text = text.replace(/z\\.infer<typeof\\s+(\\w+)>/g, 'typeof $1.infer');\n text = text.replace(/z\\.input<typeof\\s+(\\w+)>/g, 'typeof $1.in');\n text = text.replace(/z\\.output<typeof\\s+(\\w+)>/g, 'typeof $1.infer');\n\n sourceFile.replaceWithText(text);\n }\n\n private checkManualReviewPatterns(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const text = sourceFile.getFullText();\n\n for (const pattern of MANUAL_REVIEW_PATTERNS) {\n if (text.includes(`.${pattern}(`)) {\n const guidance = this.getManualGuidance(pattern);\n this.warnings.push(\n `${filePath}: .${pattern}() requires manual conversion to ArkType. ${guidance}`,\n );\n }\n }\n }\n\n private getManualGuidance(pattern: string): string {\n const guidance: Record<string, string> = {\n discriminatedUnion:\n \"ArkType uses native TypeScript union syntax: type(\\\"{ kind: 'a', ... } | { kind: 'b', ... }\\\").\",\n superRefine:\n 'ArkType uses .narrow() for refinements: type(\"string\").narrow((s) => s.length > 0).',\n transform: 'ArkType uses morphs: type(\"string\").pipe((s) => s.toUpperCase()).',\n preprocess: 'ArkType uses .from() for input transforms.',\n lazy: 'ArkType handles recursion with scope(): const types = scope({ node: { left: \"node | null\", right: \"node | null\" } }).export().',\n brand: 'ArkType has no .brand() equivalent. Use nominal types or tagged unions instead.',\n coerce: 'ArkType uses .from() morphs for coercion: type(\"string\").from(\"number\").',\n pipe: 'ArkType uses .pipe() with different semantics for morphs.',\n catch: 'ArkType has no .catch() equivalent. Handle fallback values at the application level.',\n };\n return guidance[pattern] || 'See ArkType documentation for equivalent pattern.';\n }\n}\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodToArktypeTransformer } from './zod-to-arktype-transformer.js';\n\nexport function createZodToArktypeHandler(): TransformHandler {\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n const transformer = new ZodToArktypeTransformer();\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TransformHandler } from '@schemashift/core';
|
|
2
|
+
|
|
3
|
+
declare function createArktypeToZodHandler(): TransformHandler;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Zod ↔ ArkType Mapping Tables
|
|
7
|
+
*
|
|
8
|
+
* ArkType uses a TypeScript-like string syntax for type definitions,
|
|
9
|
+
* while Zod uses method chains. This makes the transformation quite different
|
|
10
|
+
* from other library pairs.
|
|
11
|
+
*
|
|
12
|
+
* ArkType: type({ name: "string", age: "number" })
|
|
13
|
+
* Zod: z.object({ name: z.string(), age: z.number() })
|
|
14
|
+
*/
|
|
15
|
+
declare const ZOD_TO_ARKTYPE_MAPPINGS: Record<string, string>;
|
|
16
|
+
declare const ARKTYPE_TO_ZOD_MAPPINGS: Record<string, string>;
|
|
17
|
+
|
|
18
|
+
declare function createZodToArktypeHandler(): TransformHandler;
|
|
19
|
+
|
|
20
|
+
export { ARKTYPE_TO_ZOD_MAPPINGS, ZOD_TO_ARKTYPE_MAPPINGS, createArktypeToZodHandler, createZodToArktypeHandler };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TransformHandler } from '@schemashift/core';
|
|
2
|
+
|
|
3
|
+
declare function createArktypeToZodHandler(): TransformHandler;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Zod ↔ ArkType Mapping Tables
|
|
7
|
+
*
|
|
8
|
+
* ArkType uses a TypeScript-like string syntax for type definitions,
|
|
9
|
+
* while Zod uses method chains. This makes the transformation quite different
|
|
10
|
+
* from other library pairs.
|
|
11
|
+
*
|
|
12
|
+
* ArkType: type({ name: "string", age: "number" })
|
|
13
|
+
* Zod: z.object({ name: z.string(), age: z.number() })
|
|
14
|
+
*/
|
|
15
|
+
declare const ZOD_TO_ARKTYPE_MAPPINGS: Record<string, string>;
|
|
16
|
+
declare const ARKTYPE_TO_ZOD_MAPPINGS: Record<string, string>;
|
|
17
|
+
|
|
18
|
+
declare function createZodToArktypeHandler(): TransformHandler;
|
|
19
|
+
|
|
20
|
+
export { ARKTYPE_TO_ZOD_MAPPINGS, ZOD_TO_ARKTYPE_MAPPINGS, createArktypeToZodHandler, createZodToArktypeHandler };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// src/mappings.ts
|
|
2
|
+
var ZOD_TO_ARKTYPE_MAPPINGS = {
|
|
3
|
+
"z.string()": '"string"',
|
|
4
|
+
"z.number()": '"number"',
|
|
5
|
+
"z.boolean()": '"boolean"',
|
|
6
|
+
"z.bigint()": '"bigint"',
|
|
7
|
+
"z.symbol()": '"symbol"',
|
|
8
|
+
"z.undefined()": '"undefined"',
|
|
9
|
+
"z.null()": '"null"',
|
|
10
|
+
"z.void()": '"void"',
|
|
11
|
+
"z.any()": '"unknown"',
|
|
12
|
+
"z.unknown()": '"unknown"',
|
|
13
|
+
"z.never()": '"never"',
|
|
14
|
+
"z.date()": '"Date"'
|
|
15
|
+
};
|
|
16
|
+
var ZOD_VALIDATION_TO_ARKTYPE = {
|
|
17
|
+
email: "string.email",
|
|
18
|
+
url: "string.url",
|
|
19
|
+
uuid: "string.uuid",
|
|
20
|
+
ip: "string.ip",
|
|
21
|
+
integer: "number.integer"
|
|
22
|
+
};
|
|
23
|
+
var ARKTYPE_TO_ZOD_MAPPINGS = {
|
|
24
|
+
string: "z.string()",
|
|
25
|
+
number: "z.number()",
|
|
26
|
+
boolean: "z.boolean()",
|
|
27
|
+
bigint: "z.bigint()",
|
|
28
|
+
symbol: "z.symbol()",
|
|
29
|
+
undefined: "z.undefined()",
|
|
30
|
+
null: "z.null()",
|
|
31
|
+
void: "z.void()",
|
|
32
|
+
unknown: "z.unknown()",
|
|
33
|
+
never: "z.never()",
|
|
34
|
+
Date: "z.date()",
|
|
35
|
+
"string.email": "z.string().email()",
|
|
36
|
+
"string.url": "z.string().url()",
|
|
37
|
+
"string.uuid": "z.string().uuid()",
|
|
38
|
+
"string.ip": "z.string().ip()",
|
|
39
|
+
"number.integer": "z.number().int()"
|
|
40
|
+
};
|
|
41
|
+
var MANUAL_REVIEW_PATTERNS = /* @__PURE__ */ new Set([
|
|
42
|
+
"discriminatedUnion",
|
|
43
|
+
// ArkType uses native TS union syntax
|
|
44
|
+
"superRefine",
|
|
45
|
+
// ArkType uses .narrow()
|
|
46
|
+
"transform",
|
|
47
|
+
// ArkType uses .pipe() or morphs
|
|
48
|
+
"preprocess",
|
|
49
|
+
// ArkType uses .from()
|
|
50
|
+
"lazy",
|
|
51
|
+
// ArkType handles recursion differently
|
|
52
|
+
"brand",
|
|
53
|
+
// ArkType has no equivalent
|
|
54
|
+
"coerce",
|
|
55
|
+
// ArkType uses .from() morphs
|
|
56
|
+
"pipe",
|
|
57
|
+
// Different semantics
|
|
58
|
+
"catch"
|
|
59
|
+
// ArkType has no .catch() equivalent
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
// src/arktype-to-zod-transformer.ts
|
|
63
|
+
var ArktypeToZodTransformer = class {
|
|
64
|
+
errors = [];
|
|
65
|
+
warnings = [];
|
|
66
|
+
transform(sourceFile) {
|
|
67
|
+
this.errors = [];
|
|
68
|
+
this.warnings = [];
|
|
69
|
+
const filePath = sourceFile.getFilePath();
|
|
70
|
+
const originalCode = sourceFile.getFullText();
|
|
71
|
+
try {
|
|
72
|
+
let text = originalCode;
|
|
73
|
+
text = this.rewriteImports(text, filePath);
|
|
74
|
+
text = this.transformTypeDefinitions(text, filePath);
|
|
75
|
+
text = this.transformTypeHelpers(text);
|
|
76
|
+
text = this.transformStringTypes(text);
|
|
77
|
+
sourceFile.replaceWithText(text);
|
|
78
|
+
return {
|
|
79
|
+
success: this.errors.length === 0,
|
|
80
|
+
filePath,
|
|
81
|
+
originalCode,
|
|
82
|
+
transformedCode: sourceFile.getFullText(),
|
|
83
|
+
errors: this.errors,
|
|
84
|
+
warnings: this.warnings
|
|
85
|
+
};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
this.errors.push({
|
|
88
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
filePath,
|
|
93
|
+
originalCode,
|
|
94
|
+
errors: this.errors,
|
|
95
|
+
warnings: this.warnings
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
rewriteImports(text, filePath) {
|
|
100
|
+
text = text.replace(
|
|
101
|
+
/import\s*\{\s*type\s*\}\s*from\s*['"]arktype['"]/g,
|
|
102
|
+
"import { z } from 'zod'"
|
|
103
|
+
);
|
|
104
|
+
text = text.replace(
|
|
105
|
+
/import\s*\{[^}]*\btype\b[^}]*\}\s*from\s*['"]arktype['"]/g,
|
|
106
|
+
"import { z } from 'zod'"
|
|
107
|
+
);
|
|
108
|
+
text = text.replace(
|
|
109
|
+
/import\s+type\s*\{[^}]*\}\s*from\s*['"]arktype['"]/g,
|
|
110
|
+
"import type { z } from 'zod'"
|
|
111
|
+
);
|
|
112
|
+
if (text.includes("scope(")) {
|
|
113
|
+
this.warnings.push(
|
|
114
|
+
`${filePath}: ArkType scope() has no direct Zod equivalent. Convert to individual z.object() schemas with z.lazy() for recursive types.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return text;
|
|
118
|
+
}
|
|
119
|
+
transformTypeDefinitions(text, filePath) {
|
|
120
|
+
text = text.replace(/\btype\(\{/g, "z.object({");
|
|
121
|
+
text = text.replace(/\btype\("string"\)/g, "z.string()");
|
|
122
|
+
text = text.replace(/\btype\("number"\)/g, "z.number()");
|
|
123
|
+
text = text.replace(/\btype\("boolean"\)/g, "z.boolean()");
|
|
124
|
+
text = text.replace(/\btype\("bigint"\)/g, "z.bigint()");
|
|
125
|
+
text = text.replace(/\btype\("unknown"\)/g, "z.unknown()");
|
|
126
|
+
text = text.replace(/\btype\("never"\)/g, "z.never()");
|
|
127
|
+
text = text.replace(/\btype\("Date"\)/g, "z.date()");
|
|
128
|
+
text = text.replace(/\btype\("string\.email"\)/g, "z.string().email()");
|
|
129
|
+
text = text.replace(/\btype\("string\.url"\)/g, "z.string().url()");
|
|
130
|
+
text = text.replace(/\btype\("string\.uuid"\)/g, "z.string().uuid()");
|
|
131
|
+
text = text.replace(/\btype\("string\.ip"\)/g, "z.string().ip()");
|
|
132
|
+
text = text.replace(/\btype\("number\.integer"\)/g, "z.number().int()");
|
|
133
|
+
text = text.replace(/\btype\("(\w+)\[\]"\)/g, (_match, typeName) => {
|
|
134
|
+
const zodType = ARKTYPE_TO_ZOD_MAPPINGS[typeName];
|
|
135
|
+
return zodType ? `z.array(${zodType})` : `z.array(z.${typeName}())`;
|
|
136
|
+
});
|
|
137
|
+
text = text.replace(/\btype\("([^"]+\|[^"]+)"\)/g, (_match, unionStr) => {
|
|
138
|
+
const types = unionStr.split("|").map((t) => {
|
|
139
|
+
const trimmed = t.trim();
|
|
140
|
+
const zodType = ARKTYPE_TO_ZOD_MAPPINGS[trimmed];
|
|
141
|
+
if (zodType) return zodType;
|
|
142
|
+
if (trimmed === "null") return "z.null()";
|
|
143
|
+
return `z.${trimmed}()`;
|
|
144
|
+
});
|
|
145
|
+
return `z.union([${types.join(", ")}])`;
|
|
146
|
+
});
|
|
147
|
+
if (text.includes(".narrow(")) {
|
|
148
|
+
this.warnings.push(
|
|
149
|
+
`${filePath}: ArkType .narrow() should be converted to z.refine() or z.superRefine().`
|
|
150
|
+
);
|
|
151
|
+
text = text.replace(/\.narrow\(/g, ".refine(");
|
|
152
|
+
}
|
|
153
|
+
if (text.includes(".pipe(")) {
|
|
154
|
+
this.warnings.push(
|
|
155
|
+
`${filePath}: ArkType .pipe() morphs should be reviewed \u2014 Zod .transform() or .pipe() may apply.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return text;
|
|
159
|
+
}
|
|
160
|
+
transformTypeHelpers(text) {
|
|
161
|
+
text = text.replace(/typeof\s+(\w+)\.infer\b/g, "z.infer<typeof $1>");
|
|
162
|
+
text = text.replace(/typeof\s+(\w+)\.in\b/g, "z.input<typeof $1>");
|
|
163
|
+
text = text.replace(/Type<typeof\s+(\w+)>/g, "z.infer<typeof $1>");
|
|
164
|
+
return text;
|
|
165
|
+
}
|
|
166
|
+
transformStringTypes(text) {
|
|
167
|
+
text = text.replace(/"string\?"/g, "z.string().optional()");
|
|
168
|
+
text = text.replace(/"number\?"/g, "z.number().optional()");
|
|
169
|
+
text = text.replace(/"boolean\?"/g, "z.boolean().optional()");
|
|
170
|
+
text = text.replace(/"string \| null"/g, "z.string().nullable()");
|
|
171
|
+
text = text.replace(/"number \| null"/g, "z.number().nullable()");
|
|
172
|
+
text = text.replace(/"boolean \| null"/g, "z.boolean().nullable()");
|
|
173
|
+
text = text.replace(/:\s*"string"/g, ": z.string()");
|
|
174
|
+
text = text.replace(/:\s*"number"/g, ": z.number()");
|
|
175
|
+
text = text.replace(/:\s*"boolean"/g, ": z.boolean()");
|
|
176
|
+
text = text.replace(/:\s*"Date"/g, ": z.date()");
|
|
177
|
+
text = text.replace(/:\s*"bigint"/g, ": z.bigint()");
|
|
178
|
+
text = text.replace(/:\s*"unknown"/g, ": z.unknown()");
|
|
179
|
+
text = text.replace(/:\s*"string\.email"/g, ": z.string().email()");
|
|
180
|
+
text = text.replace(/:\s*"string\.url"/g, ": z.string().url()");
|
|
181
|
+
text = text.replace(/:\s*"string\.uuid"/g, ": z.string().uuid()");
|
|
182
|
+
return text;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/arktype-to-zod-handler.ts
|
|
187
|
+
function createArktypeToZodHandler() {
|
|
188
|
+
return {
|
|
189
|
+
transform(sourceFile, _options) {
|
|
190
|
+
const transformer = new ArktypeToZodTransformer();
|
|
191
|
+
return transformer.transform(sourceFile);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/zod-to-arktype-transformer.ts
|
|
197
|
+
var ZodToArktypeTransformer = class {
|
|
198
|
+
errors = [];
|
|
199
|
+
warnings = [];
|
|
200
|
+
transform(sourceFile) {
|
|
201
|
+
this.errors = [];
|
|
202
|
+
this.warnings = [];
|
|
203
|
+
const filePath = sourceFile.getFilePath();
|
|
204
|
+
const originalCode = sourceFile.getFullText();
|
|
205
|
+
try {
|
|
206
|
+
this.rewriteImports(sourceFile);
|
|
207
|
+
this.transformSchemas(sourceFile);
|
|
208
|
+
this.transformTypeHelpers(sourceFile);
|
|
209
|
+
this.checkManualReviewPatterns(sourceFile);
|
|
210
|
+
return {
|
|
211
|
+
success: this.errors.length === 0,
|
|
212
|
+
filePath,
|
|
213
|
+
originalCode,
|
|
214
|
+
transformedCode: sourceFile.getFullText(),
|
|
215
|
+
errors: this.errors,
|
|
216
|
+
warnings: this.warnings
|
|
217
|
+
};
|
|
218
|
+
} catch (error) {
|
|
219
|
+
this.errors.push({
|
|
220
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
success: false,
|
|
224
|
+
filePath,
|
|
225
|
+
originalCode,
|
|
226
|
+
errors: this.errors,
|
|
227
|
+
warnings: this.warnings
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
rewriteImports(sourceFile) {
|
|
232
|
+
for (const importDecl of sourceFile.getImportDeclarations()) {
|
|
233
|
+
const moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
234
|
+
if (moduleSpecifier === "zod") {
|
|
235
|
+
importDecl.setModuleSpecifier("arktype");
|
|
236
|
+
const namedImports = importDecl.getNamedImports();
|
|
237
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
238
|
+
const namespaceImport = importDecl.getNamespaceImport();
|
|
239
|
+
if (namespaceImport) {
|
|
240
|
+
importDecl.removeNamespaceImport();
|
|
241
|
+
importDecl.addNamedImport("type");
|
|
242
|
+
} else if (namedImports.length > 0) {
|
|
243
|
+
for (const namedImport of namedImports) {
|
|
244
|
+
const name = namedImport.getName();
|
|
245
|
+
if (name === "z") {
|
|
246
|
+
namedImport.remove();
|
|
247
|
+
} else {
|
|
248
|
+
this.warnings.push(
|
|
249
|
+
`${sourceFile.getFilePath()}: '${name}' import requires manual conversion to ArkType equivalent.`
|
|
250
|
+
);
|
|
251
|
+
namedImport.remove();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
importDecl.addNamedImport("type");
|
|
255
|
+
} else if (defaultImport) {
|
|
256
|
+
importDecl.removeDefaultImport();
|
|
257
|
+
importDecl.addNamedImport("type");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
transformSchemas(sourceFile) {
|
|
263
|
+
let text = sourceFile.getFullText();
|
|
264
|
+
const filePath = sourceFile.getFilePath();
|
|
265
|
+
const simpleReplacements = [
|
|
266
|
+
// z.object({...}) → type({...}) — handled separately for nested content
|
|
267
|
+
[/\bz\.string\(\)/g, '"string"'],
|
|
268
|
+
[/\bz\.number\(\)/g, '"number"'],
|
|
269
|
+
[/\bz\.boolean\(\)/g, '"boolean"'],
|
|
270
|
+
[/\bz\.bigint\(\)/g, '"bigint"'],
|
|
271
|
+
[/\bz\.symbol\(\)/g, '"symbol"'],
|
|
272
|
+
[/\bz\.undefined\(\)/g, '"undefined"'],
|
|
273
|
+
[/\bz\.null\(\)/g, '"null"'],
|
|
274
|
+
[/\bz\.void\(\)/g, '"void"'],
|
|
275
|
+
[/\bz\.any\(\)/g, '"unknown"'],
|
|
276
|
+
[/\bz\.unknown\(\)/g, '"unknown"'],
|
|
277
|
+
[/\bz\.never\(\)/g, '"never"'],
|
|
278
|
+
[/\bz\.date\(\)/g, '"Date"'],
|
|
279
|
+
[/\bz\.nan\(\)/g, '"number"']
|
|
280
|
+
];
|
|
281
|
+
for (const [pattern, replacement] of simpleReplacements) {
|
|
282
|
+
text = text.replace(pattern, replacement);
|
|
283
|
+
}
|
|
284
|
+
text = text.replace(/\bz\.object\(/g, "type(");
|
|
285
|
+
text = text.replace(/\bz\.array\(("[\w.]+")\)/g, 'type("$1[]")');
|
|
286
|
+
text = text.replace(/\bz\.enum\(\[([^\]]+)\]\)/g, (_match, values) => {
|
|
287
|
+
const items = values.split(",").map((v) => v.trim());
|
|
288
|
+
return `type("${items.join(" | ")}")`;
|
|
289
|
+
});
|
|
290
|
+
text = text.replace(/"([\w.]+)"\.optional\(\)/g, '"$1?"');
|
|
291
|
+
text = text.replace(/"([\w.?]+)"\.nullable\(\)/g, '"$1 | null"');
|
|
292
|
+
for (const [zodMethod, arktypeType] of Object.entries(ZOD_VALIDATION_TO_ARKTYPE)) {
|
|
293
|
+
const pattern = new RegExp(`"string"\\.${zodMethod}\\(\\)`, "g");
|
|
294
|
+
text = text.replace(pattern, `"${arktypeType}"`);
|
|
295
|
+
}
|
|
296
|
+
text = text.replace(/\bz\.union\(\[([^\]]+)\]\)/g, (_match, items) => {
|
|
297
|
+
const types = items.split(",").map((t) => t.trim().replace(/^"|"$/g, ""));
|
|
298
|
+
return `type("${types.join(" | ")}")`;
|
|
299
|
+
});
|
|
300
|
+
text = text.replace(/\bz\.literal\((\d+)\)/g, 'type("=== $1")');
|
|
301
|
+
text = text.replace(/\bz\.literal\((['"][^'"]+['"])\)/g, "type($1)");
|
|
302
|
+
text = text.replace(/\bz\.literal\((true|false)\)/g, 'type("=== $1")');
|
|
303
|
+
text = text.replace(/\bz\.record\("string", "(\w+)"\)/g, 'type("Record<string, $1>")');
|
|
304
|
+
sourceFile.replaceWithText(text);
|
|
305
|
+
const currentText = sourceFile.getFullText();
|
|
306
|
+
if (currentText.includes("z.")) {
|
|
307
|
+
this.warnings.push(
|
|
308
|
+
`${filePath}: Some Zod patterns could not be auto-transformed to ArkType. Look for remaining z.* references and convert manually.`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
transformTypeHelpers(sourceFile) {
|
|
313
|
+
let text = sourceFile.getFullText();
|
|
314
|
+
text = text.replace(/z\.infer<typeof\s+(\w+)>/g, "typeof $1.infer");
|
|
315
|
+
text = text.replace(/z\.input<typeof\s+(\w+)>/g, "typeof $1.in");
|
|
316
|
+
text = text.replace(/z\.output<typeof\s+(\w+)>/g, "typeof $1.infer");
|
|
317
|
+
sourceFile.replaceWithText(text);
|
|
318
|
+
}
|
|
319
|
+
checkManualReviewPatterns(sourceFile) {
|
|
320
|
+
const filePath = sourceFile.getFilePath();
|
|
321
|
+
const text = sourceFile.getFullText();
|
|
322
|
+
for (const pattern of MANUAL_REVIEW_PATTERNS) {
|
|
323
|
+
if (text.includes(`.${pattern}(`)) {
|
|
324
|
+
const guidance = this.getManualGuidance(pattern);
|
|
325
|
+
this.warnings.push(
|
|
326
|
+
`${filePath}: .${pattern}() requires manual conversion to ArkType. ${guidance}`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
getManualGuidance(pattern) {
|
|
332
|
+
const guidance = {
|
|
333
|
+
discriminatedUnion: `ArkType uses native TypeScript union syntax: type("{ kind: 'a', ... } | { kind: 'b', ... }").`,
|
|
334
|
+
superRefine: 'ArkType uses .narrow() for refinements: type("string").narrow((s) => s.length > 0).',
|
|
335
|
+
transform: 'ArkType uses morphs: type("string").pipe((s) => s.toUpperCase()).',
|
|
336
|
+
preprocess: "ArkType uses .from() for input transforms.",
|
|
337
|
+
lazy: 'ArkType handles recursion with scope(): const types = scope({ node: { left: "node | null", right: "node | null" } }).export().',
|
|
338
|
+
brand: "ArkType has no .brand() equivalent. Use nominal types or tagged unions instead.",
|
|
339
|
+
coerce: 'ArkType uses .from() morphs for coercion: type("string").from("number").',
|
|
340
|
+
pipe: "ArkType uses .pipe() with different semantics for morphs.",
|
|
341
|
+
catch: "ArkType has no .catch() equivalent. Handle fallback values at the application level."
|
|
342
|
+
};
|
|
343
|
+
return guidance[pattern] || "See ArkType documentation for equivalent pattern.";
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/zod-to-arktype-handler.ts
|
|
348
|
+
function createZodToArktypeHandler() {
|
|
349
|
+
return {
|
|
350
|
+
transform(sourceFile, _options) {
|
|
351
|
+
const transformer = new ZodToArktypeTransformer();
|
|
352
|
+
return transformer.transform(sourceFile);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
export {
|
|
357
|
+
ARKTYPE_TO_ZOD_MAPPINGS,
|
|
358
|
+
ZOD_TO_ARKTYPE_MAPPINGS,
|
|
359
|
+
createArktypeToZodHandler,
|
|
360
|
+
createZodToArktypeHandler
|
|
361
|
+
};
|
|
362
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mappings.ts","../src/arktype-to-zod-transformer.ts","../src/arktype-to-zod-handler.ts","../src/zod-to-arktype-transformer.ts","../src/zod-to-arktype-handler.ts"],"sourcesContent":["/**\n * Zod ↔ ArkType Mapping Tables\n *\n * ArkType uses a TypeScript-like string syntax for type definitions,\n * while Zod uses method chains. This makes the transformation quite different\n * from other library pairs.\n *\n * ArkType: type({ name: \"string\", age: \"number\" })\n * Zod: z.object({ name: z.string(), age: z.number() })\n */\n\n// Zod factory → ArkType string type\nexport const ZOD_TO_ARKTYPE_MAPPINGS: Record<string, string> = {\n 'z.string()': '\"string\"',\n 'z.number()': '\"number\"',\n 'z.boolean()': '\"boolean\"',\n 'z.bigint()': '\"bigint\"',\n 'z.symbol()': '\"symbol\"',\n 'z.undefined()': '\"undefined\"',\n 'z.null()': '\"null\"',\n 'z.void()': '\"void\"',\n 'z.any()': '\"unknown\"',\n 'z.unknown()': '\"unknown\"',\n 'z.never()': '\"never\"',\n 'z.date()': '\"Date\"',\n};\n\n// Zod validation methods → ArkType constraints\nexport const ZOD_VALIDATION_TO_ARKTYPE: Record<string, string> = {\n email: 'string.email',\n url: 'string.url',\n uuid: 'string.uuid',\n ip: 'string.ip',\n integer: 'number.integer',\n};\n\n// ArkType string type → Zod factory\nexport const ARKTYPE_TO_ZOD_MAPPINGS: Record<string, string> = {\n string: 'z.string()',\n number: 'z.number()',\n boolean: 'z.boolean()',\n bigint: 'z.bigint()',\n symbol: 'z.symbol()',\n undefined: 'z.undefined()',\n null: 'z.null()',\n void: 'z.void()',\n unknown: 'z.unknown()',\n never: 'z.never()',\n Date: 'z.date()',\n 'string.email': 'z.string().email()',\n 'string.url': 'z.string().url()',\n 'string.uuid': 'z.string().uuid()',\n 'string.ip': 'z.string().ip()',\n 'number.integer': 'z.number().int()',\n};\n\n// Import mappings\nexport const IMPORT_MAPPINGS = {\n zod: {\n from: \"import { z } from 'zod'\",\n to: \"import { type } from 'arktype'\",\n },\n arktype: {\n from: \"import { type } from 'arktype'\",\n to: \"import { z } from 'zod'\",\n },\n};\n\n// Type helper mappings\nexport const TYPE_HELPER_MAPPINGS = {\n zodToArktype: {\n 'z.infer': 'typeof',\n 'z.input': 'typeof',\n 'z.output': 'typeof',\n },\n arktypeToZod: {\n 'Type<typeof': 'z.infer<typeof',\n },\n};\n\n// Patterns requiring manual review\nexport const MANUAL_REVIEW_PATTERNS = new Set([\n 'discriminatedUnion', // ArkType uses native TS union syntax\n 'superRefine', // ArkType uses .narrow()\n 'transform', // ArkType uses .pipe() or morphs\n 'preprocess', // ArkType uses .from()\n 'lazy', // ArkType handles recursion differently\n 'brand', // ArkType has no equivalent\n 'coerce', // ArkType uses .from() morphs\n 'pipe', // Different semantics\n 'catch', // ArkType has no .catch() equivalent\n]);\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ARKTYPE_TO_ZOD_MAPPINGS } from './mappings.js';\n\n/**\n * ArkType → Zod Transformer (Backward Migration)\n *\n * Converts ArkType type definitions to Zod schemas.\n * ArkType uses string-based type syntax which makes AST-based\n * transformation challenging, so this uses text-based approach.\n *\n * ArkType: type({ name: \"string.email\", age: \"number\" })\n * Zod: z.object({ name: z.string().email(), age: z.number() })\n */\nexport class ArktypeToZodTransformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n let text = originalCode;\n\n // Step 1: Rewrite imports\n text = this.rewriteImports(text, filePath);\n\n // Step 2: Transform type() calls to z.object() etc.\n text = this.transformTypeDefinitions(text, filePath);\n\n // Step 3: Transform type helpers\n text = this.transformTypeHelpers(text);\n\n // Step 4: Transform string type references to Zod factories\n text = this.transformStringTypes(text);\n\n sourceFile.replaceWithText(text);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n private rewriteImports(text: string, filePath: string): string {\n // import { type } from 'arktype' → import { z } from 'zod'\n text = text.replace(\n /import\\s*\\{\\s*type\\s*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import { z } from 'zod'\",\n );\n\n // import { type, scope } from 'arktype' → import { z } from 'zod'\n text = text.replace(\n /import\\s*\\{[^}]*\\btype\\b[^}]*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import { z } from 'zod'\",\n );\n\n // import type { Type } from 'arktype' → import type { z } from 'zod'\n text = text.replace(\n /import\\s+type\\s*\\{[^}]*\\}\\s*from\\s*['\"]arktype['\"]/g,\n \"import type { z } from 'zod'\",\n );\n\n // Check for scope() usage\n if (text.includes('scope(')) {\n this.warnings.push(\n `${filePath}: ArkType scope() has no direct Zod equivalent. ` +\n 'Convert to individual z.object() schemas with z.lazy() for recursive types.',\n );\n }\n\n return text;\n }\n\n private transformTypeDefinitions(text: string, filePath: string): string {\n // type({ ... }) → z.object({ ... })\n text = text.replace(/\\btype\\(\\{/g, 'z.object({');\n\n // type(\"string\") → z.string()\n text = text.replace(/\\btype\\(\"string\"\\)/g, 'z.string()');\n text = text.replace(/\\btype\\(\"number\"\\)/g, 'z.number()');\n text = text.replace(/\\btype\\(\"boolean\"\\)/g, 'z.boolean()');\n text = text.replace(/\\btype\\(\"bigint\"\\)/g, 'z.bigint()');\n text = text.replace(/\\btype\\(\"unknown\"\\)/g, 'z.unknown()');\n text = text.replace(/\\btype\\(\"never\"\\)/g, 'z.never()');\n text = text.replace(/\\btype\\(\"Date\"\\)/g, 'z.date()');\n\n // type(\"string.email\") → z.string().email()\n text = text.replace(/\\btype\\(\"string\\.email\"\\)/g, 'z.string().email()');\n text = text.replace(/\\btype\\(\"string\\.url\"\\)/g, 'z.string().url()');\n text = text.replace(/\\btype\\(\"string\\.uuid\"\\)/g, 'z.string().uuid()');\n text = text.replace(/\\btype\\(\"string\\.ip\"\\)/g, 'z.string().ip()');\n text = text.replace(/\\btype\\(\"number\\.integer\"\\)/g, 'z.number().int()');\n\n // type(\"X[]\") → z.array(z.X())\n text = text.replace(/\\btype\\(\"(\\w+)\\[\\]\"\\)/g, (_match, typeName: string) => {\n const zodType = ARKTYPE_TO_ZOD_MAPPINGS[typeName];\n return zodType ? `z.array(${zodType})` : `z.array(z.${typeName}())`;\n });\n\n // type(\"X | Y\") → z.union([z.X(), z.Y()])\n text = text.replace(/\\btype\\(\"([^\"]+\\|[^\"]+)\"\\)/g, (_match, unionStr: string) => {\n const types = unionStr.split('|').map((t: string) => {\n const trimmed = t.trim();\n const zodType = ARKTYPE_TO_ZOD_MAPPINGS[trimmed];\n if (zodType) return zodType;\n if (trimmed === 'null') return 'z.null()';\n return `z.${trimmed}()`;\n });\n return `z.union([${types.join(', ')}])`;\n });\n\n // Check for .narrow() — ArkType refinement\n if (text.includes('.narrow(')) {\n this.warnings.push(\n `${filePath}: ArkType .narrow() should be converted to z.refine() or z.superRefine().`,\n );\n text = text.replace(/\\.narrow\\(/g, '.refine(');\n }\n\n // Check for .pipe() morphs — ArkType transforms\n if (text.includes('.pipe(')) {\n this.warnings.push(\n `${filePath}: ArkType .pipe() morphs should be reviewed — Zod .transform() or .pipe() may apply.`,\n );\n }\n\n return text;\n }\n\n private transformTypeHelpers(text: string): string {\n // typeof schema.infer → z.infer<typeof schema>\n text = text.replace(/typeof\\s+(\\w+)\\.infer\\b/g, 'z.infer<typeof $1>');\n text = text.replace(/typeof\\s+(\\w+)\\.in\\b/g, 'z.input<typeof $1>');\n\n // Type<typeof schema> → z.infer<typeof schema>\n text = text.replace(/Type<typeof\\s+(\\w+)>/g, 'z.infer<typeof $1>');\n\n return text;\n }\n\n private transformStringTypes(text: string): string {\n // Inside object definitions, transform string type references\n // \"string\" → z.string()\n // \"number\" → z.number()\n // \"string?\" → z.string().optional()\n // \"string | null\" → z.string().nullable()\n\n // Optional types\n text = text.replace(/\"string\\?\"/g, 'z.string().optional()');\n text = text.replace(/\"number\\?\"/g, 'z.number().optional()');\n text = text.replace(/\"boolean\\?\"/g, 'z.boolean().optional()');\n\n // Nullable types\n text = text.replace(/\"string \\| null\"/g, 'z.string().nullable()');\n text = text.replace(/\"number \\| null\"/g, 'z.number().nullable()');\n text = text.replace(/\"boolean \\| null\"/g, 'z.boolean().nullable()');\n\n // Simple types in property positions\n text = text.replace(/:\\s*\"string\"/g, ': z.string()');\n text = text.replace(/:\\s*\"number\"/g, ': z.number()');\n text = text.replace(/:\\s*\"boolean\"/g, ': z.boolean()');\n text = text.replace(/:\\s*\"Date\"/g, ': z.date()');\n text = text.replace(/:\\s*\"bigint\"/g, ': z.bigint()');\n text = text.replace(/:\\s*\"unknown\"/g, ': z.unknown()');\n\n // Validated string types in property positions\n text = text.replace(/:\\s*\"string\\.email\"/g, ': z.string().email()');\n text = text.replace(/:\\s*\"string\\.url\"/g, ': z.string().url()');\n text = text.replace(/:\\s*\"string\\.uuid\"/g, ': z.string().uuid()');\n\n return text;\n }\n}\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ArktypeToZodTransformer } from './arktype-to-zod-transformer.js';\n\nexport function createArktypeToZodHandler(): TransformHandler {\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n const transformer = new ArktypeToZodTransformer();\n return transformer.transform(sourceFile);\n },\n };\n}\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { MANUAL_REVIEW_PATTERNS, ZOD_VALIDATION_TO_ARKTYPE } from './mappings.js';\n\n/**\n * Zod → ArkType Transformer\n *\n * Converts Zod schemas to ArkType type definitions.\n * ArkType uses a fundamentally different paradigm:\n * Zod: z.object({ name: z.string().email() })\n * ArkType: type({ name: \"string.email\" })\n *\n * This transformer uses text-based transformation with AST-guided\n * import rewriting for the initial implementation.\n */\nexport class ZodToArktypeTransformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n // Step 1: Rewrite imports\n this.rewriteImports(sourceFile);\n\n // Step 2: Transform schema definitions\n this.transformSchemas(sourceFile);\n\n // Step 3: Transform type helpers\n this.transformTypeHelpers(sourceFile);\n\n // Step 4: Check for patterns requiring manual review\n this.checkManualReviewPatterns(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n private rewriteImports(sourceFile: SourceFile): void {\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (moduleSpecifier === 'zod') {\n importDecl.setModuleSpecifier('arktype');\n\n // Replace `import { z } from 'zod'` with `import { type } from 'arktype'`\n const namedImports = importDecl.getNamedImports();\n const defaultImport = importDecl.getDefaultImport();\n const namespaceImport = importDecl.getNamespaceImport();\n\n if (namespaceImport) {\n // import * as z from 'zod' → import { type } from 'arktype'\n importDecl.removeNamespaceImport();\n importDecl.addNamedImport('type');\n } else if (namedImports.length > 0) {\n // Remove z, keep other type imports with warnings\n for (const namedImport of namedImports) {\n const name = namedImport.getName();\n if (name === 'z') {\n namedImport.remove();\n } else {\n // Type imports like ZodType need manual conversion\n this.warnings.push(\n `${sourceFile.getFilePath()}: '${name}' import requires manual conversion to ArkType equivalent.`,\n );\n namedImport.remove();\n }\n }\n importDecl.addNamedImport('type');\n } else if (defaultImport) {\n importDecl.removeDefaultImport();\n importDecl.addNamedImport('type');\n }\n }\n }\n }\n\n private transformSchemas(sourceFile: SourceFile): void {\n let text = sourceFile.getFullText();\n const filePath = sourceFile.getFilePath();\n\n // Transform z.object({...}) → type({...})\n // First pass: simple factory replacements\n const simpleReplacements: Array<[RegExp, string]> = [\n // z.object({...}) → type({...}) — handled separately for nested content\n [/\\bz\\.string\\(\\)/g, '\"string\"'],\n [/\\bz\\.number\\(\\)/g, '\"number\"'],\n [/\\bz\\.boolean\\(\\)/g, '\"boolean\"'],\n [/\\bz\\.bigint\\(\\)/g, '\"bigint\"'],\n [/\\bz\\.symbol\\(\\)/g, '\"symbol\"'],\n [/\\bz\\.undefined\\(\\)/g, '\"undefined\"'],\n [/\\bz\\.null\\(\\)/g, '\"null\"'],\n [/\\bz\\.void\\(\\)/g, '\"void\"'],\n [/\\bz\\.any\\(\\)/g, '\"unknown\"'],\n [/\\bz\\.unknown\\(\\)/g, '\"unknown\"'],\n [/\\bz\\.never\\(\\)/g, '\"never\"'],\n [/\\bz\\.date\\(\\)/g, '\"Date\"'],\n [/\\bz\\.nan\\(\\)/g, '\"number\"'],\n ];\n\n for (const [pattern, replacement] of simpleReplacements) {\n text = text.replace(pattern, replacement);\n }\n\n // Transform z.object() → type()\n text = text.replace(/\\bz\\.object\\(/g, 'type(');\n\n // Transform z.array(X) → type(\"X[]\") for simple types\n text = text.replace(/\\bz\\.array\\((\"[\\w.]+\")\\)/g, 'type(\"$1[]\")');\n\n // Transform z.enum([\"a\", \"b\"]) → type(\"'a' | 'b'\")\n text = text.replace(/\\bz\\.enum\\(\\[([^\\]]+)\\]\\)/g, (_match, values: string) => {\n const items = values.split(',').map((v: string) => v.trim());\n return `type(\"${items.join(' | ')}\")`;\n });\n\n // Transform .optional() → add \"?\" suffix or wrap\n text = text.replace(/\"([\\w.]+)\"\\.optional\\(\\)/g, '\"$1?\"');\n\n // Transform .nullable() → add \" | null\"\n text = text.replace(/\"([\\w.?]+)\"\\.nullable\\(\\)/g, '\"$1 | null\"');\n\n // Transform validation chains on strings\n for (const [zodMethod, arktypeType] of Object.entries(ZOD_VALIDATION_TO_ARKTYPE)) {\n const pattern = new RegExp(`\"string\"\\\\.${zodMethod}\\\\(\\\\)`, 'g');\n text = text.replace(pattern, `\"${arktypeType}\"`);\n }\n\n // Transform z.union([...]) → type(\"X | Y\")\n text = text.replace(/\\bz\\.union\\(\\[([^\\]]+)\\]\\)/g, (_match, items: string) => {\n const types = items.split(',').map((t: string) => t.trim().replace(/^\"|\"$/g, ''));\n return `type(\"${types.join(' | ')}\")`;\n });\n\n // Transform z.literal(value) → type(\"=== value\") for simple literals\n text = text.replace(/\\bz\\.literal\\((\\d+)\\)/g, 'type(\"=== $1\")');\n text = text.replace(/\\bz\\.literal\\((['\"][^'\"]+['\"])\\)/g, 'type($1)');\n text = text.replace(/\\bz\\.literal\\((true|false)\\)/g, 'type(\"=== $1\")');\n\n // Transform z.record(keySchema, valueSchema) → type(\"Record<string, X>\")\n text = text.replace(/\\bz\\.record\\(\"string\", \"(\\w+)\"\\)/g, 'type(\"Record<string, $1>\")');\n\n // Transform z.tuple([...]) → type([\"X\", \"Y\"])\n // Leave as-is since ArkType has similar tuple syntax\n\n // Transform z.intersection(a, b) → type(\"A & B\")\n // Complex - add TODO for now\n\n sourceFile.replaceWithText(text);\n\n // Add warnings for complex patterns\n const currentText = sourceFile.getFullText();\n if (currentText.includes('z.')) {\n this.warnings.push(\n `${filePath}: Some Zod patterns could not be auto-transformed to ArkType. ` +\n 'Look for remaining z.* references and convert manually.',\n );\n }\n }\n\n private transformTypeHelpers(sourceFile: SourceFile): void {\n let text = sourceFile.getFullText();\n\n // z.infer<typeof schema> → typeof schema.infer (ArkType)\n // Actually in ArkType: type().infer is the type, used as typeof schema.infer\n text = text.replace(/z\\.infer<typeof\\s+(\\w+)>/g, 'typeof $1.infer');\n text = text.replace(/z\\.input<typeof\\s+(\\w+)>/g, 'typeof $1.in');\n text = text.replace(/z\\.output<typeof\\s+(\\w+)>/g, 'typeof $1.infer');\n\n sourceFile.replaceWithText(text);\n }\n\n private checkManualReviewPatterns(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const text = sourceFile.getFullText();\n\n for (const pattern of MANUAL_REVIEW_PATTERNS) {\n if (text.includes(`.${pattern}(`)) {\n const guidance = this.getManualGuidance(pattern);\n this.warnings.push(\n `${filePath}: .${pattern}() requires manual conversion to ArkType. ${guidance}`,\n );\n }\n }\n }\n\n private getManualGuidance(pattern: string): string {\n const guidance: Record<string, string> = {\n discriminatedUnion:\n \"ArkType uses native TypeScript union syntax: type(\\\"{ kind: 'a', ... } | { kind: 'b', ... }\\\").\",\n superRefine:\n 'ArkType uses .narrow() for refinements: type(\"string\").narrow((s) => s.length > 0).',\n transform: 'ArkType uses morphs: type(\"string\").pipe((s) => s.toUpperCase()).',\n preprocess: 'ArkType uses .from() for input transforms.',\n lazy: 'ArkType handles recursion with scope(): const types = scope({ node: { left: \"node | null\", right: \"node | null\" } }).export().',\n brand: 'ArkType has no .brand() equivalent. Use nominal types or tagged unions instead.',\n coerce: 'ArkType uses .from() morphs for coercion: type(\"string\").from(\"number\").',\n pipe: 'ArkType uses .pipe() with different semantics for morphs.',\n catch: 'ArkType has no .catch() equivalent. Handle fallback values at the application level.',\n };\n return guidance[pattern] || 'See ArkType documentation for equivalent pattern.';\n }\n}\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodToArktypeTransformer } from './zod-to-arktype-transformer.js';\n\nexport function createZodToArktypeHandler(): TransformHandler {\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n const transformer = new ZodToArktypeTransformer();\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@schemashift/zod-arktype",
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "Zod ↔ ArkType bidirectional transformer for SchemaShift",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"schemashift",
|
|
7
|
+
"zod",
|
|
8
|
+
"arktype",
|
|
9
|
+
"migration",
|
|
10
|
+
"schema",
|
|
11
|
+
"codemod"
|
|
12
|
+
],
|
|
13
|
+
"author": "Joseph May",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=22.0.0"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/index.d.cts",
|
|
30
|
+
"default": "./dist/index.cjs"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@schemashift/core": "0.10.0",
|
|
44
|
+
"ts-morph": "27.0.2"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|