@schemashift/core 0.2.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 ADDED
@@ -0,0 +1,129 @@
1
+ # @schemashift/core
2
+
3
+ Core functionality for SchemaShift schema migrations. Provides schema analysis, detection, and the transform engine.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @schemashift/core
9
+ ```
10
+
11
+ ## API
12
+
13
+ ### SchemaAnalyzer
14
+
15
+ Analyzes TypeScript/JavaScript files to detect schema definitions.
16
+
17
+ ```typescript
18
+ import { SchemaAnalyzer } from '@schemashift/core';
19
+
20
+ const analyzer = new SchemaAnalyzer('./tsconfig.json');
21
+ analyzer.addSourceFiles(['src/**/*.ts']);
22
+
23
+ const result = analyzer.analyze();
24
+ console.log(`Found ${result.schemas.length} schemas in ${result.filesWithSchemas} files`);
25
+ ```
26
+
27
+ #### Methods
28
+
29
+ - `addSourceFiles(patterns: string[])` - Add files to analyze by glob patterns
30
+ - `analyze(): AnalysisResult` - Run analysis and return results
31
+ - `getProject(): Project` - Get the underlying ts-morph Project
32
+
33
+ #### AnalysisResult
34
+
35
+ ```typescript
36
+ interface AnalysisResult {
37
+ schemas: SchemaInfo[];
38
+ imports: Map<string, SchemaLibrary>;
39
+ totalFiles: number;
40
+ filesWithSchemas: number;
41
+ }
42
+ ```
43
+
44
+ ### detectSchemaLibrary
45
+
46
+ Detects which schema library a module import refers to.
47
+
48
+ ```typescript
49
+ import { detectSchemaLibrary } from '@schemashift/core';
50
+
51
+ detectSchemaLibrary('zod'); // 'zod'
52
+ detectSchemaLibrary('yup'); // 'yup'
53
+ detectSchemaLibrary('joi'); // 'joi'
54
+ detectSchemaLibrary('io-ts'); // 'io-ts'
55
+ detectSchemaLibrary('valibot'); // 'valibot'
56
+ detectSchemaLibrary('lodash'); // 'unknown'
57
+ ```
58
+
59
+ ### TransformEngine
60
+
61
+ Manages transformation handlers and executes migrations.
62
+
63
+ ```typescript
64
+ import { TransformEngine } from '@schemashift/core';
65
+ import { createYupToZodHandler } from '@schemashift/yup-zod';
66
+
67
+ const engine = new TransformEngine();
68
+ engine.registerHandler('yup', 'zod', createYupToZodHandler());
69
+
70
+ const sourceFile = project.getSourceFileOrThrow('schema.ts');
71
+ const result = engine.transform(sourceFile, 'yup', 'zod');
72
+
73
+ if (result.success) {
74
+ console.log(result.transformedCode);
75
+ } else {
76
+ console.error(result.errors);
77
+ }
78
+ ```
79
+
80
+ #### Methods
81
+
82
+ - `registerHandler(from, to, handler)` - Register a transformation handler
83
+ - `getHandler(from, to)` - Get a registered handler
84
+ - `transform(sourceFile, from, to)` - Transform a source file
85
+
86
+ ### Types
87
+
88
+ ```typescript
89
+ type SchemaLibrary =
90
+ | 'zod'
91
+ | 'zod-v3'
92
+ | 'yup'
93
+ | 'joi'
94
+ | 'io-ts'
95
+ | 'valibot'
96
+ | 'v4'
97
+ | 'unknown';
98
+
99
+ interface SchemaInfo {
100
+ name: string;
101
+ filePath: string;
102
+ library: SchemaLibrary;
103
+ lineNumber: number;
104
+ code: string;
105
+ }
106
+
107
+ interface TransformResult {
108
+ success: boolean;
109
+ filePath: string;
110
+ originalCode: string;
111
+ transformedCode?: string;
112
+ errors: TransformError[];
113
+ warnings: string[];
114
+ }
115
+
116
+ interface TransformError {
117
+ message: string;
118
+ lineNumber?: number;
119
+ code?: string;
120
+ }
121
+
122
+ interface TransformHandler {
123
+ transform(sourceFile: SourceFile): TransformResult;
124
+ }
125
+ ```
126
+
127
+ ## License
128
+
129
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,206 @@
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
+ SchemaAnalyzer: () => SchemaAnalyzer,
24
+ TransformEngine: () => TransformEngine,
25
+ detectSchemaLibrary: () => detectSchemaLibrary,
26
+ loadConfig: () => loadConfig
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/analyzer.ts
31
+ var import_ts_morph = require("ts-morph");
32
+
33
+ // src/detect.ts
34
+ var LIBRARY_PATTERNS = {
35
+ zod: [/^zod$/, /^zod\//],
36
+ "zod-v3": [/^zod$/],
37
+ // Detected same as zod, version determined by package.json
38
+ yup: [/^yup$/],
39
+ joi: [/^joi$/, /^@hapi\/joi$/],
40
+ "io-ts": [/^io-ts$/, /^io-ts\//],
41
+ valibot: [/^valibot$/],
42
+ v4: [],
43
+ // Target version, not detectable from imports
44
+ unknown: []
45
+ };
46
+ function detectSchemaLibrary(moduleSpecifier) {
47
+ for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {
48
+ if (library === "unknown") continue;
49
+ if (patterns.some((pattern) => pattern.test(moduleSpecifier))) {
50
+ return library;
51
+ }
52
+ }
53
+ return "unknown";
54
+ }
55
+
56
+ // src/analyzer.ts
57
+ var SchemaAnalyzer = class {
58
+ project;
59
+ constructor(tsconfigPath) {
60
+ this.project = new import_ts_morph.Project({
61
+ tsConfigFilePath: tsconfigPath,
62
+ skipAddingFilesFromTsConfig: !tsconfigPath
63
+ });
64
+ }
65
+ addSourceFiles(patterns) {
66
+ this.project.addSourceFilesAtPaths(patterns);
67
+ }
68
+ analyze() {
69
+ const schemas = [];
70
+ const imports = /* @__PURE__ */ new Map();
71
+ let filesWithSchemas = 0;
72
+ for (const sourceFile of this.project.getSourceFiles()) {
73
+ const fileSchemas = this.analyzeFile(sourceFile);
74
+ if (fileSchemas.length > 0) {
75
+ filesWithSchemas++;
76
+ schemas.push(...fileSchemas);
77
+ }
78
+ for (const imp of sourceFile.getImportDeclarations()) {
79
+ const moduleSpecifier = imp.getModuleSpecifierValue();
80
+ const lib = detectSchemaLibrary(moduleSpecifier);
81
+ if (lib !== "unknown") {
82
+ imports.set(sourceFile.getFilePath(), lib);
83
+ }
84
+ }
85
+ }
86
+ return {
87
+ schemas,
88
+ imports,
89
+ totalFiles: this.project.getSourceFiles().length,
90
+ filesWithSchemas
91
+ };
92
+ }
93
+ analyzeFile(sourceFile) {
94
+ const schemas = [];
95
+ const filePath = sourceFile.getFilePath();
96
+ const library = this.detectFileLibrary(sourceFile);
97
+ if (library === "unknown") return schemas;
98
+ sourceFile.getVariableDeclarations().forEach((varDecl) => {
99
+ const initializer = varDecl.getInitializer();
100
+ if (initializer && this.isSchemaExpression(initializer, library)) {
101
+ schemas.push({
102
+ name: varDecl.getName(),
103
+ filePath,
104
+ library,
105
+ lineNumber: varDecl.getStartLineNumber(),
106
+ code: varDecl.getText()
107
+ });
108
+ }
109
+ });
110
+ return schemas;
111
+ }
112
+ detectFileLibrary(sourceFile) {
113
+ for (const imp of sourceFile.getImportDeclarations()) {
114
+ const lib = detectSchemaLibrary(imp.getModuleSpecifierValue());
115
+ if (lib !== "unknown") return lib;
116
+ }
117
+ return "unknown";
118
+ }
119
+ isSchemaExpression(node, library) {
120
+ const text = node.getText();
121
+ switch (library) {
122
+ case "zod":
123
+ return text.includes("z.") || text.includes("zod.");
124
+ case "yup":
125
+ return text.includes("yup.") || text.includes("Yup.");
126
+ case "joi":
127
+ return text.includes("Joi.") || text.includes("joi.");
128
+ case "io-ts":
129
+ return text.includes("t.") && node.getSourceFile().getText().includes("from 'io-ts'");
130
+ case "valibot":
131
+ return text.includes("v.") || text.includes("valibot.");
132
+ default:
133
+ return false;
134
+ }
135
+ }
136
+ getProject() {
137
+ return this.project;
138
+ }
139
+ };
140
+
141
+ // src/config.ts
142
+ var import_cosmiconfig = require("cosmiconfig");
143
+ async function loadConfig(configPath) {
144
+ const explorer = (0, import_cosmiconfig.cosmiconfig)("schemashift", {
145
+ searchPlaces: [
146
+ ".schemashiftrc",
147
+ ".schemashiftrc.json",
148
+ ".schemashiftrc.yaml",
149
+ ".schemashiftrc.yml",
150
+ ".schemashiftrc.js",
151
+ ".schemashiftrc.cjs",
152
+ "schemashift.config.js",
153
+ "schemashift.config.cjs",
154
+ "package.json"
155
+ ]
156
+ });
157
+ const result = configPath ? await explorer.load(configPath) : await explorer.search();
158
+ return {
159
+ include: ["**/*.ts", "**/*.tsx"],
160
+ exclude: ["**/node_modules/**", "**/dist/**", "**/*.d.ts"],
161
+ git: { enabled: false },
162
+ backup: { enabled: true, dir: ".schemashift-backup" },
163
+ ...result?.config
164
+ };
165
+ }
166
+
167
+ // src/transform.ts
168
+ var TransformEngine = class {
169
+ handlers = /* @__PURE__ */ new Map();
170
+ registerHandler(from, to, handler) {
171
+ this.handlers.set(`${from}->${to}`, handler);
172
+ }
173
+ getHandler(from, to) {
174
+ return this.handlers.get(`${from}->${to}`);
175
+ }
176
+ hasHandler(from, to) {
177
+ return this.handlers.has(`${from}->${to}`);
178
+ }
179
+ getSupportedPaths() {
180
+ return Array.from(this.handlers.keys()).map((key) => {
181
+ const [from, to] = key.split("->");
182
+ return { from, to };
183
+ });
184
+ }
185
+ transform(sourceFile, from, to, options) {
186
+ const handler = this.getHandler(from, to);
187
+ if (!handler) {
188
+ return {
189
+ success: false,
190
+ filePath: sourceFile.getFilePath(),
191
+ originalCode: sourceFile.getFullText(),
192
+ errors: [{ message: `No handler for ${from}->${to}` }],
193
+ warnings: []
194
+ };
195
+ }
196
+ return handler.transform(sourceFile, options);
197
+ }
198
+ };
199
+ // Annotate the CommonJS export names for ESM import in node:
200
+ 0 && (module.exports = {
201
+ SchemaAnalyzer,
202
+ TransformEngine,
203
+ detectSchemaLibrary,
204
+ loadConfig
205
+ });
206
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/analyzer.ts","../src/detect.ts","../src/config.ts","../src/transform.ts"],"sourcesContent":["export { type AnalysisResult, SchemaAnalyzer } from './analyzer.js';\nexport {\n type CustomRule,\n loadConfig,\n type SchemaShiftConfig,\n} from './config.js';\nexport { detectSchemaLibrary } from './detect.js';\nexport { TransformEngine, type TransformHandler } from './transform.js';\nexport * from './types.js';\n","import { type Node, Project, type SourceFile, type VariableDeclaration } from 'ts-morph';\nimport { detectSchemaLibrary } from './detect.js';\nimport type { SchemaInfo, SchemaLibrary } from './types.js';\n\nexport interface AnalysisResult {\n schemas: SchemaInfo[];\n imports: Map<string, SchemaLibrary>;\n totalFiles: number;\n filesWithSchemas: number;\n}\n\nexport class SchemaAnalyzer {\n private project: Project;\n\n constructor(tsconfigPath?: string) {\n this.project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: !tsconfigPath,\n });\n }\n\n addSourceFiles(patterns: string[]): void {\n this.project.addSourceFilesAtPaths(patterns);\n }\n\n analyze(): AnalysisResult {\n const schemas: SchemaInfo[] = [];\n const imports = new Map<string, SchemaLibrary>();\n let filesWithSchemas = 0;\n\n for (const sourceFile of this.project.getSourceFiles()) {\n const fileSchemas = this.analyzeFile(sourceFile);\n if (fileSchemas.length > 0) {\n filesWithSchemas++;\n schemas.push(...fileSchemas);\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = imp.getModuleSpecifierValue();\n const lib = detectSchemaLibrary(moduleSpecifier);\n if (lib !== 'unknown') {\n imports.set(sourceFile.getFilePath(), lib);\n }\n }\n }\n\n return {\n schemas,\n imports,\n totalFiles: this.project.getSourceFiles().length,\n filesWithSchemas,\n };\n }\n\n private analyzeFile(sourceFile: SourceFile): SchemaInfo[] {\n const schemas: SchemaInfo[] = [];\n const filePath = sourceFile.getFilePath();\n const library = this.detectFileLibrary(sourceFile);\n\n if (library === 'unknown') return schemas;\n\n sourceFile.getVariableDeclarations().forEach((varDecl: VariableDeclaration) => {\n const initializer = varDecl.getInitializer();\n if (initializer && this.isSchemaExpression(initializer, library)) {\n schemas.push({\n name: varDecl.getName(),\n filePath,\n library,\n lineNumber: varDecl.getStartLineNumber(),\n code: varDecl.getText(),\n });\n }\n });\n\n return schemas;\n }\n\n private detectFileLibrary(sourceFile: SourceFile): SchemaLibrary {\n for (const imp of sourceFile.getImportDeclarations()) {\n const lib = detectSchemaLibrary(imp.getModuleSpecifierValue());\n if (lib !== 'unknown') return lib;\n }\n return 'unknown';\n }\n\n private isSchemaExpression(node: Node, library: SchemaLibrary): boolean {\n const text = node.getText();\n switch (library) {\n case 'zod':\n return text.includes('z.') || text.includes('zod.');\n case 'yup':\n return text.includes('yup.') || text.includes('Yup.');\n case 'joi':\n return text.includes('Joi.') || text.includes('joi.');\n case 'io-ts':\n return text.includes('t.') && node.getSourceFile().getText().includes(\"from 'io-ts'\");\n case 'valibot':\n return text.includes('v.') || text.includes('valibot.');\n default:\n return false;\n }\n }\n\n getProject(): Project {\n return this.project;\n }\n}\n","import type { SchemaLibrary } from './types.js';\n\nconst LIBRARY_PATTERNS: Record<SchemaLibrary, RegExp[]> = {\n zod: [/^zod$/, /^zod\\//],\n 'zod-v3': [/^zod$/], // Detected same as zod, version determined by package.json\n yup: [/^yup$/],\n joi: [/^joi$/, /^@hapi\\/joi$/],\n 'io-ts': [/^io-ts$/, /^io-ts\\//],\n valibot: [/^valibot$/],\n v4: [], // Target version, not detectable from imports\n unknown: [],\n};\n\nexport function detectSchemaLibrary(moduleSpecifier: string): SchemaLibrary {\n for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {\n if (library === 'unknown') continue;\n if (patterns.some((pattern) => pattern.test(moduleSpecifier))) {\n return library as SchemaLibrary;\n }\n }\n return 'unknown';\n}\n","import { cosmiconfig } from 'cosmiconfig';\n\nexport interface SchemaShiftConfig {\n // File patterns\n include: string[];\n exclude: string[];\n\n // Migration defaults\n defaultFrom?: string;\n defaultTo?: string;\n\n // Output\n outputDir?: string;\n reportFormat?: 'json' | 'html' | 'console';\n\n // Git integration\n git?: {\n enabled: boolean;\n createBranch?: boolean;\n branchPrefix?: string;\n autoCommit?: boolean;\n commitMessage?: string;\n };\n\n // Backup/Rollback\n backup?: {\n enabled: boolean;\n dir?: string;\n };\n\n // Custom rules\n customRules?: CustomRule[];\n\n // CI mode\n ci?: boolean;\n}\n\nexport interface CustomRule {\n name: string;\n description?: string;\n match: {\n library: string;\n method: string;\n pattern?: string;\n };\n transform: {\n method: string;\n args?: string[];\n warning?: string;\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<SchemaShiftConfig> {\n const explorer = cosmiconfig('schemashift', {\n searchPlaces: [\n '.schemashiftrc',\n '.schemashiftrc.json',\n '.schemashiftrc.yaml',\n '.schemashiftrc.yml',\n '.schemashiftrc.js',\n '.schemashiftrc.cjs',\n 'schemashift.config.js',\n 'schemashift.config.cjs',\n 'package.json',\n ],\n });\n\n const result = configPath ? await explorer.load(configPath) : await explorer.search();\n\n return {\n include: ['**/*.ts', '**/*.tsx'],\n exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'],\n git: { enabled: false },\n backup: { enabled: true, dir: '.schemashift-backup' },\n ...result?.config,\n };\n}\n","import type { SourceFile } from 'ts-morph';\nimport type { SchemaLibrary, TransformOptions, TransformResult } from './types.js';\n\nexport interface TransformHandler {\n transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;\n}\n\nexport class TransformEngine {\n private handlers = new Map<string, TransformHandler>();\n\n registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void {\n this.handlers.set(`${from}->${to}`, handler);\n }\n\n getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined {\n return this.handlers.get(`${from}->${to}`);\n }\n\n hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean {\n return this.handlers.has(`${from}->${to}`);\n }\n\n getSupportedPaths(): Array<{ from: SchemaLibrary; to: SchemaLibrary }> {\n return Array.from(this.handlers.keys()).map((key) => {\n const [from, to] = key.split('->') as [SchemaLibrary, SchemaLibrary];\n return { from, to };\n });\n }\n\n transform(\n sourceFile: SourceFile,\n from: SchemaLibrary,\n to: SchemaLibrary,\n options: TransformOptions,\n ): TransformResult {\n const handler = this.getHandler(from, to);\n if (!handler) {\n return {\n success: false,\n filePath: sourceFile.getFilePath(),\n originalCode: sourceFile.getFullText(),\n errors: [{ message: `No handler for ${from}->${to}` }],\n warnings: [],\n };\n }\n return handler.transform(sourceFile, options);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,103 @@
1
+ import { Project, SourceFile } from 'ts-morph';
2
+
3
+ type SchemaLibrary = 'zod' | 'zod-v3' | 'yup' | 'joi' | 'io-ts' | 'valibot' | 'v4' | 'unknown';
4
+ interface SchemaInfo {
5
+ name: string;
6
+ filePath: string;
7
+ library: SchemaLibrary;
8
+ lineNumber: number;
9
+ code: string;
10
+ }
11
+ interface TransformResult {
12
+ success: boolean;
13
+ filePath: string;
14
+ originalCode: string;
15
+ transformedCode?: string;
16
+ errors: TransformError[];
17
+ warnings: string[];
18
+ }
19
+ interface TransformError {
20
+ message: string;
21
+ line?: number;
22
+ column?: number;
23
+ suggestion?: string;
24
+ }
25
+ interface TransformOptions {
26
+ from: SchemaLibrary;
27
+ to: SchemaLibrary;
28
+ dryRun?: boolean;
29
+ preserveComments?: boolean;
30
+ }
31
+
32
+ interface AnalysisResult {
33
+ schemas: SchemaInfo[];
34
+ imports: Map<string, SchemaLibrary>;
35
+ totalFiles: number;
36
+ filesWithSchemas: number;
37
+ }
38
+ declare class SchemaAnalyzer {
39
+ private project;
40
+ constructor(tsconfigPath?: string);
41
+ addSourceFiles(patterns: string[]): void;
42
+ analyze(): AnalysisResult;
43
+ private analyzeFile;
44
+ private detectFileLibrary;
45
+ private isSchemaExpression;
46
+ getProject(): Project;
47
+ }
48
+
49
+ interface SchemaShiftConfig {
50
+ include: string[];
51
+ exclude: string[];
52
+ defaultFrom?: string;
53
+ defaultTo?: string;
54
+ outputDir?: string;
55
+ reportFormat?: 'json' | 'html' | 'console';
56
+ git?: {
57
+ enabled: boolean;
58
+ createBranch?: boolean;
59
+ branchPrefix?: string;
60
+ autoCommit?: boolean;
61
+ commitMessage?: string;
62
+ };
63
+ backup?: {
64
+ enabled: boolean;
65
+ dir?: string;
66
+ };
67
+ customRules?: CustomRule[];
68
+ ci?: boolean;
69
+ }
70
+ interface CustomRule {
71
+ name: string;
72
+ description?: string;
73
+ match: {
74
+ library: string;
75
+ method: string;
76
+ pattern?: string;
77
+ };
78
+ transform: {
79
+ method: string;
80
+ args?: string[];
81
+ warning?: string;
82
+ };
83
+ }
84
+ declare function loadConfig(configPath?: string): Promise<SchemaShiftConfig>;
85
+
86
+ declare function detectSchemaLibrary(moduleSpecifier: string): SchemaLibrary;
87
+
88
+ interface TransformHandler {
89
+ transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;
90
+ }
91
+ declare class TransformEngine {
92
+ private handlers;
93
+ registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void;
94
+ getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined;
95
+ hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean;
96
+ getSupportedPaths(): Array<{
97
+ from: SchemaLibrary;
98
+ to: SchemaLibrary;
99
+ }>;
100
+ transform(sourceFile: SourceFile, from: SchemaLibrary, to: SchemaLibrary, options: TransformOptions): TransformResult;
101
+ }
102
+
103
+ export { type AnalysisResult, type CustomRule, SchemaAnalyzer, type SchemaInfo, type SchemaLibrary, type SchemaShiftConfig, TransformEngine, type TransformError, type TransformHandler, type TransformOptions, type TransformResult, detectSchemaLibrary, loadConfig };
@@ -0,0 +1,103 @@
1
+ import { Project, SourceFile } from 'ts-morph';
2
+
3
+ type SchemaLibrary = 'zod' | 'zod-v3' | 'yup' | 'joi' | 'io-ts' | 'valibot' | 'v4' | 'unknown';
4
+ interface SchemaInfo {
5
+ name: string;
6
+ filePath: string;
7
+ library: SchemaLibrary;
8
+ lineNumber: number;
9
+ code: string;
10
+ }
11
+ interface TransformResult {
12
+ success: boolean;
13
+ filePath: string;
14
+ originalCode: string;
15
+ transformedCode?: string;
16
+ errors: TransformError[];
17
+ warnings: string[];
18
+ }
19
+ interface TransformError {
20
+ message: string;
21
+ line?: number;
22
+ column?: number;
23
+ suggestion?: string;
24
+ }
25
+ interface TransformOptions {
26
+ from: SchemaLibrary;
27
+ to: SchemaLibrary;
28
+ dryRun?: boolean;
29
+ preserveComments?: boolean;
30
+ }
31
+
32
+ interface AnalysisResult {
33
+ schemas: SchemaInfo[];
34
+ imports: Map<string, SchemaLibrary>;
35
+ totalFiles: number;
36
+ filesWithSchemas: number;
37
+ }
38
+ declare class SchemaAnalyzer {
39
+ private project;
40
+ constructor(tsconfigPath?: string);
41
+ addSourceFiles(patterns: string[]): void;
42
+ analyze(): AnalysisResult;
43
+ private analyzeFile;
44
+ private detectFileLibrary;
45
+ private isSchemaExpression;
46
+ getProject(): Project;
47
+ }
48
+
49
+ interface SchemaShiftConfig {
50
+ include: string[];
51
+ exclude: string[];
52
+ defaultFrom?: string;
53
+ defaultTo?: string;
54
+ outputDir?: string;
55
+ reportFormat?: 'json' | 'html' | 'console';
56
+ git?: {
57
+ enabled: boolean;
58
+ createBranch?: boolean;
59
+ branchPrefix?: string;
60
+ autoCommit?: boolean;
61
+ commitMessage?: string;
62
+ };
63
+ backup?: {
64
+ enabled: boolean;
65
+ dir?: string;
66
+ };
67
+ customRules?: CustomRule[];
68
+ ci?: boolean;
69
+ }
70
+ interface CustomRule {
71
+ name: string;
72
+ description?: string;
73
+ match: {
74
+ library: string;
75
+ method: string;
76
+ pattern?: string;
77
+ };
78
+ transform: {
79
+ method: string;
80
+ args?: string[];
81
+ warning?: string;
82
+ };
83
+ }
84
+ declare function loadConfig(configPath?: string): Promise<SchemaShiftConfig>;
85
+
86
+ declare function detectSchemaLibrary(moduleSpecifier: string): SchemaLibrary;
87
+
88
+ interface TransformHandler {
89
+ transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;
90
+ }
91
+ declare class TransformEngine {
92
+ private handlers;
93
+ registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void;
94
+ getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined;
95
+ hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean;
96
+ getSupportedPaths(): Array<{
97
+ from: SchemaLibrary;
98
+ to: SchemaLibrary;
99
+ }>;
100
+ transform(sourceFile: SourceFile, from: SchemaLibrary, to: SchemaLibrary, options: TransformOptions): TransformResult;
101
+ }
102
+
103
+ export { type AnalysisResult, type CustomRule, SchemaAnalyzer, type SchemaInfo, type SchemaLibrary, type SchemaShiftConfig, TransformEngine, type TransformError, type TransformHandler, type TransformOptions, type TransformResult, detectSchemaLibrary, loadConfig };
package/dist/index.js ADDED
@@ -0,0 +1,176 @@
1
+ // src/analyzer.ts
2
+ import { Project } from "ts-morph";
3
+
4
+ // src/detect.ts
5
+ var LIBRARY_PATTERNS = {
6
+ zod: [/^zod$/, /^zod\//],
7
+ "zod-v3": [/^zod$/],
8
+ // Detected same as zod, version determined by package.json
9
+ yup: [/^yup$/],
10
+ joi: [/^joi$/, /^@hapi\/joi$/],
11
+ "io-ts": [/^io-ts$/, /^io-ts\//],
12
+ valibot: [/^valibot$/],
13
+ v4: [],
14
+ // Target version, not detectable from imports
15
+ unknown: []
16
+ };
17
+ function detectSchemaLibrary(moduleSpecifier) {
18
+ for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {
19
+ if (library === "unknown") continue;
20
+ if (patterns.some((pattern) => pattern.test(moduleSpecifier))) {
21
+ return library;
22
+ }
23
+ }
24
+ return "unknown";
25
+ }
26
+
27
+ // src/analyzer.ts
28
+ var SchemaAnalyzer = class {
29
+ project;
30
+ constructor(tsconfigPath) {
31
+ this.project = new Project({
32
+ tsConfigFilePath: tsconfigPath,
33
+ skipAddingFilesFromTsConfig: !tsconfigPath
34
+ });
35
+ }
36
+ addSourceFiles(patterns) {
37
+ this.project.addSourceFilesAtPaths(patterns);
38
+ }
39
+ analyze() {
40
+ const schemas = [];
41
+ const imports = /* @__PURE__ */ new Map();
42
+ let filesWithSchemas = 0;
43
+ for (const sourceFile of this.project.getSourceFiles()) {
44
+ const fileSchemas = this.analyzeFile(sourceFile);
45
+ if (fileSchemas.length > 0) {
46
+ filesWithSchemas++;
47
+ schemas.push(...fileSchemas);
48
+ }
49
+ for (const imp of sourceFile.getImportDeclarations()) {
50
+ const moduleSpecifier = imp.getModuleSpecifierValue();
51
+ const lib = detectSchemaLibrary(moduleSpecifier);
52
+ if (lib !== "unknown") {
53
+ imports.set(sourceFile.getFilePath(), lib);
54
+ }
55
+ }
56
+ }
57
+ return {
58
+ schemas,
59
+ imports,
60
+ totalFiles: this.project.getSourceFiles().length,
61
+ filesWithSchemas
62
+ };
63
+ }
64
+ analyzeFile(sourceFile) {
65
+ const schemas = [];
66
+ const filePath = sourceFile.getFilePath();
67
+ const library = this.detectFileLibrary(sourceFile);
68
+ if (library === "unknown") return schemas;
69
+ sourceFile.getVariableDeclarations().forEach((varDecl) => {
70
+ const initializer = varDecl.getInitializer();
71
+ if (initializer && this.isSchemaExpression(initializer, library)) {
72
+ schemas.push({
73
+ name: varDecl.getName(),
74
+ filePath,
75
+ library,
76
+ lineNumber: varDecl.getStartLineNumber(),
77
+ code: varDecl.getText()
78
+ });
79
+ }
80
+ });
81
+ return schemas;
82
+ }
83
+ detectFileLibrary(sourceFile) {
84
+ for (const imp of sourceFile.getImportDeclarations()) {
85
+ const lib = detectSchemaLibrary(imp.getModuleSpecifierValue());
86
+ if (lib !== "unknown") return lib;
87
+ }
88
+ return "unknown";
89
+ }
90
+ isSchemaExpression(node, library) {
91
+ const text = node.getText();
92
+ switch (library) {
93
+ case "zod":
94
+ return text.includes("z.") || text.includes("zod.");
95
+ case "yup":
96
+ return text.includes("yup.") || text.includes("Yup.");
97
+ case "joi":
98
+ return text.includes("Joi.") || text.includes("joi.");
99
+ case "io-ts":
100
+ return text.includes("t.") && node.getSourceFile().getText().includes("from 'io-ts'");
101
+ case "valibot":
102
+ return text.includes("v.") || text.includes("valibot.");
103
+ default:
104
+ return false;
105
+ }
106
+ }
107
+ getProject() {
108
+ return this.project;
109
+ }
110
+ };
111
+
112
+ // src/config.ts
113
+ import { cosmiconfig } from "cosmiconfig";
114
+ async function loadConfig(configPath) {
115
+ const explorer = cosmiconfig("schemashift", {
116
+ searchPlaces: [
117
+ ".schemashiftrc",
118
+ ".schemashiftrc.json",
119
+ ".schemashiftrc.yaml",
120
+ ".schemashiftrc.yml",
121
+ ".schemashiftrc.js",
122
+ ".schemashiftrc.cjs",
123
+ "schemashift.config.js",
124
+ "schemashift.config.cjs",
125
+ "package.json"
126
+ ]
127
+ });
128
+ const result = configPath ? await explorer.load(configPath) : await explorer.search();
129
+ return {
130
+ include: ["**/*.ts", "**/*.tsx"],
131
+ exclude: ["**/node_modules/**", "**/dist/**", "**/*.d.ts"],
132
+ git: { enabled: false },
133
+ backup: { enabled: true, dir: ".schemashift-backup" },
134
+ ...result?.config
135
+ };
136
+ }
137
+
138
+ // src/transform.ts
139
+ var TransformEngine = class {
140
+ handlers = /* @__PURE__ */ new Map();
141
+ registerHandler(from, to, handler) {
142
+ this.handlers.set(`${from}->${to}`, handler);
143
+ }
144
+ getHandler(from, to) {
145
+ return this.handlers.get(`${from}->${to}`);
146
+ }
147
+ hasHandler(from, to) {
148
+ return this.handlers.has(`${from}->${to}`);
149
+ }
150
+ getSupportedPaths() {
151
+ return Array.from(this.handlers.keys()).map((key) => {
152
+ const [from, to] = key.split("->");
153
+ return { from, to };
154
+ });
155
+ }
156
+ transform(sourceFile, from, to, options) {
157
+ const handler = this.getHandler(from, to);
158
+ if (!handler) {
159
+ return {
160
+ success: false,
161
+ filePath: sourceFile.getFilePath(),
162
+ originalCode: sourceFile.getFullText(),
163
+ errors: [{ message: `No handler for ${from}->${to}` }],
164
+ warnings: []
165
+ };
166
+ }
167
+ return handler.transform(sourceFile, options);
168
+ }
169
+ };
170
+ export {
171
+ SchemaAnalyzer,
172
+ TransformEngine,
173
+ detectSchemaLibrary,
174
+ loadConfig
175
+ };
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/analyzer.ts","../src/detect.ts","../src/config.ts","../src/transform.ts"],"sourcesContent":["import { type Node, Project, type SourceFile, type VariableDeclaration } from 'ts-morph';\nimport { detectSchemaLibrary } from './detect.js';\nimport type { SchemaInfo, SchemaLibrary } from './types.js';\n\nexport interface AnalysisResult {\n schemas: SchemaInfo[];\n imports: Map<string, SchemaLibrary>;\n totalFiles: number;\n filesWithSchemas: number;\n}\n\nexport class SchemaAnalyzer {\n private project: Project;\n\n constructor(tsconfigPath?: string) {\n this.project = new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: !tsconfigPath,\n });\n }\n\n addSourceFiles(patterns: string[]): void {\n this.project.addSourceFilesAtPaths(patterns);\n }\n\n analyze(): AnalysisResult {\n const schemas: SchemaInfo[] = [];\n const imports = new Map<string, SchemaLibrary>();\n let filesWithSchemas = 0;\n\n for (const sourceFile of this.project.getSourceFiles()) {\n const fileSchemas = this.analyzeFile(sourceFile);\n if (fileSchemas.length > 0) {\n filesWithSchemas++;\n schemas.push(...fileSchemas);\n }\n\n for (const imp of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = imp.getModuleSpecifierValue();\n const lib = detectSchemaLibrary(moduleSpecifier);\n if (lib !== 'unknown') {\n imports.set(sourceFile.getFilePath(), lib);\n }\n }\n }\n\n return {\n schemas,\n imports,\n totalFiles: this.project.getSourceFiles().length,\n filesWithSchemas,\n };\n }\n\n private analyzeFile(sourceFile: SourceFile): SchemaInfo[] {\n const schemas: SchemaInfo[] = [];\n const filePath = sourceFile.getFilePath();\n const library = this.detectFileLibrary(sourceFile);\n\n if (library === 'unknown') return schemas;\n\n sourceFile.getVariableDeclarations().forEach((varDecl: VariableDeclaration) => {\n const initializer = varDecl.getInitializer();\n if (initializer && this.isSchemaExpression(initializer, library)) {\n schemas.push({\n name: varDecl.getName(),\n filePath,\n library,\n lineNumber: varDecl.getStartLineNumber(),\n code: varDecl.getText(),\n });\n }\n });\n\n return schemas;\n }\n\n private detectFileLibrary(sourceFile: SourceFile): SchemaLibrary {\n for (const imp of sourceFile.getImportDeclarations()) {\n const lib = detectSchemaLibrary(imp.getModuleSpecifierValue());\n if (lib !== 'unknown') return lib;\n }\n return 'unknown';\n }\n\n private isSchemaExpression(node: Node, library: SchemaLibrary): boolean {\n const text = node.getText();\n switch (library) {\n case 'zod':\n return text.includes('z.') || text.includes('zod.');\n case 'yup':\n return text.includes('yup.') || text.includes('Yup.');\n case 'joi':\n return text.includes('Joi.') || text.includes('joi.');\n case 'io-ts':\n return text.includes('t.') && node.getSourceFile().getText().includes(\"from 'io-ts'\");\n case 'valibot':\n return text.includes('v.') || text.includes('valibot.');\n default:\n return false;\n }\n }\n\n getProject(): Project {\n return this.project;\n }\n}\n","import type { SchemaLibrary } from './types.js';\n\nconst LIBRARY_PATTERNS: Record<SchemaLibrary, RegExp[]> = {\n zod: [/^zod$/, /^zod\\//],\n 'zod-v3': [/^zod$/], // Detected same as zod, version determined by package.json\n yup: [/^yup$/],\n joi: [/^joi$/, /^@hapi\\/joi$/],\n 'io-ts': [/^io-ts$/, /^io-ts\\//],\n valibot: [/^valibot$/],\n v4: [], // Target version, not detectable from imports\n unknown: [],\n};\n\nexport function detectSchemaLibrary(moduleSpecifier: string): SchemaLibrary {\n for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {\n if (library === 'unknown') continue;\n if (patterns.some((pattern) => pattern.test(moduleSpecifier))) {\n return library as SchemaLibrary;\n }\n }\n return 'unknown';\n}\n","import { cosmiconfig } from 'cosmiconfig';\n\nexport interface SchemaShiftConfig {\n // File patterns\n include: string[];\n exclude: string[];\n\n // Migration defaults\n defaultFrom?: string;\n defaultTo?: string;\n\n // Output\n outputDir?: string;\n reportFormat?: 'json' | 'html' | 'console';\n\n // Git integration\n git?: {\n enabled: boolean;\n createBranch?: boolean;\n branchPrefix?: string;\n autoCommit?: boolean;\n commitMessage?: string;\n };\n\n // Backup/Rollback\n backup?: {\n enabled: boolean;\n dir?: string;\n };\n\n // Custom rules\n customRules?: CustomRule[];\n\n // CI mode\n ci?: boolean;\n}\n\nexport interface CustomRule {\n name: string;\n description?: string;\n match: {\n library: string;\n method: string;\n pattern?: string;\n };\n transform: {\n method: string;\n args?: string[];\n warning?: string;\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<SchemaShiftConfig> {\n const explorer = cosmiconfig('schemashift', {\n searchPlaces: [\n '.schemashiftrc',\n '.schemashiftrc.json',\n '.schemashiftrc.yaml',\n '.schemashiftrc.yml',\n '.schemashiftrc.js',\n '.schemashiftrc.cjs',\n 'schemashift.config.js',\n 'schemashift.config.cjs',\n 'package.json',\n ],\n });\n\n const result = configPath ? await explorer.load(configPath) : await explorer.search();\n\n return {\n include: ['**/*.ts', '**/*.tsx'],\n exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'],\n git: { enabled: false },\n backup: { enabled: true, dir: '.schemashift-backup' },\n ...result?.config,\n };\n}\n","import type { SourceFile } from 'ts-morph';\nimport type { SchemaLibrary, TransformOptions, TransformResult } from './types.js';\n\nexport interface TransformHandler {\n transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;\n}\n\nexport class TransformEngine {\n private handlers = new Map<string, TransformHandler>();\n\n registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void {\n this.handlers.set(`${from}->${to}`, handler);\n }\n\n getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined {\n return this.handlers.get(`${from}->${to}`);\n }\n\n hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean {\n return this.handlers.has(`${from}->${to}`);\n }\n\n getSupportedPaths(): Array<{ from: SchemaLibrary; to: SchemaLibrary }> {\n return Array.from(this.handlers.keys()).map((key) => {\n const [from, to] = key.split('->') as [SchemaLibrary, SchemaLibrary];\n return { from, to };\n });\n }\n\n transform(\n sourceFile: SourceFile,\n from: SchemaLibrary,\n to: SchemaLibrary,\n options: TransformOptions,\n ): TransformResult {\n const handler = this.getHandler(from, to);\n if (!handler) {\n return {\n success: false,\n filePath: sourceFile.getFilePath(),\n originalCode: sourceFile.getFullText(),\n errors: [{ message: `No handler for ${from}->${to}` }],\n warnings: [],\n };\n }\n return handler.transform(sourceFile, options);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@schemashift/core",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "test": "vitest run",
26
+ "typecheck": "tsc --noEmit"
27
+ },
28
+ "dependencies": {
29
+ "ts-morph": "27.0.2",
30
+ "cosmiconfig": "9.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }